/* ================================================================
   style.css — Shoulders of Giants
   Visual style: 1990s SNES / arcade aesthetic
   Inspired by: Earthbound, Final Fantasy VI, Street Fighter II
   Font: CT Galbite (pixel/bitmap feel) loaded from fonts/
   ================================================================ */


/* ── Pixel font ─────────────────────────────────────────────────── */
@font-face {
  font-family: 'CTGalbite';
  src: url('../fonts/CT Galbite-Regular.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}


/* ── CSS Custom Properties ──────────────────────────────────────── */
:root {
  /* Backgrounds */
  --bg-base:        #0a001e;   /* deep purple-black — title/main bg  */
  --bg-surface:     #0e0030;   /* slightly lighter — panels          */
  --bg-dialog:      #050015;   /* darkest — SNES dialogue interior   */
  --bg-header:      #07001a;   /* header bar                         */
  --bg-btn:         #12004a;   /* button resting state               */
  --bg-btn-hover:   #1e0878;   /* button hover                       */

  /* SNES border system */
  --border-bright:  #8898ff;   /* inner border — periwinkle          */
  --border-mid:     #3848c0;   /* outer border ring                  */
  --border-dark:    #000000;   /* gap layer                          */

  /* Accent palette */
  --snes-yellow:    #f8d000;   /* selection / highlight              */
  --snes-cyan:      #40e0e0;   /* secondary accent                   */
  --snes-green:     #48d848;   /* positive / "in deck"               */
  --snes-red:       #f04030;   /* danger / remove                    */
  --snes-white:     #ffffff;

  /* Card type colors — vivid SNES-saturated */
  --c-political:    #c060ff;
  --c-religious:    #ffa820;
  --c-military:     #ff4840;
  --c-cultural:     #30d898;
  --c-exploration:  #30a8ff;
  --c-scientific:   #e0c040;
  --c-labor:        #b5742e;  /* earthy burnt-orange — soil, agriculture, manual work */
  --c-economic:     #ffcf33;  /* bright coin-gold — commerce, prosperity */
  --c-prehistory:   #c8a878;  /* warm tan/beige — cave painting, ancient stone, parchment */

  /* Text */
  --text-white:     #ffffff;
  --text-dim:       #8888b8;
  --text-muted:     #444468;

  /* Font shorthand */
  --font:           'CTGalbite', 'Courier New', monospace;

  /* Layout */
  --header-h:       58px;
  --gap:            14px;
}


/* ── Reset & base ───────────────────────────────────────────────── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html, body {
  margin: 0;
  padding: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background: #000;
}
body {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-white);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  /* Sharpen pixel font rendering */
  -webkit-font-smoothing: none;
  font-smooth: never;
}

/* ── Fixed-stage container (1280×720, scaled by SOG.Stage) ─── */
#sog-stage {
  width: 1280px;
  height: 720px;
  position: relative;
  transform-origin: center center;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--bg-base);
}

button { font-family: var(--font); cursor: pointer; }
img    { display: block; }


/* ── Screen management ──────────────────────────────────────────── */
.screen           { position: absolute; inset: 0; display: none; }
.screen.active    { display: block; }


/* ── Shared SNES button ─────────────────────────────────────────── */
/*
  Three-layer visual stack (bottom → top):
    outer dark shadow → colored raised edge → flat face → text
  Press: element drops 4px to "consume" the raised edge.
*/
.btn-snes {
  display: inline-block;
  background: var(--bg-btn);
  border: 2px solid var(--border-bright);
  color: var(--text-white);
  font-family: var(--font);
  font-size: 14px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  padding: 10px 24px;
  cursor: pointer;
  /* Raised edge: 4px colored drop + 1px black beneath */
  box-shadow: 0 4px 0 var(--border-mid), 0 5px 0 #000;
  transition: background 0.08s, border-color 0.08s, color 0.08s,
              transform 0.06s, box-shadow 0.06s;
  outline: none;
}

.btn-snes:hover {
  background: var(--bg-btn-hover);
  border-color: var(--snes-yellow);
  color: var(--snes-yellow);
}

.btn-snes:active {
  transform: translateY(4px);
  box-shadow: 0 0 0 var(--border-mid), 0 1px 0 #000;
}


.btn-snes.btn-snes-remove {
  border-color: var(--snes-red);
  color: var(--snes-red);
}
.btn-snes.btn-snes-remove:hover {
  background: #200000;
  border-color: var(--snes-red);
  color: var(--snes-red);
}

.btn-snes.btn-snes-close {
  border-color: var(--text-dim);
  color: var(--text-dim);
}
.btn-snes.btn-snes-close:hover {
  border-color: var(--text-white);
  color: var(--text-white);
}

.btn-snes:disabled {
  background: #0a0020;
  border-color: #333358;
  color: var(--text-muted);
  box-shadow: 0 2px 0 #111, 0 3px 0 #000;
  cursor: not-allowed;
}

/* Larger variant used on the Home screen */
.btn-primary {
  font-size: 18px;
  padding: 13px 52px;
  letter-spacing: 0.10em;
}


/* ══════════════════════════════════════════════════════════════════
   HOME SCREEN — Wood-textured welcome / "Are you ready?" screen
══════════════════════════════════════════════════════════════════ */

#screen-home.active {
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  width: 100%;
  height: 100%;
}

/* Full-screen wood texture layer behind all content */
#screen-home::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  /* Fine horizontal grain lines + plank bands + warm brown base */
  background:
    repeating-linear-gradient(
      0deg,
      transparent 0px, transparent 7px,
      rgba(0,0,0,0.07) 7px, rgba(0,0,0,0.07) 8px
    ),
    repeating-linear-gradient(
      0deg,
      transparent             0px,  transparent             38px,
      rgba(255,255,255,0.045) 38px, rgba(255,255,255,0.045) 42px,
      transparent             42px, transparent             78px,
      rgba(0,0,0,0.07)        78px, rgba(0,0,0,0.07)        82px
    ),
    linear-gradient(180deg,
      #6e3e1a 0%,
      #885028 18%,
      #7a4822 36%,
      #8e5a2e 54%,
      #7a4822 72%,
      #885028 90%,
      #6e3e1a 100%
    );
  pointer-events: none;
}

.home-content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 40px;
  width: 100%;
  height: 100%;
}


.home-nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}

/* ── Home screen buttons — unified system ─────────────────────────
   All four buttons share one visual treatment (dark fill, gold border,
   gold text in CTGalbite). The tutorial button gets a subtle border-
   glow nudge so the eye lands there first without breaking the system.
─────────────────────────────────────────────────────────────────── */

/* Shared sizing — identical width + height across all home buttons.
   .btn-home-account is NOT part of this group on purpose — it's a smaller,
   auto-width .btn-snes pill (see the standalone rule near the bottom of
   this section), not sized to match the three wood-plank buttons. */
.btn-home-ready,
.btn-home-versus,
.btn-home-about,
.btn-home-arcadium,
.btn-home-adventure-new {
  width: 360px;
  box-sizing: border-box;
  text-align: center;
  text-transform: uppercase;
}

/* Shared visual — every button gets the same gold border, gold text,
   raised SNES edge, and CTGalbite font. Per-button fills override
   `background` below so each button has its own colour identity. */
.btn-home-ready,
.btn-home-versus,
.btn-home-about,
.btn-home-arcadium,
.btn-home-adventure-new {
  font-family: var(--font);          /* CTGalbite — same as page title */
  font-size: 28px;
  padding: 12px 52px;
  color: #f0cf6c;
  background: #2a1608;               /* fallback / About fill */
  border: 3px solid #d4aa50;         /* unified gold border across all */
  border-radius: 2px;
  letter-spacing: 0.06em;
  cursor: pointer;
  /* 4-direction pixel outline + soft drop — keeps gold text legible
     on every coloured fill, including the warm amber Learn button. */
  text-shadow:
    1px 1px 0 #000,
   -1px -1px 0 #000,
    1px -1px 0 #000,
   -1px 1px 0 #000,
    0 2px 4px rgba(0, 0, 0, 0.55);
  box-shadow: 0 4px 0 #1a0c04, 0 5px 0 #000;
  transition: background 0.15s, border-color 0.15s, color 0.15s,
              box-shadow 0.15s, transform 0.06s;
}

/* Shared hover/tap — same border brighten + warm halo for all */
.btn-home-ready:hover,
.btn-home-versus:hover,
.btn-home-about:hover,
.btn-home-arcadium:hover,
.btn-home-adventure-new:hover {
  border-color: #f0cf6c;
  color: #fff5d8;
  box-shadow:
    0 4px 0 #1a0c04,
    0 5px 0 #000,
    0 0 14px rgba(240, 207, 108, 0.35);
}

/* Shared pressed state — flatten the drop shadow */
.btn-home-ready:active,
.btn-home-versus:active,
.btn-home-about:active,
.btn-home-arcadium:active,
.btn-home-adventure-new:active {
  transform: translateY(4px);
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000;
}

/* ── Per-button colour fills ─────────────────────────────────────
   Saturated, recognisable at a glance. Each fill is a subtle
   top-to-bottom gradient (lighter top → darker bottom) for a
   raised pixel-button feel; gold border + gold text from the
   shared rules above tie them all together as a family.
─────────────────────────────────────────────────────────────── */

/* "I'm Ready" — saturated royal purple (core gameplay, energetic) */
.btn-home-ready {
  background: linear-gradient(180deg, #7a3aab 0%, #5e2890 100%);
}
.btn-home-ready:hover {
  background: linear-gradient(180deg, #9450c8 0%, #6e34a8 100%);
}


/* "Multiplayer" — saturated teal (social / outward play) */
.btn-home-versus {
  background: linear-gradient(180deg, #1e7a8a 0%, #135060 100%);
}
.btn-home-versus:hover {
  background: linear-gradient(180deg, #2a9aa8 0%, #1c6878 100%);
}

/* "About the Game" — neutral dark, no tint (quietest button by design).
   Inherits the shared base fill + shared hover. */


/* ── Home-screen Feedback button ─────────────────────────────────
   Conditional 5th button. Hidden by inline style="display:none" until
   js/feedback.js shows it — everyone except a brand-new guest's first visit.
   Smaller and quieter than the four primary buttons so it doesn't
   compete with the main navigation. */
.btn-home-feedback {
  display: inline-block;
  width: 220px;
  box-sizing: border-box;
  margin-top: 6px;
  padding: 7px 24px;
  font-family: var(--font);
  font-size: 16px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  color: rgba(232, 192, 96, 0.78);
  background: #2a1608;
  border: 2px solid #6a4418;
  border-radius: 2px;
  cursor: pointer;
  text-shadow: 1px 1px 0 #000;
  box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000;
  transition: background 0.15s, border-color 0.15s, color 0.15s,
              box-shadow 0.15s, transform 0.06s;
}
.btn-home-feedback:hover {
  background: #3a200c;
  border-color: #d4aa50;
  color: #f0cf6c;
  box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000,
              0 0 10px rgba(212, 170, 80, 0.20);
}
.btn-home-feedback:active {
  transform: translateY(3px);
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000;
}

/* ── State-2 back arrow ──────────────────────────────────────────
   Small secondary control for returning from path-choice (State 2)
   to the initial home view (State 1). Lower visual weight than
   the primary buttons — text-button feel with a subtle gold border. */
.btn-state2-back {
  display: inline-block;
  margin-top: 8px;
  padding: 4px 18px;
  font-family: var(--font);
  font-size: 16px;
  letter-spacing: 0.06em;
  color: #b89968;
  background: transparent;
  border: 1px solid #6a4a20;
  border-radius: 2px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s, transform 0.06s;
}
.btn-state2-back:hover {
  color: #f0cf6c;
  border-color: #d4aa50;
  background: rgba(42, 22, 8, 0.6);
}
.btn-state2-back:active {
  transform: translateY(1px);
}


/* ══════════════════════════════════════════════════════════════════
   FEEDBACK POPUP — first-time prompt after the 3rd qualifying match
   Single gold border (no SNES double-ring), bronze-amber palette,
   matches the unified visual system.
══════════════════════════════════════════════════════════════════ */

#feedback-backdrop {
  background: rgba(20, 10, 2, 0.82);
}

.feedback-popup {
  width: 540px;
  max-width: 1178px;
  padding: 28px 36px 26px;
  background: linear-gradient(180deg,
    #2a1608 0%,
    #3a200c 50%,
    #2a1608 100%);
  border: 3px solid #d4aa50;
  border-radius: 2px;
  box-shadow:
    0 0 0 1px #1a0c04,
    0 8px 24px rgba(0, 0, 0, 0.65),
    inset 0 0 28px rgba(60, 30, 0, 0.50);
}

/* Header — title + italic game-name subhead */
.feedback-popup .popup-card-name {
  color: #e8c060;
  font-family: var(--font);
  font-size: 24px;
  text-align: center;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-shadow: 2px 2px 0 #000, 0 0 8px rgba(220, 170, 60, 0.30);
  line-height: 1.25;
  margin-bottom: 12px;
}
.feedback-subhead {
  font-style: italic;
  font-size: 26px;
  color: #f0d8a0;
  display: inline-block;
  margin-top: 4px;
  letter-spacing: 0.05em;
}

/* Bronze divider, single hairline (no neon glow) */
.feedback-popup .popup-divider {
  height: 2px;
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(180, 130, 40, 0.65) 18%,
    #d4aa50 50%,
    rgba(180, 130, 40, 0.65) 82%,
    transparent 100%);
  box-shadow: none;
  margin-bottom: 18px;
}

/* Body copy */
.feedback-body {
  font-family: var(--font);
  font-size: 17px;
  color: #f3e6c4;
  line-height: 1.55;
  text-shadow: 1px 1px 0 #000;
  margin-bottom: 22px;
  text-align: center;
}
.feedback-body p { margin: 0; }

/* Button stack (Feedback Form / Continue), equal width, consistent spacing */
.feedback-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: stretch;
}

/* Shared button base — same family as home buttons (gold border,
   gold text, raised SNES edge, 4-direction pixel outline). */
.btn-feedback {
  width: 100%;
  padding: 11px 24px;
  font-family: var(--font);
  font-size: 18px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  color: #f0cf6c;
  background: #2a1608;
  border: 3px solid #d4aa50;
  border-radius: 2px;
  cursor: pointer;
  text-shadow:
    1px 1px 0 #000,
    -1px -1px 0 #000,
    1px -1px 0 #000,
    -1px 1px 0 #000,
    0 2px 4px rgba(0, 0, 0, 0.55);
  box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000;
  transition: background 0.15s, border-color 0.15s, color 0.15s,
              box-shadow 0.15s, transform 0.06s;
}
.btn-feedback:hover {
  border-color: #f0cf6c;
  color: #fff5d8;
  box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000,
              0 0 12px rgba(240, 207, 108, 0.30);
}
.btn-feedback:active {
  transform: translateY(3px);
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000;
}

/* Primary "Feedback Form" — warm amber tint + outer halo
   (mirrors the "I'm Ready To Learn" home-button emphasis). */
.btn-feedback-primary {
  background: linear-gradient(180deg, #b86a1c 0%, #8a4f12 100%);
  font-size: 20px;
  padding: 13px 24px;
  box-shadow:
    0 3px 0 #1a0c04,
    0 4px 0 #000,
    0 0 14px rgba(240, 207, 108, 0.35);
}
.btn-feedback-primary:hover {
  background: linear-gradient(180deg, #d68228 0%, #a86018 100%);
  border-color: #f0cf6c;
  color: #fff5d8;
  box-shadow:
    0 3px 0 #1a0c04,
    0 4px 0 #000,
    0 0 22px rgba(240, 207, 108, 0.55);
}

/* ── End-of-content popup — reuses the feedback panel; adds paragraph
   spacing and the visible, clickable form link. */
#endgame-backdrop {
  background: rgba(20, 10, 2, 0.82);
}
.endgame-popup .feedback-body p + p { margin-top: 10px; }
.endgame-link {
  display: block;
  margin-top: 12px;
  font-size: 13px;
  line-height: 1.4;
  color: #f0cf6c;
  text-decoration: underline;
  word-break: break-all;
  text-shadow: 1px 1px 0 #000;
}
.endgame-link:hover { color: #fff5d8; }


/* ── Video intro screen ────────────────────────────────────────── */

#screen-video.active {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
}

#intro-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}

/* Skip control — lets a slow connection bail out of the intro without
   waiting on the (large) video to buffer/finish. Only visible while the
   video screen is active. */
.intro-skip-btn {
  position: absolute;
  bottom: 24px;
  right: 28px;
  z-index: 10;
  padding: 10px 20px;
  font-family: var(--font);
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
  border: 2px solid rgba(255, 255, 255, 0.6);
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.intro-skip-btn:hover {
  background: rgba(0, 0, 0, 0.8);
  border-color: #fff;
}


/* ══════════════════════════════════════════════════════════════════
   DECK BUILDER SCREEN
══════════════════════════════════════════════════════════════════ */

#screen-deckbuilder.active {
  display: flex;
  flex-direction: column;
  /* Warm dark wood — same texture as the battle screen outer area */
  background:
    repeating-linear-gradient(
      90deg,
      rgba(80, 40, 0, 0.07) 0px, rgba(80, 40, 0, 0.07) 1px,
      transparent           1px, transparent           9px
    ),
    repeating-linear-gradient(
      0deg,
      rgba(0, 0, 0, 0.06)  0px, rgba(0, 0, 0, 0.06)  1px,
      transparent           1px, transparent           13px
    ),
    linear-gradient(168deg, #2c1a08 0%, #1e1106 35%, #261608 65%, #1a0e04 100%);
}


/* ── Header: ONE 56px bar, split on the same 320 / 960 line as the body ──
   Left cell (over the filter column): back button + screen title.
   Right cell (over the cards): deck tabs · ? · counter · Let's Play. */
.db-header {
  flex-shrink: 0;
  height: 56px;
  box-sizing: border-box;
  display: flex;
  align-items: stretch;
  background: rgba(12, 6, 2, 0.94);
  border-bottom: 2px solid rgba(200, 160, 32, 0.55);
  box-shadow: 0 2px 0 rgba(0,0,0,0.6), 0 3px 12px rgba(0,0,0,0.5);
  position: relative;
  z-index: 10;
}
.db-header-left {
  flex: 0 0 320px;
  min-width: 0;
  box-sizing: border-box;
  padding: 0 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-right: 2px solid rgba(200, 160, 32, 0.45);
}
.db-header-right {
  flex: 1;
  min-width: 0;
  box-sizing: border-box;
  padding: 0 16px 0 14px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.db-header-divider {
  flex-shrink: 0;
  width: 2px;
  height: 30px;
  margin: 0 2px;
  background: rgba(200, 160, 32, 0.35);
}

.btn-back {
  flex-shrink: 0;
  padding: 7px 16px;
  font-size: 12px;
  font-family: var(--font);
  /* Matches the Let's Play (enabled) button — warm fill + bright bronze border */
  background: rgba(60, 36, 8, 0.92);
  border: 2px solid rgba(212, 170, 80, 0.95);
  border-radius: 2px;
  color: #f4d678;
  letter-spacing: 0.08em;
  text-shadow: 1px 1px 0 #000, 0 0 8px rgba(212, 170, 80, 0.30);
  box-shadow: 0 2px 0 rgba(0,0,0,0.6), 0 0 12px rgba(212, 170, 80, 0.15);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s, box-shadow 0.12s;
  margin-top: 4px;
}
.btn-back:hover {
  background: rgba(90, 56, 16, 0.98);
  border-color: #f0cf6c;
  color: #fff5d8;
  box-shadow: 0 2px 0 rgba(0,0,0,0.6), 0 0 16px rgba(240, 207, 108, 0.35);
}
/* In the deck-builder bar every control is 36px tall and vertically centred. */
.db-header .btn-back {
  height: 36px;
  box-sizing: border-box;
  padding: 0 12px;
  margin-top: 0;
  white-space: nowrap;
}

/* Title fills the rest of the left cell. It shrinks (then truncates) when the
   back button carries a longer label such as "Back to Map". */
.db-title {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-family: var(--font);
  font-size: 18px;
  color: #e8c060;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  text-shadow: 1px 1px 0 #000, 0 0 12px rgba(200, 160, 0, 0.30);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.db-header.long-back .db-title { font-size: 14px; letter-spacing: 0.10em; }

/* "Let's Play" button + its tooltip-style hint stack */
.db-play-wrap {
  position: relative;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

/* Hidden by default; visible only when Play button is hovered while disabled */
.db-save-hint {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 6px;
  padding: 5px 10px;
  background: rgba(20, 10, 2, 0.95);
  border: 1px solid rgba(212, 170, 80, 0.55);
  border-radius: 2px;
  font-family: var(--font);
  font-size: 10px;
  color: rgba(243, 230, 196, 0.85);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-shadow: 1px 1px 0 #000;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s;
  z-index: 5;
}
.db-play-wrap:hover .btn-save:disabled ~ .db-save-hint {
  opacity: 1;
}

/* Deck counter — gold while building, green once the deck is complete */
.db-counter {
  flex-shrink: 0;
  min-width: 74px;
  text-align: center;
  font-family: var(--font);
  font-size: 15px;
  color: #f4d678;
  letter-spacing: 0.06em;
  text-shadow: 1px 1px 0 #000;
  white-space: nowrap;
  transition: color 0.15s, text-shadow 0.15s;
}

.db-counter.complete {
  color: #7ef08a;
  text-shadow: 1px 1px 0 #000, 0 0 8px rgba(126, 240, 138, 0.35);
}

.db-counter.flash {
  animation: counter-flash 0.42s steps(4, end);
}

@keyframes counter-flash {
  0%, 100% { color: #f4d678; transform: translateX(0); }
  25%      { color: #e85a3a; transform: translateX(-4px); }
  75%      { color: #e85a3a; transform: translateX(4px); }
}

/* Let's Play button — the primary action: filled gold when the deck is ready */
.btn-save {
  height: 36px;
  box-sizing: border-box;
  padding: 0 18px;
  font-size: 13px;
  font-family: var(--font);
  background: linear-gradient(180deg, #f0d488 0%, #c9a24a 100%);
  border: 2px solid #f0d890;
  border-radius: 2px;
  color: #2a1608;
  letter-spacing: 0.08em;
  text-shadow: none;
  box-shadow: 0 2px 0 rgba(0,0,0,0.6), 0 0 10px rgba(240, 207, 108, 0.35);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, border-color 0.12s, color 0.12s, box-shadow 0.12s;
}
.btn-save:not(:disabled):hover {
  background: linear-gradient(180deg, #fbe3a0 0%, #d9b258 100%);
  border-color: #fff5d8;
  box-shadow: 0 2px 0 rgba(0,0,0,0.6), 0 0 16px rgba(240, 207, 108, 0.55);
}
.btn-save:disabled {
  background: rgba(40, 24, 8, 0.85);
  border-color: rgba(150, 112, 40, 0.55);
  color: #7a6a48;
  box-shadow: 0 2px 0 rgba(0,0,0,0.4);
  cursor: not-allowed;
}
/* Brief "Saved ✓" confirmation flash on the adventure-mode Save Decks button */
.btn-save.db-saved-flash,
.btn-save.db-saved-flash:hover {
  background: rgba(40, 78, 28, 0.96);
  border-color: #7fcf5a;
  color: #e8ffd8;
  box-shadow: 0 2px 0 rgba(0,0,0,0.6), 0 0 16px rgba(127, 207, 90, 0.45);
}


/* ── Deck slot tabs (inside the header's right cell) ─────────────── */

.db-slot-row {
  flex: 1;
  min-width: 0;
  display: flex;
  gap: 6px;
}

.db-slot-card {
  flex: 1;
  min-width: 0;
  height: 36px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  padding: 0 4px 0 8px;
  background: rgba(40, 24, 8, 0.85);
  border: 2px solid rgba(150, 112, 40, 0.55);
  border-radius: 2px;
  cursor: pointer;
  overflow: hidden;
  transition: background 0.12s, border-color 0.12s, box-shadow 0.12s;
}
.db-slot-card:hover {
  background: rgba(70, 44, 14, 0.95);
  border-color: rgba(212, 170, 80, 0.9);
}

/* Active slot — filled gold */
.db-slot-card.active {
  background: linear-gradient(180deg, #e8c878 0%, #c9a24a 100%);
  border-color: #f0d890;
  cursor: default;
}

.db-slot-name {
  flex: 1;
  min-width: 0;
  font-family: var(--font);
  font-size: 12px;
  color: #b89a5a;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-shadow: 1px 1px 0 #000;
  /* Truncate long custom names cleanly */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.db-slot-card.active .db-slot-name {
  color: #2a1608;
  text-shadow: none;
}

/* Pencil/edit icon */
.db-slot-edit {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 2px;
  color: rgba(184, 154, 90, 0.8);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.db-slot-edit:hover {
  border-color: rgba(212, 170, 80, 0.9);
  color: #fff5d8;
}
.db-slot-card.active .db-slot-edit { color: rgba(42, 22, 8, 0.75); }
.db-slot-card.active .db-slot-edit:hover { border-color: #2a1608; color: #1a0c04; background: rgba(42, 22, 8, 0.12); }


/* ── Rename Deck modal ──────────────────────────────────────────── */

/* Compact width — just enough for the input + buttons */
.rename-deck-popup {
  width: 460px;
  max-width: 1178px;
}

.rename-deck-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 4px;
}

.rename-deck-input {
  font-family: var(--font);
  font-size: 22px;
  color: #f3e6c4;
  background: rgba(20, 10, 2, 0.85);
  border: 2px solid rgba(180, 130, 40, 0.55);
  border-radius: 2px;
  padding: 10px 14px;
  letter-spacing: 0.04em;
  text-shadow: 1px 1px 0 #000;
  outline: none;
  transition: border-color 0.12s, background 0.12s;
}
.rename-deck-input:focus {
  border-color: #d4aa50;
  background: rgba(30, 16, 4, 0.95);
}

.rename-deck-counter {
  font-family: var(--font);
  font-size: 11px;
  color: rgba(243, 230, 196, 0.45);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: right;
  text-shadow: 1px 1px 0 #000;
}

/* Bronze theme for both buttons in the rename modal */
#rename-deck-backdrop .popup-actions .btn-snes {
  background: #3a200c;
  border-color: #d4aa50;
  color: #f3e6c4;
  box-shadow: 0 4px 0 #1a0c04, 0 5px 0 #000;
}
#rename-deck-backdrop .popup-actions .btn-snes:hover {
  background: #4a2a10;
  border-color: #f0cf6c;
  color: #fff5d8;
}
#rename-deck-backdrop .popup-actions .btn-snes:active {
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000;
}

/* SAVE button gets a slight emphasis bump — brighter border to mark it as primary */
#rename-deck-save {
  border-color: #f0cf6c;
}


/* ── Body: filter column (320px, 25%) + cards (960px, 75%) ───────── */
.db-body {
  flex: 1;
  min-height: 0;
  display: flex;
}

.db-side {
  flex: 0 0 320px;
  box-sizing: border-box;
  /* bottom padding keeps the last control clear of the music widget */
  padding: 14px 16px 60px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow-y: auto;
  background: rgba(18, 10, 3, 0.92);
  border-right: 2px solid rgba(200, 160, 32, 0.45);
}

/* Search box */
.db-search { position: relative; flex-shrink: 0; }
.db-search input {
  width: 100%;
  height: 36px;
  box-sizing: border-box;
  padding: 0 30px 0 34px;
  font: 600 15px 'Source Sans 3', sans-serif;
  color: #f3e6c4;
  background: rgba(8, 4, 1, 0.85);
  border: 2px solid rgba(180, 130, 40, 0.65);
  border-radius: 2px;
  outline: none;
}
.db-search input:focus { border-color: #f0cf6c; box-shadow: 0 0 8px rgba(240, 207, 108, 0.35); }
.db-search input::placeholder { color: rgba(243, 230, 196, 0.45); font-weight: 400; }
.db-search::before {
  content: '\2315';
  position: absolute;
  left: 10px;
  top: 5px;
  font-size: 20px;
  color: #d4aa50;
  pointer-events: none;
}
.db-search-clear {
  display: none;
  position: absolute;
  right: 6px;
  top: 6px;
  width: 24px;
  height: 24px;
  padding: 0;
  background: transparent;
  border: 0;
  color: #d4aa50;
  font-size: 15px;
  line-height: 24px;
  cursor: pointer;
}
.db-search.has-text .db-search-clear { display: block; }

.db-side-group { flex-shrink: 0; display: flex; flex-direction: column; gap: 7px; }
.db-side-label {
  font-family: var(--font);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(232, 192, 96, 0.85);
  padding-bottom: 4px;
  border-bottom: 1px solid rgba(180, 130, 40, 0.35);
}

/* Sort buttons and filter chips share one look */
.db-sort  { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; }
.db-chips { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.db-sort-btn,
.db-chip {
  --c: #d4aa50;
  height: 30px;
  box-sizing: border-box;
  padding: 0 10px;
  display: flex;
  align-items: center;
  gap: 7px;
  font: 600 13px 'Source Sans 3', sans-serif;
  letter-spacing: 0.02em;
  color: #d9c8a0;
  white-space: nowrap;
  background: rgba(8, 4, 1, 0.7);
  border: 2px solid rgba(120, 90, 40, 0.6);
  border-radius: 2px;
  cursor: pointer;
  user-select: none;
  transition: background 0.1s, border-color 0.1s, color 0.1s;
}
.db-sort-btn { justify-content: center; gap: 6px; }
.db-sort-btn:hover,
.db-chip:hover { border-color: var(--c); color: #fff5d8; }
.db-sort-btn.on,
.db-chip.on {
  background: var(--c);
  border-color: #fff5d8;
  color: #140a02;
  box-shadow: 0 0 8px color-mix(in srgb, var(--c) 60%, transparent);
}
.db-sort-arrow { font-size: 11px; visibility: hidden; }
.db-sort-btn.on .db-sort-arrow { visibility: visible; }
/* Type chips carry a dot in the type's colour */
.db-chip-type::before {
  content: '';
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--c);
}
.db-chip-type.on::before { background: #140a02; }
.db-chip-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.db-chip-count { margin-left: auto; font-weight: 400; font-size: 11px; opacity: 0.7; }

/* Appears only while a search or filter is active */
.db-clear-filters {
  flex-shrink: 0;
  margin-top: 2px;
  padding: 8px 10px;
  font-family: var(--font);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: #ffb4a8;
  background: rgba(60, 12, 8, 0.9);
  border: 2px solid rgba(255, 122, 106, 0.8);
  border-radius: 2px;
  cursor: pointer;
  visibility: hidden;
}
.db-side.filtering .db-clear-filters { visibility: visible; }
.db-clear-filters:hover { background: rgba(90, 20, 12, 0.95); color: #ffd8d0; }

.db-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* Results strip: what is showing, in words */
.db-strip {
  flex: 0 0 40px;
  box-sizing: border-box;
  padding: 0 20px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: rgba(24, 13, 4, 0.75);
  border-bottom: 1px solid rgba(180, 130, 40, 0.3);
}
.db-result-count {
  font: 600 14px 'Source Sans 3', sans-serif;
  color: #f3e6c4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.db-result-count b { color: #f0cf6c; }
.db-strip-hint {
  flex-shrink: 0;
  margin-left: auto;
  font: 400 12px 'Source Sans 3', sans-serif;
  color: rgba(243, 230, 196, 0.55);
  white-space: nowrap;
}

/* ── Scrollable card area ──────────────────────────────────────────
   5 across at 174 x 262, sized so 2.25 ROWS show: the third row peeks in,
   which tells the player there is more below.
     624 tall (720 - 56 bar - 40 strip), 14 top padding → 610 of cards:
     2 rows (262 x 2) + 2 gaps (12 x 2) = 548, leaving 62 of row three. */
.db-main {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  box-sizing: border-box;
  padding: 14px 16px 16px;
}

.db-main::-webkit-scrollbar       { width: 8px; }
.db-main::-webkit-scrollbar-track { background: rgba(20, 10, 2, 0.80); }
.db-main::-webkit-scrollbar-thumb {
  background: rgba(180, 130, 40, 0.70);
  border: 1px solid rgba(100, 65, 10, 0.40);
}
.db-main::-webkit-scrollbar-thumb:hover { background: rgba(200, 150, 40, 0.80); }
.db-side::-webkit-scrollbar       { width: 6px; }
.db-side::-webkit-scrollbar-thumb { background: rgba(180, 130, 40, 0.5); }

.db-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
}

/* Heading between the player's cards and the ones still locked */
.db-locked-divider {
  grid-column: 1 / -1;
  margin-top: 6px;
  padding: 7px 14px;
  font-family: var(--font);
  font-size: 13px;
  letter-spacing: 0.06em;
  color: #f0cf6c;
  text-shadow: 1px 1px 0 #000;
  background: rgba(12, 6, 2, 0.8);
  border-left: 4px solid #d4aa50;
  border-top: 1px solid rgba(180, 130, 40, 0.28);
  border-bottom: 1px solid rgba(180, 130, 40, 0.28);
}
.db-locked-divider:first-child { margin-top: 0; }

.db-empty {
  padding: 80px 0;
  font: 400 16px 'Crimson Text', serif;
  color: #d9c8a0;
  text-align: center;
}


/* ══════════════════════════════════════════════════════════════════
   DECK BUILDER — CARD TILE
   Full-bleed PNG, no frame. CC top-left, IP top-right.
══════════════════════════════════════════════════════════════════ */

.db-card {
  position: relative;
  z-index: 0;          /* creates stacking context — keeps overlays inside card */
  aspect-ratio: 2 / 3;
  overflow: hidden;
  cursor: pointer;
  user-select: none;
  /* 2px gap border so selecting doesn't shift layout */
  border: 2px solid transparent;
  /* Pixel-sharp corners */
  border-radius: 0;
  /* Container query unit source for the CC / IP overlays */
  container-type: inline-size;
  transition: transform 0.10s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}

.db-card:hover { transform: translateY(-3px); }

/* Hover: type-coloured border */
.db-card.type-political:not(.selected):hover   { border-color: var(--c-political);   }
.db-card.type-religious:not(.selected):hover   { border-color: var(--c-religious);   }
.db-card.type-military:not(.selected):hover    { border-color: var(--c-military);    }
.db-card.type-cultural:not(.selected):hover    { border-color: var(--c-cultural);    }
.db-card.type-exploration:not(.selected):hover { border-color: var(--c-exploration); }
.db-card.type-scientific:not(.selected):hover  { border-color: var(--c-scientific); }
.db-card.type-labor:not(.selected):hover       { border-color: var(--c-labor);      }
.db-card.type-economic:not(.selected):hover    { border-color: var(--c-economic);   }
.db-card.type-prehistory:not(.selected):hover  { border-color: var(--c-prehistory); }

/* Selected: bright yellow SNES-style highlight */
.db-card.selected {
  border-color: var(--snes-yellow);
  box-shadow:
    0 0 0 1px #000,
    0 0 0 4px var(--snes-yellow),
    0 0 12px rgba(248,208,0,0.4);
}

/* Image fills the entire tile */
.db-card-img-wrap {
  position: absolute;
  inset: 0;
  background: #100a02;
}

/* bug 24: source images bake a pure-black band into top and bottom edges
   (verified via raw pixel sampling) but leave left/right as image content.
   Earlier attempts used box-shadow:inset on the wrap, which paints in the
   parent's background layer — the <img> child paints on top and hides it.
   This ::after pseudo-element renders the frame AS A FOREGROUND LAYER
   above the image (z-index 5, above the CC/IP overlays' z-index 4), with
   pointer-events:none to keep clicks reaching the card. */
.db-card-img-wrap::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Border width in cqw scales with card size — matches the baked-in
     top/bottom band proportionally on any viewport.
     SNES-style two-tone bevel: dark-gray highlight on top + left,
     deep-shadow on bottom + right (light source top-left = raised look).
     Gray reads cleanly against the warm-gold baked-in card frame
     without blending into it the way a gold highlight did. */
  border-style: solid;
  border-width: 1.5cqw;
  border-top-color:    #4a4a4a;
  border-left-color:   #4a4a4a;
  border-right-color:  #1a0a04;
  border-bottom-color: #1a0a04;
  box-sizing: border-box;
  pointer-events: none;
  z-index: 5;
}

.db-card-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Card art is a photographic export with a baked-in dither pattern, and
     it is always DOWNSCALED here (hand 328x492 -> 119x180, deck builder
     624x900 -> 111x168, board slot 731x1054 -> 91x136). `pixelated` makes
     Chrome nearest-neighbour those ratios — it discards pixels instead of
     averaging them, so the dither grid beats against the sampling grid and
     shimmers. `auto` lets the browser filter properly. Sprites and map art
     elsewhere still use `pixelated`; that art really is pixel art. */
  image-rendering: auto;
}

/* Faint initial letter — visible when art is missing */
.db-card-img-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font);
  font-size: 52px;
  color: rgba(255,255,255,0.04);
  pointer-events: none;
}

/* ── CC / IP corner numerals — proportional to card width ────────
   Sized in container query width units (cqw) so they scale with
   the card container, not with viewport or fixed pixels. Every
   card-shaped wrapper that hosts these overlays declares
   `container-type: inline-size` (see card container rules below).
   Targets ≈ 22% of card width — same visual weight as the
   numerals baked into the card art itself.                      */
.db-overlay-cc,
.db-overlay-ip {
  position: absolute;
  top: 3cqw;
  z-index: 4;
  font-family: var(--font);
  font-size: 22cqw;
  line-height: 1;
  pointer-events: none;
}

/* CC — top-left, white at 75% opacity, soft dark halo */
.db-overlay-cc {
  left: 4cqw;
  color: rgba(255, 255, 255, 0.75);
  text-shadow:
    2px  2px 0 rgba(0,0,0,0.85),
    -1px -1px 0 rgba(0,0,0,0.60),
    3px  3px 4px rgba(0,0,0,0.70);
}

/* IP — top-right, black fill with multi-direction white stroke */
.db-overlay-ip {
  right: 4cqw;
  color: #000000;
  text-shadow:
    -1px -1px 0 #fff,  1px -1px 0 #fff,
    -1px  1px 0 #fff,  1px  1px 0 #fff,
    -2px  0   0 #fff,  2px  0   0 #fff,
     0   -2px 0 #fff,  0    2px 0 #fff;
}
/* Negative IP (damage has no floor). Same badge, tinted so the minus sign reads
   as a value and not a smudge; nowrap keeps "-2" on one line at any size. */
.db-overlay-ip { white-space: nowrap; }
.db-overlay-ip.ip-negative { color: #ff7a6a; }

/* ── Double-click flash animations ──────────────────────────────── */
@keyframes flash-add {
  /* Bright green pulse — card is being added to deck */
  0%   { filter: brightness(1) drop-shadow(0 0  0px #48d848); }
  25%  { filter: brightness(2) drop-shadow(0 0 14px #48d848); }
  100% { filter: brightness(1) drop-shadow(0 0  0px #48d848); }
}

@keyframes flash-remove {
  /* Brief dim-out — card is being removed from deck */
  0%   { filter: brightness(1); }
  30%  { filter: brightness(0.35) saturate(0.2); }
  100% { filter: brightness(1); }
}

.db-card.flash-add    { animation: flash-add    0.36s ease-out forwards; }
.db-card.flash-remove { animation: flash-remove 0.36s ease-out forwards; }

/* ── Pick circle — bottom-right of every selectable tile ──
   EMPTY when the card is out of the deck, a green CHECK when it is in.
   Clicking it adds/removes the card (double-clicking the card does too).
   The hit area is 36px around a 24px circle. It sits clear of the CC / IP
   corners, the type icon and the name printed on the art. */
.db-pick {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 6;
  width: 36px;
  height: 36px;
  cursor: pointer;
}
.db-pick::before {
  content: '';
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 24px;
  height: 24px;
  box-sizing: border-box;
  /* ONE radial gradient draws the fill, the 2px ring and its 1px dark edge.
     No border / border-radius / box-shadow: on the GPU a thin border on a
     fully rounded box is drawn in pieces, and at the stage's fractional
     scale the pieces left a faint dark cross through the circle. Glows go
     through filter: drop-shadow, which follows the drawn circle. */
  --pick-fill: rgba(10, 5, 1, 0.72);
  --pick-ring: #fff5d8;
  background: radial-gradient(circle closest-side,
    var(--pick-fill) calc(100% - 3.5px), var(--pick-ring) calc(100% - 3px),
    var(--pick-ring) calc(100% - 1.5px), rgba(0, 0, 0, 0.85) calc(100% - 1px), rgba(0, 0, 0, 0) 100%);
  filter: drop-shadow(0 0 2.5px rgba(0, 0, 0, 0.6));
  font: 700 15px/24px 'Source Sans 3', sans-serif;
  text-align: center;
  color: #0c1f0c;
}
.db-pick:hover::before {
  --pick-ring: #6fe08a;
  filter: drop-shadow(0 0 4px rgba(111, 224, 138, 0.9));
}
.db-card.selected .db-pick::before {
  content: '\2713';
  --pick-fill: #6fe08a;
  --pick-ring: #0c1f0c;
  filter: drop-shadow(0 0 3px rgba(111, 224, 138, 0.8));
}


/* ══════════════════════════════════════════════════════════════════
   CARD DETAIL POPUP — SNES DIALOGUE BOX
   Double-border frame: bright inner | dark gap | darker outer ring
══════════════════════════════════════════════════════════════════ */

/* Full-screen backdrop */
.popup-backdrop {
  position: absolute;
  inset: 0;
  z-index: 200;
  background: rgba(0, 0, 14, 0.80);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.14s ease;
}

.popup-backdrop.visible {
  opacity: 1;
  pointer-events: all;
}

/* SNES-style dialogue panel */
.card-popup {
  width: 700px;
  padding: 18px 32px 20px;
  position: relative;            /* anchor the absolute X close button */
  background: var(--bg-dialog);

  /* Double-border via border + box-shadow:
     inner bright → dark gap → darker outer ring            */
  border: 3px solid var(--border-bright);
  box-shadow:
    0 0 0 3px var(--border-dark),   /* dark gap */
    0 0 0 6px var(--border-mid),    /* outer ring */
    0 0 0 7px var(--border-dark);   /* outermost dark edge */

  border-radius: 0;                 /* pixel-perfect, no rounded corners */

  /* Pop-in */
  transform: scale(0.90);
  transition: transform 0.16s cubic-bezier(0.22, 1, 0.36, 1);
}

.popup-backdrop.visible .card-popup { transform: scale(1); }

/* ── Battle Rules popup (SOG.BattleRulesPopup) ──────────────────────
   Shares the dark-wood + bronze-gold panel of the card-detail popup (the
   panel bg/border/shadow are applied via the retint group further below,
   which now lists .rules-popup) so all three boss rules popups read as part
   of the same UI. Only the title/body text treatment lives here. */
.rules-popup {
  text-align: center;
}
.rules-popup-title {
  font-family: var(--font);
  font-size: 24px;
  color: #e8c060;                                /* warm gold — matches .popup-card-name */
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-shadow: 2px 2px 0 #000, 0 0 8px rgba(220, 170, 60, 0.30);
  line-height: 1.25;
  margin: 4px 0 16px;
}
.rules-popup-body {
  font-family: var(--font);
  font-size: 26px;        /* match the card-detail popup body (.popup-ability-text) — chunkier, not the thin 17px */
  line-height: 1.6;
  color: #f3e6c4;                                /* cream — matches card-popup ability text */
  text-shadow: 1px 1px 0 #000;
  text-align: left;
}
.rules-popup-list { margin: 0 auto; padding-left: 1.3em; max-width: 90%; }
.rules-popup-list li { margin-bottom: 10px; }
.rules-popup-prose { white-space: pre-line; }

/* ── Difficulty picker (boss rematch) — two options inside the parchment rules
   popup (overworld _showDifficultyPicker). Reuses .btn-snes structure but re-tints
   to the bronze/parchment palette (like the welcome-modal "GOT IT" button) so the
   buttons read as part of the wood-and-gold popup instead of the purple SNES default. */
/* Narrow the picker panel — the wide 700px boss-rules width is overkill for two
   buttons. Scoped to this popup so the boss rules popups keep their width. */
.difficulty-picker-popup { width: 440px; max-width: 92vw; }
.tier-picker { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; margin: 6px auto 2px; }
.tier-pick-btn {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  min-width: 150px; padding: 14px 18px; line-height: 1.2;
  background: #3a200c;
  border-color: #d4aa50;
  color: #f3e6c4;
  box-shadow: 0 4px 0 #1a0c04, 0 5px 0 #000;
}
.tier-pick-btn:hover {
  background: #4a2a10;
  border-color: #f0cf6c;
  color: #fff5d8;
}
.tier-pick-btn:active {
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000;
}

/* ── Opening-flow PLAY button (SOG.BattleRulesPopup playButton mode, shown by
   js/game.js's opening rules gate before the hands are dealt). Same bronze/
   parchment re-tint as the tier picker so it reads as part of the panel. */
.rules-popup-actions { display: flex; justify-content: center; margin: 18px auto 2px; }
.rules-play-btn {
  min-width: 200px; padding: 12px 30px; font-size: 26px; letter-spacing: 0.08em;
  background: #3a200c;
  border-color: #d4aa50;
  color: #f3e6c4;
  box-shadow: 0 4px 0 #1a0c04, 0 5px 0 #000;
}
.rules-play-btn:hover {
  background: #4a2a10;
  border-color: #f0cf6c;
  color: #fff5d8;
}
.rules-play-btn:active {
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000;
}
/* Choice-mode buttons (SOG.BattleRulesPopup choices, e.g. the Ötzi hints
   Yes / No prompt) — the same bronze re-tint as the PLAY button, side by side. */
.rules-choice-btn {
  min-width: 140px; padding: 12px 26px; font-size: 24px; letter-spacing: 0.08em;
  margin: 0 8px;
  background: #3a200c;
  border-color: #d4aa50;
  color: #f3e6c4;
  box-shadow: 0 4px 0 #1a0c04, 0 5px 0 #000;
}
.rules-choice-btn:hover {
  background: #4a2a10;
  border-color: #f0cf6c;
  color: #fff5d8;
}
.rules-choice-btn:active {
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000;
}
/* Ötzi hints prompt: a short question, so a narrow panel with centred text. */
.otzi-hints-prompt { width: 520px; max-width: 92vw; }
.otzi-hints-prompt .rules-popup-body { text-align: center; }
/* End Turn nudge (js/game.js _showEndTurnNudge): same short-question panel, over
   a LIGHTER dim than the other rules popups so the ringed CARDS TO PLAY number in
   the top-left box stays readable behind it. */
.end-turn-nudge { width: 520px; max-width: 92vw; }
#battle-rules-backdrop.end-turn-nudge-backdrop { background: rgba(20, 10, 2, 0.42); }
.end-turn-nudge .rules-popup-body { text-align: center; }
/* …and the CARDS TO PLAY number while the nudge is up: a pulsing gold aura on
   the glyph itself (text-shadow, so nothing is drawn over the label above it),
   gold to read as part of the box's own frame. The dim is also cut away over
   the whole top-left box (js/game.js masks the backdrop), so the number sits
   at full brightness behind the prompt. */
.battle-capital-num.end-turn-nudge-ring {
  position: relative;
  animation: endTurnNudgeGlow 1.1s ease-in-out infinite;
}
/* …with a gold arrow just to the LEFT of the number, pointing at it, bobbing
   toward it in time with the glow. A border triangle (no glyph/font dependency),
   vertically centred on the digit. */
.battle-capital-num.end-turn-nudge-ring::before {
  content: '';
  position: absolute;
  right: 100%;
  top: 50%;
  margin-right: 12px;
  width: 0;
  height: 0;
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
  border-left: 14px solid #ffd54a;
  filter: drop-shadow(0 0 4px #ffd54a) drop-shadow(0 0 8px rgba(255, 196, 40, 0.8)) drop-shadow(1px 1px 0 #000);
  transform: translateY(-50%);
  animation: endTurnNudgeArrow 1.1s ease-in-out infinite;
  pointer-events: none;
}
@keyframes endTurnNudgeArrow {
  0%, 100% { transform: translate(0, -50%); }
  50%      { transform: translate(4px, -50%); }
}
@keyframes endTurnNudgeGlow {
  0%, 100% { text-shadow: 0 0 4px #ffe89a, 0 0 10px #ffd54a, 0 0 18px rgba(255, 196, 40, 0.75), 1px 1px 0 #000; }
  50%      { text-shadow: 0 0 6px #fff3c4, 0 0 16px #ffd54a, 0 0 32px rgba(255, 196, 40, 1), 0 0 48px rgba(255, 170, 0, 0.6), 1px 1px 0 #000; }
}
.tier-pick-name { font-size: 18px; letter-spacing: 0.08em; }
.tier-pick-sub  { font-size: 11px; text-transform: none; letter-spacing: 0.02em; opacity: 0.85; }

/* ── Learning Check popup (SOG.LearningCheck) ───────────────────────
   Reuses the parchment panel (.card-popup .rules-popup); these rules cover the
   question/answer/feedback layout inside it. SNES-styled answer + action buttons
   match the Options-panel / btn-snes treatment. */
.learning-check-popup { width: 600px; max-width: 92vw; text-align: center; }
.lc-body { font-family: var(--font); }
.lc-prompt {
  font-size: 15px;
  color: #c9b48a;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-shadow: 1px 1px 0 #000;
  margin-bottom: 10px;
}
.lc-question {
  font-size: 22px;
  line-height: 1.4;
  color: #f3e6c4;
  text-shadow: 1px 1px 0 #000;
  margin: 0 auto 18px;
  max-width: 94%;
}
.lc-options { display: flex; flex-direction: column; gap: 10px; align-items: stretch; }
.lc-options-tf { flex-direction: row; justify-content: center; }
.lc-options-tf .lc-option { flex: 0 0 38%; }
.lc-option {
  font-family: var(--font);
  font-size: 18px;
  color: #f3e6c4;
  text-shadow: 1px 1px 0 #000;
  background: #5a3418;
  border: 2px solid #8a5a26;
  border-radius: 6px;
  padding: 12px 16px;
  box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000;
  cursor: pointer;
  text-align: center;
  transition: background 0.1s ease, border-color 0.1s ease;
}
.lc-option:hover:not(:disabled)  { background: #6e4220; border-color: #d4aa50; color: #e8c060; }
.lc-option:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 #1a0c04, 0 2px 0 #000; }
.lc-option:disabled { cursor: default; opacity: 0.85; }
.lc-option.lc-option-correct { background: #2f6a2e; border-color: #6fcf5a; color: #eafbe4; }
.lc-option.lc-option-wrong   { background: #6a2626; border-color: #cf5a5a; color: #fbe4e4; opacity: 1; }

/* Feedback + footer actions (after an answer) */
.lc-feedback { margin-top: 16px; min-height: 1px; }
.lc-result {
  font-size: 26px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-shadow: 2px 2px 0 #000;
}
.lc-result-correct { color: #6fcf5a; }
.lc-result-wrong   { color: #e88a5a; }
.lc-result-sub {
  font-size: 15px;
  color: #e8c060;
  text-shadow: 1px 1px 0 #000;
  margin-top: 4px;
}
.lc-actions { display: flex; justify-content: center; gap: 14px; margin-top: 16px; }
.lc-btn {
  font-family: var(--font);
  font-size: 16px;
  color: #f3e6c4;
  text-shadow: 1px 1px 0 #000;
  background: #5a3418;
  border: 2px solid #8a5a26;
  border-radius: 6px;
  padding: 10px 22px;
  box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000;
  cursor: pointer;
}
.lc-btn:hover  { background: #6e4220; border-color: #d4aa50; color: #e8c060; }
.lc-btn:active { transform: translateY(2px); box-shadow: 0 1px 0 #1a0c04, 0 2px 0 #000; }
.lc-btn-next { color: #e8c060; border-color: #d4aa50; }

/* Gilgamesh battle — clickable opponent portrait (opens the rules popup) */
.battle-avatar-opponent.gilgamesh-clickable { cursor: pointer; pointer-events: auto; }
.battle-avatar-opponent.gilgamesh-clickable:hover .battle-avatar-frame {
  filter: brightness(1.15);
  box-shadow: 0 0 12px rgba(248, 208, 0, 0.5);
}
/* Shared "click opponent → rules popup" affordance (Sargon / Hammurabi / Nebuchadnezzar). */
.battle-avatar-opponent.rules-clickable { cursor: pointer; pointer-events: auto; }
.battle-avatar-opponent.rules-clickable:hover .battle-avatar-frame {
  filter: brightness(1.15);
  box-shadow: 0 0 12px rgba(248, 208, 0, 0.5);
}

/* Card name — displayed as the "NPC speaker" header */
.popup-card-name {
  font-family: var(--font);
  font-size: 34px;
  color: var(--snes-yellow);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  text-shadow: 1px 1px 0 #000;
  margin-bottom: 8px;
}

/* Category-type label (icon + e.g. "RELIGIOUS") — sits between name and
   divider. 70% of the card-name size; paler-gold via #battle-popup-backdrop
   override below. Symbol PNG is rendered as a CSS mask filled with
   currentColor so the icon picks up the same gold as the label text on
   every platform, with no per-category tinting. */
.popup-card-type {
  font-family: var(--font);
  font-size: 24px;
  line-height: 1;            /* tight box so the text glyphs hug their bounds */
  text-transform: uppercase;
  letter-spacing: 0.07em;
  text-shadow: 1px 1px 0 #000;
  margin-bottom: 8px;
  display: flex;
  align-items: baseline;     /* anchor icon bottom to text baseline */
  gap: 0.4em;
}
.popup-card-type .cat-icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  /* Render the symbol art directly as a background image (universally supported —
     unlike CSS mask, which didn't render on some browsers). The art is solid
     black on transparent; it's inverted to a light tint on the dark popups below. */
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
}
/* Per-category translate values compensate for transparent padding
   inside each source PNG so the visible ink's bottom anchors to the
   text baseline. Measured padding ratios:
     politcal.png:    6.05% → translateY(0.06em)
     religious.png:   2.54% → translateY(0.025em)
     military / cultural / exploration: 0% → no translate */
.popup-card-type .cat-icon--political {
  background-image: url('../images/symbols/politcal.png');
  transform: translateY(0.06em);
}
.popup-card-type .cat-icon--religious {
  background-image: url('../images/symbols/religious.png');
  width: 0.80em;
  height: 0.80em;
  transform: translateY(0.02em);
}
.popup-card-type .cat-icon--military {
  background-image: url('../images/symbols/military.png');
  width: 0.80em;
  height: 0.80em;
}
.popup-card-type .cat-icon--cultural {
  background-image: url('../images/symbols/cultural.png');
  width: 0.80em;
  height: 0.80em;
}
.popup-card-type .cat-icon--exploration {
  background-image: url('../images/symbols/exploration.png');
  width: 0.80em;
  height: 0.80em;
}
.popup-card-type .cat-icon--scientific {
  background-image: url('../images/symbols/scientific.png');
}
.popup-card-type .cat-icon--prehistory {
  background-image: url('../images/symbols/prehistory.png');
  transform: translateY(0.06em);   /* 6.3% bottom padding → baseline nudge */
}

/* The battle / deck-builder popups are dark (their type sits in a
   .popup-header-row); the black symbol art would vanish, so invert it to a
   light tint there. The marketplace popup is light parchment (its type is a
   bare .popup-card-type, NOT in a header row), so the black art is left as-is. */
.popup-header-row .popup-card-type .cat-icon {
  filter: invert(1);
}

/* Horizontal rule between name and ability */
.popup-divider {
  height: 2px;
  background: var(--border-bright);
  box-shadow: 0 0 4px var(--border-bright);
  margin-bottom: 10px;
}

/* Ability name — italic-style label in SNES cyan */
.popup-ability-name {
  font-family: var(--font);
  font-size: 26px;
  color: var(--snes-cyan);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin-bottom: 8px;
  text-shadow: 0 0 6px var(--snes-cyan), 1px 1px 0 #000;
}

/* Ability text — main body copy, plain white */
.popup-ability-text {
  font-family: var(--font);
  font-size: 26px;
  color: var(--text-white);
  line-height: 1.65;
  margin-bottom: 14px;
  text-shadow: 1px 1px 0 #000;
  white-space: pre-line;   /* honour explicit "\n" line breaks in ability text (e.g. Chariot); long lines still wrap */
}

/* Vanilla card: muted dimmed text */
.popup-ability-text.vanilla { color: var(--text-dim); }

/* IP breakdown line — shown for revealed board cards (single inline expression) */
.popup-ip-breakdown {
  font-family: var(--font);
  font-size:   22px;
  color:       var(--snes-yellow);
  text-align:  center;
  letter-spacing: 0.04em;
  padding:     4px 0 0;
  border-top:  1px solid rgba(136,152,255,0.25);
}

/* Action row — hint left, CLOSE button right */
.popup-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}

/* Dim instruction text telling players to double-click */
.popup-hint {
  flex: 1;
  font-family: var(--font);
  font-size: 20px;
  color: var(--text-muted);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1.4;
}

/* Close button in popup */
.popup-actions .btn-snes {
  font-size: 24px;
  padding: 10px 22px;
  flex-shrink: 0;
}

/* ── Card-detail popup: redesigned layout classes ─────────────────
   Used by #card-popup-backdrop (deck builder) and
   #battle-popup-backdrop (in-game). Other popups keep the old
   structure and are unaffected by these rules.
─────────────────────────────────────────────────────────────────── */

/* Header row: card name  ·  type icon + label on a single flex line */
.popup-header-row {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: nowrap;
  overflow: hidden;
  min-width: 0;
  margin-bottom: 10px;
}

/* Card name inside header — shrink from the base 34px, allow truncation */
.popup-header-row .popup-card-name {
  font-size: 24px;
  margin-bottom: 0;   /* override base block margin */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1 1 auto;
  min-width: 0;
  letter-spacing: 0.06em;
}

/* X close button — flush against popup border, top-right corner */
.popup-close-x {
  position: absolute;
  top: 3px;
  right: 4px;
  background: transparent;
  border: none;
  font-family: var(--font);
  font-size: 20px;
  color: rgba(212, 170, 80, 0.55);
  cursor: pointer;
  line-height: 1;
  padding: 4px 6px;
  border-radius: 2px;
  transition: color 0.15s, background-color 0.15s;
  user-select: none;
}
.popup-close-x:hover {
  color: #f3e6c4;
  background: rgba(212, 170, 80, 0.15);
}
.popup-close-x:active {
  color: #fff5d8;
  background: rgba(212, 170, 80, 0.28);
}

/* Type label inside header — smaller than name, no wrap */
.popup-header-row .popup-card-type {
  font-size: 16px;
  flex-shrink: 0;
  white-space: nowrap;
  margin-bottom: 0;   /* override base block margin */
  letter-spacing: 0.06em;
}

/* Rescale cat-icon to match the 16px type label */
.popup-header-row .popup-card-type .cat-icon {
  width: 1em;
  height: 1em;
}

/* Footer row: IP breakdown (or hint) left, close button right */
.popup-footer-row {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* IP breakdown inside footer — fills left, text-align reset */
.popup-footer-row .popup-ip-breakdown {
  flex: 1;
  font-size: 15px;
  text-align: left;
  padding: 0;
  border-top: none;
  letter-spacing: 0.02em;
  line-height: 1.5;
}

/* Hint text inside footer */
.popup-footer-row .popup-hint {
  flex: 1;
  font-family: var(--font);
  font-size: 15px;
  color: var(--text-muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.4;
}

/* ── IP breakdown 2-row grid ──────────────────────────────────────
   Columns: [IP label + base] · [thumb + delta]... · [large total]
   The total is always shown. Modifier columns added per source.
─────────────────────────────────────────────────────────────────── */

/* Outer flex row — all columns stretch to the same height */
.ip-grid {
  display: flex;
  align-items: stretch;
  gap: 8px;
  width: 100%;          /* fill the breakdown container */
}

/* Every column: vertical flex stack */
.ip-col {
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Column 1: "IP" label top, base number bottom */
.ip-col-base {
  min-width: 41px;
  justify-content: space-between;
}

.ip-label {
  font-family: var(--font);
  font-size: 46px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1;
}

.ip-basenum {
  font-family: var(--font);
  font-size: 20px;
  line-height: 1;
  text-align: left;
  width: 100%;
  padding-left: 7px;
}

/* Middle columns: thumbnail+badge top, modifier value bottom */
.ip-col-mod {
  gap: 4px;
  justify-content: flex-start;
}

/* Wrapper for thumbnail + optional reset badge */
.ip-thumb-wrap {
  position: relative;
  display: block;
  width: 41px;
  height: 41px;
  flex-shrink: 0;
}

/* Portrait thumbnail — 1:1 square crop centred on the face region */
.ip-thumb {
  display: block;
  width: 41px;
  height: 41px;
  background-size: 280%;
  background-position: 50% 28%;
  border: 1px solid rgba(212, 170, 80, 0.45);
  border-radius: 2px;
}

/* Location thumbnail — uses its own crop (bgSize/bgPos inline) */
.ip-thumb-loc {
  background-size: 200%;
  background-position: 50% 50%;
}

/* Placeholder when no card art found for the source name */
.ip-thumb-empty {
  background-color: rgba(180, 140, 60, 0.08);
}

/* Justinian-reset overlay badge — large red initial centered on greyed thumbnail */
.ip-reset-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font);
  font-size: 28px;
  font-weight: bold;
  color: #e04040;
  line-height: 1;
  pointer-events: none;
  z-index: 1;
}

/* Reset columns: desaturate + dim the thumbnail and delta */
.ip-col-mod--reset .ip-thumb {
  filter: grayscale(1) opacity(0.45);
}

/* Modifier value under its thumbnail — same min-width as thumb */
.ip-delta {
  font-family: var(--font);
  font-size: 20px;
  line-height: 1;
  text-align: center;
  min-width: 41px;
}

/* Dimmed delta for reset bonuses */
.ip-delta--reset {
  opacity: 0.35;
}

/* Total column: right-aligned, largest element, separated by a rule */
.ip-col-total {
  justify-content: center;
  margin-left: auto;   /* push to the right edge of the grid */
  padding-left: 10px;
  border-left: 1px solid rgba(180, 140, 60, 0.20);
}

/* The effective IP — most visually prominent element in the breakdown */
.ip-total {
  font-family: var(--font);
  font-size: 52px;
  font-weight: 600;
  line-height: 1;
}


/* ══════════════════════════════════════════════════════════════════
   WELCOME ("Before You Begin") POPUP — first-load only
   Reskinned with the parchment/wood + bronze-gold palette used by
   the home screen and deck builder, instead of the SNES neon palette.
══════════════════════════════════════════════════════════════════ */

/* Sepia-tinted backdrop — warmer than the default near-black/blue */
#welcome-backdrop {
  background: rgba(20, 10, 2, 0.82);
}

/* Dark-wood panel with bronze double-border (replaces the periwinkle ring) */
.welcome-popup {
  width: 760px;
  max-width: 1178px;
  padding: 26px 34px 24px;
  /* Subtle vertical wood-grain gradient (warm dark browns) */
  background:
    repeating-linear-gradient(
      0deg,
      transparent 0px, transparent 6px,
      rgba(0,0,0,0.10) 6px, rgba(0,0,0,0.10) 7px
    ),
    linear-gradient(180deg,
      #2a1608 0%,
      #3a200c 50%,
      #2a1608 100%
    );
  /* Bronze inner border + dark gap + warm-bronze outer ring */
  border: 3px solid #d4aa50;
  box-shadow:
    0 0 0 3px #1a0c04,                          /* dark gap            */
    0 0 0 6px #6a4418,                          /* bronze-brown ring   */
    0 0 0 7px #1a0c04,                          /* outermost dark edge */
    inset 0 0 28px rgba(60, 30, 0, 0.55);       /* aged inner glow     */
}

/* Title bar — warm gold like the home screen title, not SNES neon */
.welcome-popup .popup-card-name {
  color: #e8c060;
  text-shadow:
    2px 2px 0 #000,
    0 0 8px rgba(220, 170, 60, 0.35);
  margin-bottom: 12px;
}

/* Bronze divider, no neon glow */
.welcome-popup .popup-divider {
  height: 2px;
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(180, 130, 40, 0.65) 18%,
    #d4aa50 50%,
    rgba(180, 130, 40, 0.65) 82%,
    transparent 100%
  );
  box-shadow: none;
  margin-bottom: 16px;
}

/* Body copy: cream-tinted off-white, generous line-height for readability */
.welcome-body {
  font-family: var(--font);
  font-size: 22px;
  color: #f3e6c4;
  line-height: 1.55;
  text-shadow: 1px 1px 0 #000;
  margin-bottom: 6px;
}
.welcome-body p {
  margin: 0 0 18px;
}
.welcome-body p:last-child {
  margin-bottom: 0;
}

/* Italicized game title — warm gold accent, distinct from body text */
.welcome-title {
  font-style: italic;
  color: #e8c060;
  text-shadow: 1px 1px 0 #000, 0 0 6px rgba(220, 170, 60, 0.30);
}

/* Centered "Enjoy!" sign-off — bronze-gold accent */
.welcome-enjoy {
  text-align: center;
  color: #e8c060;
  letter-spacing: 0.08em;
  margin-top: 6px;
  text-shadow: 2px 2px 0 #000;
}

/* "GOT IT" button — re-tint to bronze so it reads as part of the parchment/wood
   world instead of the cyan SNES default. Scoped to this popup only. */
.welcome-popup .popup-actions .btn-snes {
  background: #3a200c;
  border-color: #d4aa50;
  color: #f3e6c4;
  box-shadow: 0 4px 0 #1a0c04, 0 5px 0 #000;
}
.welcome-popup .popup-actions .btn-snes:hover {
  background: #4a2a10;
  border-color: #f0cf6c;
  color: #fff5d8;
}
.welcome-popup .popup-actions .btn-snes:active {
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000;
}


/* ══════════════════════════════════════════════════════════════════
   CARD-DETAIL + DIFFICULTY POPUPS — history palette
   Scoped to #card-popup-backdrop (deck builder), #battle-popup-backdrop
   (in-game), and #difficulty-backdrop (difficulty mode select).
   Keeps the SNES font, sizes, and structure — only retints colors
   to match the parchment/wood + bronze-gold palette used by the
   welcome modal and About page. Other popups (.card-popup) keep the
   SNES palette.
══════════════════════════════════════════════════════════════════ */

/* Sepia-tinted backdrop instead of cool near-black */
#card-popup-backdrop,
#battle-popup-backdrop,
#difficulty-backdrop,
#rename-deck-backdrop,
.rules-popup-backdrop {
  background: rgba(20, 10, 2, 0.82);
}

/* Card-detail popups: narrowed 20% from the 700px base */
#card-popup-backdrop .card-popup,
#battle-popup-backdrop .card-popup {
  width: 560px;
}

/* Dark-wood panel with bronze double-border (replaces periwinkle SNES rings) */
#card-popup-backdrop .card-popup,
#battle-popup-backdrop .card-popup,
#battle-hover-popup,
#difficulty-backdrop .card-popup,
#rename-deck-backdrop .card-popup,
.rules-popup,
.options-panel {
  background:
    repeating-linear-gradient(
      0deg,
      transparent 0px, transparent 6px,
      rgba(0, 0, 0, 0.10) 6px, rgba(0, 0, 0, 0.10) 7px
    ),
    linear-gradient(180deg,
      #2a1608 0%,
      #3a200c 50%,
      #2a1608 100%
    );
  border-color: #d4aa50;
  box-shadow:
    0 0 0 3px #1a0c04,                          /* dark gap            */
    0 0 0 6px #6a4418,                          /* bronze-brown ring   */
    0 0 0 7px #1a0c04,                          /* outermost dark edge */
    inset 0 0 28px rgba(60, 30, 0, 0.55);       /* aged inner glow     */
}

/* Card name header — warm gold (matches About title + welcome popup) */
#card-popup-backdrop .popup-card-name,
#battle-popup-backdrop .popup-card-name,
#battle-hover-popup .popup-card-name,
#difficulty-backdrop .popup-card-name,
#rename-deck-backdrop .popup-card-name {
  color: #e8c060;
  text-shadow:
    2px 2px 0 #000,
    0 0 8px rgba(220, 170, 60, 0.30);
}

/* Bronze divider — no neon glow */
#card-popup-backdrop .popup-divider,
#battle-popup-backdrop .popup-divider,
#battle-hover-popup .popup-divider,
#difficulty-backdrop .popup-divider,
#rename-deck-backdrop .popup-divider {
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(180, 130, 40, 0.65) 18%,
    #d4aa50 50%,
    rgba(180, 130, 40, 0.65) 82%,
    transparent 100%
  );
  box-shadow: none;
}

/* Difficulty buttons (Serf / Giant) — bronze theme.
   Background is intentionally a few stops lighter than the panel
   gradient (#2a1608 → #3a200c) so the buttons read as raised. */
#difficulty-backdrop .btn-difficulty {
  background: #5a3418;
  border-color: #8a5a26;
  color: #f3e6c4;
  box-shadow: 0 4px 0 #1a0c04, 0 5px 0 #000;
}
#difficulty-backdrop .btn-difficulty:hover {
  background: #6e4220;
  border-color: #d4aa50;
  color: #e8c060;
}
#difficulty-backdrop .btn-difficulty:active {
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000;
}
#difficulty-backdrop .btn-difficulty .diff-label {
  color: inherit;                       /* picks up button text colour above */
}
#difficulty-backdrop .btn-difficulty .diff-desc {
  color: rgba(243, 230, 196, 0.55);
}
#difficulty-backdrop .btn-difficulty:hover .diff-desc {
  color: #f0d8a0;
  opacity: 1;
}

/* ── Header row palette (redesigned card-detail popup) ──────────

   Hierarchy (dim → prominent):
     type label (smallest, muted)  →  separator (ghost)
     ability name (medium, gold)   →  card name (medium, gold)
     ability text (largest, cream) — the visual focal point        */

/* Card name in the header row — warm gold, no text-shadow to keep it quiet */
#card-popup-backdrop .popup-header-row .popup-card-name,
#battle-popup-backdrop .popup-header-row .popup-card-name,
#battle-hover-popup .popup-header-row .popup-card-name {
  color: #e8c060;
  text-shadow: 1px 1px 0 #000;
}

/* Type icon + label — smaller, muted gold-cream */
#card-popup-backdrop .popup-header-row .popup-card-type,
#battle-popup-backdrop .popup-header-row .popup-card-type,
#battle-hover-popup .popup-header-row .popup-card-type {
  color: rgba(240, 216, 160, 0.58);
  text-shadow: none;
}

/* ── Ability section ─────────────────────────────────────────── */

/* Ability name — gold, acts as a mini-heading; same gold as card name */
#card-popup-backdrop .popup-ability-name,
#battle-popup-backdrop .popup-ability-name,
#battle-hover-popup .popup-ability-name {
  font-size: 21px;
  color: #e0b84c;
  text-shadow: 1px 1px 0 #000;
  margin-bottom: 10px;
}

/* Ability text — cream, the largest readable block (focal point) */
#card-popup-backdrop .popup-ability-text,
#battle-popup-backdrop .popup-ability-text,
#battle-hover-popup .popup-ability-text {
  font-size: 26px;
  color: #f3e6c4;
  line-height: 1.6;
  margin-bottom: 12px;
}

/* Vanilla card (no ability) — dimmed cream, same comfortable size */
#card-popup-backdrop .popup-ability-text.vanilla,
#battle-popup-backdrop .popup-ability-text.vanilla,
#battle-hover-popup .popup-ability-text.vanilla {
  color: rgba(243, 230, 196, 0.50);
}

/* ── Footer row palette ─────────────────────────────────────── */

/* Hint text in footer */
#card-popup-backdrop .popup-footer-row .popup-hint,
#battle-popup-backdrop .popup-footer-row .popup-hint,
#battle-hover-popup .popup-footer-row .popup-hint {
  color: rgba(243, 230, 196, 0.50);
}

/* IP breakdown — muted cream, smallest text, bronze thumbnails */
#battle-popup-backdrop .popup-footer-row .popup-ip-breakdown {
  color: rgba(243, 230, 196, 0.58);
}

/* IP thumbnail border tint — bronze to match panel */
#battle-popup-backdrop .ip-thumb {
  border-color: rgba(212, 170, 80, 0.50);
}

/* IP total — brightest element, full cream */
#card-popup-backdrop .ip-total,
#battle-popup-backdrop .ip-total {
  color: #f3e6c4;
}

/* IP base number and label — muted gold */
#card-popup-backdrop .ip-basenum,
#battle-popup-backdrop .ip-basenum {
  color: rgba(243, 230, 196, 0.75);
}
#card-popup-backdrop .ip-label,
#battle-popup-backdrop .ip-label {
  color: rgba(243, 230, 196, 0.45);
}

/* IP delta signs — warm gold */
#card-popup-backdrop .ip-delta,
#battle-popup-backdrop .ip-delta {
  color: rgba(240, 200, 100, 0.85);
}

/* X close button — scoped palette: gold-cream on dark bronze hover */
#card-popup-backdrop .popup-close-x,
#battle-popup-backdrop .popup-close-x {
  color: rgba(212, 170, 80, 0.60);
}
#card-popup-backdrop .popup-close-x:hover,
#battle-popup-backdrop .popup-close-x:hover {
  color: #f3e6c4;
  background: rgba(212, 170, 80, 0.15);
}


/* ══════════════════════════════════════════════════════════════════
   DIFFICULTY POPUP
══════════════════════════════════════════════════════════════════ */

.difficulty-popup {
  max-width: 480px;
  width: 90%;
}

.difficulty-options {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 10px;
}

.btn-difficulty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 14px 20px;
  width: 100%;
  text-align: left;
  border-color: var(--border-mid);
  cursor: pointer;
}

.btn-difficulty:hover {
  border-color: var(--snes-yellow);
  color: var(--snes-yellow);
}

.btn-difficulty:hover .diff-desc {
  color: var(--snes-yellow);
  opacity: 0.85;
}

.diff-label {
  font-family: var(--font);
  font-size: 22px;
  letter-spacing: 0.08em;
}

.diff-desc {
  font-family: var(--font);
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.06em;
  transition: color 0.15s, opacity 0.15s;
}

/* ══════════════════════════════════════════════════════════════════
   SAVE TOAST
══════════════════════════════════════════════════════════════════ */


/* ══════════════════════════════════════════════════════════════════
   BATTLE SCREEN
══════════════════════════════════════════════════════════════════ */

#screen-battle.active {
  display: flex;
  flex-direction: column;
  width: 1280px;
  height: 720px;   /* locked to stage height — was 800px for old viewport layout */
  overflow: hidden;
  position: relative;
  /* Warm dark wood-grain table */
  background:
    repeating-linear-gradient(
      90deg,
      rgba(80, 40, 0, 0.07) 0px, rgba(80, 40, 0, 0.07) 1px,
      transparent           1px, transparent           9px
    ),
    repeating-linear-gradient(
      0deg,
      rgba(0, 0, 0, 0.06)  0px, rgba(0, 0, 0, 0.06)  1px,
      transparent           1px, transparent           13px
    ),
    linear-gradient(168deg, #2c1a08 0%, #1e1106 35%, #261608 65%, #1a0e04 100%);
}


/* ── Battle HUD — Top Left (Turn + Capital, parchment box) ─────── */

.battle-hud-topleft {
  position: absolute;
  top: 14px;
  left: 18px;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
  /* Deep aged-parchment interior — clearly distinct from the dark wood behind it */
  background:
    radial-gradient(ellipse at 60% 20%, rgba(180, 130, 40, 0.18) 0%, transparent 65%),
    linear-gradient(160deg, #3a2208 0%, #2a1804 55%, #321e06 100%);
  border: 2px solid rgba(200, 160, 32, 0.72);
  box-shadow:
    inset 0 0 0 1px rgba(248, 208, 0, 0.12),
    inset 0 1px 8px rgba(200, 140, 20, 0.14),
    0 4px 14px rgba(0, 0, 0, 0.6);
  border-radius: 4px;
  padding: 10px 24px 12px;
  min-width: 210px;
}

/* ── Battle HUD — Bottom Right (Reset + End Turn buttons) ────────── */

.battle-hud-bottomright {
  position: fixed;
  bottom: 18px;   /* the corner music widget is retired in battle → sit in the actual corner */
  right: 20px;    /* +4px extra breathing room from gameboard frame */
  z-index: 55;
  display: flex;
  flex-direction: column;
  gap: 7px;
  align-items: center;   /* hug + center the grouped buttons in the bottom corner */
  min-width: 0;
}

.battle-hud-bottomright .btn-end-turn,
.battle-hud-bottomright .btn-back-results {
  padding: 13px 19px;  /* −25%: was 18px 25px (orig) → −10% of prev */
  font-size: 13px;     /* −25%: was 16px (orig) → −10% of prev */
  width: 100%;
  text-align: center;
  letter-spacing: 0.10em;
}

/* Option B cluster: large labeled End Turn + a compact icon strip beside it. */
.battle-action-cluster {
  display: flex;
  flex-direction: column;   /* icon strip on top, End Turn underneath */
  align-items: center;
  gap: 6px;                 /* tight — one grouped unit */
}
.battle-action-cluster .btn-end-turn {
  width: auto;
  min-width: 150px;
  padding: 15px 28px;   /* ~20% shorter (vertical) than before; width unchanged */
  font-size: 19px;
}
.battle-icon-strip {
  display: grid;
  grid-template-columns: repeat(2, 78px);   /* +50% */
  grid-auto-rows: 78px;
  gap: 8px;
  align-content: center;
  justify-content: center;
}
.battle-icon-strip .btn-hud-icon {
  width: 78px;          /* +50% */
  height: 78px;
  min-width: 0;
  padding: 0;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font, monospace);
  font-size: 48px;      /* +50% */
  line-height: 1;
  letter-spacing: 0;
  color: #f0cf6c;
  background: none;       /* no box — just the icon */
  border: none;
  box-shadow: none;
  cursor: pointer;
}
.battle-icon-strip .btn-hud-icon img { width: 70px; height: 70px; object-fit: contain; display: block; }  /* cog fills most of the 78px button */
.battle-icon-strip .btn-hud-icon:hover:not(:disabled)  { filter: brightness(1.15); transform: scale(1.08); }
.battle-icon-strip .btn-hud-icon:active:not(:disabled) { transform: scale(0.94); }
.battle-icon-strip .btn-hud-icon:disabled { opacity: 0.4; cursor: not-allowed; }

.btn-undo-endturn {
  background:   var(--snes-yellow);
  color:        #000;
  border-color: #a07800;
  font-family:  var(--font);
}

.battle-turn-info {
  font-size: 16px;
  color: var(--snes-yellow);
  letter-spacing: 0.10em;
  text-transform: uppercase;
  text-align: center;
  text-shadow: 1px 1px 0 #000, 0 0 12px rgba(200, 160, 0, 0.35);
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(200, 160, 32, 0.32);
}

.battle-capital-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 0;
  border: none;
}

.battle-capital-label {
  font-family: var(--font);
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1;
}

.battle-capital-num {
  font-family: var(--font);
  font-size: 34px;
  color: var(--snes-cyan);
  line-height: 1;
  letter-spacing: 0.04em;
  text-shadow:
    0 0 14px rgba(64, 224, 224, 0.60),
    1px 1px 0 #000;
}


/* ── Opponent Hand ─────────────────────────────────────────────── */

.battle-opp-hand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 145px;   /* was 160: the board sits 15px higher, so the order badges under it clear the hand */
  flex-shrink: 0;
  /* The 15px top pad keeps the cards where they sat in the old 160px band
     (top at 43.5px): the band got shorter, the hand did not move. The Ötzi
     battle drops its hand further, under its goal banner (otzi-lessons rule). */
  padding: 15px 20px 0;
  background: rgba(28, 14, 4, 0.68);
  border-bottom: 1px solid rgba(100, 65, 10, 0.50);
}

/* Face-down card back */
.battle-card-back {
  width: 48px;
  height: 72px;
  flex-shrink: 0;
  border-radius: 2px;
  border: 2px solid var(--border-mid);
  box-shadow:
    0 0 0 1px #000,
    inset 0 0 0 2px var(--border-dark);
  /* Opponent hand backs render at 48x72 — use the pre-scaled Small (229x320)
     and let the browser smooth it (no pixelated/crisp-edges, which was forcing
     nearest-neighbour downscaling and badly aliasing the back art). */
  background: var(--bg-surface) url('../images/cards/cardsmisc/SOG_Card_Back_Small.jpeg') center / cover no-repeat;
}


/* ── Play Board (3 columns) ────────────────────────────────────── */

.battle-board {
  display: flex;
  flex: 1;
  min-height: 0;
  gap: 28px;
  padding: 4px 16px;
  position: relative;
  /* Aged parchment / map surface */
  background:
    radial-gradient(ellipse at 94% 92%, rgba(100, 65, 10, 0.40) 0%, transparent 52%),
    radial-gradient(ellipse at 8%  10%, rgba(140, 100, 30, 0.20) 0%, transparent 40%),
    linear-gradient(158deg, #c9a96e 0%, #b89458 18%, #c5a464 48%, #b08a42 78%, #a27832 100%);
  box-shadow: inset 0 0 36px rgba(60, 30, 0, 0.38);
}

/* Compass-rose watermark in bottom-right of the board */
.battle-board::after {
  content: '✦';
  position: absolute;
  bottom: 18px;
  right: 26px;
  font-size: 72px;
  color: rgba(80, 48, 8, 0.18);
  pointer-events: none;
  line-height: 1;
  font-family: serif;
}

.battle-col {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  gap: 6px;
  border-radius: 4px;
  /* overflow visible so per-card reveal glows aren't clipped at the column edge */
  overflow: visible;
  isolation: isolate;
}

/* Vertical divider line between location columns */
.battle-col:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 4px;
  bottom: 4px;
  right: -15px;         /* midpoint of the 28px gap */
  width: 2px;
  background: linear-gradient(
    to bottom,
    transparent,
    var(--border-mid) 12%,
    var(--border-mid) 88%,
    transparent
  );
  pointer-events: none;
}


/* ── Card Slot Areas ───────────────────────────────────────────── */

.battle-slots-opp,
.battle-slots-player {
  display: flex;
  flex-direction: row;
  gap: 6px;
  height: 140px;
  flex-shrink: 0;
}

.battle-slots-opp    { align-items: flex-end;   }
.battle-slots-player { align-items: flex-start; }

.battle-card-slot {
  flex: 1;
  aspect-ratio: 2 / 3;
  max-height: 100%;
  border: 2px dashed rgba(200, 155, 45, 0.65);
  border-radius: 2px;
  background: rgba(100, 65, 10, 0.08);
  position: relative;
  overflow: hidden;
  /* Container query unit source for the CC / IP overlays */
  container-type: inline-size;
}

.battle-card-slot.occupied {
  border-style: solid;
  border-color: var(--border-mid);
}


/* ── Location Tile ─────────────────────────────────────────────── */

.battle-location {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: row;
  align-items: stretch;
  position: relative;
  /* overflow visible so reveal glows on perimeter cards aren't clipped */
  overflow: visible;
  background: transparent;
  /* SNES double-border */
  border: 3px solid var(--border-bright);
  box-shadow:
    0 0 0 3px #000,
    0 0 0 6px var(--border-mid);
}

/* ── Column background images — full vertical strip per location ─── */

.battle-col[data-loc-id="1"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/scandinavia.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

.battle-col[data-loc-id="2"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/greatriftvalley.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

.battle-col[data-loc-id="3"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/capeofgoodhope.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

.battle-col[data-loc-id="4"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/levant.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

.battle-col[data-loc-id="5"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/timbuktu.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

.battle-col[data-loc-id="6"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/sahara.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

.battle-col[data-loc-id="7"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/savannah.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

.battle-col[data-loc-id="8"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/desert.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

/* ── ARCADIUM location art for the boss locations now in the LOCATIONS catalog
   (js/locations.js). The boss battles paint the same ids under their own
   body.<boss>-battle selectors below, which win on specificity where the two
   disagree (Hammurabi's 102 is the Fertile Crescent; Hyksos's 131-133 are its
   own Nile Delta / Thebes / Aswan — the catalog re-ids those as 161-163). ── */
.battle-col[data-loc-id="101"]::before, .battle-col[data-loc-id="102"]::before, .battle-col[data-loc-id="103"]::before,
.battle-col[data-loc-id="121"]::before, .battle-col[data-loc-id="122"]::before, .battle-col[data-loc-id="123"]::before,
.battle-col[data-loc-id="131"]::before, .battle-col[data-loc-id="132"]::before, .battle-col[data-loc-id="133"]::before,
.battle-col[data-loc-id="141"]::before, .battle-col[data-loc-id="142"]::before, .battle-col[data-loc-id="143"]::before,
.battle-col[data-loc-id="151"]::before, .battle-col[data-loc-id="152"]::before, .battle-col[data-loc-id="153"]::before,
.battle-col[data-loc-id="161"]::before, .battle-col[data-loc-id="162"]::before, .battle-col[data-loc-id="163"]::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.5;
  z-index: -1;
}
.battle-col[data-loc-id="101"]::before { background: url('../images/locations/euphrates.jpg')         center / cover no-repeat; } /* Euphrates River (Nebuchadnezzar) */
.battle-col[data-loc-id="102"]::before { background: url('../images/locations/babylon.jpg')           center / cover no-repeat; } /* Babylon */
.battle-col[data-loc-id="103"]::before { background: url('../images/locations/tigris.jpg')            center / cover no-repeat; } /* Tigris River */
.battle-col[data-loc-id="121"]::before { background: url('../images/locations/thebes.jpg')            center / cover no-repeat; } /* Thebes (Hatshepsut) */
.battle-col[data-loc-id="122"]::before { background: url('../images/locations/redsea.jpg')            center / cover no-repeat; } /* The Red Sea */
.battle-col[data-loc-id="123"]::before { background: url('../images/locations/punt.jpg')              center / cover no-repeat; } /* Punt */
.battle-col[data-loc-id="131"]::before { background: url('../images/locations/piramses.jpg')          center / cover no-repeat; } /* Pi-Ramses (Ramses) */
.battle-col[data-loc-id="132"]::before { background: url('../images/locations/karnaktemple.jpg')      center / cover no-repeat; } /* Karnak Temple */
.battle-col[data-loc-id="133"]::before { background: url('../images/locations/abusimbel.jpg')         center / cover no-repeat; } /* Abu Simbel */
.battle-col[data-loc-id="141"]::before { background: url('../images/locations/closed_temples.jpg')    center / cover no-repeat; } /* The Closed Temples (Akhenaten) */
.battle-col[data-loc-id="142"]::before { background: url('../images/locations/temple_of_aten.jpg')    center / cover no-repeat; } /* The Great Temple of the Aten */
.battle-col[data-loc-id="143"]::before { background: url('../images/locations/royal_tomb.jpg')        center / cover no-repeat; } /* The Royal Tomb */
.battle-col[data-loc-id="151"]::before { background: url('../images/locations/meroe.jpg')             center / cover no-repeat; } /* Meroe (Kush) */
.battle-col[data-loc-id="152"]::before { background: url('../images/locations/napata.jpg')            center / cover no-repeat; } /* Napata */
.battle-col[data-loc-id="153"]::before { background: url('../images/locations/nubian_gold_mines.jpg') center / cover no-repeat; } /* Nubian Gold Mines */
.battle-col[data-loc-id="161"]::before { background: url('../images/locations/nile_delta.jpg')        center / cover no-repeat; } /* The Nile Delta (Hyksos) */
.battle-col[data-loc-id="162"]::before { background: url('../images/locations/thebes.jpg')            center / cover no-repeat; } /* Thebes (Hyksos) */
.battle-col[data-loc-id="163"]::before { background: url('../images/locations/aswan_cataract.jpg')    center / cover no-repeat; } /* Aswan Cataract */

body.gilgamesh-battle .battle-col[data-loc-id="8"]::before { background: url('../images/locations/cedarforest.jpg') center / cover no-repeat; } /* Cedar Forest */
body.gilgamesh-battle .battle-col[data-loc-id="7"]::before { background: url('../images/locations/uruk.jpg')        center / cover no-repeat; } /* Uruk */
body.gilgamesh-battle .battle-col[data-loc-id="2"]::before { background: url('../images/locations/mountmashu.jpg')  center / cover no-repeat; } /* Mount Mashu */

/* Sargon battle — its own Mesopotamia location art (Upper Sea / Akkad / Lower
   Sea). Reuses loc-ids 8/7/2 but scoped to body.sargon-battle so it overrides
   only here, leaving the Gilgamesh + Otzi battles untouched. */
body.sargon-battle .battle-col[data-loc-id="8"]::before { background: url('../images/locations/uppersea.jpg') center / cover no-repeat; } /* Upper Sea  (Mediterranean Coast) */
body.sargon-battle .battle-col[data-loc-id="7"]::before { background: url('../images/locations/akkad.jpg')    center / cover no-repeat; } /* Akkad */
body.sargon-battle .battle-col[data-loc-id="2"]::before { background: url('../images/locations/lowersea.jpg') center / cover no-repeat; } /* Lower Sea  (Persian Gulf Coast) */

/* Hammurabi battle — 3 ability-carrying locations (ids 101/102/103):
   Euphrates / Fertile Crescent / Tigris. */
/* Hammurabi locations use pseudo-ids 101/102/103, which have NO base
   .battle-col[data-loc-id]::before rule — so these must declare the full pseudo
   (content/position/inset/opacity/z-index), not just the background, or the strip
   never renders. Matches the base 1–8 ::before treatment (50% dim, behind cards). */
body.hammurabi-battle .battle-col[data-loc-id="101"]::before,
body.hammurabi-battle .battle-col[data-loc-id="102"]::before,
body.hammurabi-battle .battle-col[data-loc-id="103"]::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.5;
  z-index: -1;
}
body.hammurabi-battle .battle-col[data-loc-id="101"]::before { background: url('../images/locations/euphrates.jpg')       center / cover no-repeat; } /* Banks of the Euphrates */
body.hammurabi-battle .battle-col[data-loc-id="102"]::before { background: url('../images/locations/fertilecrescent.jpg') center / cover no-repeat; } /* The Fertile Crescent */
body.hammurabi-battle .battle-col[data-loc-id="103"]::before { background: url('../images/locations/tigris.jpg')          center / cover no-repeat; } /* Banks of the Tigris */

/* Hanging Gardens (Nebuchadnezzar) battle location backgrounds. Pseudo-ids
   101/102/103 (one battle at a time) need the full ::before like Hammurabi's.
   Left → Euphrates River, center → Babylon, right → Tigris River. */
body.hanging-gardens-battle .battle-col[data-loc-id="101"]::before,
body.hanging-gardens-battle .battle-col[data-loc-id="102"]::before,
body.hanging-gardens-battle .battle-col[data-loc-id="103"]::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.5;
  z-index: -1;
}
body.hanging-gardens-battle .battle-col[data-loc-id="101"]::before { background: url('../images/locations/euphrates.jpg') center / cover no-repeat; } /* Euphrates River */
body.hanging-gardens-battle .battle-col[data-loc-id="102"]::before { background: url('../images/locations/babylon.jpg')   center / cover no-repeat; } /* Babylon */
body.hanging-gardens-battle .battle-col[data-loc-id="103"]::before { background: url('../images/locations/tigris.jpg')    center / cover no-repeat; } /* Tigris River */

/* ── HATSHEPSUT BATTLE location art (body.hatshepsut-battle) ──────────────
   Custom loc ids 121-123 sit outside the base .battle-col[data-loc-id="1..8"]
   ::before rules, so — exactly as the Hammurabi / Hanging Gardens blocks above
   note — these must declare the FULL pseudo-element themselves, not just the
   background. Same 0.5 dim so the cards stay legible over the art. */
body.hatshepsut-battle .battle-col[data-loc-id="121"]::before,
body.hatshepsut-battle .battle-col[data-loc-id="122"]::before,
body.hatshepsut-battle .battle-col[data-loc-id="123"]::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.5;
  z-index: -1;
}
body.hatshepsut-battle .battle-col[data-loc-id="121"]::before { background: url('../images/locations/thebes.jpg') center / cover no-repeat; } /* Thebes  — MOVE_HERE_CAPITAL */
body.hatshepsut-battle .battle-col[data-loc-id="122"]::before { background: url('../images/locations/redsea.jpg') center / cover no-repeat; } /* Red Sea — ANY_FREE_MOVE_AWAY */
body.hatshepsut-battle .battle-col[data-loc-id="123"]::before { background: url('../images/locations/punt.jpg')   center / cover no-repeat; } /* Punt    — MOVE_HERE_IP */

/* ── RAMSES BATTLE location art (body.ramses-battle) ───────────────────────
   Custom loc ids 131-133 sit outside the base .battle-col[data-loc-id="1..8"]
   ::before rules, so — exactly as the Hammurabi / Hanging Gardens / Hatshepsut
   blocks above note — these must declare the FULL pseudo-element themselves,
   not just the background. Same 0.5 dim so the cards stay legible over the art. */
body.ramses-battle .battle-col[data-loc-id="131"]::before,
body.ramses-battle .battle-col[data-loc-id="132"]::before,
body.ramses-battle .battle-col[data-loc-id="133"]::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.5;
  z-index: -1;
}
body.ramses-battle .battle-col[data-loc-id="131"]::before { background: url('../images/locations/piramses.jpg')   center / cover no-repeat; } /* Pi-Ramses     — HIGHEST_IP_PLUS_2_HERE */
body.ramses-battle .battle-col[data-loc-id="132"]::before { background: url('../images/locations/karnaktemple.jpg') center / cover no-repeat; } /* Karnak Temple — DOUBLE_HIGHEST_IP_HERE */
body.ramses-battle .battle-col[data-loc-id="133"]::before { background: url('../images/locations/abusimbel.jpg')  center / cover no-repeat; } /* Abu Simbel    — FULL_SLOTS_PLUS_6_HERE */

/* ── AKHENATEN BATTLE location art (body.akhenaten-battle) ─────────────────
   Custom loc ids 141-143, so — as the Ramses / Hatshepsut / Hammurabi blocks
   above note — these must declare the FULL pseudo-element themselves, not just
   the background. Same 0.5 dim so the cards stay legible over the art.

   Art is real and on disk (464x576 each), matching the nile_delta.jpg /
   aswan_cataract.jpg snake_case convention. Note temple_of_aten.jpg — NOT the
   great_temple_aten.jpg this block originally guessed at while the files were
   still placeholders. */
body.akhenaten-battle .battle-col[data-loc-id="141"]::before,
body.akhenaten-battle .battle-col[data-loc-id="142"]::before,
body.akhenaten-battle .battle-col[data-loc-id="143"]::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.5;
  z-index: -1;
}
body.akhenaten-battle .battle-col[data-loc-id="141"]::before { background: url('../images/locations/closed_temples.jpg')   center / cover no-repeat; } /* The Closed Temples      — RELIGIOUS_PLAY_DISCARDS */
body.akhenaten-battle .battle-col[data-loc-id="142"]::before { background: url('../images/locations/temple_of_aten.jpg')   center / cover no-repeat; } /* Great Temple of the Aten — SOLO_CARD_PLUS_4_HERE */
body.akhenaten-battle .battle-col[data-loc-id="143"]::before { background: url('../images/locations/royal_tomb.jpg')       center / cover no-repeat; } /* The Royal Tomb          — SUMMON_FROM_DISCARD_AT_END */

/* ── KUSH BATTLE location art (body.kush-battle) ───────────────────────────
   Custom loc ids 151-153 — same reason as the Ramses / Akhenaten blocks above:
   outside the base .battle-col[data-loc-id="1..8"] rules, so these declare the
   FULL pseudo-element, not just the background. Same 0.5 dim. */
body.kush-battle .battle-col[data-loc-id="151"]::before,
body.kush-battle .battle-col[data-loc-id="152"]::before,
body.kush-battle .battle-col[data-loc-id="153"]::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.5;
  z-index: -1;
}
body.kush-battle .battle-col[data-loc-id="151"]::before { background: url('../images/locations/meroe.jpg')             center / cover no-repeat; } /* Meroe             — REPEAT_LABOR_ECONOMIC_AT_ONCE */
body.kush-battle .battle-col[data-loc-id="152"]::before { background: url('../images/locations/napata.jpg')            center / cover no-repeat; } /* Napata            — POLITICAL_PLUS_1_STAMP */
body.kush-battle .battle-col[data-loc-id="153"]::before { background: url('../images/locations/nubian_gold_mines.jpg') center / cover no-repeat; } /* Nubian Gold Mines — GOLD_CHANCE_ON_PLAY */

/* ── INDIA BATTLE location art (body.greatbath-battle / siddhartha-battle /
   gupta-battle). Same shape as the Kush block. The two SEASONAL locations (the
   Indus River 173, the Ganges Plain 179) paint their DRY art in ::before and
   their WET art in a ::after layer that the shared flood/season module fades in
   with .hg-flooded (see the FLOOD block below for the crossfade rule). ── */
body.greatbath-battle  .battle-col[data-loc-id="171"]::before,
body.greatbath-battle  .battle-col[data-loc-id="172"]::before,
body.greatbath-battle  .battle-col[data-loc-id="173"]::before,
body.siddhartha-battle .battle-col[data-loc-id="174"]::before,
body.siddhartha-battle .battle-col[data-loc-id="175"]::before,
body.siddhartha-battle .battle-col[data-loc-id="176"]::before,
body.gupta-battle      .battle-col[data-loc-id="177"]::before,
body.gupta-battle      .battle-col[data-loc-id="178"]::before,
body.gupta-battle      .battle-col[data-loc-id="179"]::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.5;
  z-index: -1;
}
body.greatbath-battle  .battle-col[data-loc-id="171"]::before { background: url('../images/locations/citadel.jpeg')          center / cover no-repeat; } /* The Citadel      — NO_DAMAGE_HERE */
body.greatbath-battle  .battle-col[data-loc-id="172"]::before { background: url('../images/locations/lower_town.jpeg')       center / cover no-repeat; } /* The Lower Town   — ALL_PLUS_ONE_HERE */
body.greatbath-battle  .battle-col[data-loc-id="173"]::before { background: url('../images/locations/indus_river_dry.jpeg')  center / cover no-repeat; } /* The Indus River  — SEASON_WET_DRY (dry) */
body.siddhartha-battle .battle-col[data-loc-id="174"]::before { background: url('../images/locations/kapilavastu.jpeg')      center / cover no-repeat; } /* Kapilavastu      — EOT_HIGHEST_MINUS_ONE_MOVE */
body.siddhartha-battle .battle-col[data-loc-id="175"]::before { background: url('../images/locations/bodh_gaya.jpeg')        center / cover no-repeat; } /* Bodh Gaya        — EOT_ALL_PLUS_ONE */
body.siddhartha-battle .battle-col[data-loc-id="176"]::before { background: url('../images/locations/ganges.jpeg')           center / cover no-repeat; } /* The Ganges       — EOT_LOWEST_PLUS_ONE */
body.gupta-battle      .battle-col[data-loc-id="177"]::before { background: url('../images/locations/nalanda.jpeg')          center / cover no-repeat; } /* Nalanda          — DRAW_SCIENTIFIC_ON_PLAY */
body.gupta-battle      .battle-col[data-loc-id="178"]::before { background: url('../images/locations/pataliputra.jpeg')      center / cover no-repeat; } /* Pataliputra      — ECHO_GAINS_PLUS_ONE */
body.gupta-battle      .battle-col[data-loc-id="179"]::before { background: url('../images/locations/ganges_plain_dry.jpeg') center / cover no-repeat; } /* The Ganges Plain — MONSOON_CHANCE (dry) */
/* Seasonal WET layers — faded in by .hg-flooded (shared crossfade rule below). */
body.greatbath-battle  .battle-col[data-loc-id="173"]::after,
body.gupta-battle      .battle-col[data-loc-id="179"]::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  transition: opacity 1.05s ease;
  pointer-events: none;
}
body.greatbath-battle  .battle-col[data-loc-id="173"]::after { background: url('../images/locations/indus_river_wet.jpeg')  center / cover no-repeat; } /* Indus — wet season */
body.gupta-battle      .battle-col[data-loc-id="179"]::after { background: url('../images/locations/ganges_plain_wet.jpeg') center / cover no-repeat; } /* Ganges Plain — monsoon */
/* The base rules above are body-scoped and so outrank the shared un-scoped
   `.battle-col.hg-flooded::after` crossfade rule; restate the "on" opacity at the
   same scope so the season module's class actually fades the wet art in. */
body.greatbath-battle  .battle-col[data-loc-id="173"].hg-flooded::after,
body.gupta-battle      .battle-col[data-loc-id="179"].hg-flooded::after { opacity: 0.5; }

/* FLOOD (shared — js/game/flood.js). Un-scoped on purpose: the Euphrates (101) and
   Tigris (103) flood in the Nebuchadnezzar battle AND in Arcadium, and only the flood
   module ever adds these classes. Crossfade layer — a ::after over the river art (101/103 only),
   opacity 0 normally, fading to the river ::before's 0.5 dim when JS adds .hg-flooded.
   ::after paints above the ::before river art (tree order) but stays behind the
   nameplate/cards (z-index -1). The opacity transition IS the crossfade. */
.battle-col[data-loc-id="101"]::after,
.battle-col[data-loc-id="103"]::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  transition: opacity 1.05s ease;   /* flood crossfade — 50% slower than the original 0.7s */
  pointer-events: none;
}
.battle-col[data-loc-id="101"]::after { background: url('../images/locations/euphratesflood.jpg') center / cover no-repeat; } /* Euphrates flooded */
.battle-col[data-loc-id="103"]::after { background: url('../images/locations/tigrisflood.jpg')    center / cover no-repeat; } /* Tigris flooded */
.battle-col.hg-flooded::after { opacity: 0.5; }

/* FLOOD water-RUSH (Stage 4d) — a transient blue surge that sweeps DOWN over the
   river column the instant it floods, then fades, leaving the persistent .hg-flooded
   art behind. JS (_spawnFloodRush) appends one .hg-flood-rush per flood event and
   removes it when the animation ends. overflow:hidden clips the wipe to the column
   (the column is overflow:visible for reveal glows). */
.battle-col .hg-flood-rush {
  position: absolute;
  inset: 0;
  z-index: 3;                /* over the river art + cards, under the bubbles */
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
}
/* The water body: a blue gradient (lighter foam crest up top) that wipes down to
   cover the column, holds a beat, then dissolves. */
.battle-col .hg-flood-rush::before {
  content: '';
  position: absolute;
  left: -12%; right: -12%; top: 0; bottom: 0;
  background:
    linear-gradient(180deg,
      rgba(225, 244, 255, 0.92) 0%,
      rgba(120, 192, 236, 0.80) 9%,
      rgba(46, 130, 206, 0.74) 30%,
      rgba(26,  96, 182, 0.80) 70%,
      rgba(16,  72, 156, 0.86) 100%);
  transform: translateY(-108%);
  animation: hgFloodRushIn 1.875s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;   /* 50% slower */
}
/* A drifting current shimmer layered over the body so the water reads as moving. */
.battle-col .hg-flood-rush::after {
  content: '';
  position: absolute;
  left: -30%; right: -30%; top: 0; bottom: 0;
  background:
    repeating-linear-gradient(115deg,
      rgba(255, 255, 255, 0) 0px,
      rgba(255, 255, 255, 0.10) 6px,
      rgba(255, 255, 255, 0) 16px);
  transform: translateY(-108%);
  animation: hgFloodRushIn 1.875s cubic-bezier(0.22, 0.61, 0.36, 1) forwards,   /* 50% slower */
             hgFloodCurrent 1.35s linear 0.525s 2;
}
@keyframes hgFloodRushIn {
  0%   { transform: translateY(-108%); opacity: 1; }
  62%  { transform: translateY(0);     opacity: 1; }
  78%  { transform: translateY(0);     opacity: 1; }
  100% { transform: translateY(0);     opacity: 0; }
}
@keyframes hgFloodCurrent {
  from { background-position: 0 0; }
  to   { background-position: 64px 0; }
}

/* FLOOD blue TINT — a persistent 20% blue wash over the flooded location (art +
   cards + nameplate), fading in with the (slowed) flood crossfade. JS
   (_spawnFloodRush's sibling) appends one .hg-flood-tint per flooded river and
   removes it on un-flood / teardown. */
.battle-col .hg-flood-tint {
  position: absolute;
  inset: 0;
  z-index: 2;                /* over the river art + cards, under the water-rush (3) */
  background: rgba(46, 118, 200, 0.20);   /* 20% blue */
  pointer-events: none;
  border-radius: inherit;
  animation: hgFloodTintIn 1.05s ease both;
}
@keyframes hgFloodTintIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.battle-loc-score-opp,
.battle-loc-score-player {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  flex-shrink: 0;
  font-size: 28px;
  font-weight: bold;
  line-height: 1;
  text-shadow:
    1px 1px 4px rgba(0, 0, 0, 0.95),
    0 0 10px rgba(0, 0, 0, 0.85);
  background: rgba(0, 0, 0, 0.30);
}

.battle-loc-score-opp    { color: var(--snes-red);  }
.battle-loc-score-player { color: var(--snes-cyan); }

.battle-loc-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 4px 8px;
  gap: 5px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.68);
}

.battle-loc-name {
  font-size: 13px;
  color: var(--snes-yellow);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 1px 1px 3px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.8);
}

.battle-loc-ability {
  font-size: 13px;
  color: #e8e0d0;
  line-height: 1.35;
  overflow: hidden;
  text-shadow: 1px 1px 3px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.8);
}


/* ── Player Hand ───────────────────────────────────────────────── */

.battle-player-hand {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  height: 225px;   /* 145 opp band + 350 board + 225 = the 720px stage */
  flex-shrink: 0;
  padding: 10px 20px 0;   /* the top 10px keeps the cards clear of the order badges under the board */
  background: rgba(28, 14, 4, 0.62);
  border-top: 2px solid rgba(100, 65, 10, 0.45);
  box-shadow: inset 0 10px 20px rgba(8, 4, 0, 0.52);
  overflow: visible;
}


/* ── Hand Cards (player) ───────────────────────────────────────── */

.battle-hand-card {
  position: relative;
  width: 117px;    /* 123 × 0.95 */
  height: 175px;   /* 184 × 0.95 */
  flex-shrink: 0;
  cursor: pointer;
  border: 2px solid transparent;
  border-radius: 2px;
  overflow: hidden;
  /* Fan layout: overlap each card (first card has no margin — see rule below) */
  margin-left: -48px;
  z-index: 1;
  transform-origin: bottom center;
  /* Container query unit source for the CC / IP overlays */
  container-type: inline-size;
  /* Only border/shadow transition — GSAP owns scale/translate */
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

/* First hand card has no overlap offset */
.battle-player-hand .battle-hand-card:first-child {
  margin-left: 0;
}

/* GSAP hover applied in JS; show border glow on hover */
.battle-hand-card:hover {
  border-color: var(--snes-yellow);
  box-shadow: 0 0 0 1px #000, 0 0 0 3px var(--snes-yellow);
}

.battle-hand-card.selected {
  border-color: var(--snes-green);   /* its box-shadow comes from the shared .selected rule below */
}

/* Card name — hidden at rest, fades in on hover */
/* CC / IP overlays now scale automatically via cqw — no override
   needed for hand cards. */


/* ── Deck Pile ─────────────────────────────────────────────────── */
/* Represents the remaining undrawn deck for each player.
   Two pseudo-element layers give the "stacked cards" illusion.    */

.battle-deck-pile {
  position: relative;
  flex-shrink: 0;
  border-radius: 2px;
  border: 2px solid var(--border-mid);
  box-shadow: 0 0 0 1px #000, inset 0 0 0 2px var(--border-dark);
  background: var(--bg-surface) url('../images/cards/cardsmisc/SOG_Card_Back_Small.jpeg') center / cover no-repeat;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  cursor: default;
}

/* Back layer of the stack */
.battle-deck-pile::before,
.battle-deck-pile::after {
  content: '';
  position: absolute;
  inset: -2px;           /* match the border sizing of the element */
  border-radius: 2px;
  border: 2px solid var(--border-mid);
  background: var(--bg-surface) url('../images/cards/cardsmisc/SOG_Card_Back_Small.jpeg') center / cover no-repeat;
  box-shadow: 0 0 0 1px #000;
}

.battle-deck-pile::before { transform: translate(-5px,  5px); z-index: -2; }
.battle-deck-pile::after  { transform: translate(-3px,  3px); z-index: -1; }

/* Sizing for each context */
.battle-opp-hand    .battle-deck-pile { width: 48px;  height: 72px;  }
.battle-player-hand .battle-deck-pile { width: 82px;  height: 123px; }

/* "DECK" label */
.battle-deck-label {
  position: relative;
  z-index: 1;
  font-family: var(--font);
  font-size: 10px;
  color: var(--border-bright);
  letter-spacing: 0.12em;
  text-shadow: 1px 1px 0 #000;
  line-height: 1;
}

/* Card-count number */
.battle-deck-count {
  position: relative;
  z-index: 1;
  font-family: var(--font);
  font-size: 13px;
  color: var(--border-bright);
  text-shadow: 1px 1px 0 #000;
  background: rgba(0,0,0,0.55);
  padding: 1px 6px;
  border: 1px solid rgba(136,152,255,0.4);
  line-height: 1.4;
}

/* Separator between pile and hand cards */
.battle-hand-sep {
  width: 1px;
  height: 52px;
  flex-shrink: 0;
  background: rgba(136,152,255,0.25);
  align-self: center;
  margin-left: 14px;
  margin-right: 4px;
}

/* Ghost element mirrors right-side (sep + pile) width so the fan cards
   center independently of the pile. ::before is not a DOM node, so
   .battle-hand-card:first-child still correctly targets the first card. */
.battle-player-hand::before {
  content: '';
  flex-shrink: 0;
  /* sep: 1px + 14px margin-left + 4px margin-right = 19px
     pile: 82px + 14px margin-left              = 96px
     total                                       = 115px */
  width: 115px;
  pointer-events: none;
}

/* Deck pile sits inline, directly to the right of the last hand card */
.battle-player-hand .battle-deck-pile {
  margin-left: 14px;
}


/* ══════════════════════════════════════════════════════════════════
   BATTLE SCREEN — GAME ENGINE UI  (Step 4)
══════════════════════════════════════════════════════════════════ */

/* ── Header left section (review button + turn info) ──────────── */


/* Back to Results — shown only during gameboard review */
.btn-back-results {
  padding: 6px 14px;
  font-family: var(--font);
  font-size: 11px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  background: var(--bg-btn);
  border: 2px solid var(--border-bright);
  color: var(--text-white);
  cursor: pointer;
  box-shadow: 0 3px 0 var(--border-mid), 0 4px 0 #000;
  transition: background 0.08s, border-color 0.08s, color 0.08s,
              transform 0.06s, box-shadow 0.06s;
  white-space: nowrap;
  flex-shrink: 0;
}
.btn-back-results:hover {
  background: var(--bg-btn-hover);
  border-color: var(--snes-yellow);
  color: var(--snes-yellow);
}
.btn-back-results:active {
  transform: translateY(3px);
  box-shadow: 0 0 0 var(--border-mid), 0 1px 0 #000;
}


/* ── End Turn button ───────────────────────────────────────────── */

.btn-end-turn {
  padding: 6px 14px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border: 2px solid var(--snes-green);
  color: var(--snes-green);
  background: rgba(0, 30, 0, 0.85);
  box-shadow: 0 0 0 1px #000, 0 3px 0 #003300;
  transition: background 0.1s;
}

.btn-end-turn:hover:not(:disabled) {
  background: rgba(0, 55, 0, 0.95);
}

.btn-end-turn:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: 0 0 0 1px #000, 0 1px 0 #003300;
}

.btn-end-turn:disabled {
  border-color: var(--text-muted);
  color: var(--text-muted);
  background: var(--bg-btn);
  box-shadow: none;
  cursor: default;
}


/* ── Board slot states ─────────────────────────────────────────── */

/* Empty player slots are clickable targets */
.battle-card-slot[data-owner="player"]:not(.occupied) {
  cursor: pointer;
}

.battle-card-slot[data-owner="player"]:not(.occupied):hover {
  border-color: rgba(136, 152, 255, 0.50);
  background: rgba(0, 0, 0, 0.40);
}

/* Face-down: card committed but not yet revealed. Board-slot sized → the
   pre-scaled Medium (457x640) keeps it crisp without the full 750x1050 weight. */
.battle-card-slot.face-down {
  background: var(--bg-surface) url('../images/cards/cardsmisc/SOG_Card_Back_Medium.jpeg') center / cover no-repeat;
}

/* Face-up: card revealed — contains card art and overlays */
.battle-card-slot.face-up {
  z-index: 0;   /* stacking context so overlays stay inside slot */
}

/* CC / IP overlays scale automatically via cqw — no per-context
   override needed for board slots. */


/* ── Animations ────────────────────────────────────────────────── */


/* Deny flash — invalid action (not enough capital / slot occupied) */
@keyframes flash-deny {
  /* bug 12: inset prevents clipping by ancestor overflow:hidden
     on .battle-col / .battle-location. Outer shadows would be cut
     off on the bottom edge of the bottom-most player slot. */
  0%, 40% {
    box-shadow:
      inset 0 0 0 2px var(--snes-red),
      inset 0 0 8px var(--snes-red);
  }
  100% { box-shadow: none; }
}

.flash-deny {
  animation: flash-deny 0.40s ease-out;
}


/* ── Reset Turn button ─────────────────────────────────────────── */

.btn-reset-turn {
  padding: 6px 14px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border: 2px solid var(--text-dim);
  color: var(--text-dim);
  background: rgba(10, 0, 30, 0.85);
  box-shadow: 0 0 0 1px #000, 0 3px 0 #111130;
  transition: background 0.1s, border-color 0.1s, color 0.1s;
}

.btn-reset-turn:hover:not(:disabled) {
  border-color: var(--snes-red);
  color: var(--snes-red);
  background: rgba(25, 0, 0, 0.95);
}

.btn-reset-turn:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: 0 0 0 1px #000, 0 1px 0 #111130;
}

.btn-reset-turn:disabled {
  border-color: var(--text-muted);
  color: var(--text-muted);
  background: var(--bg-btn);
  box-shadow: none;
  cursor: default;
}


/* ── Drag-and-drop visual states ───────────────────────────────── */

/* Card being dragged from hand */
.battle-hand-card.dragging {
  opacity: 0.35;
}

/* Face-down board slot being dragged back to hand */
.battle-card-slot.dragging {
  opacity: 0.35;
}

/* Valid drop target highlight */
.battle-card-slot.drag-over {
  border-color: var(--snes-cyan);
  border-style: solid;
  background: rgba(64, 224, 224, 0.12);
  box-shadow: inset 0 0 0 1px var(--snes-cyan);
}

/* ── Click + keyboard selection ─────────────────────────────────────
   .selected   — the currently-chosen card (in hand or on the board)
   .legal-target — every slot a click/Enter would commit into
   These mirror the drag-and-drop visuals so the two input paths
   feel like the same system. Reuses .drag-over styling for the
   target highlight via a shared rule below. */
.battle-hand-card.selected,
.battle-card-slot.selected {
  outline: 3px solid var(--snes-yellow);
  outline-offset: 2px;
  box-shadow: 0 0 12px rgba(248, 208, 0, 0.55),
              inset 0 0 0 1px var(--snes-yellow);
}

.battle-card-slot.legal-target {
  border-color: var(--snes-cyan);
  border-style: solid;
  background: rgba(64, 224, 224, 0.12);
  box-shadow: inset 0 0 0 1px var(--snes-cyan);
}

/* Hand area glows when an own face-down slot is selected for undo,
   indicating that clicking the hand will undo the play. */
#battle-player-hand.legal-target-zone {
  outline: 2px dashed var(--snes-cyan);
  outline-offset: 4px;
}

/* Keyboard focus ring — distinct from .selected so a user can scan
   with Tab without committing, and only see the selection ring when
   they explicitly Enter. */
.battle-hand-card:focus-visible,
.battle-card-slot:focus-visible {
  outline: 2px solid var(--snes-cyan);
  outline-offset: 2px;
}

/* Moveable card indicator — Magellan / Columbus during select phase */
@keyframes moveable-pulse {
  0%   { box-shadow: 0 0 0 2px var(--snes-yellow), inset 0 0 0 1px var(--snes-yellow); }
  50%  { box-shadow: 0 0 8px 3px rgba(248,208,0,0.6), inset 0 0 0 1px var(--snes-yellow); }
  100% { box-shadow: 0 0 0 2px var(--snes-yellow), inset 0 0 0 1px var(--snes-yellow); }
}

.battle-card-slot.moveable {
  border-color: var(--snes-yellow);
  border-style: solid;
  cursor: grab;
  animation: moveable-pulse 1.4s ease-in-out infinite;
}

.battle-card-slot.moveable:active {
  cursor: grabbing;
}

/* Queued move indicator — card stays in place with pulsing arrow overlay */
/* Queued-move destination: card appears at dest during select phase with pulsing gold border */
@keyframes queued-dest-pulse {
  0%, 100% { box-shadow: 0 0 0 2px #f5c518, inset 0 0 0 1px #f5c518; }
  50%       { box-shadow: 0 0 0 5px #f5c518, inset 0 0 0 2px rgba(245,197,24,0.5); }
}

.battle-card-slot.queued-dest {
  border-color: #f5c518;
  border-style: solid;
  animation: queued-dest-pulse 1s ease-in-out infinite;
  position: relative;
  pointer-events: none;   /* can't interact with a preview card */
  opacity: 0.88;
}

.battle-card-slot.queued-dest::after {
  content: '→';
  position: absolute;
  bottom: 3px;
  right: 5px;
  font-size: 13px;
  color: #f5c518;
  pointer-events: none;
  z-index: 5;
  text-shadow: 0 0 4px rgba(0,0,0,0.8);
}

/* ── Discard chooser modal (Erasmus + Francis of Assisi) ──────────── */

.discard-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(5, 0, 21, 0.82);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
}

.discard-panel {
  max-width: 1216px;
  padding: 24px 28px;
  background: var(--bg-surface);
  border: 3px solid var(--border-mid);
  box-shadow:
    0 0 0 1px var(--border-dark),
    inset 0 0 0 1px var(--border-bright);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.discard-title {
  font-family: 'CTGalbite', monospace;
  font-size: 0.85rem;
  color: var(--snes-cyan);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-align: center;
  white-space: nowrap;
}

.discard-card-row {
  display: flex;
  flex-direction: row;
  gap: 12px;
  overflow-x: auto;
  padding-bottom: 2px;
}

/* Choice countdown clock (chooser timer) — a depleting gold ring + center number
   shown above the chooser title. The arc starts as a full circle at 12 o'clock and
   retreats clockwise back to 12 over the 5s window; if it empties, the chooser
   auto-picks at random (js/game/abilities.js showDiscardChooser). r=44 →
   circumference 2·π·44 ≈ 276.46 (the stroke-dasharray / depletion target). */
.chooser-timer {
  position: relative;
  width: 58px;
  height: 58px;
}
.chooser-timer-ring {
  width: 100%;
  height: 100%;
  /* Anchor the arc's break point at 12 o'clock. (Direction is set by the negative
     dash-offset animation below, so no mirror is needed — a mirror would shift the
     break point off 12.) */
  transform: rotate(-90deg);
}
.chooser-timer-track {
  fill: none;
  stroke: #2a1608;              /* warm dark-brown well (history palette) */
  stroke-width: 7;
}
.chooser-timer-arc {
  fill: none;
  stroke: #d4aa50;              /* antique gold (HUD / options-panel gold) */
  stroke-width: 7;
  stroke-linecap: round;
  stroke-dasharray: 276.46;
  stroke-dashoffset: 0;
  filter: drop-shadow(0 0 3px rgba(212, 170, 80, 0.6));
  animation: chooserTimerDeplete 5s linear forwards;
}
@keyframes chooserTimerDeplete {
  from { stroke-dashoffset: 0; }
  to   { stroke-dashoffset: -276.46; }   /* negative → empties CLOCKWISE, break stays at 12 o'clock */
}
.chooser-timer-num {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'CTGalbite', monospace;
  font-size: 1.5rem;
  color: #f3e6c4;              /* parchment cream (history text) */
  text-shadow: 1px 1px 0 rgba(26, 12, 4, 0.9);
  pointer-events: none;
}

/* Visual card option — same dimensions and structure as .battle-hand-card */
.discard-card-option {
  position: relative;
  width:  164px;
  height: 246px;
  flex-shrink: 0;
  cursor: pointer;
  border: 2px solid transparent;
  border-radius: 2px;
  overflow: hidden;
  /* Container query unit source for the CC / IP overlays */
  container-type: inline-size;
  transition: transform 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}

.discard-card-option:hover {
  transform: translateY(-8px);
  border-color: var(--snes-yellow);
  box-shadow: 0 0 0 1px #000, 0 0 0 3px var(--snes-yellow);
}


/* CC / IP overlays scale automatically via cqw — no per-context
   override needed for the discard chooser cards. */


/* ── Score flash when a location score changes ─────────────────── */

@keyframes score-pop {
  0%   { transform: scale(1);    color: inherit; }
  40%  { transform: scale(1.35); color: var(--snes-yellow); }
  100% { transform: scale(1);    color: inherit; }
}

.score-pop {
  animation: score-pop 0.35s ease-out;
}


/* ══════════════════════════════════════════════════════════════════
   RESULT SCREEN
   ══════════════════════════════════════════════════════════════════ */

#screen-result.active {
  display:         flex;
  align-items:     center;
  justify-content: center;
  position:        absolute;
  top: 0; left: 0; right: 0; bottom: 0;
}

/* Dark wood background — identical to battle screen outer area */
#screen-result::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background:
    repeating-linear-gradient(
      90deg,
      rgba(80, 40, 0, 0.07) 0px, rgba(80, 40, 0, 0.07) 1px,
      transparent            1px, transparent            9px
    ),
    repeating-linear-gradient(
      0deg,
      rgba(0, 0, 0, 0.06)  0px, rgba(0, 0, 0, 0.06)  1px,
      transparent           1px, transparent           13px
    ),
    linear-gradient(168deg, #2c1a08 0%, #1e1106 35%, #261608 65%, #1a0e04 100%);
  pointer-events: none;
  z-index: 0;
}

.result-wrap {
  position:       relative;
  z-index:        1;
  display:        flex;
  flex-direction: column;
  align-items:    center;
  gap:            18px;
  width:          620px;
  padding:        44px 52px 40px;
  /* Aged parchment map surface — same as battle board */
  background:
    radial-gradient(ellipse at 92% 94%, rgba(100, 65, 10, 0.42) 0%, transparent 50%),
    radial-gradient(ellipse at 8%  8%,  rgba(140, 100, 30, 0.22) 0%, transparent 42%),
    linear-gradient(158deg, #c9a96e 0%, #b89458 18%, #c5a464 48%, #b08a42 78%, #a27832 100%);
  box-shadow:
    inset 0 0 52px rgba(60, 30, 0, 0.38),
    /* SNES double-border: dark gap → gold ring → bronze shadow → dark rim */
    0 0 0 2px #1a0e04,
    0 0 0 5px #c8a020,
    0 0 0 7px #7a5800,
    0 0 0 10px #2e1800,
    0 16px 56px rgba(0, 0, 0, 0.75);
}

/* Inner accent hairline — completes the SNES double-border look */
.result-wrap::before {
  content: '';
  position: absolute;
  inset: 8px;
  border: 1px solid rgba(248, 208, 0, 0.28);
  pointer-events: none;
}

/* ── Headline ─────────────────────────────────────────────────── */

@keyframes result-victory-glow {
  0%, 100% { text-shadow: 0 0 10px rgba(248,208,0,0.55), 2px 3px 0 rgba(60,30,0,0.85); }
  50%      { text-shadow: 0 0 24px rgba(248,208,0,0.90), 0 0 48px rgba(248,208,0,0.35), 2px 3px 0 rgba(60,30,0,0.85); }
}

@keyframes result-defeat-glow {
  0%, 100% { text-shadow: 0 0 10px rgba(160,0,10,0.55), 2px 3px 0 rgba(50,0,0,0.85); }
  50%      { text-shadow: 0 0 26px rgba(210,0,16,0.85), 0 0 52px rgba(160,0,10,0.40), 2px 3px 0 rgba(50,0,0,0.85); }
}
@keyframes result-giant-glow {
  0%, 100% { text-shadow: 3px 4px 0 rgba(60,30,0,0.9), 0 0 18px rgba(248,208,0,0.75), 0 0 36px rgba(248,160,0,0.35); }
  50%      { text-shadow: 3px 4px 0 rgba(60,30,0,0.9), 0 0 32px rgba(248,208,0,1.00), 0 0 64px rgba(248,160,0,0.65), 0 0 90px rgba(255,200,0,0.30); }
}

.result-headline {
  font-family:    'CTGalbite', monospace;
  font-size:      4rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height:    1;
}

.result-headline.result-player {
  color:     #f8d000;
  animation: result-victory-glow 2.2s ease-in-out infinite;
  text-shadow: 3px 4px 0 rgba(60,30,0,0.9), 0 0 10px rgba(248,208,0,0.55);
}
.result-headline.result-giant {
  color:       #f8d000;
  font-size:   5rem;
  animation:   result-giant-glow 1.8s ease-in-out infinite;
  text-shadow: 3px 4px 0 rgba(60,30,0,0.9),
               0 0 18px rgba(248,208,0,0.85),
               0 0 36px rgba(248,160,0,0.5);
}
.result-headline.result-ai {
  color:     #b01020;
  animation: result-defeat-glow 2.2s ease-in-out infinite;
  text-shadow: 3px 4px 0 rgba(50,0,0,0.9), 0 0 10px rgba(160,0,10,0.55);
}
.result-headline.result-draw,
.result-headline.result-tie {
  color:       var(--snes-cyan);
  text-shadow: 3px 4px 0 rgba(0,40,40,0.85), 0 0 12px rgba(64,224,224,0.55);
}

/* Gold rule beneath headline */
.result-headline::after {
  content:    '';
  display:    block;
  width:      80%;
  height:     2px;
  margin:     10px auto 0;
  background: linear-gradient(90deg,
    transparent, rgba(200,160,32,0.5) 20%,
    #f0c840 50%, rgba(200,160,32,0.5) 80%, transparent
  );
}

.result-subline {
  font-family:    'CTGalbite', monospace;
  font-size:      1.05rem;
  color:          #ffffff;
  text-align:     center;
  letter-spacing: 0.07em;
  text-shadow:    1px 1px 3px rgba(0,0,0,0.85), 0 2px 6px rgba(0,0,0,0.7);
  margin-top:     -4px;
}

/* ── Location breakdown ───────────────────────────────────────── */

.result-locs {
  width:          100%;
  display:        flex;
  flex-direction: column;
  gap:            6px;
}

.result-loc-row {
  display:     flex;
  align-items: center;
  gap:         12px;
  padding:     11px 14px;
  background:  rgba(30, 14, 2, 0.45);
  border-top:  1px solid rgba(210, 168, 48, 0.35);
  border-bottom: 1px solid rgba(20, 8, 0, 0.6);
  font-family: 'CTGalbite', monospace;
  font-size:   0.78rem;
}
.result-loc-row:first-child { border-top: 2px solid rgba(210,168,48,0.5); border-radius: 2px 2px 0 0; }
.result-loc-row:last-child  { border-bottom: 2px solid rgba(20,8,0,0.7); border-radius: 0 0 2px 2px; }

.result-loc-name {
  flex:        1;
  font-size:   0.9rem;
  color:       #f0e0b0;
  white-space: nowrap;
  overflow:    hidden;
  text-overflow: ellipsis;
  text-shadow: 1px 1px 0 rgba(0,0,0,0.7);
}

.result-loc-scores {
  display:     flex;
  align-items: center;
  gap:         10px;
  font-size:   1.0rem;
}

.result-loc-you { color: #c8a060; }
.result-loc-opp { color: #c8a060; }
.result-loc-vs  { color: #806040; font-size: 0.65rem; }

/* Winning side — bright accent */
.result-loc-you.result-loc-winner { color: #40d8d8; font-size: 1.1rem; }  /* cyan — player   */
.result-loc-opp.result-loc-winner { color: #e83040; font-size: 1.1rem; }  /* red  — opponent */

.result-loc-badge {
  min-width:    50px;
  padding:      4px 10px;
  text-align:   center;
  font-size:    0.78rem;
  font-family:  'CTGalbite', monospace;
  font-weight:  bold;
  border:       2px solid currentColor;
  border-radius: 1px;
}

.result-loc-badge-player { color: #40d8d8; background: rgba(64,216,216,0.14); }
.result-loc-badge-ai     { color: #e83040; background: rgba(232,48,64,0.14);  }
.result-loc-badge-tie    { color: #b08040; background: rgba(176,128,64,0.12); }

/* ── Tiebreaker panel ─────────────────────────────────────────── */

.result-tiebreaker {
  width:        100%;
  padding:      16px 20px;
  background:   rgba(10, 4, 0, 0.78);
  border:       2px solid rgba(200, 160, 32, 0.58);
  box-shadow:   inset 0 0 0 1px rgba(248, 208, 0, 0.18);
  text-align:   center;
  border-radius: 2px;
}

.result-tb-label {
  font-family:    'CTGalbite', monospace;
  font-size:      0.75rem;
  font-weight:    bold;
  color:          #ffffff;
  letter-spacing: 0.1em;
  text-shadow:    0 1px 4px rgba(0,0,0,0.9);
  margin-bottom:  12px;
}

.result-tb-scores {
  display:         flex;
  justify-content: center;
  align-items:     center;
  gap:             32px;
}

.result-tb-col {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  gap:            4px;
}

.result-tb-who {
  font-family: 'CTGalbite', monospace;
  font-size:   0.7rem;
  color:       #ffffff;
  text-shadow: 0 1px 3px rgba(0,0,0,0.9);
}

.result-tb-num {
  font-family: 'CTGalbite', monospace;
  font-size:   2.4rem;
  color:       #f8d000;
  text-shadow: 0 2px 6px rgba(0,0,0,0.9), 0 0 10px rgba(248,208,0,0.4);
}

.result-tb-vs {
  font-family: 'CTGalbite', monospace;
  font-size:   0.9rem;
  color:       #ffffff;
  text-shadow: 0 1px 3px rgba(0,0,0,0.9);
}

/* ── Action buttons ───────────────────────────────────────────── */

.result-actions {
  display:    flex;
  gap:        12px;
  margin-top: 6px;
}

/* Override btn-primary inside result screen with warm SNES style */
.result-actions .btn-primary {
  font-family:    'CTGalbite', monospace;
  font-size:      13px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  padding:        11px 22px;
  cursor:         pointer;
  background:     rgba(20, 10, 2, 0.88);
  border:         2px solid rgba(200, 160, 32, 0.72);
  color:          #e8c060;
  text-shadow:    1px 1px 0 #000;
  box-shadow:     0 4px 0 rgba(80, 40, 0, 0.68), 0 5px 0 rgba(0,0,0,0.5);
  transition:     background 0.08s, border-color 0.08s, color 0.08s,
                  transform 0.06s, box-shadow 0.06s;
  outline:        none;
  border-radius:  2px;
}
.result-actions .btn-primary:hover {
  background:   rgba(38, 18, 4, 0.96);
  border-color: #f0c840;
  color:        #f8d000;
  text-shadow:  0 0 8px rgba(248,208,0,0.38), 1px 1px 0 #000;
}
.result-actions .btn-primary:active {
  transform:  translateY(4px);
  box-shadow: 0 0 0 rgba(80,40,0,0.68), 0 1px 0 rgba(0,0,0,0.5);
}


/* ════════════════════════════════════════════════════════════════
   SNES ABILITY ANIMATIONS
   ════════════════════════════════════════════════════════════════ */


/* Sargon (id 37) reveal flourish — a gold beam of light from his card to each
   ADJACENT location he boosts (+3), and a glow around those full location boxes for
   the length of ssfxsargon.m4a (JS fades the glow's opacity out when the sound ends). */
.sargon-beam {
  background: linear-gradient(90deg, rgba(255, 238, 170, 0.95), rgba(255, 205, 80, 0.9) 55%, rgba(255, 180, 40, 0));
  border-radius: 4px;
  box-shadow: 0 0 12px 3px rgba(255, 210, 90, 0.7);
}
/* Gilgamesh (43) rally: the "+1" that lifts off each of the owner's Cultural
   cards and flies to Gilgamesh (reveal-fx.js gilgameshRally). Body-level flyer;
   position/size are set inline by the FX. */
.gilgamesh-plus {
  font-family: var(--font);
  font-weight: bold;
  color: #7ef08a;                                   /* green, per the Gilgamesh spec */
  text-shadow: 0 0 6px rgba(60, 200, 90, 0.95), 1px 1px 0 #000, -1px -1px 0 #000;
  line-height: 1;
  white-space: nowrap;
}
.sargon-loc-glow {
  border-radius: 8px;
  border: 2px solid rgba(255, 225, 130, 0.9);
  box-shadow: 0 0 22px 6px rgba(255, 210, 90, 0.85), inset 0 0 16px 3px rgba(255, 200, 70, 0.5);
  transition: opacity 0.4s ease;   /* JS toggles opacity for the fade in / fade-out-on-sound-end */
  animation: sargonLocGlowPulse 1.0s ease-in-out infinite;
}
@keyframes sargonLocGlowPulse {
  0%, 100% { box-shadow: 0 0 18px 4px rgba(255, 210, 90, 0.70),  inset 0 0 12px 2px rgba(255, 200, 70, 0.40); }
  50%      { box-shadow: 0 0 30px 9px rgba(255, 228, 125, 0.95), inset 0 0 20px 5px rgba(255, 212, 85, 0.60); }
}


/* ── Animation classes ───────────────────────────────────────── */


/* Floating IP number */
.anim-float-num {
  position:      absolute;
  font-family:   'CTGalbite', monospace;
  font-size:     13px;
  font-weight:   bold;
  pointer-events: none;
  z-index:       200;
  left:          50%;
  top:           28%;
  white-space:   nowrap;
}

/* GAME-WIDE GAIN-INDICATOR CONVENTION
     IP gain      → BLUE   (.anim-float-plus, below)
     Capital gain → GOLD   (.anim-float-capital)
     IP loss      → RED    (.anim-float-minus)
   Every floating +N in the game routes through Anim.floatNumber / Anim.floatCapital,
   so these three rules ARE the convention — there is no per-card colour to chase.
   IP gain was green, which collided with nothing but said nothing either; blue now
   reads as "IP" everywhere it appears. */
.anim-float-plus {
  color:       #6cc0ff;
  text-shadow: 0 0 6px #1e90ff, 1px 1px 0 #000, -1px -1px 0 #000;
}

.anim-float-minus {
  color:       #ff5555;
  text-shadow: 0 0 6px #ff2222, 1px 1px 0 #000, -1px -1px 0 #000;
}

.anim-float-capital {
  position:      absolute;
  font-family:   'CTGalbite', monospace;
  font-size:     12px;
  font-weight:   bold;
  pointer-events: none;
  z-index:       200;
  left:          50%;
  top:           50%;
  transform:     translateX(-50%);
  white-space:   nowrap;
  color:         #ffd700;
  text-shadow:   0 0 8px #ffaa00, 1px 1px 0 #000, -1px -1px 0 #000;
}

/* Continuous ability glow — persistent blue-cyan border */
.anim-cont-glow {
  box-shadow: 0 0 0 2px rgba(64, 224, 224, 0.43),
              0 0 10px 2px rgba(64, 224, 224, 0.2);
}


/* Ensure slots and hand cards are position:relative for floatNumber */
.battle-card-slot {
  position: relative;
}

.battle-hand-card {
  position: relative;
}


/* ── Global music player widget (always-visible, contextually adapts) ───────────
 * SNES-themed: solid dialog background, periwinkle border, yellow accents, with
 * a subtle drop-shadow that anchors the widget to its corner without competing
 * with primary buttons. Mirrors the .btn-snes vocabulary at a quieter scale. */
.music-ctrl {
  position: fixed;
  bottom: 14px;
  right: 20px;       /* +4px extra breathing room; aligns with HUD above */
  display: flex;
  flex-direction: column;
  gap: 5px;
  background: var(--bg-dialog);
  border: 2px solid var(--border-bright);
  border-radius: 6px;
  padding: 6px 6px 5px; /* horizontal −25% of 8px → 6px; height unchanged */
  z-index: 50;
  min-width: 98px;   /* −25% horizontal: was 130px → 130 × 0.75 = 98px */
  box-shadow: 0 2px 0 var(--border-mid), 0 3px 0 #000;
  font-family: var(--font);
  /* bug 23: opacity transition so the widget fades when dbtutorial toggles. */
  transition: opacity 400ms ease-out;
}

/* bug 23: hide music widget while the deck-builder tutorial (Lucy) is active.
 * Keeps focus on Lucy's instructions and prevents the Skip Tutorial button
 * from visually overlapping the bottom-right widget. */
body[data-dbtutorial="active"] .music-ctrl {
  opacity: 0;
  pointer-events: none;
}

/* Context-dependent visibility for music widget sub-controls.
 * Battle screen shows all controls (prev/play/next + volume + track name).
 * All other screens show only play/pause + volume — single-track, no playlist. */
body:not([data-screen="battle"]) #music-prev-btn,
body:not([data-screen="battle"]) #music-next-btn,
body:not([data-screen="battle"]) #music-track-name {
  display: none;
}

.music-track-name {
  font-family: var(--font);
  font-size: 9px;
  color: var(--snes-yellow);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border-mid);
  padding-bottom: 4px;
}

.music-controls {
  display: flex;
  align-items: center;
  gap: 3px;  /* −25% horizontal: was 4px */
}

.music-ctrl-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--font);
  font-size: 10px;
  color: var(--snes-yellow);
  padding: 3px 4px;  /* horizontal −25%: was 5px → 4px; height unchanged */
  line-height: 1;
  transition: color 0.15s, text-shadow 0.15s;
  user-select: none;
  flex-shrink: 0;
}
.music-ctrl-btn:hover {
  color: var(--snes-white);
  text-shadow: 0 0 6px var(--snes-yellow);
}
.music-ctrl-btn:active {
  transform: translateY(1px);
}
.music-play-btn { font-size: 13px; padding: 3px 4px; } /* horiz −25%: was 6px → 4px */

.music-volume-slider {
  -webkit-appearance: none;
  appearance: none;
  flex: 1;
  height: 6px;
  background: var(--bg-base);
  border: 1px solid var(--border-bright);
  border-radius: 3px;
  outline: none;
  cursor: pointer;
  margin-left: 4px; /* −25% horizontal: was 5px → 4px */
}
.music-volume-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--snes-yellow);
  cursor: pointer;
  border: 1px solid var(--border-bright);
  box-shadow: 0 0 4px rgba(248, 208, 0, 0.4);
}
.music-volume-slider::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--snes-yellow);
  cursor: pointer;
  border: 1px solid var(--border-bright);
  box-shadow: 0 0 4px rgba(248, 208, 0, 0.4);
}

/* ── Guest status corner strip (AUTH_SPEC.md Phase 2) ────────────────────────
 * Small, quiet, informational-only badge. Top-left, staying clear of
 * #adv-hud's top-right utility icons and .music-ctrl's bottom-right anchor.
 * Not interactive — the account-creation affordance lives on the home
 * screen instead. Screen-gated (follows .music-ctrl's per-screen opt-in
 * pattern after all): only relevant on the overworld map, hidden everywhere
 * else (battle, home, deckbuilder, etc.) so it doesn't compete with in-battle
 * UI or other screens' own chrome. */
.guest-status-strip {
  position: fixed;
  top: 10px;
  left: 14px;
  z-index: 60;
  background: rgba(0, 0, 0, 0.35);
  border-radius: 4px;
  padding: 3px 8px;
  pointer-events: none;
  display: none;
}
body[data-screen="overworld"] .guest-status-strip {
  display: block;
}

.guest-status-text {
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  white-space: nowrap;
}

/* ── Guest first-launch notice modal (AUTH_SPEC.md Phase 2) ──────────────────
 * Same visual language as .popup-backdrop/.card-popup (see "First-load welcome
 * popup" above), but position:fixed at the #sog-stage-sibling level (like
 * .music-ctrl) rather than position:absolute nested inside a .screen — so it
 * can show correctly regardless of which screen is currently active. */
.guest-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: rgba(0, 0, 14, 0.80);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.14s ease;
}
.guest-modal-backdrop.visible {
  opacity: 1;
  pointer-events: all;
}

/* ── Student account flow (AUTH_SPEC.md Phase 3) ─────────────────────────
 * Reuses .guest-modal-backdrop/.card-popup for the shell; these rules only
 * cover the bits that modal didn't need before: text inputs (the game had
 * none until this flow — "no student typing" everywhere else), the
 * credential card, and inline warning/error text. */

/* Chooser step (js/account-ui.js _stepChooser) has 4 buttons — CREATE
 * ACCOUNT / LOG IN / TEACHER SIGN UP / CANCEL — which overflow the modal's
 * right edge in the base .popup-actions single-row flex layout. Scoped to
 * :has(#af-teacher) so ONLY this step switches to a 2x2 grid; every other
 * account-flow step (2-3 buttons) keeps the normal single-row layout
 * unaffected. Button styling itself (border/shadow/font/colors) is
 * untouched — still plain .btn-snes — only width/padding change so two fit
 * per row without overflowing at narrower widths (text wraps rather than
 * clipping if a row ever gets too tight). */
#account-flow-actions:has(#af-teacher) {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
#account-flow-actions:has(#af-teacher) .btn-snes {
  width: 100%;
  box-sizing: border-box;
  padding-left: 14px;
  padding-right: 14px;
}

.account-flow-input {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin: 10px 0;
  padding: 10px 14px;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 15px;
  letter-spacing: 0.03em;
  background: var(--bg-btn);
  border: 2px solid var(--border-bright);
  border-radius: 4px;
  color: var(--text-white);
  outline: none;
}
.account-flow-input:focus {
  border-color: var(--snes-yellow);
}
.account-flow-input::placeholder {
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.account-flow-error {
  margin-top: 8px;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 13px;
  color: var(--snes-red);
}


/* Non-error info messages on the login form (forgot-password outcomes):
 * reset sent, "enter your email first", etc. — distinct from
 * .account-flow-error's red so a confirmation doesn't read as a failure. */
.account-flow-info {
  margin-top: 8px;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 13px;
  color: var(--text-white);
}

.account-flow-forgot {
  margin-top: 10px;
  text-align: right;
}
.account-flow-forgot a {
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 12px;
  color: var(--text-dim);
  text-decoration: underline;
  cursor: pointer;
}
.account-flow-forgot a:hover {
  color: var(--snes-yellow);
}

.account-flow-checkbox-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 13px;
  color: var(--text-white);
  cursor: pointer;
  margin-top: 12px;
}
.account-flow-checkbox-row input {
  margin-top: 3px;
  flex-shrink: 0;
}

.account-credential-card {
  margin: 14px 0;
  padding: 14px 18px;
  background: var(--bg-btn);
  border: 2px solid var(--snes-yellow);
  border-radius: 4px;
}
.account-credential-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 6px 0;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
}
.account-credential-row + .account-credential-row {
  border-top: 1px solid var(--border-mid);
}
.account-credential-row span {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}
.account-credential-row strong {
  font-size: 18px;
  color: var(--snes-yellow);
  letter-spacing: 0.02em;
}

/* Printable credential card: hide everything else on the page. */
@media print {
  body * { visibility: hidden; }
  #account-credential-card, #account-credential-card * { visibility: visible; }
  #account-credential-card {
    position: fixed;
    top: 40px;
    left: 50%;
    transform: translateX(-50%);
    width: 80%;
  }
}

/* ── "Summon" box (student signup credential reveal, AUTH_SPEC.md Phase 3) ──
 * .account-credential-card is reused directly for the button phase so it
 * doesn't resize when the animation starts; the options-reveal phase (see
 * .account-summon-box-options below) drops that fixed footprint since the
 * removed body copy leaves room to size the buttons up. The final username/
 * passphrase phase renders as its own fresh .account-credential-card via
 * _stepCredentialCard, unrelated to this element. position:relative +
 * overflow:hidden gives the swirling particles a contained stage. */
.account-summon-box {
  position: relative;
  overflow: hidden;
}

/* Options-reveal phase: no fixed height needed (no button/particle content),
 * so let it size to its (now much larger) button children instead of
 * matching the credential-card's original cramped footprint. */
.account-summon-box-options {
  padding: 10px 14px;
}

.account-summon-btn {
  display: block;
  width: 100%;
  background: none;
  border: none;
  padding: 22px 0;
  font-family: var(--font);
  font-size: 15px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--snes-yellow);
  cursor: pointer;
  text-align: center;
  position: relative;
  z-index: 1;
}
.account-summon-btn:hover {
  text-shadow: 0 0 8px var(--snes-yellow);
}
.account-summon-btn:disabled {
  cursor: default;
}

.account-summon-particle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: var(--snes-yellow);
  box-shadow: 0 0 6px 2px rgba(248, 208, 0, 0.7);
  pointer-events: none;
  z-index: 0;
}

.account-summon-option {
  display: block;
  width: 100%;
  margin: 10px 0;
  padding: 18px 12px;
  text-align: center;
  font-size: 21px;
  letter-spacing: 0.02em;
  line-height: 1.3;
  text-transform: none;   /* override .btn-snes's uppercase — these are shown in CamelCase */
  white-space: normal;
  word-break: break-word;
}

/* Conjuring → name-options "payoff" flash (js/account-ui.js
 * _playConjuringAnimation). Covers the whole popup card; opacity is driven
 * entirely by GSAP (see that function), never by CSS transition, so its
 * timing can be synced exactly to the conjuring fade-out. */
.account-flow-flash {
  position: absolute;
  inset: 0;
  background: #fff;
  opacity: 0;
  pointer-events: none;
  z-index: 20;
}

/* ── Teacher dashboard (AUTH_SPEC.md Phase 5) ────────────────────────────
 * An in-game MODAL, not a screen — #teacher-dashboard-backdrop reuses
 * .guest-modal-backdrop's fixed/inset/z-index/opacity-transition (same
 * mechanics as the account-flow and welcome modals), so the game
 * underneath stays visible and on whatever screen it was on. .td-modal is
 * a sibling of .card-popup rather than a reuse of it: .card-popup is
 * hardcoded to 700px, but this needs to read as "roughly 75-80% of the
 * screen" per spec, hence percentage sizing here instead. Same SNES
 * double-border treatment as .card-popup, just at a different size.
 * Internal sections scroll independently (roster can grow long) rather
 * than relying on page-level scroll. */
#teacher-dashboard-backdrop {
  /* Lighter dim than .guest-modal-backdrop's own 0.80 — the dashboard is
   * meant to be glanced at while the game keeps running behind it, not a
   * blocking modal, so the game should stay clearly visible through it.
   * Scoped by ID (not editing .guest-modal-backdrop itself) so the
   * account-flow/welcome modals keep their own darker dim. */
  background: rgba(0, 0, 14, 0.33);
}
.td-modal {
  width: 78%;
  height: 78%;
  box-sizing: border-box;
  padding: 20px 28px;
  position: relative;
  background: var(--bg-dialog);
  border: 3px solid var(--border-bright);
  box-shadow:
    0 0 0 3px var(--border-dark),
    0 0 0 6px var(--border-mid),
    0 0 0 7px var(--border-dark);
  color: var(--text-white);
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform: scale(0.90);
  transition: transform 0.16s cubic-bezier(0.22, 1, 0.36, 1);
}
.guest-modal-backdrop.visible .td-modal {
  transform: scale(1);
}

#td-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  padding-bottom: 14px;
  border-bottom: 2px solid var(--border-mid);
  margin-bottom: 18px;
}
#td-teacher-name {
  font-family: var(--font);
  font-size: 20px;
  color: var(--snes-yellow);
  letter-spacing: 0.03em;
}
#td-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
#td-header-actions .btn-snes {
  font-size: 11px;
  padding: 8px 14px;
}

#td-body {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: 40px;
  overflow: hidden;
}

/* Classes take a third, the roster two thirds: the roster is a wide table,
   the class cards wrap happily. */
#td-classes-section, #td-roster-section {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#td-classes, #td-roster {
  flex: 1;
  overflow-y: auto;
  padding-right: 6px;
}

.td-section-title {
  font-family: var(--font);
  font-size: 16px;
  color: var(--text-white);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin: 0 0 12px;
  flex-shrink: 0;
}

.td-empty {
  color: var(--text-dim);
  font-size: 14px;
}

/* Class rows: code large and readable (read off a whiteboard), editable
 * label, Regenerate made visually prominent — deactivate-and-reroll is the
 * only remedy for a leaked code, so it shouldn't be a buried, timid link. */
.td-class-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg-btn);
  border: 2px solid var(--border-bright);
  border-radius: 4px;
  padding: 10px 12px;
  margin-bottom: 10px;
}
.td-class-row-inactive {
  opacity: 0.55;
  border-color: var(--border-mid);
}

.td-class-code {
  font-family: var(--font);
  font-size: 26px;
  letter-spacing: 0.08em;
  color: var(--snes-yellow);
  flex-shrink: 0;
  min-width: 7ch;
}

.td-class-label-input {
  flex: 1;
  min-width: 0;
  box-sizing: border-box;
  padding: 8px 10px;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 14px;
  background: var(--bg-dialog);
  border: 2px solid var(--border-mid);
  border-radius: 4px;
  color: var(--text-white);
}
.td-class-label-input:focus {
  border-color: var(--snes-yellow);
  outline: none;
}
.td-class-label-input:disabled {
  color: var(--text-dim);
}

.td-class-row .btn-snes {
  font-size: 11px;
  padding: 8px 12px;
  flex-shrink: 0;
}
/* Regenerate: brighter/warmer than the default button so it reads as the
 * primary remedial action next to the quieter Deactivate. */
.td-regenerate-btn {
  border-color: var(--snes-yellow) !important;
  color: var(--snes-yellow) !important;
}

.td-class-badge {
  font-size: 11px;
  letter-spacing: 0.05em;
  color: var(--text-dim);
  border: 1px solid var(--border-mid);
  border-radius: 3px;
  padding: 4px 8px;
  flex-shrink: 0;
}

#td-inactive-toggle {
  margin: 4px 0 10px;
}
#td-inactive-toggle a {
  font-size: 12px;
  color: var(--text-dim);
  text-decoration: underline;
  cursor: pointer;
}
#td-inactive-toggle a:hover {
  color: var(--snes-yellow);
}

/* Roster: grouped by class, coarse metrics only (§6) — no per-question
 * correctness, no real names (the teacher keeps that mapping themselves). */
.td-roster-group {
  margin-bottom: 22px;
}
.td-roster-group-title {
  font-family: var(--font);
  font-size: 14px;
  color: var(--snes-yellow);
  letter-spacing: 0.03em;
  margin-bottom: 8px;
}

.td-roster-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.td-roster-table th, .td-roster-table td {
  text-align: left;
  vertical-align: top;
  padding: 8px 16px 8px 0;
  border-bottom: 1px solid var(--border-mid);
}
.td-roster-table td {
  overflow-wrap: break-word;   /* whole words size the column; a username breaks only if the table truly can't fit */
}
.td-roster-table th {
  color: var(--text-dim);
  font-weight: 600;
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.04em;
}
.td-roster-table td {
  color: var(--text-white);
}
/* "Self-reported by students" over Furthest Progress / Learning Checks / Time Played */
.td-roster-table .td-roster-note-row th {
  padding-bottom: 2px;
  border-bottom: none;
}
.td-roster-table .td-self-reported {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 12px;
  color: var(--text-dim);
}

/* ── Per-screen palette override: home screen (warm leather + gold) ─────────────
 * The home screen's wood-plank background + .btn-home-* gold-on-brown buttons
 * form the "history book" aesthetic. The music widget switches to the same
 * palette on this screen via the body[data-screen="home"] selector set by
 * showScreen(). Deckbuilder + battle keep the default SNES (cold) palette.
 *
 * Colour tokens borrowed from .btn-home-* rules:
 *   #2a1608  leather brown (plate / About fill)
 *   #d4aa50  unified gold border
 *   #f0cf6c  gold text
 *   #fff5d8  cream hover
 *   #1a0c04  deep brown shadow base
 */
body[data-screen="home"] .music-ctrl {
  background: #2a1608;
  border-color: #d4aa50;
  box-shadow: 0 2px 0 #1a0c04, 0 3px 0 #000;
}
body[data-screen="home"] .music-track-name {
  color: #f0cf6c;
  border-bottom-color: #5a3818;
}
body[data-screen="home"] .music-ctrl-btn {
  color: #f0cf6c;
}
body[data-screen="home"] .music-ctrl-btn:hover {
  color: #fff5d8;
  text-shadow: 0 0 6px #d4aa50;
}
body[data-screen="home"] .music-volume-slider {
  background: #1a0c04;
  border-color: #d4aa50;
}
body[data-screen="home"] .music-volume-slider::-webkit-slider-thumb {
  background: #f0cf6c;
  border-color: #d4aa50;
  box-shadow: 0 0 4px rgba(212, 170, 80, 0.5);
}
body[data-screen="home"] .music-volume-slider::-moz-range-thumb {
  background: #f0cf6c;
  border-color: #d4aa50;
  box-shadow: 0 0 4px rgba(212, 170, 80, 0.5);
}


/* ══════════════════════════════════════════════════════════════════
   TOUCH SUPPORT
   touch-action values control which browser gestures fire natively.
   Elements with touch-action:none are fully managed by JS (initTouchDrag).
   Elements with touch-action:manipulation get fast taps without double-
   tap zoom, while still allowing the browser to scroll.
══════════════════════════════════════════════════════════════════ */

/* Fast, zoomless taps on all buttons and deck-builder cards */
button,
.db-card { touch-action: manipulation; }

/* Volume slider: only allow horizontal panning (no accidental scroll) */
.music-volume-slider { touch-action: pan-x; }

/* ── Battle avatar portraits ───────────────────────────────────── */

.battle-avatar {
  position: absolute;
  z-index: 25;
  pointer-events: none;
}

.battle-avatar-ally {
  /* Player-hand zone = 210px. Avatar = 120px. Equal inner+outer padding:
     (210 − 120) / 2 = 45 → round to 40px for comfortable breathing room. */
  bottom: 40px;
  left: 40px;
}

.battle-avatar-opponent {
  /* The portrait spans exactly the turn box's height (top 14, 112 tall),
     measured on its outer ring (5px box-shadow): frame 102 (border-box, border
     included) + 2×5 ring = 112, so top = 14 + 5. The ring's right gap (18)
     mirrors the box's left gap. Fits the 145px opp band. */
  top: 19px;
  right: 23px;
}

.battle-avatar-frame {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid #c8a020;
  box-shadow:
    0 0 0 2px #000,
    0 0 0 5px #7a5a0a,
    0 4px 20px rgba(0, 0, 0, 0.85);
  background: #1a1206;
}
/* Side colours: each portrait's ring matches its side's location score
   (.battle-loc-score-player cyan, .battle-loc-score-opp red), so players can
   tell at a glance which score is theirs. */
.battle-avatar-ally .battle-avatar-frame {
  border-color: var(--snes-cyan);
  box-shadow:
    0 0 0 2px #000,
    0 0 0 5px #1d6f72,
    0 4px 20px rgba(0, 0, 0, 0.85);
}
.battle-avatar-opponent .battle-avatar-frame {
  width: 102px;
  height: 102px;
  border-color: var(--snes-red);
  box-shadow:
    0 0 0 2px #000,
    0 0 0 5px #7a1e16,
    0 4px 20px rgba(0, 0, 0, 0.85);
}

.battle-avatar-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  /* Clip to the frame's circle HERE rather than relying on the parent. The
     frame's `overflow:hidden` + `border-radius:50%` does not clip a child that
     carries its own transform (Chrome), so every transformed portrait bled
     square corners outside the gold ring — the mirrored opponents
     (Ramses/Hyksos, scaleX(-1)) and the zoomed ones (Otzi, scale(1.36);
     Neanderthal, scaleX(-1)) alike. Clipping the <img> instead of the frame
     leaves the border and the ring shadows intact, and circle(50%) is
     symmetric so it survives the mirror unchanged. */
  clip-path: circle(50%);
}

/* Turn-first highlight — the avatar that reveals first this turn pulses in its
   OWN side colour (cyan for the player, red for the opponent) during selection. */
@keyframes turn-first-pulse-player {
  0%, 100% { box-shadow: 0 0 0 2px #000, 0 0 0 5px #1d6f72, 0 0 14px 5px rgba(64, 224, 224, 0.50); }
  50%      { box-shadow: 0 0 0 2px #000, 0 0 0 5px #2fa8ab, 0 0 28px 12px rgba(64, 224, 224, 0.85); }
}
@keyframes turn-first-pulse-opp {
  0%, 100% { box-shadow: 0 0 0 2px #000, 0 0 0 5px #7a1e16, 0 0 14px 5px rgba(240, 64, 48, 0.50); }
  50%      { box-shadow: 0 0 0 2px #000, 0 0 0 5px #b8321f, 0 0 28px 12px rgba(240, 64, 48, 0.85); }
}
.battle-avatar-ally.turn-first .battle-avatar-frame {
  animation: turn-first-pulse-player 0.9s ease-in-out infinite;
}
.battle-avatar-opponent.turn-first .battle-avatar-frame {
  animation: turn-first-pulse-opp 0.9s ease-in-out infinite;
}

/* Draggable battle elements — JS owns all touch events (play, take-back, move) */
.battle-hand-card,
.battle-card-slot.unplayed[data-owner="player"],
.battle-card-slot.moveable[data-owner="player"] { touch-action: none; }

/* Touch-screen gestures that fight the game (touch laptops, Chromebooks in tablet
   mode). The battle board never scrolls or zooms: no pinch / double-tap zoom or
   page pan on it. A scrolling popup inside is its own scroll container, so its
   touch-action (auto) still lets it scroll. No pull-to-refresh / overscroll
   bounce anywhere; no long-press callout menu or text-selection highlight on game
   art; no grey tap flash. Text fields keep selection (class codes, logins). */
html, body { overscroll-behavior: none; -webkit-tap-highlight-color: transparent; }
#screen-battle, #screen-overworld { touch-action: none; }
#sog-stage { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
#sog-stage input, #sog-stage textarea, #sog-stage [contenteditable="true"] {
  -webkit-user-select: text; user-select: text; -webkit-touch-callout: default;
}


/* ══════════════════════════════════════════════════════════════════
   RESPONSIVE — MOBILE / TABLET  (< 768 px wide)
══════════════════════════════════════════════════════════════════ */


/* ══════════════════════════════════════════════════════════════════
   TUTORIAL OVERLAYS
   All tutorial elements sit above every game screen via z-index.
   Lucy's dialogue box uses the same SNES double-border style as
   the card popup (.card-popup) — see that block for the pattern.
══════════════════════════════════════════════════════════════════ */

/* ── Dim layer ────────────────────────────────────────────────── */
/* Covers all content below highlighted elements; pointer-events
   are intentionally left on so the dim layer can forward dialogue
   advances. Actual click handling is in tutorial.js.             */
#tut-dim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  z-index: 900;
}

/* ── Skip button — bottom-right corner, SNES style ───────────── */
#tut-skip {
  position: fixed;
  bottom: 14px;
  right: 16px;
  top: auto;
  z-index: 1100;
  font-family: var(--font);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-dim);
  background: var(--bg-surface);
  border: 2px solid var(--border-mid);
  border-radius: 4px;
  padding: 5px 12px;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 0.15s, color 0.15s, border-color 0.15s;
  touch-action: manipulation;
}
#tut-skip:hover {
  opacity: 1;
  color: var(--snes-yellow);
  border-color: var(--snes-yellow);
}

/* ── Dialogue box ─────────────────────────────────────────────── */
#tut-box {
  position: fixed;
  bottom: 24px;
  left: min(50%, 640px);
  transform: translateX(-50%);
  z-index: 1000;

  display: flex;
  align-items: stretch;
  gap: 0;

  width: 985px;

  background: var(--bg-dialog);
  border: 3px solid var(--border-bright);
  box-shadow:
    0 0 0 3px var(--border-dark),
    0 0 0 6px var(--border-mid),
    0 0 0 7px var(--border-dark);

  cursor: pointer;
  user-select: none;
}

/* ── Portrait column ──────────────────────────────────────────── */
.tut-portrait {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  width: 146px;
  padding: 0;
  background: rgba(0,0,0,0.25);
  border-right: 2px solid var(--border-mid);
  overflow: hidden;
}

/* Real photo — fills the portrait column, anchored to bottom */
.tut-lucy-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
}

/* Legacy SVG fallback (hidden unless image errors) */
.tut-lucy-svg {
  width: 80px;
  height: auto;
  display: block;
  image-rendering: pixelated;
}

/* ── Text column ──────────────────────────────────────────────── */
.tut-right {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 19px 24px 16px;
  min-height: 100px;
}

.tut-speaker {
  font-family: var(--font);
  font-size: 23px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--snes-yellow);
  margin-bottom: 8px;
}

.tut-speaker-sub {
  display: block;
  font-size: 16px;
  font-weight: 400;
  letter-spacing: 0.06em;
  opacity: 0.8;
  margin-top: 1px;
}

.tut-text {
  font-family: var(--font);
  font-size: 24px;
  line-height: 1.55;
  color: var(--text-white);
  flex: 1;
  min-height: 60px;
}

.tut-hint {
  font-family: var(--font);
  font-size: 15px;
  color: var(--text-dim);
  margin-top: 10px;
  letter-spacing: 0.06em;
  animation: tut-hint-blink 1.4s ease-in-out infinite;
}

@keyframes tut-hint-blink {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.35; }
}


/* ══════════════════════════════════════════════════════════════════
   ANALYTICS  — home title + test-mode badge
══════════════════════════════════════════════════════════════════ */

/* "Shoulders of Giants" — main title on the home screen.
   Large and prominent; also the triple-click target for the bypass menu. */
.home-title {
  font-family: var(--font);
  font-size: 97.2px;   /* 72px + 35% */
  font-weight: normal;
  color: var(--snes-yellow);
  letter-spacing: 0.06em;
  text-align: center;
  /* Evenly spaced: the title's letters sit as far below the top-right links'
     letters as above the tagline's (82px each on the 1280×720 stage).
     #home-content centres its stack, so pulling the tagline up by d moves the
     title down d/2: −22.8px balances the 70.6 / 104.8 gaps a plain 40px
     gap leaves at this size. */
  margin: 0 0 -22.8px;
  line-height: 1.1;
  cursor: default;
  user-select: none;
  text-shadow:
    3px  3px 0 #000,
   -2px -2px 0 #000,
    3px -2px 0 #000,
   -2px  3px 0 #000,
    5px  5px 0 rgba(0,0,0,0.45);
}

.home-byline {
  position: absolute;
  bottom: 18px;
  left: 24px;
  font-family: var(--font);
  font-size: 18px;
  color: #b48ad4;
  letter-spacing: 0.08em;
  margin: 0;
  text-shadow: 1px 1px 0 #000;
}

/* Fixed badge shown whenever test mode is active */
#test-mode-indicator {
  position: fixed;
  top: 10px;
  right: 14px;
  z-index: 9999;
  background: #d4260a;
  color: #fff;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  padding: 4px 10px;
  border-radius: 3px;
  border: 2px solid #000;
  box-shadow: 0 2px 0 #000;
  pointer-events: none;
}

/* ── Napata At-Once stamp: the nameplate glows light gold as a Political card
   reveals there and takes its +1 (abilities.applyNapataStampForCard). ──── */
@keyframes napata-stamp-glow {
  0%   { color: var(--snes-yellow); }
  35%  { color: #fff3c4; text-shadow: 0 0 6px #ffe9a0, 0 0 16px rgba(240, 200, 90, 0.95), 1px 1px 3px rgba(0,0,0,0.95); }
  100% { color: var(--snes-yellow); text-shadow: 1px 1px 3px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.8); }
}
.battle-loc-name.napata-stamp-glow { animation: napata-stamp-glow 1.0s ease-out 1; }


/* ══════════════════════════════════════════════════════════════════
   BYPASS ACCESS NOTICE
   Fixed overlay — shown on triple-click to a non-teacher (see js/bypass.js).
   Matches the SNES double-border of .card-popup exactly.
══════════════════════════════════════════════════════════════════ */


/* ══════════════════════════════════════════════════════════════════
   TEACHER BYPASS MENU
   Fixed overlay — same SNES double-border as .card-popup
   Triggered by triple-click on #home-title
══════════════════════════════════════════════════════════════════ */

/* Full-screen dim backdrop */
.bypass-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: rgba(0, 0, 0, 0.78);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

/* ── Dialog container ──────────────────────────────────────────── */
.bypass-dialog {
  width: 860px;
  max-height: 634px;
  display: flex;
  flex-direction: column;
  background: var(--bg-dialog);

  /* Same SNES double-border as .card-popup */
  border: 3px solid var(--border-bright);
  box-shadow:
    0 0 0 3px var(--border-dark),
    0 0 0 6px var(--border-mid),
    0 0 0 7px var(--border-dark),
    0 32px 80px rgba(0, 0, 0, 0.95);

  animation: bypass-pop-in 0.14s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes bypass-pop-in {
  from { transform: scale(0.88); opacity: 0; }
  to   { transform: scale(1);    opacity: 1; }
}

/* ── Fixed header bar ──────────────────────────────────────────── */
.bypass-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 24px 12px;
  background: var(--bg-header);
  border-bottom: 2px solid var(--border-bright);
  flex-shrink: 0;
}

.bypass-title {
  font-family: var(--font);
  font-size: 20px;
  color: var(--snes-yellow);
  text-shadow: 1px 1px 0 #000;
  letter-spacing: 0.10em;
  text-transform: uppercase;
}

.bypass-close-btn {
  font-size: 12px;
  padding: 6px 16px;
}

/* ── Scrollable body ───────────────────────────────────────────── */
.bypass-body {
  overflow-y: auto;
  padding: 0 24px 24px;
  flex: 1 1 auto;
  /* Custom thin scrollbar */
  scrollbar-width: thin;
  scrollbar-color: var(--border-mid) var(--bg-dialog);
}

.bypass-body::-webkit-scrollbar       { width: 6px; }
.bypass-body::-webkit-scrollbar-track { background: var(--bg-dialog); }
.bypass-body::-webkit-scrollbar-thumb { background: var(--border-mid); }

/* ── Sections ──────────────────────────────────────────────────── */
.bypass-section {
  margin-top: 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border-mid);
}

.bypass-section:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.bypass-section-title {
  font-family: var(--font);
  font-size: 13px;
  color: var(--snes-cyan);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  margin-bottom: 12px;
  text-shadow: 0 0 8px rgba(64, 224, 224, 0.4);
}

.bypass-section-hint {
  font-family: var(--font);
  font-size: 11px;
  color: var(--text-dim);
  margin-bottom: 12px;
  line-height: 1.6;
}

/* ── Button rows ───────────────────────────────────────────────── */
.bypass-btn-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 10px;
}

.bypass-btn-row:last-child { margin-bottom: 0; }

.bypass-btn-action {
  flex-shrink: 0;
  min-width: 200px;
  font-size: 13px;
  padding: 8px 18px;
}

.bypass-btn-sm {
  font-size: 11px;
  padding: 6px 14px;
}

.bypass-btn-desc {
  font-family: var(--font);
  font-size: 11px;
  color: var(--text-dim);
  line-height: 1.5;
}

/* Test mode button colour states */
.bypass-test-on {
  border-color: var(--snes-red) !important;
  color: var(--snes-red) !important;
  text-shadow: 0 0 6px rgba(240, 64, 48, 0.5);
}

.bypass-test-off {
  border-color: var(--snes-green);
  color: var(--snes-green);
}

/* ── Force Locations grid ──────────────────────────────────────── */
.bypass-loc-grid {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}

.bypass-loc-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-mid);
  cursor: pointer;
  transition: background 0.08s, border-color 0.08s;
}

.bypass-loc-item:hover {
  background: var(--bg-btn);
  border-color: var(--border-bright);
}

.bypass-loc-check {
  width: 16px;
  height: 16px;
  accent-color: var(--snes-yellow);
  flex-shrink: 0;
  cursor: pointer;
}

.bypass-loc-name {
  font-family: var(--font);
  font-size: 13px;
  color: var(--snes-yellow);
  min-width: 190px;
  flex-shrink: 0;
}

.bypass-loc-ability {
  font-family: var(--font);
  font-size: 11px;
  color: var(--text-dim);
}

.bypass-loc-footer {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 10px;
}

.bypass-loc-status {
  font-family: var(--font);
  font-size: 12px;
  letter-spacing: 0.06em;
  padding: 4px 10px;
  border: 1px solid;
}

.bypass-loc-random  { color: var(--text-dim);   border-color: var(--text-muted); }
.bypass-loc-locked  { color: var(--snes-red);   border-color: var(--snes-red);   text-shadow: 0 0 6px rgba(240,64,48,0.5); }
.bypass-loc-partial { color: var(--snes-yellow); border-color: var(--snes-yellow); }

/* ── Toast notification ────────────────────────────────────────── */
.bypass-toast {
  position: fixed;
  bottom: 32px;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--bg-header);
  border: 2px solid var(--border-bright);
  box-shadow: 0 0 0 2px var(--border-dark), 0 0 0 4px var(--border-mid);
  color: var(--snes-yellow);
  font-family: var(--font);
  font-size: 13px;
  letter-spacing: 0.07em;
  padding: 10px 22px;
  z-index: 9100;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
  white-space: nowrap;
  text-shadow: 1px 1px 0 #000;
}

.bypass-toast.bypass-toast-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}


/* ══════════════════════════════════════════════════════════════════
   LEGEND SCREEN — 5-win milestone victory sequence
   All children use position:absolute so GSAP can translate them freely.
   The screen itself is position:fixed so it floats above all game screens.
══════════════════════════════════════════════════════════════════ */

#screen-legend {
  position: fixed;
  inset: 0;
  z-index: 8000;
  background: #000;
  overflow: hidden;
  /* Layout used by the portrait area flex children */
  display: none;          /* shown by legend.js: style.display = 'flex' */
}

/* ── Solid black base ──────────────────────────────────────────── */
#legend-blackout {
  position: absolute;
  inset: 0;
  background: #000;
  z-index: 0;
}

/* ── Full-screen montage slide ─────────────────────────────────── */
/* Background-image is swapped by JS; GSAP translates the whole div. */
#legend-slide {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  z-index: 1;
}

/* ── "YOU HAVE MADE HISTORY" opening title ─────────────────────── */
/* Wrapper fills the screen and centers the text via flex.
   GSAP only animates the span's y-translation — no transform on wrapper. */
#legend-title-wrap {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 5;
  pointer-events: none;
}

#legend-opening-title {
  font-family: var(--font);
  font-size: 4.4rem;
  color: #f8d000;
  text-align: center;
  line-height: 1.35;
  letter-spacing: 0.07em;
  text-shadow:
    0 0 22px rgba(248, 208, 0, 0.95),
    0 0 70px rgba(248, 208, 0, 0.50),
    3px 3px 0 #000;
  /* No transform here — GSAP controls y on this element */
  max-width: 1075px;
}


/* ── "LEGEND" burst ────────────────────────────────────────────── */
/* Wrapper fills screen, centers text via flex.
   GSAP scales the span with no CSS transform conflicts. */
#legend-word-wrap {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 5;
  pointer-events: none;
}

#legend-word {
  font-family: var(--font);
  font-size: 10rem;
  color: #f8d000;
  letter-spacing: 0.12em;
  text-shadow:
    0 0 28px rgba(248, 208, 0, 1.0),
    0 0 80px rgba(248, 208, 0, 0.70),
    0 0 140px rgba(248, 208, 0, 0.40),
    5px 5px 0 #000;
  /* No transform — GSAP controls scale on this element */
  white-space: nowrap;
}

/* ── Gold particles ────────────────────────────────────────────── */
/* Container is a zero-size point at screen center; particles
   radiate outward from it via GSAP x/y translation. */
#legend-particles {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  z-index: 6;
  pointer-events: none;
  overflow: visible;
}

.legend-particle {
  position: absolute;
  border-radius: 50%;
  /* top/left set in JS to center on origin; width/height also set in JS */
}

/* ── "Click to claim your victory" subtitle ────────────────────── */
#legend-subtitle {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 16%;
  text-align: center;
  font-family: var(--font);
  font-size: 1.5rem;
  color: rgba(255, 255, 255, 0.88);
  letter-spacing: 0.09em;
  text-shadow: 1px 1px 0 #000, 0 0 10px rgba(255,255,255,0.2);
  z-index: 5;
  pointer-events: none;
  /* No transform — GSAP controls autoAlpha only */
}


/* ══════════════════════════════════════════════════════════════════
   HOME SCREEN — Versus Mode button
   ══════════════════════════════════════════════════════════════════ */

/* (Versus Mode button styling is handled by the shared
   .btn-home-* rules near the top of this file.) */

/* ══════════════════════════════════════════════════════════════════
   LOBBY SCREEN — multiplayer tournament entry + waiting room
   ══════════════════════════════════════════════════════════════════ */

#screen-lobby.active {
  display:         flex;
  align-items:     center;
  justify-content: center;
  position:        absolute;
  top: 0; left: 0; right: 0; bottom: 0;
}

/* Same dark wood grain as result screen */
#screen-lobby::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    repeating-linear-gradient(
      90deg,
      rgba(80,40,0,0.07) 0px, rgba(80,40,0,0.07) 1px,
      transparent        1px, transparent        9px
    ),
    repeating-linear-gradient(
      0deg,
      rgba(0,0,0,0.06)  0px, rgba(0,0,0,0.06)  1px,
      transparent        1px, transparent        13px
    ),
    linear-gradient(168deg, #2c1a08 0%, #1e1106 35%, #261608 65%, #1a0e04 100%);
  pointer-events: none;
  z-index: 0;
}

/* ── Panel box (shared by both entry + waiting states) ─── */
.lobby-panel {
  position:        relative;
  z-index:         1;
  display:         flex;
  flex-direction:  column;
  align-items:     center;
  width:           520px;
  padding:         36px 44px 32px;
  gap:             16px;
  background:      var(--bg-dialog);
  border:          3px solid var(--border-bright);
  box-shadow:
    0 0 0 3px var(--border-dark),
    0 0 0 6px var(--border-mid),
    0 0 0 7px var(--border-dark);
}

.lobby-panel-title {
  font-family:    'Cinzel', serif;
  font-size:      26px;
  font-weight:    700;
  color:          var(--snes-yellow);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-shadow:    1px 1px 0 #000, 0 0 16px rgba(248,208,0,0.35);
}

.lobby-panel-divider {
  width:      100%;
  height:     2px;
  background: var(--border-bright);
  box-shadow: 0 0 4px var(--border-bright);
}

/* ── Form labels ─── */
.lobby-label {
  font-family:    var(--font);
  font-size:      15px;
  color:          var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  align-self:     flex-start;
  margin-bottom:  -6px;
}

.lobby-label-hint {
  font-size:      11px;
  color:          #404068;
  text-transform: none;
  letter-spacing: 0;
}

/* ── Text inputs ─── */
.lobby-input {
  width:           100%;
  box-sizing:      border-box;
  background:      #08041a;
  border:          2px solid var(--border-mid);
  color:           var(--text-white);
  font-family:     var(--font);
  font-size:       28px;
  letter-spacing:  0.3em;
  text-align:      center;
  text-transform:  uppercase;
  padding:         10px 16px;
  outline:         none;
  transition:      border-color 0.15s;
}
.lobby-input:focus {
  border-color: var(--snes-yellow);
}
.lobby-input::placeholder {
  color:          #2a2850;
  letter-spacing: 0.2em;
}

/* Narrower ID input (3 chars) */
.lobby-input-id {
  width:          150px;
  font-size:      32px;
  letter-spacing: 0.45em;
  flex:           0 0 auto;
}

/* Row that holds ID input + shuffle button */
.lobby-id-row {
  display:    flex;
  align-items: center;
  gap:        12px;
  align-self: flex-start;
}

.lobby-shuffle-btn {
  font-size: 22px;
  padding:   9px 14px;
  line-height: 1;
}

/* ── Error message ─── */
.lobby-error {
  font-family:    var(--font);
  font-size:      15px;
  color:          var(--snes-red);
  text-align:     center;
  letter-spacing: 0.04em;
  min-height:     20px;
}

/* ── Action buttons row ─── */
.lobby-btn-row {
  display:         flex;
  gap:             14px;
  width:           100%;
  justify-content: space-between;
  margin-top:      4px;
}

.lobby-btn-join {
  font-size:  22px;
  padding:    11px 32px;
  flex:       1;
  border-color: var(--snes-yellow);
  color:        var(--snes-yellow);
}
.lobby-btn-join:hover   { background: #1a1000; }
.lobby-btn-join:disabled {
  border-color: #333358;
  color:        var(--text-muted);
  cursor:       default;
  transform:    none;
  box-shadow:   0 4px 0 var(--border-mid), 0 5px 0 #000;
}

/* ── Waiting room — your info box ─── */
.lobby-your-info {
  display:         grid;
  grid-template-columns: auto 1fr;
  gap:             6px 20px;
  align-items:     center;
  width:           100%;
  box-sizing:      border-box;
  background:      rgba(0,0,0,0.35);
  padding:         14px 20px;
  border:          1px solid #252548;
}

.lobby-info-label {
  font-family:    var(--font);
  font-size:      14px;
  color:          var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.lobby-info-val {
  font-family:    var(--font);
  font-size:      24px;
  color:          var(--text-white);
  letter-spacing: 0.15em;
}

.lobby-info-id {
  color:     var(--snes-yellow);
  font-size: 28px;
}

/* ── "Waiting…" message with spinner ─── */
.lobby-waiting-msg {
  display:     flex;
  align-items: center;
  gap:         14px;
  font-family:    var(--font);
  font-size:      17px;
  color:          var(--text-dim);
  letter-spacing: 0.06em;
}

@keyframes lobby-spin {
  to { transform: rotate(360deg); }
}
.lobby-spinner {
  width:         16px;
  height:        16px;
  border:        3px solid #252548;
  border-top-color: var(--snes-yellow);
  border-radius: 50%;
  animation:     lobby-spin 0.75s linear infinite;
  flex-shrink:   0;
}

/* ── Student count row ─── */
.lobby-student-list-wrap {
  display:     flex;
  align-items: baseline;
  gap:         12px;
}

.lobby-student-count {
  font-family: var(--font);
  font-size:   28px;
  color:       var(--snes-yellow);
}

/* ══════════════════════════════════════════════════════════════════
   TEACHER TOURNAMENT LOBBY OVERLAY
   ══════════════════════════════════════════════════════════════════ */

/* ── Full-screen dim backdrop ─── */
.teacher-lobby-backdrop {
  position:        fixed;
  inset:           0;
  z-index:         9100;
  background:      rgba(0, 0, 0, 0.82);
  display:         flex;
  align-items:     center;
  justify-content: center;
  padding:         20px;
}

/* ── Dialog container ─── */
.teacher-lobby-dialog {
  width:        820px;
  max-height:   648px;
  display:      flex;
  flex-direction: column;
  background:   var(--bg-dialog);
  border:       3px solid var(--border-bright);
  box-shadow:
    0 0 0 3px var(--border-dark),
    0 0 0 6px var(--border-mid),
    0 0 0 7px var(--border-dark),
    0 32px 80px rgba(0,0,0,0.95);
  animation: bypass-pop-in 0.14s cubic-bezier(0.22, 1, 0.36, 1) both;
  position: relative;   /* for toast positioning */
}

/* ── Header bar ─── */
.teacher-lobby-header {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  padding:         14px 20px 12px;
  border-bottom:   2px solid var(--border-mid);
  flex-shrink:     0;
}

.teacher-lobby-title {
  font-family:    var(--font);
  font-size:      20px;
  color:          var(--snes-yellow);
  letter-spacing: 0.08em;
  text-shadow:    0 0 10px rgba(248,208,0,0.3);
}

/* ── Scrollable body ─── */
.teacher-lobby-body {
  overflow-y:    auto;
  padding:       20px 24px 24px;
  flex:          1 1 auto;
  display:       flex;
  flex-direction: column;
  gap:           20px;
  scrollbar-width: thin;
  scrollbar-color: var(--border-mid) var(--bg-dialog);
}
.teacher-lobby-body::-webkit-scrollbar       { width: 6px; }
.teacher-lobby-body::-webkit-scrollbar-track { background: var(--bg-dialog); }
.teacher-lobby-body::-webkit-scrollbar-thumb { background: var(--border-mid); }

/* ── Large code display ─── */
.tlob-code-section {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  gap:            8px;
}

.tlob-code-label {
  font-family:    var(--font);
  font-size:      13px;
  color:          var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

.tlob-code-display {
  font-family:    var(--font);
  font-size:      88px;
  letter-spacing: 0.35em;
  color:          var(--snes-yellow);
  text-shadow:
    3px 3px 0 rgba(0,0,0,0.85),
    0 0 28px rgba(248,208,0,0.38);
  background:     rgba(0,0,0,0.45);
  border:         2px solid rgba(248,208,0,0.28);
  padding:        10px 36px 10px 48px;  /* extra left to compensate letter-spacing */
  text-align:     center;
  min-width:      360px;
  line-height:    1;
}

.tlob-code-hint {
  font-family:    var(--font);
  font-size:      13px;
  color:          #505070;
  letter-spacing: 0.06em;
}

/* ── Student list section ─── */
.tlob-list-section {
  display:        flex;
  flex-direction: column;
  gap:            8px;
}

.tlob-list-header {
  font-family:    var(--font);
  font-size:      15px;
  color:          var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.tlob-student-count {
  color:     var(--snes-yellow);
  font-size: 17px;
}

.tlob-student-list {
  background:  rgba(0,0,0,0.28);
  border:      1px solid #252548;
  min-height:  60px;
  max-height:  260px;
  overflow-y:  auto;
  scrollbar-width: thin;
  scrollbar-color: var(--border-mid) transparent;
}
.tlob-student-list::-webkit-scrollbar       { width: 5px; }
.tlob-student-list::-webkit-scrollbar-thumb { background: var(--border-mid); }

/* Empty state */
.tlob-empty {
  font-family:    var(--font);
  font-size:      15px;
  color:          #404060;
  text-align:     center;
  padding:        18px;
  letter-spacing: 0.06em;
}

/* Column header row */
.tlob-row-header {
  background:     rgba(30,20,60,0.6);
  border-bottom:  1px solid #252548;
}
.tlob-row-header .tlob-col-id,
.tlob-row-header .tlob-col-time {
  font-size:   11px;
  color:       var(--text-muted);
  letter-spacing: 0.14em;
}

/* Data row */
.tlob-row {
  display:     flex;
  align-items: center;
  padding:     8px 12px;
  border-bottom: 1px solid rgba(37,37,72,0.5);
  gap:         0;
}
.tlob-row:last-child { border-bottom: none; }
.tlob-row:hover      { background: rgba(255,255,255,0.03); }

.tlob-col-id {
  width:          80px;
  font-family:    var(--font);
  font-size:      20px;
  color:          var(--snes-yellow);
  letter-spacing: 0.15em;
  flex-shrink:    0;
}

.tlob-col-time {
  flex:           1;
  font-family:    var(--font);
  font-size:      14px;
  color:          var(--text-dim);
  letter-spacing: 0.06em;
}

.tlob-col-action {
  flex-shrink:  0;
}

/* Boot button */
.tlob-boot-btn {
  font-size:  13px;
  padding:    5px 14px;
  border-color: var(--snes-red);
  color:        var(--snes-red);
}
.tlob-boot-btn:hover { background: #200000; }
.tlob-boot-btn:disabled {
  border-color: #333358;
  color:        var(--text-muted);
  cursor:       default;
  transform:    none;
  box-shadow:   0 4px 0 var(--border-mid), 0 5px 0 #000;
}

/* ── Action buttons row ─── */
.tlob-actions {
  display:     flex;
  gap:         10px;
  flex-wrap:   wrap;
  align-items: center;
}

.tlob-start-btn {
  margin-left:  auto;
  border-color: var(--snes-green);
  color:        var(--snes-green);
}
.tlob-start-btn:not(:disabled):hover { background: #001800; }
.tlob-start-btn:disabled {
  border-color: #333358;
  color:        var(--text-muted);
}

/* ── Load code modal (inner overlay) ─── */
.tlob-modal {
  position:        absolute;
  inset:           0;
  background:      rgba(0,0,0,0.72);
  display:         flex;
  align-items:     center;
  justify-content: center;
  z-index:         10;
}

.tlob-modal-box {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  gap:            14px;
  width:          400px;
  padding:        28px 32px 26px;
  background:     var(--bg-dialog);
  border:         3px solid var(--border-bright);
  box-shadow:
    0 0 0 3px var(--border-dark),
    0 0 0 6px var(--border-mid),
    0 0 0 7px var(--border-dark);
}

.tlob-modal-title {
  font-family:    var(--font);
  font-size:      22px;
  color:          var(--snes-yellow);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.tlob-modal-btns {
  display: flex;
  gap:     12px;
  width:   100%;
  justify-content: space-between;
}

.tlob-modal-confirm {
  flex:        1;
  border-color: var(--snes-yellow);
  color:        var(--snes-yellow);
}
.tlob-modal-confirm:hover { background: #1a1000; }

/* ── Toast notification ─── */
.tlob-toast {
  position:       absolute;
  bottom:         16px;
  left:           50%;
  transform:      translateX(-50%);
  font-family:    var(--font);
  font-size:      14px;
  color:          var(--snes-yellow);
  background:     rgba(0,0,0,0.88);
  border:         1px solid rgba(248,208,0,0.4);
  padding:        8px 20px;
  white-space:    nowrap;
  letter-spacing: 0.06em;
  opacity:        0;
  pointer-events: none;
  transition:     opacity 0.25s;
  z-index:        20;
}
.tlob-toast.visible { opacity: 1; }
.tlob-toast.tlob-toast-error {
  color:       var(--snes-red);
  border-color: rgba(240,64,48,0.4);
}

/* ══════════════════════════════════════════════════════════════════
   GROUP ASSIGNMENT PANEL (inside teacher lobby)
   ══════════════════════════════════════════════════════════════════ */

/* Panel replaces .teacher-lobby-body — same flex+overflow context */
.tlob-groups-panel {
  flex-direction: column;
  flex:           1 1 auto;
  overflow:       hidden;
  gap:            14px;
  padding:        16px 24px 20px;
}

/* Sub-header row: back button | title | spacer */
.tlob-groups-header {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  padding-bottom:  12px;
  border-bottom:   1px solid var(--border-mid);
  flex-shrink:     0;
}

/* Config strip */
.tlob-groups-config {
  display:     flex;
  align-items: center;
  flex-wrap:   wrap;
  gap:         14px;
  background:  rgba(0,0,0,0.28);
  border:      1px solid #252548;
  padding:     10px 16px;
  flex-shrink: 0;
}

.tlob-cfg-item {
  display:     flex;
  align-items: center;
  gap:         8px;
}

.tlob-cfg-label {
  font-family:    var(--font);
  font-size:      11px;
  color:          var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

.tlob-cfg-val {
  font-family: var(--font);
  font-size:   20px;
  color:       var(--text-white);
  min-width:   22px;
  text-align:  center;
}

.tlob-cfg-bots { color: #505070; }

.tlob-cfg-sep {
  font-family: var(--font);
  font-size:   14px;
  color:       #303050;
}

/* +/- spinner buttons */
.tlob-cfg-spin {
  font-size:   17px;
  padding:     3px 10px;
  line-height: 1;
}

/* ── Scrollable group card grid ─── */
.tlob-groups-grid {
  display:               grid;
  grid-template-columns: repeat(4, 1fr);
  gap:                   8px;
  overflow-y:            auto;
  flex:                  1 1 auto;
  padding-right:         4px;
  scrollbar-width:       thin;
  scrollbar-color:       var(--border-mid) transparent;
  min-height:            0;   /* prevents grid from overflowing flex container */
}
.tlob-groups-grid::-webkit-scrollbar       { width: 5px; }
.tlob-groups-grid::-webkit-scrollbar-thumb { background: var(--border-mid); }

/* Individual group card */
.tlob-group-card {
  background:     rgba(0,0,0,0.32);
  border:         1px solid #252548;
  padding:        8px 10px;
  display:        flex;
  flex-direction: column;
  gap:            4px;
}

.tlob-group-label {
  font-family:    var(--font);
  font-size:      11px;
  color:          var(--snes-cyan);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  border-bottom:  1px solid #252548;
  padding-bottom: 4px;
  margin-bottom:  2px;
}

.tlob-group-member {
  font-family:    var(--font);
  font-size:      16px;
  color:          var(--snes-yellow);
  letter-spacing: 0.12em;
}

.tlob-group-member.is-bot {
  font-size:   13px;
  color:       #3e3e5e;
  letter-spacing: 0.05em;
}

/* ── Bottom action bar ─── */
.tlob-groups-actions {
  display:      flex;
  gap:          10px;
  justify-content: space-between;
  flex-shrink:  0;
  padding-top:  10px;
  border-top:   1px solid var(--border-mid);
}

.tlob-confirm-start-btn {
  border-color: var(--snes-green);
  color:        var(--snes-green);
  font-size:    16px;
  padding:      10px 28px;
}
.tlob-confirm-start-btn:hover    { background: #001800; }
.tlob-confirm-start-btn:disabled {
  border-color: #333358;
  color:        var(--text-muted);
  cursor:       default;
  transform:    none;
  box-shadow:   0 4px 0 var(--border-mid), 0 5px 0 #000;
}

/* ── Mode selection panel ─── */
.tlob-mode-options {
  display:        flex;
  gap:            24px;
  padding:        20px;
  justify-content: center;
  align-items:    flex-start;
  flex:           1;
  overflow-y:     auto;
}

.tlob-mode-card {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  background:     var(--bg-surface);
  border:         2px solid var(--border-mid);
  border-radius:  4px;
  padding:        20px 18px 16px;
  width:          220px;
  gap:            10px;
  transition:     border-color 0.15s, box-shadow 0.15s;
}

.tlob-mode-card:hover {
  border-color: var(--border-bright);
  box-shadow:   0 0 12px rgba(136,152,255,0.25);
}

.tlob-mode-icon {
  font-size: 42px;
  line-height: 1;
}

.tlob-mode-name {
  font-family:    var(--font);
  font-size:      20px;
  color:          var(--snes-yellow);
  letter-spacing: 0.1em;
}

.tlob-mode-features {
  list-style:  none;
  padding:     0;
  margin:      0;
  width:       100%;
  display:     flex;
  flex-direction: column;
  gap:         6px;
}

.tlob-mode-features li {
  font-family: var(--font-ui, sans-serif);
  font-size:   13px;
  color:       var(--text-dim);
  padding-left: 14px;
  position:    relative;
}

.tlob-mode-features li::before {
  content:  '▸';
  position: absolute;
  left:     0;
  color:    var(--snes-cyan);
}

.tlob-mode-select-btn {
  margin-top:   8px;
  width:        100%;
  font-size:    16px;
  padding:      10px 0;
  border-color: var(--snes-cyan);
  color:        var(--snes-cyan);
}

.tlob-mode-select-btn:hover { background: #001820; }

/* ── Quick Match panel content ─── */
.tlob-qm-content {
  flex:       1;
  overflow-y: auto;
  padding:    16px 20px;
  display:    flex;
  flex-direction: column;
  gap:        14px;
}

.tlob-qm-section-label {
  font-family:    var(--font);
  font-size:      15px;
  color:          var(--text-dim);
  letter-spacing: 0.05em;
}

.tlob-qm-available {
  display:    flex;
  flex-wrap:  wrap;
  gap:        8px;
  min-height: 44px;
}

.tlob-qm-chip {
  font-family:    var(--font);
  font-size:      17px;
  letter-spacing: 0.12em;
  color:          var(--snes-yellow);
  background:     var(--bg-surface);
  border:         2px solid var(--border-mid);
  border-radius:  3px;
  padding:        6px 14px;
  cursor:         pointer;
  transition:     border-color 0.12s, background 0.12s;
  user-select:    none;
}

.tlob-qm-chip:hover {
  border-color: var(--border-bright);
  background:   #0e0040;
}

.tlob-qm-chip.selected {
  border-color: var(--snes-cyan);
  color:        var(--snes-cyan);
  background:   #001820;
}

.tlob-qm-chip.in-match {
  color:        var(--text-muted);
  border-color: #222244;
  cursor:       default;
  opacity:      0.5;
}

.tlob-qm-pair-display {
  display:     flex;
  align-items: center;
  gap:         16px;
  justify-content: center;
  padding:     10px 0;
}

.tlob-qm-player {
  font-family:    var(--font);
  font-size:      26px;
  letter-spacing: 0.15em;
  color:          var(--snes-cyan);
  min-width:      70px;
  text-align:     center;
  background:     var(--bg-surface);
  border:         2px solid var(--border-mid);
  border-radius:  3px;
  padding:        8px 14px;
}

.tlob-qm-player.tlob-qm-empty {
  color:        #333358;
  border-color: #1a1a38;
}

.tlob-qm-vs {
  font-family:    var(--font);
  font-size:      22px;
  color:          var(--snes-red);
  letter-spacing: 0.1em;
}

.tlob-qm-active-section {
  display:        flex;
  flex-direction: column;
  gap:            8px;
  border-top:     1px solid var(--border-mid);
  padding-top:    12px;
}

.tlob-qm-active-list {
  display:        flex;
  flex-direction: column;
  gap:            6px;
}

.tlob-qm-match-row {
  display:         flex;
  align-items:     center;
  gap:             10px;
  font-family:     var(--font);
  font-size:       15px;
  color:           var(--text-dim);
  background:      var(--bg-surface);
  border:          1px solid var(--border-mid);
  border-radius:   3px;
  padding:         6px 12px;
}

.tlob-qm-match-row .match-players {
  flex:   1;
  color:  var(--snes-yellow);
}

.tlob-qm-match-row .match-status {
  font-size:   13px;
  color:       var(--snes-green);
}

/* ── Result screen — lobby return button ─── */
.result-lobby-btn {
  display: block;
  margin:  8px auto 0;
  /* Inherits warm gold style from .result-actions .btn-primary */
}

/* ═══════════════════════════════════════════════════════════
   PART 5 — Selection Phase Timer
═══════════════════════════════════════════════════════════ */

/* Legacy timer box — kept in DOM for JS compat but never shown */
.battle-timer { display: none !important; }

/* ── Selection phase timer bar (under Lucy avatar) ───────────── */
.battle-timer-bar-wrap {
  width:         120px;   /* matches avatar frame width */
  height:        7px;
  margin-top:    7px;
  border-radius: 4px;
  background:    rgba(0, 0, 0, 0.45);
  overflow:      hidden;
  border:        1px solid rgba(200, 160, 32, 0.25);
}

.battle-timer-bar {
  height:           100%;
  width:            100%;
  border-radius:    4px;
  background:       var(--snes-cyan);
  transition:       width 1s linear, background-color 0.4s ease;
  transform-origin: left center;
}

.battle-timer-bar.warning {
  background: var(--snes-yellow);
}

.battle-timer-bar.urgent {
  background: var(--snes-red);
  animation:  timer-pulse 0.5s ease-in-out infinite alternate;
}

@keyframes timer-pulse {
  from { opacity: 1;    }
  to   { opacity: 0.45; }
}

/* ═══════════════════════════════════════════════════════════
   PART 5 — Group Stage Lobby Panel
═══════════════════════════════════════════════════════════ */

.lobby-group-panel {
  max-width:  520px;
  gap:        14px;
}

.lobby-group-standings-wrap {
  width:       100%;
  overflow-x:  auto;
}

.lobby-group-standings {
  width:           100%;
  border-collapse: collapse;
  font-family:     var(--font);
  font-size:       15px;
}

.lobby-group-standings th {
  color:           var(--text-dim);
  font-size:       12px;
  letter-spacing:  0.1em;
  text-align:      left;
  padding:         4px 10px;
  border-bottom:   1px solid var(--border-mid);
}

.lobby-group-standings td {
  padding:         7px 10px;
  color:           var(--snes-yellow);
  border-bottom:   1px solid #111130;
}

.lobby-group-standings td.gs-col-wdl {
  color:   var(--text-dim);
  font-size: 13px;
}

.lobby-group-standings td.gs-col-pts {
  color:       var(--snes-cyan);
  font-weight: bold;
}

.lobby-group-standings tr.gs-me td {
  color: #ffffff;
}

.lobby-group-standings tr.gs-me td.gs-col-id {
  color: var(--snes-green);
}

.lobby-group-standings td.gs-col-bot {
  color: #3e3e5e;
}

/* ── Round schedule ─── */
.lobby-round-list {
  display:        flex;
  flex-direction: column;
  gap:            8px;
  width:          100%;
}

.lobby-round-row {
  display:         grid;
  grid-template-columns: 70px 1fr auto;
  align-items:     center;
  gap:             10px;
  background:      var(--bg-surface);
  border:          1px solid var(--border-mid);
  border-radius:   3px;
  padding:         10px 14px;
}

.lobby-round-label {
  font-family:    var(--font);
  font-size:      14px;
  color:          var(--text-dim);
  letter-spacing: 0.08em;
}

.lobby-round-opp {
  font-family:    var(--font);
  font-size:      18px;
  color:          var(--snes-yellow);
  letter-spacing: 0.12em;
}

.lobby-round-opp.is-bot {
  color:     #3e3e5e;
  font-size: 15px;
}

.lobby-round-btn {
  font-family:    var(--font);
  font-size:      14px;
  padding:        7px 18px;
  cursor:         pointer;
  border:         2px solid var(--snes-green);
  color:          var(--snes-green);
  background:     var(--bg-btn);
  border-radius:  2px;
  transition:     background 0.12s;
  white-space:    nowrap;
}

.lobby-round-btn:hover:not(:disabled) { background: #001800; }

.lobby-round-btn:disabled {
  border-color: #222244;
  color:        var(--text-muted);
  cursor:       default;
}

.lobby-round-result {
  font-family:    var(--font);
  font-size:      15px;
  letter-spacing: 0.08em;
  text-align:     right;
  white-space:    nowrap;
}

.lobby-round-result.win  { color: var(--snes-green); }
.lobby-round-result.draw { color: var(--snes-yellow); }
.lobby-round-result.loss { color: var(--snes-red); }

/* ═══════════════════════════════════════════════════════════
   PART 6 — Knockout Panel (student)
═══════════════════════════════════════════════════════════ */

.lobby-knockout-panel {
  max-width: 440px;
  gap:       14px;
}

.lobby-ko-banner {
  width:       100%;
  text-align:  center;
  font-family: var(--font);
  font-size:   20px;
  padding:     10px 0;
  border-radius: 3px;
}

.lobby-ko-banner.advanced {
  color:      var(--snes-green);
  background: #001800;
  border:     1px solid var(--snes-green);
}

.lobby-ko-banner.eliminated {
  color:      var(--snes-red);
  background: #180000;
  border:     1px solid var(--snes-red);
}

.lobby-ko-banner.champion {
  color:      var(--snes-yellow);
  background: #1a1200;
  border:     2px solid var(--snes-yellow);
  font-size:  24px;
  animation:  champion-glow 1.5s ease-in-out infinite alternate;
}

@keyframes champion-glow {
  from { box-shadow: 0 0 8px rgba(248,208,0,0.3); }
  to   { box-shadow: 0 0 24px rgba(248,208,0,0.7); }
}

/* Knockout ladder — one row per round */
.lobby-ko-ladder {
  display:        flex;
  flex-direction: column;
  gap:            6px;
  width:          100%;
}

.lobby-ko-row {
  display:     grid;
  grid-template-columns: 80px 1fr auto;
  align-items: center;
  gap:         10px;
  background:  var(--bg-surface);
  border:      1px solid var(--border-mid);
  border-radius: 3px;
  padding:     9px 14px;
}

.lobby-ko-row.active {
  border-color: var(--snes-cyan);
  background:   #000e18;
}

.lobby-ko-row-label {
  font-family:    var(--font);
  font-size:      13px;
  color:          var(--text-dim);
  letter-spacing: 0.08em;
}

.lobby-ko-row-label.active-lbl { color: var(--snes-cyan); }

.lobby-ko-row-info {
  font-family: var(--font);
  font-size:   16px;
  color:       var(--text-dim);
}

.lobby-ko-row-info.eligible { color: var(--snes-yellow); }
.lobby-ko-row-info.locked   { color: #222244; }

.lobby-ko-play-wrap {
  display:         flex;
  justify-content: center;
  width:           100%;
  padding-top:     4px;
}

/* ── Teacher knockout panel ─── */
.tlob-ko-content {
  flex:       1;
  overflow-y: auto;
  padding:    16px 20px;
  display:    flex;
  flex-direction: column;
  gap:        16px;
}

.tlob-ko-section-title {
  font-family:    var(--font);
  font-size:      16px;
  color:          var(--snes-yellow);
  letter-spacing: 0.1em;
  padding-bottom: 6px;
  border-bottom:  1px solid var(--border-mid);
}

.tlob-ko-groups-grid {
  display:               grid;
  grid-template-columns: repeat(4, 1fr);
  gap:                   10px;
}

.tlob-ko-group-block {
  background:   var(--bg-surface);
  border:       1px solid var(--border-mid);
  border-radius: 3px;
  padding:      8px 10px;
  display:      flex;
  flex-direction: column;
  gap:          4px;
}

.tlob-ko-group-name {
  font-family:    var(--font);
  font-size:      12px;
  color:          var(--text-dim);
  letter-spacing: 0.08em;
}

.tlob-ko-advancer {
  font-family: var(--font);
  font-size:   15px;
  color:       var(--snes-green);
  letter-spacing: 0.1em;
}

.tlob-ko-advancer.rank2 { color: var(--snes-cyan); }
.tlob-ko-advancer.bot   { color: #3e3e5e; font-size: 12px; }

.tlob-ko-status-msg {
  font-family: var(--font);
  font-size:   14px;
  color:       var(--text-dim);
  flex:        1;
}

/* Bracket round table */
.tlob-ko-bracket {
  width:           100%;
  border-collapse: collapse;
}

.tlob-ko-bracket th {
  font-family:    var(--font);
  font-size:      13px;
  color:          var(--text-dim);
  letter-spacing: 0.08em;
  text-align:     left;
  padding:        4px 10px;
  border-bottom:  1px solid var(--border-mid);
}

.tlob-ko-bracket td {
  font-family: var(--font);
  font-size:   15px;
  padding:     6px 10px;
  border-bottom: 1px solid #111130;
}

.tlob-ko-bracket td.ko-id        { color: var(--snes-yellow); }
.tlob-ko-bracket td.ko-round     { color: var(--text-dim); font-size: 13px; }
.tlob-ko-bracket td.ko-win       { color: var(--snes-green); }
.tlob-ko-bracket td.ko-loss      { color: var(--snes-red); }
.tlob-ko-bracket td.ko-pending   { color: #333358; }

/* Phase 2 actions strip */
.tlob-actions-phase2 {
  border-top:  1px solid var(--border-mid);
  padding-top: 8px;
}

/* ── 2P blind-submit waiting overlay ────────────────────────── */
.match-wait-overlay {
  position:        absolute;
  inset:           0;
  z-index:         300;
  background:      rgba(0, 0, 14, 0.82);
  display:         flex;
  align-items:     center;
  justify-content: center;
}

.match-wait-box {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  gap:            18px;
}

.match-wait-text {
  color:       var(--snes-cyan);
  font-family: var(--font-heading);
  font-size:   20px;
  letter-spacing: 1px;
}

.match-wait-spinner {
  width:  44px;
  height: 44px;
  border: 4px solid rgba(0, 255, 255, 0.18);
  border-top-color: var(--snes-cyan);
  border-radius: 50%;
  animation: match-spin 0.8s linear infinite;
}

@keyframes match-spin {
  to { transform: rotate(360deg); }
}

/* ── Group round waiting-for-opponent row state ──────────────── */
.lobby-round-waiting {
  display:     flex;
  align-items: center;
  gap:         8px;
}

.lobby-round-wait-msg {
  color:     var(--snes-cyan);
  font-size: 13px;
}

.lobby-round-spinner {
  width:  16px;
  height: 16px;
  flex-shrink: 0;
  border: 2px solid rgba(0, 255, 255, 0.2);
  border-top-color: var(--snes-cyan);
  border-radius: 50%;
  animation: match-spin 0.8s linear infinite;
}

/* ══════════════════════════════════════════════════════════════════
   BATTLE LOBBY  —  Warm Parchment / Dark Wood Aesthetic
══════════════════════════════════════════════════════════════════ */

/* ── Base overlay backdrop ────────────────────────────────────── */
.bl-backdrop {
  display:         none;
  position:        fixed;
  inset:           0;
  background:      rgba(0, 0, 0, 0.82);
  z-index:         9100;
  align-items:     center;
  justify-content: center;
}
.bl-backdrop.visible { display: flex; }

/* ── Dialog panel — dark wood with SNES double-border ─────────── */
.bl-dialog {
  position:      relative;
  background:
    radial-gradient(ellipse at 88% 94%, rgba(90, 50, 6, 0.38) 0%, transparent 52%),
    radial-gradient(ellipse at 10% 8%,  rgba(120, 82, 22, 0.18) 0%, transparent 44%),
    linear-gradient(158deg, #2c1a08 0%, #1e1106 35%, #261608 65%, #1a0e04 100%);
  box-shadow:
    0 0 0 2px #1a0e04,
    0 0 0 5px rgba(200, 160, 32, 0.82),
    0 0 0 7px #7a5800,
    0 0 0 10px #2e1800,
    0 16px 56px rgba(0, 0, 0, 0.88);
  border:        none;
  border-radius: 3px;
  padding:       30px 34px 26px;
  min-width:     300px;
  max-width:     480px;
  width:         90%;
  color:         #f0e0b0;
  font-family:   'CTGalbite', monospace;
}

/* Inner accent hairline */
.bl-dialog::before {
  content:        '';
  position:       absolute;
  inset:          8px;
  border:         1px solid rgba(248, 208, 0, 0.22);
  pointer-events: none;
  z-index:        0;
}

.bl-dialog-title {
  font-family:    'CTGalbite', monospace;
  font-size:      1.3rem;
  color:          #f8d000;
  text-align:     center;
  margin-bottom:  22px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-shadow:    2px 2px 0 rgba(60, 30, 0, 0.9), 0 0 10px rgba(248, 208, 0, 0.28);
  position:       relative;
  z-index:        1;
}

/* Gold rule beneath title */
.bl-dialog-title::after {
  content:    '';
  display:    block;
  width:      68%;
  height:     1px;
  margin:     8px auto 0;
  background: linear-gradient(90deg,
    transparent, rgba(200, 160, 32, 0.45) 20%,
    #f0c840 50%, rgba(200, 160, 32, 0.45) 80%, transparent
  );
}

.bl-field {
  margin-bottom: 14px;
  position:      relative;
  z-index:       1;
}

.bl-label {
  display:        block;
  font-family:    'CTGalbite', monospace;
  font-size:      0.7rem;
  color:          #c8a060;
  margin-bottom:  5px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
}

.bl-input {
  width:         100%;
  background:    rgba(8, 4, 0, 0.72);
  border:        2px solid rgba(150, 100, 28, 0.55);
  border-radius: 2px;
  color:         #f0e0b0;
  font-family:   'CTGalbite', monospace;
  font-size:     0.95rem;
  padding:       9px 11px;
  box-sizing:    border-box;
  outline:       none;
  transition:    border-color 0.15s;
}
.bl-input:focus        { border-color: rgba(248, 208, 0, 0.62); }
.bl-input-mono         { letter-spacing: 0.14em; font-size: 1.05rem; }
.bl-input::placeholder { color: rgba(200, 160, 60, 0.32); }

.bl-error {
  font-family:   'CTGalbite', monospace;
  color:         #e06060;
  font-size:     0.72rem;
  min-height:    18px;
  margin-bottom: 8px;
  text-align:    center;
  text-shadow:   0 1px 3px rgba(0, 0, 0, 0.8);
  position:      relative;
  z-index:       1;
}

.bl-actions {
  display:         flex;
  gap:             10px;
  justify-content: center;
  margin-top:      18px;
  flex-wrap:       wrap;
  position:        relative;
  z-index:         1;
}

.bl-body-text {
  font-family:   'CTGalbite', monospace;
  color:         #d0b880;
  text-align:    center;
  font-size:     0.82rem;
  line-height:   1.75;
  margin-bottom: 4px;
  position:      relative;
  z-index:       1;
}

/* ── All buttons within Battle Lobby — gold-bordered dark style ── */
.bl-backdrop .btn-snes {
  font-family:    'CTGalbite', monospace !important;
  font-size:      13px !important;
  letter-spacing: 0.07em !important;
  text-transform: uppercase !important;
  padding:        10px 20px !important;
  cursor:         pointer !important;
  background:     rgba(20, 10, 2, 0.88) !important;
  border:         2px solid rgba(200, 160, 32, 0.72) !important;
  color:          #e8c060 !important;
  text-shadow:    1px 1px 0 #000 !important;
  box-shadow:     0 4px 0 rgba(80, 40, 0, 0.68), 0 5px 0 rgba(0, 0, 0, 0.5) !important;
  border-radius:  2px !important;
  transition:     background 0.08s, border-color 0.08s, color 0.08s,
                  transform 0.06s, box-shadow 0.06s !important;
  line-height:    1.2 !important;
  white-space:    nowrap !important;
}
.bl-backdrop .btn-snes:hover {
  background:   rgba(38, 18, 4, 0.96) !important;
  border-color: #f0c840 !important;
  color:        #f8d000 !important;
  text-shadow:  0 0 8px rgba(248, 208, 0, 0.38), 1px 1px 0 #000 !important;
}
.bl-backdrop .btn-snes:active {
  transform:  translateY(4px) !important;
  box-shadow: 0 0 0 rgba(80, 40, 0, 0.68), 0 1px 0 rgba(0, 0, 0, 0.5) !important;
}
.bl-backdrop .btn-snes:disabled {
  opacity: 0.4 !important;
  cursor:  not-allowed !important;
  transform: none !important;
  box-shadow: none !important;
}

/* ── Mode select ──────────────────────────────────────────────── */
.bl-mode-dialog { max-width: 420px; }

.bl-mode-options {
  display:        flex;
  flex-direction: column;
  gap:            10px;
  margin-bottom:  8px;
  position:       relative;
  z-index:        1;
}

.bl-mode-btn {
  display:        flex !important;
  flex-direction: column !important;
  align-items:    flex-start !important;
  padding:        14px 18px !important;
  width:          100%;
  text-align:     left;
  white-space:    normal !important;
  height:         auto !important;
  line-height:    1.4 !important;
  background:     linear-gradient(158deg, rgba(55, 32, 8, 0.72) 0%, rgba(32, 16, 4, 0.85) 100%) !important;
  border:         2px solid rgba(200, 160, 32, 0.52) !important;
}
.bl-mode-btn:hover {
  background:   linear-gradient(158deg, rgba(75, 44, 10, 0.88) 0%, rgba(48, 24, 6, 0.96) 100%) !important;
  border-color: #f0c840 !important;
}

.bl-mode-label {
  font-family:    'CTGalbite', monospace !important;
  font-size:      0.95rem !important;
  color:          #f8d000 !important;
  text-shadow:    1px 1px 0 rgba(0, 0, 0, 0.85) !important;
  display:        block;
  letter-spacing: 0.06em !important;
  box-shadow:     none !important;
}

.bl-mode-desc {
  font-family:    'CTGalbite', monospace;
  font-size:      0.66rem;
  color:          #c8a060;
  margin-top:     5px;
  display:        block;
  opacity:        0.85;
  letter-spacing: 0.03em;
}

/* ── Tournament menu ──────────────────────────────────────────── */
.bl-tournament-options {
  display:        flex;
  flex-direction: column;
  gap:            10px;
  margin-bottom:  4px;
  position:       relative;
  z-index:        1;
}

.bl-tourn-btn { width: 100%; }

.bl-load-row {
  display:     flex;
  gap:         8px;
  align-items: center;
  position:    relative;
  z-index:     1;
}
.bl-load-row .bl-input { flex: 1; }

/* ── Teacher Versus Lobby ─────────────────────────────────────── */
.vt-backdrop {
  align-items: flex-start;
  padding:     32px 16px 24px;
  overflow-y:  auto;
}

.vt-dialog {
  position:      relative;
  background:
    radial-gradient(ellipse at 88% 98%, rgba(90, 50, 6, 0.30) 0%, transparent 55%),
    radial-gradient(ellipse at 8%  4%,  rgba(120, 82, 22, 0.14) 0%, transparent 46%),
    linear-gradient(158deg, #2c1a08 0%, #1e1106 35%, #261608 65%, #1a0e04 100%);
  box-shadow:
    0 0 0 2px #1a0e04,
    0 0 0 5px rgba(200, 160, 32, 0.78),
    0 0 0 7px #7a5800,
    0 0 0 10px #2e1800,
    0 16px 56px rgba(0, 0, 0, 0.88);
  border:        none;
  border-radius: 3px;
  padding:       20px 24px 24px;
  width:         100%;
  max-width:     820px;
  color:         #f0e0b0;
  font-family:   'CTGalbite', monospace;
}

/* Inner accent hairline */
.vt-dialog::before {
  content:        '';
  position:       absolute;
  inset:          8px;
  border:         1px solid rgba(248, 208, 0, 0.18);
  pointer-events: none;
  z-index:        0;
}

.vt-header {
  display:        flex;
  align-items:    center;
  gap:            14px;
  margin-bottom:  16px;
  flex-wrap:      wrap;
  position:       relative;
  z-index:        1;
  padding-bottom: 12px;
  border-bottom:  1px solid rgba(200, 160, 32, 0.28);
}

.vt-title {
  font-family:    'CTGalbite', monospace;
  font-size:      1.2rem;
  color:          #f8d000;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-shadow:    2px 2px 0 rgba(60, 30, 0, 0.9), 0 0 10px rgba(248, 208, 0, 0.25);
}

.vt-code-wrap {
  font-family:    'CTGalbite', monospace;
  font-size:      0.8rem;
  color:          #c8a060;
  letter-spacing: 0.04em;
}
.vt-code-wrap strong {
  font-family:    'CTGalbite', monospace;
  color:          #f8d000;
  font-size:      1.35rem;
  letter-spacing: 0.2em;
  text-shadow:    0 0 10px rgba(248, 208, 0, 0.45), 1px 1px 0 rgba(0, 0, 0, 0.85);
}

.vt-student-count {
  font-family:    'CTGalbite', monospace;
  font-size:      0.7rem;
  color:          #a08050;
  margin-left:    auto;
  letter-spacing: 0.04em;
}

.vt-close-hdr { flex-shrink: 0; }

.vt-panels {
  display:       flex;
  gap:           14px;
  margin-bottom: 14px;
  position:      relative;
  z-index:       1;
}

.vt-panel {
  flex:          1;
  background:    rgba(8, 4, 0, 0.62);
  border:        2px solid rgba(200, 160, 32, 0.38);
  border-radius: 2px;
  padding:       12px;
  min-height:    160px;
  max-height:    340px;
  overflow-y:    auto;
  box-shadow:    inset 0 0 24px rgba(0, 0, 0, 0.45);
}

.vt-panel-title {
  font-family:    'CTGalbite', monospace;
  font-size:      0.7rem;
  color:          #f8d000;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom:  8px;
  padding-bottom: 7px;
  border-bottom:  1px solid rgba(200, 160, 32, 0.32);
  text-shadow:    1px 1px 0 rgba(0, 0, 0, 0.8);
}

.vt-list {
  display:        flex;
  flex-direction: column;
  gap:            4px;
}

.vt-empty {
  font-family:  'CTGalbite', monospace;
  color:        #7a5830;
  font-size:    0.72rem;
  font-style:   italic;
  text-align:   center;
  padding:      18px 0;
}

/* Waiting-room student rows */
.vt-student-row {
  display:       flex;
  align-items:   center;
  gap:           8px;
  padding:       6px 10px;
  background:    rgba(30, 14, 2, 0.52);
  border-top:    1px solid rgba(200, 160, 32, 0.18);
  border-bottom: 1px solid rgba(0, 0, 0, 0.45);
}

.vt-student-id {
  font-family:    'CTGalbite', monospace;
  font-size:      0.88rem;
  color:          #f0e0b0;
  min-width:      36px;
  letter-spacing: 0.06em;
}

.vt-lock-badge {
  font-family:    'CTGalbite', monospace;
  font-size:      0.6rem;
  color:          #7a5030;
  background:     rgba(18, 8, 0, 0.55);
  border:         1px solid rgba(120, 78, 18, 0.38);
  border-radius:  2px;
  padding:        2px 6px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.vt-lock-badge.locked {
  color:        #6dcc6d;
  background:   rgba(8, 20, 8, 0.6);
  border-color: rgba(80, 160, 80, 0.42);
}

/* Matchup rows */
.vt-matchup-row {
  display:       flex;
  align-items:   center;
  gap:           8px;
  padding:       6px 10px;
  background:    rgba(30, 14, 2, 0.52);
  border-top:    1px solid rgba(200, 160, 32, 0.18);
  border-bottom: 1px solid rgba(0, 0, 0, 0.45);
}

.vt-mp-player {
  flex:           1;
  font-family:    'CTGalbite', monospace;
  font-size:      0.82rem;
  color:          #f0e0b0;
  text-align:     center;
  letter-spacing: 0.06em;
}

.vt-mp-vs {
  font-family:    'CTGalbite', monospace;
  font-size:      0.62rem;
  color:          #7a5030;
  text-transform: uppercase;
  flex-shrink:    0;
}

.vt-boot-btn {
  font-size:  0.58rem !important;
  padding:    3px 8px !important;
  flex-shrink: 0;
  box-shadow: none !important;
}

/* Teacher controls */
.vt-controls {
  display:         flex;
  gap:             10px;
  justify-content: center;
  flex-wrap:       wrap;
  position:        relative;
  z-index:         1;
}

/* Ready button — warm green accent override */
.bl-backdrop .vt-ready-btn {
  background:   rgba(10, 26, 10, 0.88) !important;
  border-color: rgba(80, 160, 80, 0.62) !important;
  color:        #6dcc6d !important;
}
.bl-backdrop .vt-ready-btn:not(:disabled):hover {
  background:   rgba(18, 42, 18, 0.96) !important;
  border-color: #80e880 !important;
  color:        #90ee90 !important;
  text-shadow:  0 0 8px rgba(100, 200, 100, 0.35), 1px 1px 0 #000 !important;
}
.bl-backdrop .vt-ready-btn:disabled {
  background:   rgba(6, 14, 6, 0.7) !important;
  border-color: rgba(45, 88, 45, 0.38) !important;
  color:        #4a7a4a !important;
  opacity:      0.55 !important;
  cursor:       not-allowed !important;
  box-shadow:   none !important;
}

/* Inline countdown (teacher) */
.vt-countdown-wrap {
  display:         none;
  flex-direction:  column;
  align-items:     center;
  margin-top:      16px;
  padding:         18px;
  background:      rgba(8, 4, 0, 0.72);
  border:          2px solid rgba(200, 160, 32, 0.52);
  box-shadow:      inset 0 0 0 1px rgba(248, 208, 0, 0.14);
  border-radius:   2px;
  position:        relative;
  z-index:         1;
}
.vt-countdown-wrap.visible { display: flex; }

.vt-countdown-label {
  font-family:    'CTGalbite', monospace;
  font-size:      0.72rem;
  color:          #c8a060;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom:  10px;
}

.vt-countdown-num {
  font-family:  'CTGalbite', monospace;
  font-size:    3.5rem;
  color:        #f8d000;
  line-height:  1;
  text-shadow:  2px 3px 0 rgba(60, 30, 0, 0.9), 0 0 18px rgba(248, 208, 0, 0.45);
}

/* ── Student fullscreen overlays ──────────────────────────────── */
.bl-fullscreen-overlay {
  display:         none;
  position:        fixed;
  inset:           0;
  background:
    repeating-linear-gradient(
      90deg,
      rgba(80, 40, 0, 0.07) 0px, rgba(80, 40, 0, 0.07) 1px,
      transparent            1px, transparent            9px
    ),
    repeating-linear-gradient(
      0deg,
      rgba(0, 0, 0, 0.06)  0px, rgba(0, 0, 0, 0.06)  1px,
      transparent           1px, transparent           13px
    ),
    linear-gradient(168deg, #2c1a08 0%, #1e1106 35%, #261608 65%, #1a0e04 100%);
  z-index:         9200;
  align-items:     center;
  justify-content: center;
  flex-direction:  column;
}
.bl-fullscreen-overlay.visible { display: flex; }

.bl-fullscreen-box {
  position:      relative;
  text-align:    center;
  color:         #f0e0b0;
  padding:       44px 56px;
  background:
    radial-gradient(ellipse at 88% 95%, rgba(90, 50, 6, 0.38) 0%, transparent 54%),
    radial-gradient(ellipse at 10% 8%,  rgba(120, 82, 22, 0.18) 0%, transparent 44%),
    linear-gradient(158deg, #2c1a08 0%, #1e1106 35%, #261608 65%, #1a0e04 100%);
  box-shadow:
    0 0 0 2px #1a0e04,
    0 0 0 5px rgba(200, 160, 32, 0.72),
    0 0 0 7px #7a5800,
    0 0 0 10px #2e1800,
    0 16px 56px rgba(0, 0, 0, 0.88);
  border-radius: 3px;
  min-width:     300px;
}

/* Inner hairline */
.bl-fullscreen-box::before {
  content:        '';
  position:       absolute;
  inset:          8px;
  border:         1px solid rgba(248, 208, 0, 0.22);
  pointer-events: none;
}

.bl-fullscreen-title {
  font-family:    'CTGalbite', monospace;
  font-size:      1.8rem;
  color:          #f8d000;
  margin-bottom:  16px;
  letter-spacing: 0.08em;
  text-shadow:    2px 3px 0 rgba(60, 30, 0, 0.9), 0 0 16px rgba(248, 208, 0, 0.38);
  position:       relative;
}

.bl-fullscreen-body {
  font-family:   'CTGalbite', monospace;
  font-size:     0.88rem;
  color:         #d0b880;
  margin-bottom: 28px;
  line-height:   1.7;
  position:      relative;
}

.bl-countdown-label {
  font-family:    'CTGalbite', monospace;
  font-size:      0.78rem;
  color:          #c8a060;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom:  8px;
  position:       relative;
}

.bl-countdown-num {
  font-family:  'CTGalbite', monospace;
  font-size:    5.5rem;
  color:        #f8d000;
  line-height:  1;
  text-shadow:  3px 4px 0 rgba(60, 30, 0, 0.9), 0 0 40px rgba(248, 208, 0, 0.50);
  position:     relative;
}

/* Waiting spinner */
.bl-wait-spinner {
  width:            40px;
  height:           40px;
  border:           3px solid rgba(120, 78, 18, 0.45);
  border-top-color: #f8d000;
  border-radius:    50%;
  animation:        bl-spin 0.85s linear infinite;
  margin:           0 auto;
  position:         relative;
}
@keyframes bl-spin { to { transform: rotate(360deg); } }

/* ── Result screen: versus auto-return countdown ──────────────── */
.vs-result-return-wrap {
  display:        none;
  text-align:     center;
  margin-top:     14px;
  font-family:    'CTGalbite', monospace;
  color:          #a08050;
  font-size:      0.78rem;
  letter-spacing: 0.04em;
}
.vs-result-return-wrap.visible { display: block; }

/* ================================================================
   CARD UNLOCK PROGRESSION — Locked card styles
   ================================================================ */

.db-card-locked {
  filter: saturate(0.15) brightness(0.6);
  cursor: not-allowed;
}
.db-card-locked:hover {
  transform: none !important;
  border-color: transparent !important;
}
.db-card-lock-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 2;
  background: rgba(0, 0, 0, 0.35);
  border-radius: 6px;
}
.lock-icon {
  font-size: 28px;
  line-height: 1;
}

/* Grayscale popup for locked card preview */
.popup-locked .card-popup { filter: grayscale(1); }

/* ── Location chooser (India: Lord of the Beasts picks a destination). Same
   modal as the card chooser; the options are location names instead of faces. */
.chooser-loc-row { gap: 14px; }
.chooser-loc-btn {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  min-width: 150px; padding: 12px 16px;
  font-family: var(--font); text-transform: uppercase; letter-spacing: 0.05em;
  color: #f0cf6c; background: #2a1608; border: 3px solid #d4aa50; border-radius: 2px;
  cursor: pointer; text-shadow: 1px 1px 0 #000; box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000;
}
.chooser-loc-btn:hover { border-color: #f0cf6c; color: #fff5d8; }
.chooser-loc-name   { font-size: 16px; }
.chooser-loc-region { font-size: 11px; opacity: 0.8; text-transform: none; letter-spacing: 0; }


/* ══════════════════════════════════════════════════════════════════
   ABOUT SCREEN — "About the Game"
   Full-screen page linked from the home menu. Wood-and-parchment
   aesthetic to match the home/welcome modal palette.
══════════════════════════════════════════════════════════════════ */

#screen-about.active {
  display: flex;
  flex-direction: column;
  position: absolute;
  inset: 0;
  /* Same wood-grain backdrop as the home screen */
  background:
    repeating-linear-gradient(
      0deg,
      transparent 0px, transparent 7px,
      rgba(0,0,0,0.07) 7px, rgba(0,0,0,0.07) 8px
    ),
    repeating-linear-gradient(
      0deg,
      transparent             0px,  transparent             38px,
      rgba(255,255,255,0.045) 38px, rgba(255,255,255,0.045) 42px,
      transparent             42px, transparent             78px,
      rgba(0,0,0,0.07)        78px, rgba(0,0,0,0.07)        82px
    ),
    linear-gradient(180deg,
      #6e3e1a 0%,
      #885028 18%,
      #7a4822 36%,
      #8e5a2e 54%,
      #7a4822 72%,
      #885028 90%,
      #6e3e1a 100%
    );
}

/* Sticky header — Back button stays reachable while scrolling */
.about-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 22px;
  background: linear-gradient(
    180deg,
    rgba(20, 10, 2, 0.92) 0%,
    rgba(20, 10, 2, 0.78) 100%
  );
  border-bottom: 1px solid rgba(212, 170, 80, 0.45);
  flex-shrink: 0;
}
.about-header-title {
  flex: 1;
  text-align: center;
  font-family: var(--font);
  font-size: 18px;
  letter-spacing: 0.18em;
  color: rgba(232, 192, 96, 0.85);
  text-transform: uppercase;
  text-shadow: 1px 1px 0 #000;
}
.about-header-spacer {
  /* Mirrors the back button's footprint so the title stays optically centered */
  width: 96px;
  flex-shrink: 0;
}

/* Scrolling content region */
.about-main {
  flex: 1;
  overflow-y: auto;
  padding: 36px 24px 60px;
  /* Keep custom scrollbar consistent with deck builder */
  scrollbar-width: thin;
  scrollbar-color: rgba(160, 110, 30, 0.60) rgba(20, 10, 2, 0.80);
}
.about-main::-webkit-scrollbar       { width: 8px; }
.about-main::-webkit-scrollbar-track { background: rgba(20, 10, 2, 0.80); }
.about-main::-webkit-scrollbar-thumb {
  background: rgba(160, 110, 30, 0.60);
  border: 1px solid rgba(100, 65, 10, 0.40);
}
.about-main::-webkit-scrollbar-thumb:hover { background: rgba(200, 150, 40, 0.80); }

/* Centred parchment-inside-wood content panel */
.about-content {
  max-width: 760px;
  margin: 0 auto;
  padding: 38px 44px 36px;
  background:
    radial-gradient(ellipse at 94% 92%, rgba(100, 65, 10, 0.28) 0%, transparent 52%),
    radial-gradient(ellipse at 8%  10%, rgba(140, 100, 30, 0.18) 0%, transparent 40%),
    linear-gradient(180deg,
      rgba(28, 14, 4, 0.94) 0%,
      rgba(38, 22, 10, 0.94) 50%,
      rgba(28, 14, 4, 0.94) 100%
    );
  border: 3px solid #d4aa50;
  box-shadow:
    0 0 0 3px #1a0c04,
    0 0 0 6px #6a4418,
    0 0 0 7px #1a0c04,
    inset 0 0 36px rgba(60, 30, 0, 0.50);
}

/* Page title — largest element, warm gold with chunky pixel outline */
.about-title {
  font-family: var(--font);
  font-size: 48px;
  color: #e8c060;
  text-align: center;
  letter-spacing: 0.05em;
  line-height: 1.15;
  margin: 0;
  font-weight: normal;
  text-shadow:
    3px 3px 0 #000,
    -2px -2px 0 #000,
    3px -2px 0 #000,
    -2px 3px 0 #000,
    0 0 12px rgba(220, 170, 60, 0.30);
}
.about-title-italic {
  font-style: italic;
}

/* Bronze divider beneath the title */
.about-title-divider {
  height: 2px;
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(180, 130, 40, 0.55) 18%,
    #d4aa50 50%,
    rgba(180, 130, 40, 0.55) 82%,
    transparent 100%
  );
  margin: 18px auto 32px;
}

/* Section blocks */
.about-section {
  margin-bottom: 30px;
}
.about-section:last-of-type {
  margin-bottom: 18px;
}

/* Section headings — same treatment for every section */
.about-section-heading {
  font-family: var(--font);
  font-size: 28px;
  color: #e8c060;
  letter-spacing: 0.06em;
  margin: 0 0 14px;
  font-weight: normal;
  text-shadow: 2px 2px 0 #000;
  border-bottom: 1px solid rgba(212, 170, 80, 0.32);
  padding-bottom: 6px;
}

/* Body copy */
.about-section p {
  font-family: var(--font);
  font-size: 18px;
  color: #f3e6c4;
  line-height: 1.6;
  margin: 0 0 14px;
  text-shadow: 1px 1px 0 #000;
}
.about-section p:last-child {
  margin-bottom: 0;
}

/* Italicized game title (inline) */
.about-italic {
  font-style: italic;
  color: #e8c060;
}

/* Newton quote — italic, slightly lighter gold so it stands apart from the .about-italic accent */
.about-quote {
  font-style: italic;
  color: #f0d8a0;
}

/* Email + external links */
.about-link {
  color: #f4d678;
  text-decoration: none;
  border-bottom: 1px dashed rgba(244, 214, 120, 0.55);
  transition: color 0.12s, border-bottom-color 0.12s;
}
.about-link:hover {
  color: #fff5d8;
  border-bottom-color: #fff5d8;
}

/* Acknowledgments list — diamond bullets in bronze, bolded labels in gold */
.about-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.about-list li {
  font-family: var(--font);
  font-size: 18px;
  color: #f3e6c4;
  line-height: 1.55;
  margin: 0 0 16px;
  padding-left: 22px;
  position: relative;
  text-shadow: 1px 1px 0 #000;
}
.about-list li:last-child { margin-bottom: 0; }
.about-list li::before {
  content: '\25C6';                  /* ◆ diamond */
  position: absolute;
  left: 0;
  top: 0;
  color: #d4aa50;
  font-size: 14px;
  line-height: 1.85;
}
.about-list strong {
  color: #e8c060;
  font-weight: normal;               /* CTGalbite is already chunky */
  letter-spacing: 0.02em;
}

/* Footer — de-emphasized build info */
.about-footer {
  margin-top: 36px;
  padding-top: 18px;
  border-top: 1px solid rgba(212, 170, 80, 0.22);
  text-align: center;
  font-family: var(--font);
  font-size: 14px;
  color: rgba(243, 230, 196, 0.55);
  text-shadow: 1px 1px 0 #000;
  letter-spacing: 0.05em;
}


/* ══════════════════════════════════════════════════════════════════
   MULTIPLAYER (student-join) POPUP — unified with home button system
   Scoped to #vs-join-backdrop only, so the other .bl-dialog popups
   (password prompt, teacher lobby, mode select, etc.) keep their
   existing look.
══════════════════════════════════════════════════════════════════ */

/* Sepia-tinted backdrop matching the rest of the history-themed UI */
#vs-join-backdrop {
  background: rgba(20, 10, 2, 0.82);
}

/* Single 3px gold border — drops the SNES double-border ring stack */
#vs-join-backdrop .bl-dialog {
  background:
    repeating-linear-gradient(
      0deg,
      transparent 0px, transparent 6px,
      rgba(0, 0, 0, 0.10) 6px, rgba(0, 0, 0, 0.10) 7px
    ),
    linear-gradient(180deg,
      #2a1608 0%,
      #3a200c 50%,
      #2a1608 100%
    );
  border: 3px solid #d4aa50;
  border-radius: 2px;
  box-shadow:
    0 8px 28px rgba(0, 0, 0, 0.75),
    inset 0 0 28px rgba(60, 30, 0, 0.55);
  padding: 32px 36px 28px;
  max-width: 460px;
  width: 90%;
  color: #f3e6c4;
}

/* Remove the inner hairline frame (the second border) */
#vs-join-backdrop .bl-dialog::before {
  content: none;
}

/* Title — large warm gold, matches home screen treatment */
#vs-join-backdrop .bl-dialog-title {
  font-family: 'CTGalbite', monospace;
  font-size: 32px;
  color: #e8c060;
  letter-spacing: 0.06em;
  margin-bottom: 24px;
  text-shadow:
    2px 2px 0 #000,
   -1px -1px 0 #000,
    2px -1px 0 #000,
   -1px 2px 0 #000,
    0 0 10px rgba(220, 170, 60, 0.30);
}
/* Bronze rule beneath title (replaces the dim gold gradient) */
#vs-join-backdrop .bl-dialog-title::after {
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(180, 130, 40, 0.65) 18%,
    #d4aa50 50%,
    rgba(180, 130, 40, 0.65) 82%,
    transparent 100%
  );
}

/* Field spacing — give labels and inputs room to breathe */
#vs-join-backdrop .bl-field {
  margin-bottom: 18px;
}

/* Labels — bigger, gold, CTGalbite */
#vs-join-backdrop .bl-label {
  font-family: 'CTGalbite', monospace;
  font-size: 14px;
  color: #e8c060;
  letter-spacing: 0.10em;
  margin-bottom: 8px;
  text-shadow: 1px 1px 0 #000;
}

/* Inputs — larger, gold border, cream text, CTGalbite */
#vs-join-backdrop .bl-input {
  background: rgba(20, 10, 2, 0.85);
  border: 2px solid rgba(212, 170, 80, 0.55);
  border-radius: 2px;
  color: #f3e6c4;
  font-family: 'CTGalbite', monospace;
  font-size: 22px;
  padding: 12px 14px;
  letter-spacing: 0.06em;
  text-shadow: 1px 1px 0 #000;
}
#vs-join-backdrop .bl-input:focus {
  border-color: #d4aa50;
  background: rgba(30, 16, 4, 0.95);
}
#vs-join-backdrop .bl-input-mono {
  font-size: 26px;
  letter-spacing: 0.18em;
}
/* Placeholder — clearly distinguishable as placeholder, not real input */
#vs-join-backdrop .bl-input::placeholder {
  color: rgba(243, 230, 196, 0.30);
  font-style: italic;
  letter-spacing: 0.10em;
}

/* Error text — warm red that still fits the parchment palette */
#vs-join-backdrop .bl-error {
  font-family: 'CTGalbite', monospace;
  color: #e85a3a;
  font-size: 13px;
  letter-spacing: 0.06em;
  min-height: 18px;
  margin-bottom: 8px;
}

/* Action row — slightly more breathing room above the buttons */
#vs-join-backdrop .bl-actions {
  margin-top: 20px;
  gap: 12px;
}

/* ── Buttons match home-screen unified button family ─────────────
   Both buttons share gold border, CTGalbite font, gold text, and
   the same raised SNES edge as the home buttons. JOIN LOBBY uses
   the teal Multiplayer fill; CANCEL stays neutral dark like About. */
#vs-join-backdrop .btn-snes {
  font-family: 'CTGalbite', monospace !important;
  font-size: 18px !important;
  padding: 10px 28px !important;
  letter-spacing: 0.06em !important;
  text-transform: uppercase !important;
  border: 3px solid #d4aa50 !important;
  border-radius: 2px !important;
  color: #f0cf6c !important;
  text-shadow:
    1px 1px 0 #000,
   -1px -1px 0 #000,
    1px -1px 0 #000,
   -1px 1px 0 #000 !important;
  box-shadow: 0 4px 0 #1a0c04, 0 5px 0 #000 !important;
  cursor: pointer !important;
  transition: background 0.15s, border-color 0.15s, color 0.15s,
              box-shadow 0.15s, transform 0.06s !important;
}

/* JOIN LOBBY (form submit) — saturated teal, mirrors Multiplayer home button */
#vs-join-backdrop button[type="submit"] {
  background: linear-gradient(180deg, #1e7a8a 0%, #135060 100%) !important;
}
#vs-join-backdrop button[type="submit"]:hover {
  background: linear-gradient(180deg, #2a9aa8 0%, #1c6878 100%) !important;
  border-color: #f0cf6c !important;
  color: #fff5d8 !important;
  box-shadow:
    0 4px 0 #1a0c04,
    0 5px 0 #000,
    0 0 14px rgba(240, 207, 108, 0.35) !important;
}

/* CANCEL — neutral dark, mirrors About home button */
#vs-join-backdrop #vs-join-cancel {
  background: #2a1608 !important;
}
#vs-join-backdrop #vs-join-cancel:hover {
  background: #3a200c !important;
  border-color: #f0cf6c !important;
  color: #fff5d8 !important;
  box-shadow:
    0 4px 0 #1a0c04,
    0 5px 0 #000,
    0 0 14px rgba(240, 207, 108, 0.35) !important;
}

/* Shared press state */
#vs-join-backdrop .btn-snes:active {
  transform: translateY(4px) !important;
  box-shadow: 0 0 0 #1a0c04, 0 1px 0 #000 !important;
}

/* ================================================================
   HOME SCREEN — multi-state entry flow
   ================================================================ */

/* Uniform home-screen button size. Matched to the largest existing
   button (I'm Ready: 38px font, 14/64 padding). Every home button
   uses the same width + min-height so all states feel consistent. */
.btn-home-uniform {
  min-width: 360px;
  font-size: 30px;
  padding: 16px 40px;
  letter-spacing: 0.06em;
  line-height: 1.1;
  box-sizing: border-box;
}

/* Path-choice trio (State 2) — share the gold-border / parchment family
   from the State 1 rules above; only the fill differs per button. */

/* "Arcadium" — saturated royal purple (gameplay path) */
.btn-home-arcadium {
  background: linear-gradient(180deg, #7a3aab 0%, #5e2890 100%);
}
.btn-home-arcadium:hover {
  background: linear-gradient(180deg, #9450c8 0%, #6e34a8 100%);
}

/* "Adventure" — earthy forest green (exploration path) */
.btn-home-adventure-new {
  background: linear-gradient(180deg, #4a8540 0%, #2c5224 100%);
}
.btn-home-adventure-new:hover {
  background: linear-gradient(180deg, #5ca050 0%, #3c6a30 100%);
}


/* ── Adventure in-development warning popup ──────────────────────
   Reuses .popup-backdrop + .card-popup; just widens the body text
   and adds breathing room between the two action buttons.          */
.adv-dev-warning-popup {
  max-width: 480px;
}
.adv-dev-warning-body {
  text-align: center;
  line-height: 1.6;
  padding: 4px 8px 8px;
}
.adv-dev-warning-actions {
  display: flex;
  gap: 16px;
  justify-content: center;
}

/* Path-choice buttons start hidden; JS toggles .btn-visible to show them.
   Using class toggle (not inline `display:''`) so the CSS fallback stays
   correct. */
#btn-arcadium,
#btn-adventure-new,
#btn-versus { display: none; }
#btn-arcadium.btn-visible,
#btn-adventure-new.btn-visible,
#btn-versus.btn-visible { display: block; }

/* Subtitle stack — both subtitles live in the same slot and crossfade.
   Fixed wide width + white-space:nowrap keeps the text on one line. */
.home-subtitle-stack {
  position: relative;
  width: 100%;
  max-width: 900px;
  height: 48px;
  margin: 28px auto 32px;
  text-align: center;
}
.home-subtitle {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  font-family: 'CT Galbite', monospace;
  font-size: 28px;
  color: #ffffff;
  letter-spacing: 0.04em;
  text-shadow: 0 2px 6px rgba(0, 0, 0, 0.85);
  opacity: 0;
  transition: opacity 0.3s ease;
}
.home-subtitle.is-visible { opacity: 1; }

/* ── Adventurer selection stage ─────────────────────────── */
#home-adventure-stage {
  position: absolute;
  inset: 0;
  display: none;
  z-index: 20;
}
#home-adventure-stage.active { display: block; }

.home-adventure-back {
  position: absolute;
  top: 20px;
  left: 20px;
  font-family: 'CT Galbite', monospace;
  font-size: 36px;
  background: rgba(0, 0, 0, 0.35);
  color: #ffe39a;
  border: 2px solid rgba(255, 227, 154, 0.6);
  border-radius: 4px;
  padding: 4px 14px;
  cursor: pointer;
  opacity: 0.8;
  transition: opacity 0.15s, background 0.15s;
  z-index: 30;
}
.home-adventure-back:hover { opacity: 1; background: rgba(0, 0, 0, 0.55); }

/* home-subtitle-adventurer inherits all styles from .home-subtitle
   so it sits in the same slot as "Choose your path" */

/* Adventurer sprites — match overworld size (84px wide, pixel art). */
.home-adventurer {
  position: absolute;
  bottom: 15%;
  width: 84px;
  height: auto;
  image-rendering: pixelated;
  user-select: none;
  pointer-events: auto;
  cursor: pointer;
  opacity: 0;
  transform: translate(-50%, 0);
  filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.6));
  z-index: 25;
}
.home-adventurer:hover { filter: drop-shadow(0 0 10px rgba(255, 215, 0, 0.7)); }

/* Secret-door rectangle and iris wipe overlay (used after character pick) */
#home-secret-door {
  position: absolute;
  background: #000;
  transform: translate(-50%, -50%);
  z-index: 40;
  display: none;
}
#home-secret-door.active { display: block; }

#home-iris-wipe {
  position: absolute;
  inset: 0;
  background: #000;
  z-index: 50;
  display: none;
  /* clip-path set via JS: circle(RADIUS at X% Y%) */
}
#home-iris-wipe.active { display: block; }

/* ================================================================
   ADVENTURE MODE — Overworld Map (East Africa regional map)
   ================================================================ */

#screen-overworld {
  background: #0a0a14;
  overflow: hidden;
}

/* Regional map image fills the screen. Natural proportions preserved
   via object-fit: cover (cropped if needed). */
#overworld-map {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  user-select: none;
  pointer-events: none;
  z-index: 0;
}

/* Full-screen fog — shown on first visit to Egypt / Mesopotamia,
   faded away with GSAP once the player arrives. */
#overworld-fog-full {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  pointer-events: none;
  z-index: 25;
  opacity: 0;
  visibility: hidden;
}
#overworld-fog-full.active {
  opacity: 1;
  visibility: visible;
}

/* Exit zones — clickable rectangles at map edges that travel to other maps */
.overworld-exit {
  position: absolute;
  cursor: pointer;
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px dashed rgba(255, 215, 0, 0);
  transition: border-color 0.2s ease, background 0.2s ease;
  z-index: 5000;   /* above the depth-sorted band (overworld.js _depthZ, ~400–2800) */
}
.overworld-exit:hover {
  border-color: rgba(255, 215, 0, 0.5);
  background: rgba(255, 215, 0, 0.06);
}
.overworld-exit-label {
  font-family: 'CT Galbite', monospace;
  font-size: 15px;
  color: #ffe39a;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.9);
  padding: 6px 12px;
  background: rgba(0, 0, 0, 0.55);
  border-radius: 3px;
  letter-spacing: 0.04em;
  opacity: 0;
  transition: opacity 0.2s ease;
  white-space: nowrap;
}
.overworld-exit:hover .overworld-exit-label { opacity: 1; }
/* Transient "flash" — reveal an exit box + label for a moment (e.g. 1.5s after
   an arrival dialogue) to point the player at the next exit, then fade back to
   hover-only. Mirrors the hover appearance; the label's 0.2s opacity transition
   gives it a gentle fade in/out. */
.overworld-exit--flash {
  border-color: rgba(255, 215, 0, 0.5);
  background: rgba(255, 215, 0, 0.06);
}
.overworld-exit--flash .overworld-exit-label { opacity: 1; }

/* Transition: full-screen black fade with 'Traveling...' text */
#overworld-transition {
  position: absolute;
  inset: 0;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
#overworld-transition-text {
  font-family: 'CT Galbite', monospace;
  font-size: 32px;
  color: #ffe39a;
  letter-spacing: 0.08em;
  text-shadow: 0 0 20px rgba(255, 215, 0, 0.4);
  opacity: 0;
}

/* Overlay layer for character + nodes. Sits above the fog on its
   visible side, but since fog reaches ~50% right, the node/character
   must live in the explored (left-bottom) region. */
#overworld-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 30;
}

/* Civilization node. A node STANDS on its point: left/top is the bottom-centre
   of its (trimmed) art — its base line — and it rotates and scales about that
   point. overworld.js sets the full transform (_nodeTransform) and its z-index
   (depth-sorted by that base line, _applyDepth). */
.overworld-node {
  position: absolute;
  transform: translate(-50%, -100%);
  transform-origin: 50% 100%;
  cursor: pointer;
  pointer-events: auto;
  user-select: none;
  text-align: center;
}
.overworld-node > img:not(.ow-cast-shadow):not(.ow-ground-rim) {
  width: 84px;
  /* SEATED: the visible base sits SINK_PX into the ground, not on the trim's
     transparent padding (--seat, node-local px, set by overworld.js). */
  translate: 0 var(--seat, 0px);
  height: auto;
  display: block;
  margin: 0 auto;
  /* Hover grows the art 8%, up from its base line (so the building never
     sinks into the ground). The `scale` property composes with any inline
     `transform` (flipX nodes set scaleX(-1)) instead of overwriting it. */
  scale: 1;
  transform-origin: 50% 100%;
  transition: scale 120ms ease-out;
}
.overworld-node:hover > img:not(.ow-cast-shadow):not(.ow-ground-rim) { scale: 1.08; }
/* The gold pulse marks ONLY the player's next objective (overworld.js
   _refreshObjectiveGlow) — never a beaten node or a market. */
.overworld-node.is-objective > img:not(.ow-cast-shadow):not(.ow-ground-rim) {
  animation: overworld-node-pulse 2.2s ease-in-out infinite;
}
[data-id="egypt-signpost"] > img:not(.ow-cast-shadow):not(.ow-ground-rim) { width: 126px; }

/* ── Boss-node tier flags + victory stamps (flag/stamp progression) ──────────
   Two flags per boss node (Serf + Giant) are planted BEHIND the node and fan out
   from behind it — pole bases occluded by the node (z-index below it), banners
   sticking out; beating a tier stamps that tier's flag (tracked independently).
   The cluster is a 0-size anchor on the node's base line (JS positions it at the
   node's map %-coords + its flagNudge). The two poles are TUCKED IN BEHIND the
   art: overworld.js measures the node's trimmed art and sets --flag-spread and
   --flag-plant per node (FLAG_FIT — inset as a share of the art's width, feet
   raised just enough for the cloth to clear the roofline), so the building
   hides the pole feet and the banners fly above/beside it on narrow and wide
   art alike. The other by-eye knobs are the custom properties below.
   Art: images/ui_images/{serfflag,giantflag,victorystamp}.png (lowercase). */
.node-flags {
  /* ── EDITABLE KNOBS (tune by eye) ─────────────────────────────── */
  /* --flag-scale sizes the whole cluster (flags + stamps). overworld.js sets it
     per boss (FLAG_SCALE / FLAG_SCALE_BY_HOOK) so its pole maths uses the
     same number; this is only the fallback. */
  --flag-scale:     1.15;
  --flag-size:      calc(74px * var(--flag-scale));   /* GIANT flag's width */
  --flag-serf-size: calc(64px * var(--flag-scale));   /* SERF flag ~13% smaller than the Giant, so the two read apart at a glance */
  --flag-spread: 24px;    /* each POLE's distance from the node's centre line (JS sets it per node) */
  --flag-plant:  12px;    /* how far ABOVE the node's base line the pole feet stand (JS sets it per node) */
  --flag-tilt:   13deg;   /* outward fan angle of the two flags, about each pole's foot */
  /* Where the pole's FOOT is in each flag image (serf pole on the right of its
     banner, giant pole on the left) — art facts, not knobs. */
  --serf-pole-x:  73.8%;
  --giant-pole-x: 26.6%;
  --pole-foot-y:  88.7%;
  --stamp-size:      calc(22px * var(--flag-scale));   /* GIANT victory-stamp size */
  --stamp-serf-size: calc(19px * var(--flag-scale));   /* SERF stamp ~13% smaller, to match the smaller serf flag */
  --stamp-tilt:  30deg;   /* stamp lean, mirrored per tier (serf +, giant −); follows the banner */
  /* Per-tier stamp anchor WITHIN its flag: cx = horizontal % (←smaller = left),
     cy = vertical % from the top (↑bigger = lower). Serf/Giant fully independent. */
  --stamp-serf-cx:  45%;
  --stamp-serf-cy:  47%;
  --stamp-giant-cx: 55%;
  --stamp-giant-cy: 48%;
  /* Per-flag nudges — defaults 0, overridden PER NODE below. dx = horizontal (% of
     flag width, or px; − = left, + = right); dy = vertical (px; + = down);
     rot = extra rotation (− = CCW, + = CW). 1% of the map ≈ 12.8px across, 6px down. */
  --serf-dx:  0px;  --serf-dy:  0px;  --serf-rot:  0deg;
  --giant-dx: 0px;  --giant-dy: 0px;  --giant-rot: 0deg;
  /* ─────────────────────────────────────────────────────────────── */

  position: absolute;
  width: 0;
  height: 0;                       /* 0-size anchor point on the node's base line */
  /* z-index: set inline to one BEHIND its node (overworld.js _renderNodeFlags),
     so the node occludes the pole bases and the pair depth-sorts as one. */
  pointer-events: none;            /* flags never intercept node clicks */
}
.node-flag {
  position: absolute;
  left: 0;
  top: 0;                          /* both anchored at the cluster point */
  width: var(--flag-size);
  /* a small shadow under the overworld's one sun (front-left: falls up and
     to the right — SUN in overworld.js) */
  filter: drop-shadow(3px -2px 1px rgba(0, 0, 0, 0.4));
}
/* Each flag's POLE FOOT lands --flag-spread left/right of the node's centre line,
   --flag-plant above its base line, then the flag fans outward by --flag-tilt
   about that foot (serf left, giant right). */
.node-flag-serf {
  width: var(--flag-serf-size);    /* serf flag smaller than the giant (distinct at a glance) */
  transform-origin: var(--serf-pole-x) var(--pole-foot-y);
  transform: translate(calc(-1 * var(--serf-pole-x) - var(--flag-spread) + var(--serf-dx)), calc(-1 * var(--pole-foot-y) - var(--flag-plant) + var(--serf-dy))) rotate(calc(-1 * var(--flag-tilt) + var(--serf-rot)));
}
.node-flag-giant {
  transform-origin: var(--giant-pole-x) var(--pole-foot-y);
  transform: translate(calc(-1 * var(--giant-pole-x) + var(--flag-spread) + var(--giant-dx)), calc(-1 * var(--pole-foot-y) - var(--flag-plant) + var(--giant-dy))) rotate(calc(var(--flag-tilt) + var(--giant-rot)));
}

/* ── Per-node flag nudges (set the --*-dx / --*-rot vars above) ─────────────── */
.node-flags[data-hook="narmer"]    { --serf-dx: -1%; --serf-rot: -5deg; }  /* serf left 1%, 5° CCW */
.node-flags[data-hook="sargon"]    { --serf-dx: calc(-8% - 12.8px); }       /* serf left 8% + 1% of the map */
.node-flags[data-hook="hammurabi"] { --serf-dx: calc(-1% - 8px); --giant-dx: calc(1% + 8px); }  /* spread a little wider */
.node-flags[data-hook="hatshepsut"] { --giant-dx: 12.8px; --giant-dy: 6px; }  /* giant right 1% + down 1% of the map */
.node-flags[data-hook="ramses"]     { --serf-dx: -12.8px; --giant-dx: 12.8px; }  /* each 1% of the map wider */
.node-flag-img {
  display: block;
  width: 100%;
  height: auto;
  image-rendering: auto;           /* smooth, like every overworld sprite */
}
/* Common stamp props; per-tier anchor + lean set in the two rules below. The stamp
   already inherits the flag's fan-tilt as a child; --stamp-tilt is the extra lean.
   GSAP drives the thunk, settling to this same per-tier tilt (see _animatePendingStamp). */
.node-flag-stamp {
  position: absolute;
  width: var(--stamp-size);
  height: auto;
  pointer-events: none;
  image-rendering: auto;
}
.node-flag-serf .node-flag-stamp {
  width: var(--stamp-serf-size);   /* smaller serf stamp to match the smaller serf flag */
  left: var(--stamp-serf-cx);
  top:  var(--stamp-serf-cy);
  transform: translate(-50%, -50%) rotate(var(--stamp-tilt));
}
.node-flag-giant .node-flag-stamp {
  left: var(--stamp-giant-cx);
  top:  var(--stamp-giant-cy);
  transform: translate(-50%, -50%) rotate(calc(-1 * var(--stamp-tilt)));   /* mirror lean for the giant flag */
}
.ow-cast-shadow {
  position: absolute;
  left: 0;
  top: 0;
  height: auto;
  pointer-events: none;
  user-select: none;
}
/* GROUND rim: the art's own blurred silhouette over its base band (a plain
   image overworld.js builds once per art) — the "touching the ground" cue. */
.ow-ground-rim {
  position: absolute;
  left: 0;
  top: 0;
  height: auto;
  pointer-events: none;
  user-select: none;
}
/* Inside a node: behind its art, within the node's own stacking context —
   cast under rim under art — and seated with it (--seat). */
.overworld-node > .ow-cast-shadow { z-index: -2; translate: 0 var(--seat, 0px); }
.overworld-node > .ow-ground-rim  { z-index: -1; }
/* A prop's shadows sit in a sibling box with the prop's own size and transform. They
   and the Explorer's shadows lie on the GROUND (z 2), under everything that
   stands up — the depth-sorted band (overworld.js _depthZ) starts far above. */
.overworld-topo-prop-shadow { position: absolute; pointer-events: none; z-index: 2; }
#overworld-character-shadow { z-index: 2; }
#overworld-character-castshadow { width: 92px; transform-origin: 50% 100%; z-index: 2; }

/* Topography props (renamed from .egypt-topo-prop — props are per-map data now)
   are depth-sorted by their base line like nodes: z-index set inline by
   overworld.js _applyDepth. */
.overworld-node-label {
  font-family: 'CT Galbite', monospace;
  font-size: 16px;
  color: #ffe39a;
  text-shadow:
    0 0 6px rgba(0, 0, 0, 0.9),
    0 2px 4px rgba(0, 0, 0, 0.85);
  margin-top: 4px;
  letter-spacing: 0.04em;
  white-space: nowrap;
  /* Hidden by default; fades in on hover */
  opacity: 0;
  transition: opacity 0.2s ease;
}
.overworld-node:hover .overworld-node-label { opacity: 1; }
/* The hover NAME label. One element on #overworld-overlay, placed under the
   hovered node's art by overworld.js — not inside the node, where it would
   join the node's centred box (shifting its anchor) and inherit its scale and
   rotation (a 2× market would get 32 px text). */
.overworld-node-label.overworld-node-label--float {
  position: absolute;
  margin-top: 0;
  transform: translateX(-50%);
  pointer-events: none;
  z-index: 5100;   /* above the depth-sorted band and the exits */
  padding: 2px 8px;
  background: rgba(0, 0, 0, 0.55);
  border-radius: 3px;
}
.overworld-node-label.overworld-node-label--float.is-visible { opacity: 1; }

/* ── Otzi overworld sprite ───────────────────────────────────────
   Injected onto #overworld-overlay by JS when the encounter starts.
   Anchored at top-centre (same transform as the character/nodes). */
#overworld-otzi-sprite {
  position: absolute;
  width: 60px;
  height: auto;
  transform: translate(-50%, -100%);
  pointer-events: none;
  border-radius: 3px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.65);
  object-fit: cover;
}

@keyframes overworld-node-pulse {
  /* Gold halo with a thin WARM DARK rim under it: the rim gives the gold an
     edge to read against pale sand, where gold-on-yellow alone vanishes; on
     green it just reads as a crisper glow. (No dark silhouette shadow —
     grounding is the contact + cast shadows.) */
  0%, 100% {
    filter: drop-shadow(0 0 1px rgba(70, 35, 5, 0.55))
            drop-shadow(0 0 4px rgba(255, 205, 40, 0.35));
  }
  50% {
    filter: drop-shadow(0 0 1.5px rgba(70, 35, 5, 0.85))
            drop-shadow(0 0 9px rgba(255, 205, 40, 0.85))
            drop-shadow(0 0 18px rgba(255, 190, 30, 0.35));
  }
}
/* …and a soft gold GROUND RING round the objective's base, pulsing with it —
   readable on any ground colour because it carries its own dark outer edge.
   Inside the node (behind its art, like the ground shadow), so it is sized as
   a share of the art's width; line widths divide by --node-s (the node's
   scale, set by overworld.js) to stay ~2px on screen at any node size. */
.overworld-node.is-objective::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 100%;
  width: max(104%, calc(80px / var(--node-s, 1)));   /* never a thin sliver under a narrow stele */
  aspect-ratio: 3.4 / 1;
  border-radius: 50%;
  border: calc(3px / var(--node-s, 1)) solid rgba(255, 218, 100, 0.95);
  box-shadow: 0 0 0 calc(1.5px / var(--node-s, 1)) rgba(70, 35, 5, 0.6),
              inset 0 0 0 calc(1px / var(--node-s, 1)) rgba(70, 35, 5, 0.35),
              0 0 calc(10px / var(--node-s, 1)) rgba(255, 200, 40, 0.6),
              inset 0 0 calc(10px / var(--node-s, 1)) rgba(255, 200, 40, 0.4);
  /* Centred a little ABOVE the base point: on isometric art the base point is
     the front corner, and the footprint's middle sits higher. */
  transform: translate(-50%, -85%);
  z-index: -1;
  pointer-events: none;
  animation: overworld-node-ring 2.2s ease-in-out infinite;
}
@keyframes overworld-node-ring {
  0%, 100% { opacity: 0.5;  transform: translate(-50%, -85%) scale(0.94); }
  50%      { opacity: 1;    transform: translate(-50%, -85%) scale(1.04); }
}

/* Phase D4 — Sargon dust-storm reveal. A short-lived layer of sand grains that
   SWIRL outward from the node's spot and dissipate, "uncovering" the node (which
   fades in mid-storm; JS removes the layer at the end). Each grain carries its own
   randomized --ang / --dist / --dur / --delay (set inline in overworld.js). */
/* ══ REUSABLE OVERWORLD SPRITE ANIMATOR ═══════════════════════════
   The container for createOwSpriteAnimator (js/overworld.js). Percentage-
   positioned like every other overworld element, so it survives a resize the way
   the nodes do; the animator swaps the img's src for the frame cycle, so nothing
   here is per-sprite. image-rendering keeps the pixel art crisp at scale. */
.ow-sprite-anim {
  position: absolute;
  transform: translate(-50%, -50%);
  pointer-events: none;
  user-select: none;
  image-rendering: auto;
  will-change: left, top;
}
/* An ambush horde: a soft ground shadow so three layered sprites read with depth
   instead of as flat cut-outs. Each rider is depth-sorted by its feet
   (createOwSpriteAnimator), so the group overlaps consistently — and correctly
   against the Explorer and the nodes — regardless of DOM order. */
.ow-ambush-sprite {
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.55));
}

/* ══ OVERWORLD DIRT TRAIL ═════════════════════════════════════════
   Re-parameterized from .sargon-duststorm below: same "layer of grain spans
   driven by custom properties" shape, but a TRAIL rather than a swirl. The
   grains are emitted repeatedly at the sprite's CURRENT position as it travels
   (see _dirtTrail), and each kicks BACKWARD (+--dx, to the right, away from the
   leftward gallop) while settling DOWN (+--dy) instead of orbiting a centre. */
.ow-dirt-trail {
  position: absolute;
  left: 0; top: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 3;   /* on the ground; the ambush sets it one behind its rider instead */
}
.ow-dirt-grain {
  position: absolute;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, #e6cfa0 0%, #bd9256 70%, rgba(170, 130, 75, 0) 100%);
  opacity: 0;
  will-change: transform, opacity;
  animation: owDirtKick var(--dur, 0.8s) ease-out 1 both;
}
@keyframes owDirtKick {
  0%   { opacity: 0;    transform: translate(-50%, -50%) scale(0.5); }
  15%  { opacity: 0.85; }
  100% { opacity: 0;    transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1.25); }
}

.sargon-duststorm {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 0; height: 0;
  pointer-events: none;
}
.sargon-duststorm-grain {
  position: absolute;
  left: 0; top: 0;
  border-radius: 50%;
  background: radial-gradient(circle, #ecd49a 0%, #c89a55 70%, rgba(180,140,80,0) 100%);
  opacity: 0;
  will-change: transform, opacity;
  animation: sargonDustSwirl var(--dur, 1.2s) ease-out var(--delay, 0s) 1 both;
}
@keyframes sargonDustSwirl {
  0%   { opacity: 0;    transform: rotate(var(--ang)) translateX(0)            scale(0.6); }
  20%  { opacity: 0.95; }
  100% { opacity: 0;    transform: rotate(calc(var(--ang) + 230deg)) translateX(var(--dist)) scale(1.15); }
}

/* Hammurabi node reveal — dirt clods kicked up as the node rises from the ground.
   Each clod erupts up to a peak (--dy, negative) while scattering horizontally
   (--dx), then falls below the base and fades. Self-removing layer. */
.hammurabi-dirt {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 0; height: 0;
  pointer-events: none;
}
.hammurabi-dirt-grain {
  position: absolute;
  left: 0; top: 0;
  border-radius: 2px;
  background: #6b4a2b;
  box-shadow: 0 0 0 1px rgba(40, 26, 12, 0.55);
  opacity: 0;
  will-change: transform, opacity;
  animation: hammurabiDirtKick var(--dur, 1s) ease-out var(--delay, 0s) 1 both;
}
@keyframes hammurabiDirtKick {
  0%   { opacity: 0;   transform: translate(0, 0) scale(0.5) rotate(0deg); }
  20%  { opacity: 1; }
  45%  { transform: translate(calc(var(--dx) * 0.5), var(--dy)) scale(1) rotate(calc(var(--rot) * 0.5)); }
  100% { opacity: 0;   transform: translate(var(--dx), 16px) scale(0.8) rotate(var(--rot)); }
}

/* Hanging Gardens node reveal — a magical sparkle/shimmer (distinct from the
   Sargon dust-storm and Hammurabi earth-rise). Star-shaped sparkles twinkle in,
   drift outward (--sx/--sy) and rotate, then fade; the node itself fades in with a
   soft blue-white glow pulse. Self-removing layer. */
.hanging-gardens-sparkle {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 0; height: 0;
  pointer-events: none;
}
.hanging-gardens-sparkle-grain {
  position: absolute;
  left: 0; top: 0;
  background: radial-gradient(circle, #ffffff 0%, #d6f2ff 42%, rgba(150, 220, 255, 0) 72%);
  /* 8-point star sparkle */
  clip-path: polygon(50% 0%, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0% 50%, 39% 39%);
  opacity: 0;
  will-change: transform, opacity;
  animation: hangingGardensSparkle var(--dur, 1.3s) ease-in-out var(--delay, 0s) 1 both;
}
@keyframes hangingGardensSparkle {
  0%   { opacity: 0;   transform: translate(0, 0) scale(0.2) rotate(0deg); }
  30%  { opacity: 1;   transform: translate(calc(var(--sx) * 0.5), calc(var(--sy) * 0.5)) scale(1.1) rotate(45deg); }
  60%  { opacity: 0.9; }
  100% { opacity: 0;   transform: translate(var(--sx), var(--sy)) scale(0.45) rotate(90deg); }
}
/* Soft magical glow pulse on the node while it fades in (filter only — does not
   touch the node's transform, which GSAP owns during the reveal). */
.overworld-node.hanging-gardens-reveal-glow {
  animation: hangingGardensGlow 2.1s ease-out 1 both;
}
@keyframes hangingGardensGlow {
  0%   { filter: brightness(1.8)  drop-shadow(0 0 2px  rgba(170, 225, 255, 0.0)); }
  35%  { filter: brightness(1.25) drop-shadow(0 0 16px rgba(170, 225, 255, 0.9)); }
  100% { filter: brightness(1)    drop-shadow(0 0 0    rgba(170, 225, 255, 0.0)); }
}

/* ── Narmer (id 51) "The Unifier" — PERSISTENT red glow ──────────────────────
   Marks, for as long as his Continuous ability is live, the lands his averaging
   spans: his own card plus the nameplate of his location and of each adjacent
   location. Driven by Anim.setNarmerGlow / setNarmerNameGlow (class toggles) from
   updateNarmerGlows on the evaluateContinuous tail — so these classes come and go
   with the ability itself, never on a timer.

   HIS CARD uses `filter: drop-shadow` rather than box-shadow on purpose: the slot's
   box-shadow already belongs to Anim.setGlow's cyan continuous ring, which is
   re-applied on every pass. drop-shadow layers over that ring instead of fighting
   it for the same property. */
.battle-card-slot.anim-narmer-glow {
  /* RESTING state — a plain static glow, no animation running. */
  filter: drop-shadow(0 0 5px rgba(220, 40, 40, 0.58))
          drop-shadow(0 0 11px rgba(180, 20, 20, 0.38));
  /* One-shot arrival pulse. No fill-mode, so when it ends the element simply falls
     back to the static rule above and nothing keeps animating. Re-adding a class
     that is already present does not restart a CSS animation, so this fires once
     when the glow turns on — not on every continuous recompute — and fires again
     only when Narmer actually moves (class removed, then re-added elsewhere). */
  animation: narmerSourceIntro 0.6s ease-out 1;
}
@keyframes narmerSourceIntro {
  0%   { filter: drop-shadow(0 0 2px rgba(220, 40, 40, 0.30)); }
  45%  { filter: drop-shadow(0 0 10px rgba(245, 65, 65, 1))
                 drop-shadow(0 0 24px rgba(200, 25, 25, 0.75)); }
  100% { filter: drop-shadow(0 0 5px rgba(220, 40, 40, 0.58))
                 drop-shadow(0 0 11px rgba(180, 20, 20, 0.38)); }
}

/* THE SCORE NUMBER carries the glow — per side, on the digit Narmer's averaging
   actually rewrites. It is a direct child of .battle-location (overflow:visible),
   so unlike the nameplate it can throw a real outer halo. Each side KEEPS its own
   colour (cyan player / red opponent) — only the halo and a small scale pulse are
   added, so two Narmers can light their own digits at the same location without
   either side's colour coding being hijacked. The black outline from the base rule
   is repeated here because a text-shadow animation replaces the property wholesale. */
.battle-loc-score-opp.anim-narmer-score-glow,
.battle-loc-score-player.anim-narmer-score-glow {
  /* RESTING state — a light static red glow. Animating a 4-layer text-shadow
     forever was the expensive part: text-shadow cannot be composited, so every
     frame repainted the digit, on up to six digits, for the whole battle. Static
     costs nothing once painted. */
  text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.95),
               0 0 10px rgba(0, 0, 0, 0.85),
               0 0 7px rgba(235, 60, 60, 0.55),
               0 0 14px rgba(200, 25, 25, 0.30);
  animation: narmerScoreIntro 0.55s ease-out 1;   /* one-shot; see the card glow above */
}
@keyframes narmerScoreIntro {
  0% {
    transform: scale(1);
    text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.95),
                 0 0 10px rgba(0, 0, 0, 0.85);
  }
  45% {
    transform: scale(1.22);
    text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.95),
                 0 0 10px rgba(0, 0, 0, 0.85),
                 0 0 13px rgba(255, 85, 85, 1),
                 0 0 26px rgba(220, 35, 35, 0.75);
  }
  100% {
    transform: scale(1);
    text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.95),
                 0 0 10px rgba(0, 0, 0, 0.85),
                 0 0 7px rgba(235, 60, 60, 0.55),
                 0 0 14px rgba(200, 25, 25, 0.30);
  }
}

/* Water droplets thrown up as Hatshepsut's Merchant boat lands. Pale blue-white
   beads with a soft highlight, small enough to read as spray rather than splash. */
.reveal-fx-splash-drop {
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%,
    rgba(255, 255, 255, 0.98) 0%,
    rgba(206, 238, 255, 0.92) 45%,
    rgba(150, 205, 240, 0.75) 100%);
  box-shadow: 0 0 4px rgba(190, 230, 255, 0.85);
}

/* Hatshepsut's (52) spawned Merchant, mid-flight as a boat. Lifted off the board
   with a cast shadow; transform/rotation are owned by GSAP during the launch. */
.reveal-fx-merchant-boat {
  box-shadow: 0 10px 18px rgba(0, 0, 0, 0.6), 0 2px 5px rgba(0, 0, 0, 0.5);
  border-radius: 4px;
}

/* Nebuchadnezzar (id 50) reveal flourish — visualizes the Mesopotamia -1 CC
   discount. A blue-white magic glow pulse on Neb's card + each affected in-hand
   card (filter only — not clipped by the hand card's overflow:hidden); pairs with
   the .hanging-gardens-sparkle* star grains the JS bursts over each card. */
.reveal-fx-neb-glow {
  animation: revealFxNebGlow 1.2s ease-out 1 both;
}
@keyframes revealFxNebGlow {
  0%   { filter: brightness(1.6)  drop-shadow(0 0 2px  rgba(170, 225, 255, 0.0)); }
  35%  { filter: brightness(1.25) drop-shadow(0 0 14px rgba(170, 225, 255, 0.9)); }
  100% { filter: brightness(1)    drop-shadow(0 0 0    rgba(170, 225, 255, 0.0)); }
}
/* Ramses II (id 53) reveal flourish — the SAME shimmer as Neb's above (same
   timing, same curve, same brightness ramp), tinted for Egypt: Neb's pale
   blue-white rgb(170, 225, 255) with the red and blue channels mirrored to
   rgb(255, 225, 170) — a pale warm gold. Related by construction, distinct on
   screen. */
.reveal-fx-ramses-glow {
  animation: revealFxRamsesGlow 1.2s ease-out 1 both;
}
@keyframes revealFxRamsesGlow {
  0%   { filter: brightness(1.6)  drop-shadow(0 0 2px  rgba(255, 225, 170, 0.0)); }
  35%  { filter: brightness(1.25) drop-shadow(0 0 14px rgba(255, 225, 170, 0.9)); }
  100% { filter: brightness(1)    drop-shadow(0 0 0    rgba(255, 225, 170, 0.0)); }
}
/* The CC number ticking DOWN as the shimmer lands — a quick gold pop so the drop
   reads as caused by the sparkle. */
.db-overlay-cc.reveal-fx-cc-drop {
  animation: revealFxCcDrop 0.46s ease-out 1 both;
}
@keyframes revealFxCcDrop {
  0%   { transform: scale(1);    color: #fff; }
  40%  { transform: scale(1.55); color: #ffe08a; text-shadow: 0 0 8px rgba(255, 210, 120, 0.95), 2px 2px 0 rgba(0,0,0,0.85); }
  100% { transform: scale(1);    color: rgba(255, 255, 255, 0.75); }
}

/* The IP number ticking UP as the light crosses it. */
.db-overlay-ip.reveal-fx-ip-gain {
  animation: revealFxIpGain 0.52s ease-out 1 both;
}
@keyframes revealFxIpGain {
  0%   { transform: scale(1);    color: #fff; }
  40%  { transform: scale(1.6);  color: #b8dcff; text-shadow: 0 0 8px rgba(110, 190, 255, 0.95), 2px 2px 0 rgba(0,0,0,0.85); }
  100% { transform: scale(1);    color: #fff; }
}

/* Player character sprite. Smooth resampling like every overworld sprite (the
   160 px art is drawn at 92 px — nearest-neighbour dropped ~42% of its pixels
   and made the outline shimmer frame to frame). No silhouette filter: she is
   grounded by the contact + cast shadows at her feet instead. */
#overworld-character {
  position: absolute;
  width: 92px;
  height: auto;
  transform: translate(-50%, -100%);
  transform-origin: center bottom;
  image-rendering: auto;
  user-select: none;
  pointer-events: none;
  /* Own compositing layer: she is repositioned every frame of a walk. */
  will-change: transform;
}

/* ================================================================
   ADVENTURE MODE — HUD State B: Dialogue mode (Phase H2)
   ================================================================
   When SOG.HUD.enterDialogueMode() is called, #adv-hud gains the
   .dialogue-mode class. Deck slots + music strip fade out; the
   dialogue text area fades in; NPC portrait slides up into the
   right zone. Speaker rings (is-speaker) highlight who is talking.
   ================================================================ */

/* The dialogue overlay (#adv-hud-dialogue, a child of #adv-hud-center) is left
   intentionally NOT positioned here so the overlay's `inset:0` resolves against
   the whole bar (#adv-hud, position:absolute) instead of the off-centre centre
   zone. That keeps the diagonal divider at the TRUE screen centre regardless of
   how wide the left/right resting groups are. */
#adv-hud-center { position: static; }

/* Right zone needs position:relative for absolute NPC slot */
#adv-hud-util   { position: relative; }

/* ── Resting → dialogue transitions ─────────────────────────── */

#adv-hud-region,
#adv-hud-player-name,
#adv-hud-gold,
#adv-hud-deck,
#adv-hud-btn-options {
  transition: opacity 0.25s ease;
}
#adv-hud-focus-col {
  transition: opacity 0.25s ease, width 0.25s ease, margin 0.25s ease;
}

#adv-hud.dialogue-mode #adv-hud-region,
#adv-hud.dialogue-mode #adv-hud-player-name,
#adv-hud.dialogue-mode #adv-hud-focus-col,
#adv-hud.dialogue-mode #adv-hud-gold,
#adv-hud.dialogue-mode #adv-hud-deck,
#adv-hud.dialogue-mode #adv-hud-btn-options {
  opacity: 0;
  pointer-events: none;
}

/* Left-group focus collapses its width in dialogue mode so the player portrait
   stands alone at the left edge (its retained space isn't covered by the dialogue
   overlay). The right-group gold + deck + options stay put — the NPC portrait
   slot (inset:0 over #adv-hud-util) covers them. */
#adv-hud.dialogue-mode #adv-hud-focus-col {
  width: 0;
  margin: 0;
  overflow: hidden;
}

/* ── Dialogue text area (State B center) ─────────────────────── */

#adv-hud-dialogue {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: stretch;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
  overflow: hidden;
}

#adv-hud.dialogue-mode #adv-hud-dialogue {
  opacity: 1;
  pointer-events: auto;
}

/* Diagonal slash divider between the two speaker zones */
#adv-hud-dialogue::before {
  content: '';
  position: absolute;
  left: calc(50% - 1px);
  top: 8%;
  width: 2px;
  height: 84%;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(212, 170, 80, 0.55) 20%,
    rgba(212, 170, 80, 0.55) 80%,
    transparent 100%
  );
  transform: rotate(-18deg);
  transform-origin: center center;
  pointer-events: none;
}

/* ── Speaker zones ──────────────────────────────────────────── */
/* Each zone is absolutely pinned to its own 50% half so text
   always wraps within that half, regardless of whether the other
   zone is visible.                                               */

.adv-hud-dlg-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;             /* each zone = one screen half (overlay spans the bar) */
  display: none;          /* hidden until .active */
  align-items: center;
  padding: 0 28px;
  overflow: hidden;
}

/* Player zone occupies the LEFT half; outer padding clears the player portrait. */
#adv-hud-dlg-player {
  left: 0;
  padding-left: 130px;
}

/* NPC zone occupies the RIGHT half; text floats right, outer padding clears the
   NPC portrait at the bar's right edge. */
.adv-hud-dlg-zone--npc {
  right: 0;
  justify-content: flex-end;
  padding-right: 142px;
}

.adv-hud-dlg-zone.active {
  display: flex;
}

/* ── Dialogue text ──────────────────────────────────────────── */

#adv-hud-dialogue-text,
#adv-hud-dialogue-text-npc {
  font-family: 'Source Sans 3', sans-serif;
  font-size: 24px;
  line-height: 1.35;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.85);
  white-space: pre-wrap;
  word-break: break-word;
  min-height: 0;
  max-width: 100%;
}

/* Player (Explorer) — left-aligned, cream */
#adv-hud-dialogue-text {
  color: #f5e8c0;
  text-align: left;
}

/* NPC — right-aligned, warm amber */
#adv-hud-dialogue-text-npc {
  color: #ffc870;
  text-align: right;
}

/* "▶ Tap to continue" — the battle bubbles' cue, on the bar: under the active
   speaker's text, shown once the line has finished typing. */
#adv-hud-dlg-cue {
  position: absolute;
  bottom: 7px;
  left: 130px;
  font-family: var(--font);
  font-size: 13px;
  color: #f5e8c0;
  letter-spacing: 0.05em;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.85);
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}
#adv-hud-dlg-npc.active ~ #adv-hud-dlg-cue { left: auto; right: 142px; }
#adv-hud.is-ready #adv-hud-dlg-cue {
  opacity: 0.85;
  animation: tut-hint-blink 1.4s ease-in-out infinite;
}

/* ── NPC portrait slot (State B right zone) ──────────────────── */

#adv-hud-npc-slot {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;   /* hug the right edge — util now also holds music */
  padding-right: 34px;         /* keep the NPC portrait where it sat at 168px-wide util */
  overflow: hidden;   /* clips scaled/zoomed portrait to the HUD bar bounds */
  opacity: 0;
  pointer-events: none;
  /* JS (GSAP) drives translateY + opacity for slide-up animation */
}

#adv-hud-npc-slot img {
  width: 100px;
  height: 100px;
  object-fit: cover;
  object-position: center top;
  border: 2px solid rgba(212, 170, 80, 0.4);
  border-radius: 3px;
  box-shadow:
    inset 0 0 0 1px rgba(248, 220, 80, 0.18),
    0 2px 6px rgba(0, 0, 0, 0.65);
  display: block;
  user-select: none;
  pointer-events: none;
}

/* Otzi portrait — square head-and-shoulders art (images/portraits/otzi.jpg)
   frames identically to the Explorer; only the frame color changes to an
   icy blue to match his alpine theme. Resting border (active-speaker ring
   handled by the dialogue-mode rule below). */
#adv-hud-npc-slot img.adv-hud-npc-otzi {
  border-color: #7fb4d6;
  box-shadow:
    inset 0 0 0 1px rgba(200, 232, 255, 0.22),
    0 2px 6px rgba(0, 0, 0, 0.65);
}

/* ── Active-speaker gold ring + dimming ──────────────────────── */

/* Apply transitions during dialogue mode only */
#adv-hud.dialogue-mode #adv-hud-portrait > img,
#adv-hud.dialogue-mode #adv-hud-npc-slot img {
  transition: opacity 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

/* Non-speaker dims */
#adv-hud.dialogue-mode #adv-hud-portrait:not(.is-speaker) > img,
#adv-hud.dialogue-mode #adv-hud-npc-slot:not(.is-speaker) img {
  opacity: 0.45;
}

/* Active speaker: full opacity + gold ring glow */
#adv-hud.dialogue-mode #adv-hud-portrait.is-speaker > img,
#adv-hud.dialogue-mode #adv-hud-npc-slot.is-speaker img {
  opacity: 1;
  border-color: #f8d000;
  box-shadow:
    0 0 0 2px #f8d000,
    0 0 10px rgba(248, 208, 0, 0.55),
    0 2px 6px rgba(0, 0, 0, 0.65);
}

/* Otzi active speaker: icy ring instead of the gold one (matches his frame) */
#adv-hud.dialogue-mode #adv-hud-npc-slot.is-speaker img.adv-hud-npc-otzi {
  border-color: #bfe4ff;
  box-shadow:
    0 0 0 2px #bfe4ff,
    0 0 10px rgba(150, 210, 255, 0.6),
    0 2px 6px rgba(0, 0, 0, 0.65);
}

/* ── Mesopotamian giants: themed portrait frames (same framing as Otzi,
   only the border color changes). Resting border + active-speaker ring. ── */

/* Gilgamesh — light purple */
#adv-hud-npc-slot img.adv-hud-npc-gilgamesh {
  border-color: #c4a7e7;
  box-shadow:
    inset 0 0 0 1px rgba(225, 205, 255, 0.22),
    0 2px 6px rgba(0, 0, 0, 0.65);
}
#adv-hud.dialogue-mode #adv-hud-npc-slot.is-speaker img.adv-hud-npc-gilgamesh {
  border-color: #d9c4f5;
  box-shadow:
    0 0 0 2px #d9c4f5,
    0 0 10px rgba(196, 167, 231, 0.6),
    0 2px 6px rgba(0, 0, 0, 0.65);
}

/* Sargon — burgundy / dark red */
#adv-hud-npc-slot img.adv-hud-npc-sargon {
  border-color: #7a1f2b;
  box-shadow:
    inset 0 0 0 1px rgba(200, 90, 105, 0.22),
    0 2px 6px rgba(0, 0, 0, 0.65);
}
#adv-hud.dialogue-mode #adv-hud-npc-slot.is-speaker img.adv-hud-npc-sargon {
  border-color: #a63446;
  box-shadow:
    0 0 0 2px #a63446,
    0 0 10px rgba(166, 52, 70, 0.65),
    0 2px 6px rgba(0, 0, 0, 0.65);
}

/* Hammurabi — pure black */
#adv-hud-npc-slot img.adv-hud-npc-hammurabi {
  border-color: #000000;
  box-shadow:
    inset 0 0 0 1px rgba(120, 120, 120, 0.22),
    0 2px 6px rgba(0, 0, 0, 0.65);
}
#adv-hud.dialogue-mode #adv-hud-npc-slot.is-speaker img.adv-hud-npc-hammurabi {
  border-color: #000000;
  box-shadow:
    0 0 0 2px #000000,
    0 0 10px rgba(150, 150, 160, 0.5),
    0 2px 6px rgba(0, 0, 0, 0.65);
}

/* Nebuchadnezzar — dark green */
#adv-hud-npc-slot img.adv-hud-npc-neb {
  border-color: #1e6b3a;
  box-shadow:
    inset 0 0 0 1px rgba(120, 220, 150, 0.22),
    0 2px 6px rgba(0, 0, 0, 0.65);
}
#adv-hud.dialogue-mode #adv-hud-npc-slot.is-speaker img.adv-hud-npc-neb {
  border-color: #2e9650;
  box-shadow:
    0 0 0 2px #2e9650,
    0 0 10px rgba(46, 150, 80, 0.6),
    0 2px 6px rgba(0, 0, 0, 0.65);
}

/* Narmer — Egyptian gold (the Double Crown) */
#adv-hud-npc-slot img.adv-hud-npc-narmer {
  border-color: #9a6b16;
  box-shadow:
    inset 0 0 0 1px rgba(245, 210, 120, 0.22),
    0 2px 6px rgba(0, 0, 0, 0.65);
}
#adv-hud.dialogue-mode #adv-hud-npc-slot.is-speaker img.adv-hud-npc-narmer {
  border-color: #d4a02c;
  box-shadow:
    0 0 0 2px #d4a02c,
    0 0 10px rgba(212, 160, 44, 0.6),
    0 2px 6px rgba(0, 0, 0, 0.65);
}

/* ══════════════════════════════════════════════════════════════════════
   HAND-CARD HOVER INFO PANEL  (#battle-hover-popup — js/game/card-hover.js)

   The same card-detail panel as the click-to-open modal (it is listed in every
   palette group above, so the wood/bronze/gold treatment is shared, not copied)
   — but NON-MODAL and anchored above the hovered hand card.

   Two rules carry the whole interaction and must not be weakened:
     • pointer-events: none — the panel can NEVER take the cursor. Without it the
       panel covers the card, mouseleave fires, the panel hides, mouseenter fires
       again → an infinite strobe. It also lets drag-to-play pass straight through.
     • position: absolute inside #sog-stage — the stage is a fixed 1280x720 box
       scaled by a CSS transform, so the panel is positioned in UNSCALED stage
       units (card-hover.js converts) and tracks the card at any window size.

   Sized down from the modal's 560px because it sits right next to the card:
   narrower panel, tighter padding, smaller type. Adjust WIDTH/PADDING/font-size
   here — the JS reads the rendered size, so positioning follows automatically. */
#battle-hover-popup {
  position: absolute;
  left: 0;
  top: 0;
  width: 380px;                    /* KNOB — modal is 560px */
  padding: 12px 20px 13px;         /* KNOB — modal is 18px 32px 20px */
  z-index: 5100;                   /* under the modal (5200), over the board */
  pointer-events: none;            /* see note above — do not remove */
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 0.11s ease, transform 0.11s cubic-bezier(0.22, 1, 0.36, 1);
}
#battle-hover-popup.visible {
  opacity: 1;
  transform: scale(1);
}

/* Type scale — proportionally reduced from the modal's sizes. */
#battle-hover-popup .popup-header-row .popup-card-name { font-size: 20px; }
#battle-hover-popup .popup-header-row .popup-card-type { font-size: 12px; }
#battle-hover-popup .popup-ability-name {
  font-size: 15px;
  margin-bottom: 5px;
}
#battle-hover-popup .popup-ability-text {
  font-size: 17px;
  line-height: 1.45;
  margin-bottom: 6px;
}
#battle-hover-popup .popup-footer-row .popup-hint { font-size: 11px; }
#battle-hover-popup .popup-divider { margin: 7px 0; }

/* Tail — a bronze notch pointing down at the card it describes (flips to point
   up when the panel had to render BELOW the card near the top of the stage).
   --hover-tail-x is set by the JS so the tail stays under the card's centre even
   when the panel was clamped against a stage edge. */
#battle-hover-popup .hover-popup-tail {
  position: absolute;
  left: var(--hover-tail-x, 50%);
  bottom: -9px;
  width: 0;
  height: 0;
  margin-left: -9px;
  border-left: 9px solid transparent;
  border-right: 9px solid transparent;
  border-top: 9px solid #d4aa50;
}
#battle-hover-popup.is-below .hover-popup-tail {
  bottom: auto;
  top: -9px;
  border-top: none;
  border-bottom: 9px solid #d4aa50;
}

/* Prehistory node: amplified pulse used after 30s of idle waiting */
.overworld-node.overworld-node-urgent > img:not(.ow-cast-shadow):not(.ow-ground-rim) {
  animation: overworld-node-pulse-urgent 1.1s ease-in-out infinite !important;
}
@keyframes overworld-node-pulse-urgent {
  0%, 100% {
    filter: drop-shadow(0 0 10px rgba(255, 215, 0, 0.7));
    transform: scale(1.0);
  }
  50% {
    filter: drop-shadow(0 0 28px rgba(255, 215, 0, 1.0))
            drop-shadow(0 0 48px rgba(255, 200, 60, 0.9));
    transform: scale(1.08);
  }
}

/* ================================================================
   ADVENTURE MODE — Pre-battle speech bubbles + radial wipe (phase C)
   ================================================================
   Two reaction-shot bubbles for the Neanderthal pre-battle cutscene:
     • .adv-bubble-tr  Neanderthal in the top-right (portrait on right)
     • .adv-bubble-bl  Explorer in the bottom-left  (portrait on left)
   Distinct from the .adv-dialogue dual-box system above — these are
   shorter, position:fixed, auto-advance, no click-to-continue hint.

   #adv-radial-wipe: a fullscreen black overlay clipped to a circle.
   JS animates the circle radius from 0 to viewport-cover, centered
   on the Prehistory node. Same clip-path technique as #home-iris-wipe. */

.adv-bubble {
  position: fixed;
  display: flex;
  align-items: center;
  gap: 14px;
  width: 380px;
  padding: 12px 16px;
  background: linear-gradient(180deg, #f6efdc 0%, #e8dcb8 100%);
  border: 3px solid #1a0a04;
  border-radius: 6px;
  box-shadow:
    0 0 0 2px #c89b2d,
    0 6px 18px rgba(0, 0, 0, 0.55);
  font-family: var(--font);
  font-size: 22px;
  line-height: 1.3;
  color: #1a0a04;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease;
  z-index: 9998;
  pointer-events: none;  /* cutscene — no interaction expected */
}
.adv-bubble.is-visible { opacity: 1; visibility: visible; }

/* Neanderthal: top-right, portrait on the right side of the bubble */
.adv-bubble-tr {
  top:   32px;
  right: 32px;
  flex-direction: row-reverse;
  text-align: right;
}
/* Explorer: bottom-left, portrait on the left */
.adv-bubble-bl {
  bottom: 32px;
  left:   32px;
}

.adv-bubble-portrait {
  width: 84px;
  height: 84px;
  flex-shrink: 0;
  object-fit: cover;
  object-position: center 18%;  /* crop card art down toward face */
  border: 2px solid #1a0a04;
  border-radius: 4px;
  user-select: none;
}

.adv-bubble-text {
  flex: 1;
  font-family: var(--font);
  font-size: 22px;
  line-height: 1.3;
  color: #1a0a04;
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.4);
  min-height: 1.3em;
}

/* Click-to-continue hint — hidden during typing, shown when is-ready */
.adv-bubble-hint {
  font-family: var(--font);
  font-size: 11px;
  color: #888;
  margin-top: 5px;
  text-align: right;
  letter-spacing: 0.05em;
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}
.adv-bubble.is-ready .adv-bubble-hint {
  opacity: 0.85;
  animation: tut-hint-blink 1.4s ease-in-out infinite;
}

/* ══ GIANT-STYLE SPEECH BUBBLE (reusable) ══════════════════════
   The comic-book bubble the GIANTS use in battle (see
   body.sargon-battle #adv-bubble-otzi and its siblings) factored into a
   standalone class so non-battle speakers can reuse the exact same look:
   #f0ebe0 fill, 3px ink border, 12px radius, hard offset shadow.

   The Giants' own rules are LEFT COMPLETELY UNTOUCHED — they still carry their
   per-battle positioning/anchors. This class only re-expresses the shared
   *appearance*, so nothing about boss dialogue changes.

   Tail direction is a MODIFIER, because the Giants' tails point sideways at a
   portrait while a bubble sitting below a speaker needs one pointing UP.
   --tail-x is the tail's horizontal position (a tuning value set from JS). */
.giant-bubble {
  position: absolute;
  z-index: 165;                 /* above the market shelf cards */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  padding: 12px 14px 10px;
  background: #f0ebe0;
  border: 3px solid #111;
  border-radius: 12px;
  box-shadow: -4px 4px 0 #111;
  font-family: var(--font);
  font-size: 18px;
  line-height: 1.45;
  color: #111;
  text-shadow: none;
  cursor: pointer;
  pointer-events: auto;
  opacity: 0;
  transition: opacity 0.22s ease;
  --tail-x: 50%;                /* overridden inline by JS — align to the mouth */
}
.giant-bubble.is-visible { opacity: 1; }

/* Tail pointing UP (bubble sits BELOW the speaker, e.g. over a trader's chest,
   pointing back up at his mouth). Two stacked triangles: ink outline behind,
   fill in front, so the tail reads as part of the bubble body. */
.giant-bubble--tail-up::before,
.giant-bubble--tail-up::after {
  content: '';
  position: absolute;
  left: var(--tail-x);
  width: 0;
  height: 0;
  border-style: solid;
}
.giant-bubble--tail-up::before {   /* ink outline */
  top: -21px;
  transform: translateX(-50%);
  border-width: 0 12px 21px 12px;
  border-color: transparent transparent #111 transparent;
}
.giant-bubble--tail-up::after {    /* fill */
  top: -15px;
  transform: translateX(-50%);
  border-width: 0 9px 16px 9px;
  border-color: transparent transparent #f0ebe0 transparent;
}

/* Click-to-continue hint — matches the Giants' in-battle hint treatment.
   Hidden while typing (JS toggles display), shown once a line finishes. */
.giant-bubble .mtb-hint {
  font-family: var(--font);
  font-size: 11px;
  color: #666;
  margin-top: 6px;
  align-self: flex-end;
  letter-spacing: 0.05em;
  opacity: 0.85;
  animation: tut-hint-blink 1.4s ease-in-out infinite;
}

/* ── Battle context: comic-book speech-bubble style ─────────────
   In body.prehistory-battle the .adv-bubble boxes are repositioned
   to sit BESIDE the avatar circles (not covering them), with a CSS
   tail pointing horizontally from the bubble's mid-side toward the portrait.

   Side-center anchor: top + translateY(-50%) pins the bubble's vertical
   midpoint at the portrait's centre Y. As text grows the bubble expands
   equally above and below, keeping the tail tip stationary.

   Lucy avatar:        bottom:36px; left:36px  — frame 120×120px
     Portrait centre Y from top: 720 − 36 − 60 = 624px
     Bubble left: portrait right (36+120=156px) + 12px gap = 168px
   Neanderthal avatar: top:36px;   right:36px  — frame 120×120px
     Portrait centre Y from top: 36 + 60 = 96px
     Bubble right: 1280 − (portrait left 1124px − 12px gap) = 168px
   ────────────────────────────────────────────────────────────── */

body.prehistory-battle #adv-bubble-lucy {
  /* Reset .adv-bubble-bl corner positioning */
  /* Side-center anchor: bubble vertically centred on Lucy's portrait centre.
     Portrait centre Y = 720 − 36 − 60 = 624px from stage top.
     transform: translateY(-50%) keeps the midpoint pinned as text changes.
     left = avatar right (36+120=156px) + 12px gap = 168px. */
  top: 624px;
  transform: translateY(-50%);
  left: 168px;
  right: auto;
  bottom: auto;
  /* Comic-book style */
  flex-direction: column;
  align-items: flex-start;
  width: 230px;
  gap: 0;
  background: #fffef5;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: 4px 4px 0 #111;
}
/* Tail pointing left toward Lucy — emerges from LEFT-CENTER of bubble. */
body.prehistory-battle #adv-bubble-lucy::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-right-color: #111;
}
body.prehistory-battle #adv-bubble-lucy::after {
  content: '';
  position: absolute;
  top: 50%;
  left: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-right-color: #fffef5;
}

body.prehistory-battle #adv-bubble-neanderthal {
  /* Reset .adv-bubble-tr corner positioning */
  /* Side-center anchor: bubble vertically centred on Neanderthal's portrait centre.
     Portrait centre Y = 36 + 60 = 96px from stage top.
     transform: translateY(-50%) keeps the midpoint pinned as text changes.
     right = 1280 − (avatar left 1124px − 12px gap) = 168px. */
  top: 96px;
  transform: translateY(-50%);
  right: 168px;
  left: auto;
  bottom: auto;
  /* Comic-book style */
  flex-direction: column;
  align-items: flex-start;
  width: 270px;
  gap: 0;
  background: #f0ebe0;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: -4px 4px 0 #111;
}
/* Tail pointing right toward Neanderthal — emerges from RIGHT-CENTER of bubble. */
body.prehistory-battle #adv-bubble-neanderthal::before {
  content: '';
  position: absolute;
  top: 50%;
  right: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-left-color: #111;
}
body.prehistory-battle #adv-bubble-neanderthal::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-left-color: #f0ebe0;
}

/* In battle context: hide the portrait inside the bubble —
   the circular avatar frame on the screen handles the portrait. */
body.prehistory-battle .adv-bubble .adv-bubble-portrait {
  display: none;
}

/* In battle context: match tutorial bubble text size */
body.prehistory-battle .adv-bubble .adv-bubble-text {
  font-size: 18px;
  line-height: 1.45;
  color: #111;
  text-shadow: none;
  min-height: 28px;
}

body.prehistory-battle .adv-bubble .adv-bubble-hint {
  color: #666;
  margin-top: 6px;
}

/* ── Prehistory battle: spread hand cards (smaller, tighter gap) ─ */
body.prehistory-battle .battle-hand-card {
  margin-left: 3px;   /* 50% of the 6px non-overlap gap */
  width:  111px;      /* 123px × 0.9 */
  height: 166px;      /* 184px × 0.9 */
}
body.prehistory-battle .battle-player-hand .battle-hand-card:first-child {
  margin-left: 0;
}

/* ════════════════════════════════════════════════════════════
   SHARED ADVENTURE-BATTLE STYLING — body.adv-shared-battle
   Worn by the Ötzi AND Gilgamesh battles (each config's
   presentation.bodyClassExtra; removed on teardown): no CC numerals, no
   location ability text, spread hand, plain location plates, the comic
   speech bubbles, the popping ally avatar, the opponent portrait crop.
   One battle's own tweaks go on its own class instead:
   body.otzi-battle (Ötzi only) · body.gilgamesh-battle (Gilgamesh only).
   ════════════════════════════════════════════════════════════ */

/* Opponent portrait: the base rule (fitted to the turn box). */
/* The opponent's hand sits under the goal banner ("Win 2 of 3 locations!",
   .snap-goal at top 8), as the Neanderthal battle's does. Keyed on
   body.otzi-lessons — set only while the Ötzi battle shows that banner — not
   on a battle class. */
body.otzi-lessons .battle-opp-hand {
  align-items: flex-start;
  padding-top: 60px;   /* cards 60–132: ~10px under the banner, 13px above the board */
}

/* Face zoom on Otzi's avatar circle (matches dialogue portrait) — see override below */

/* Explorer avatar (bottom-left) — starts hidden, pops in via adv-active */
body.adv-shared-battle .battle-avatar-ally {
  bottom: 36px;
  left:   36px;
  opacity: 0;
  transform: scale(0.3);
  transform-origin: center bottom;
  transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
body.adv-shared-battle .battle-avatar-ally.adv-active {
  opacity: 1;
  transform: scale(1);
}

/* Top-left box: no override. The turn row and the CARDS TO PLAY ticker render
   exactly as in capital battles (SOG.board.updateHeader). */

/* Hide CC numerals (spec: no CC numbers shown in this battle) */
body.adv-shared-battle .db-overlay-cc { display: none; }

/* Hide location ability text in Otzi battle */
body.adv-shared-battle .battle-loc-ability { display: none; }

/* Spread hand cards with positive gap (4 cards, no heavy overlap) */
body.adv-shared-battle .battle-hand-card { margin-left: 8px; }
body.adv-shared-battle .battle-player-hand .battle-hand-card:first-child { margin-left: 0; }

/* Remove purple double-ring from location nameplate; cap its height */
body.adv-shared-battle .battle-location {
  border-color: transparent;
  box-shadow: none;
  max-height: 80px;
}

/* Remove purple occupied-slot border on played cards */
body.adv-shared-battle .battle-card-slot.occupied {
  border-color: transparent;
}

/* overflow:visible no longer needed — rings are gone — but keep for safety */
body.adv-shared-battle .battle-col { overflow: visible; }

/* Otzi avatar portrait: zoom out 20% more and raise */
body.adv-shared-battle .battle-avatar-opponent .battle-avatar-frame img {
  object-position: 50% 12%;
  transform: scale(1.36);
  transform-origin: 50% 12%;
}

/* Pre-deal: hand, opp hand, and action buttons invisible until the
   card deal animation fires. visibility:hidden preserves layout so
   GSAP can measure bounding rects for the fly-in animation. */
body.otzi-battle.otzi-pre-deal .battle-player-hand,
body.otzi-battle.otzi-pre-deal .battle-opp-hand,
body.otzi-battle.otzi-pre-deal .battle-hud-bottomright {
  visibility: hidden;
}

/* ── Otzi battle speech bubbles (comic-book style, same as prehistory) ── */

/* Otzi: top-right, bubble sits to the LEFT of the Otzi avatar circle.
   Avatar: top:20px right:20px frame 120×120px
   Avatar centre Y = 20+60 = 80px from stage top.
   Avatar left edge = 1280 − 20 − 120 = 1140px. Bubble right = 1280 − (1140 − 12) = 152px. */
body.adv-shared-battle #adv-bubble-otzi {
  top: 80px;
  transform: translateY(-50%);
  right: 152px;
  left: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 270px;
  gap: 0;
  background: #f0ebe0;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: -4px 4px 0 #111;
}
/* Tail → right toward Otzi avatar */
body.adv-shared-battle #adv-bubble-otzi::before {
  content: '';
  position: absolute;
  top: 50%;
  right: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-left-color: #111;
}
body.adv-shared-battle #adv-bubble-otzi::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-left-color: #f0ebe0;
}

/* Explorer: bottom-left, bubble sits to the RIGHT of the Explorer avatar.
   Avatar: bottom:36px left:36px frame 120×120px
   Avatar centre Y = 720−36−60 = 624px from stage top.
   left = avatar right (36+120=156px) + 12px gap = 168px.              */
body.adv-shared-battle #adv-bubble-explorer {
  top: 624px;
  transform: translateY(-50%);
  left: 168px;
  right: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  /* 200px: the right edge (168 + 200 + padding/border = 402px) clears the
     leftmost card of the 4-card Ötzi hand (~414px). At 230px it covered a strip
     of that card. Longer lines (the strategy hints) wrap taller instead. */
  width: 200px;
  gap: 0;
  background: #fffef5;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: 4px 4px 0 #111;
}
/* Tail → left toward Explorer avatar */
body.adv-shared-battle #adv-bubble-explorer::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-right-color: #111;
}
body.adv-shared-battle #adv-bubble-explorer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-right-color: #fffef5;
}

/* Gilgamesh Battle-1: the bottom-left Explorer bubble (shared Otzi styling,
   left:168px) is fixed-width and wraps text, so at width:230px its right edge
   (~398px) clipped the leftmost hand card (cards start ~382px in the 4-card
   adventure hand). Narrow it so the right edge (168+200=368px) clears the hand
   with a small gap; longer lines just wrap taller, staying left of the cards.
   Scoped to gilgamesh-battle so the verified Otzi battle is untouched. */
body.gilgamesh-battle #adv-bubble-explorer,
body.sargon-battle    #adv-bubble-explorer { width: 200px; }

/* In battle context: portrait is handled by the avatar circle — hide the
   inline portrait inside the bubble itself. */
body.adv-shared-battle .adv-bubble .adv-bubble-portrait { display: none; }

/* Match tutorial text size/colour in battle context */
body.adv-shared-battle .adv-bubble .adv-bubble-text {
  font-size: 18px;
  line-height: 1.45;
  color: #111;
  text-shadow: none;
  min-height: 28px;
}
body.adv-shared-battle .adv-bubble .adv-bubble-hint {
  color: #666;
  margin-top: 6px;
}

/* ── Sargon + Hyksos battle speech bubbles — the comic-book treatment, same as
   the Otzi / Gilgamesh battles. Each battle uses its own body class (so the
   adv-shared-battle bubble rules above don't reach it) and keeps the capital UI (CC
   overlays), so we mirror ONLY the bubble styling here. Avatars sit in their
   default spots (opponent top-right 20/20, ally bottom-left 40/40), matching
   these anchors.

   HYKSOS, RAMSES, AKHENATEN AND KUSH SHARE THIS BLOCK rather than each getting a copy.
   EVERY battle must opt in by body class — the bare .adv-bubble default is a
   plain parchment box with the portrait inside, which is NOT the game's dialogue
   look and should never be seen. A new battle that forgets to add itself here
   silently falls back to that box; adding the class to these selector lists is
   the whole fix. (Hammurabi / Hanging Gardens / Narmer / Hatshepsut still carry
   their own identical blocks below — folding those in too is a tidy-up for
   another pass, deliberately not done here to avoid touching shipped battles.) */
body.sargon-battle #adv-bubble-otzi,
body.hyksos-battle #adv-bubble-otzi,
body.ramses-battle #adv-bubble-otzi,
body.akhenaten-battle #adv-bubble-otzi,
body.kush-battle #adv-bubble-otzi {
  top: 80px;
  transform: translateY(-50%);
  right: 152px;
  left: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 270px;
  gap: 0;
  background: #f0ebe0;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: -4px 4px 0 #111;
}
body.sargon-battle #adv-bubble-otzi::before,
body.hyksos-battle #adv-bubble-otzi::before,
body.ramses-battle #adv-bubble-otzi::before,
body.akhenaten-battle #adv-bubble-otzi::before,
body.kush-battle #adv-bubble-otzi::before {
  content: '';
  position: absolute;
  top: 50%;
  right: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-left-color: #111;
}
body.sargon-battle #adv-bubble-otzi::after,
body.hyksos-battle #adv-bubble-otzi::after,
body.ramses-battle #adv-bubble-otzi::after,
body.akhenaten-battle #adv-bubble-otzi::after,
body.kush-battle #adv-bubble-otzi::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-left-color: #f0ebe0;
}
body.sargon-battle #adv-bubble-explorer,
body.hyksos-battle #adv-bubble-explorer,
body.ramses-battle #adv-bubble-explorer,
body.akhenaten-battle #adv-bubble-explorer,
body.kush-battle #adv-bubble-explorer {
  top: 624px;
  transform: translateY(-50%);
  left: 168px;
  right: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 200px;
  gap: 0;
  background: #fffef5;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: 4px 4px 0 #111;
}
body.sargon-battle #adv-bubble-explorer::before,
body.hyksos-battle #adv-bubble-explorer::before,
body.ramses-battle #adv-bubble-explorer::before,
body.akhenaten-battle #adv-bubble-explorer::before,
body.kush-battle #adv-bubble-explorer::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-right-color: #111;
}
body.sargon-battle #adv-bubble-explorer::after,
body.hyksos-battle #adv-bubble-explorer::after,
body.ramses-battle #adv-bubble-explorer::after,
body.akhenaten-battle #adv-bubble-explorer::after,
body.kush-battle #adv-bubble-explorer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-right-color: #fffef5;
}
body.sargon-battle .adv-bubble .adv-bubble-portrait,
body.hyksos-battle .adv-bubble .adv-bubble-portrait,
body.ramses-battle .adv-bubble .adv-bubble-portrait,
body.akhenaten-battle .adv-bubble .adv-bubble-portrait,
body.kush-battle .adv-bubble .adv-bubble-portrait { display: none; }
body.sargon-battle .adv-bubble .adv-bubble-text,
body.hyksos-battle .adv-bubble .adv-bubble-text,
body.ramses-battle .adv-bubble .adv-bubble-text,
body.akhenaten-battle .adv-bubble .adv-bubble-text,
body.kush-battle .adv-bubble .adv-bubble-text {
  font-size: 18px;
  line-height: 1.45;
  color: #111;
  text-shadow: none;
  min-height: 28px;
}
body.sargon-battle .adv-bubble .adv-bubble-hint,
body.hyksos-battle .adv-bubble .adv-bubble-hint,
body.ramses-battle .adv-bubble .adv-bubble-hint,
body.akhenaten-battle .adv-bubble .adv-bubble-hint,
body.kush-battle .adv-bubble .adv-bubble-hint {
  color: #666;
  margin-top: 6px;
}

/* ── Hammurabi battle speech bubbles — same comic-book treatment as Sargon
   (its own body class, so the adv-shared-battle bubble rules don't reach it). */
body.hammurabi-battle #adv-bubble-otzi {
  top: 80px;
  transform: translateY(-50%);
  right: 152px;
  left: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 270px;
  gap: 0;
  background: #f0ebe0;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: -4px 4px 0 #111;
}
body.hammurabi-battle #adv-bubble-otzi::before {
  content: '';
  position: absolute;
  top: 50%;
  right: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-left-color: #111;
}
body.hammurabi-battle #adv-bubble-otzi::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-left-color: #f0ebe0;
}
body.hammurabi-battle #adv-bubble-explorer {
  top: 624px;
  transform: translateY(-50%);
  left: 168px;
  right: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 200px;
  gap: 0;
  background: #fffef5;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: 4px 4px 0 #111;
}
body.hammurabi-battle #adv-bubble-explorer::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-right-color: #111;
}
body.hammurabi-battle #adv-bubble-explorer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-right-color: #fffef5;
}
body.hammurabi-battle .adv-bubble .adv-bubble-portrait { display: none; }
body.hammurabi-battle .adv-bubble .adv-bubble-text {
  font-size: 18px;
  line-height: 1.45;
  color: #111;
  text-shadow: none;
  min-height: 28px;
}
body.hammurabi-battle .adv-bubble .adv-bubble-hint {
  color: #666;
  margin-top: 6px;
}

/* ── Hanging Gardens (Nebuchadnezzar) battle speech bubbles — same comic-book
   treatment as Hammurabi/Sargon (its own body class). */
body.hanging-gardens-battle #adv-bubble-otzi {
  top: 80px;
  transform: translateY(-50%);
  right: 152px;
  left: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 270px;
  gap: 0;
  background: #f0ebe0;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: -4px 4px 0 #111;
}
body.hanging-gardens-battle #adv-bubble-otzi::before {
  content: '';
  position: absolute;
  top: 50%;
  right: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-left-color: #111;
}
body.hanging-gardens-battle #adv-bubble-otzi::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-left-color: #f0ebe0;
}
body.hanging-gardens-battle #adv-bubble-explorer {
  top: 624px;
  transform: translateY(-50%);
  left: 168px;
  right: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 200px;
  gap: 0;
  background: #fffef5;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: 4px 4px 0 #111;
}
body.hanging-gardens-battle #adv-bubble-explorer::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-right-color: #111;
}
body.hanging-gardens-battle #adv-bubble-explorer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-right-color: #fffef5;
}
body.hanging-gardens-battle .adv-bubble .adv-bubble-portrait { display: none; }
body.hanging-gardens-battle .adv-bubble .adv-bubble-text {
  font-size: 18px;
  line-height: 1.45;
  color: #111;
  text-shadow: none;
  min-height: 28px;
}
body.hanging-gardens-battle .adv-bubble .adv-bubble-hint {
  color: #666;
  margin-top: 6px;
}

/* ── Narmer (Egypt) battle speech bubbles — same comic-book treatment as
   Hammurabi / Sargon / Hanging Gardens (its own body class, so the default
   top-right .adv-bubble box + adv-shared-battle rules don't reach it). Narmer's
   in-battle dialogue (intro / win / loss / tie) all render through the shared
   #adv-bubble-otzi (opponent) + #adv-bubble-explorer bubbles, exactly like the
   other bosses — this block is what styles them as bubbles rather than the
   raw top-right box. */
body.narmer-battle #adv-bubble-otzi {
  top: 80px;
  transform: translateY(-50%);
  right: 152px;
  left: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 270px;
  gap: 0;
  background: #f0ebe0;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: -4px 4px 0 #111;
}
body.narmer-battle #adv-bubble-otzi::before {
  content: '';
  position: absolute;
  top: 50%;
  right: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-left-color: #111;
}
body.narmer-battle #adv-bubble-otzi::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-left-color: #f0ebe0;
}
body.narmer-battle #adv-bubble-explorer {
  top: 624px;
  transform: translateY(-50%);
  left: 168px;
  right: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 200px;
  gap: 0;
  background: #fffef5;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: 4px 4px 0 #111;
}
body.narmer-battle #adv-bubble-explorer::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-right-color: #111;
}
body.narmer-battle #adv-bubble-explorer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-right-color: #fffef5;
}
body.narmer-battle .adv-bubble .adv-bubble-portrait { display: none; }
body.narmer-battle .adv-bubble .adv-bubble-text {
  font-size: 18px;
  line-height: 1.45;
  color: #111;
  text-shadow: none;
  min-height: 28px;
}
body.narmer-battle .adv-bubble .adv-bubble-hint {
  color: #666;
  margin-top: 6px;
}

/* ── Hatshepsut (Egypt) battle speech bubbles — same comic-book treatment as
   Narmer / Hammurabi / Sargon / Hanging Gardens (its own body class, so the
   default top-right .adv-bubble box + adv-shared-battle rules don't reach it).
   Hatshepsut's in-battle dialogue (intro / win / loss / tie) all render
   through the shared #adv-bubble-otzi (opponent) + #adv-bubble-explorer
   bubbles, exactly like the other bosses — this block is what styles them as
   bubbles rather than the raw top-right box. */
body.hatshepsut-battle #adv-bubble-otzi {
  top: 80px;
  transform: translateY(-50%);
  right: 152px;
  left: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 270px;
  gap: 0;
  background: #f0ebe0;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: -4px 4px 0 #111;
}
body.hatshepsut-battle #adv-bubble-otzi::before {
  content: '';
  position: absolute;
  top: 50%;
  right: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-left-color: #111;
}
body.hatshepsut-battle #adv-bubble-otzi::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-left-color: #f0ebe0;
}
body.hatshepsut-battle #adv-bubble-explorer {
  top: 624px;
  transform: translateY(-50%);
  left: 168px;
  right: auto;
  bottom: auto;
  flex-direction: column;
  align-items: flex-start;
  width: 200px;
  gap: 0;
  background: #fffef5;
  border: 3px solid #111;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow: 4px 4px 0 #111;
}
body.hatshepsut-battle #adv-bubble-explorer::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -21px;
  transform: translateY(-50%);
  border: 10px solid transparent;
  border-right-color: #111;
}
body.hatshepsut-battle #adv-bubble-explorer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: -14px;
  transform: translateY(-50%);
  border: 8px solid transparent;
  border-right-color: #fffef5;
}
body.hatshepsut-battle .adv-bubble .adv-bubble-portrait { display: none; }
body.hatshepsut-battle .adv-bubble .adv-bubble-text {
  font-size: 18px;
  line-height: 1.45;
  color: #111;
  text-shadow: none;
  min-height: 28px;
}
body.hatshepsut-battle .adv-bubble .adv-bubble-hint {
  color: #666;
  margin-top: 6px;
}

/* Radial wipe — fullscreen black, clipped to an expanding circle.
   Inline clip-path style is set by JS each frame during the GSAP
   tween. .active toggles visibility; opacity stays at 1 throughout
   the expansion (the circle's grow IS the animation). */
#adv-radial-wipe {
  position: fixed;
  inset: 0;
  background: #000;
  z-index: 10001;
  pointer-events: none;
  visibility: hidden;
  opacity: 1;
  clip-path: circle(0px at 50% 50%);
}
#adv-radial-wipe.active { visibility: visible; }

/* ================================================================
   ADVENTURE MODE — Prehistory battle (single-location board, phase D)
   ================================================================
   Context class `body.prehistory-battle` (set by JS in
   sog-adventure-prehistory.js's setupBattleBoard) gates all these
   overrides. The standard #screen-battle DOM renders normally —
   these rules just constrain it for the tutorial:
     • Hide all .battle-col except the single 'The Camp' col
     • Center the board, no compass watermark
     • Turn counter takes the place of Capital in the upper-left HUD
     • CC numerals are hidden on hand cards + slot cards (IP only)
     • Otzi avatar img is swapped to Neanderthal via JS (src override)
     • Lucy avatar is hidden until Phase E pops her in (.adv-active)

   Sub-class `body.prehistory-pre-coaching` is set by JS during the
   Phase D arrival window and removed once Phase E coaching ends.
   It additionally hides the player hand, opp hand, deck, and the
   bottom-right HUD buttons — those slide in at the end of coaching. */

/* Hide all .battle-col except the one with The Camp (data-loc-id="100"
   — assigned in JS, sidesteps collisions with the standard loc IDs 1-6). */
body.prehistory-battle .battle-col:not([data-loc-id="100"]) { display: none; }

/* Center the single remaining col + reclaim the board padding (the
   original 16px is for a 6-col row; with one col centered it pushes
   the Camp leftward). Fixed column width so the location tile and
   gold strip frame only The Camp, not the full 1280px board.       */
body.prehistory-battle .battle-board {
  justify-content: center;
  align-items: stretch;
  padding-left: 0;
  padding-right: 0;
  gap: 0;
}
body.prehistory-battle .battle-board::after { display: none; } /* compass watermark off */

/* Standard Arcadium 3-location column width:
   (1280px − 32px padding − 2×28px gap) / 3 ≈ 397px.
   Matches one of three locations in the standard Arcadium board layout.
   Base CSS flex:1; aspect-ratio:2/3; max-height:100% slots fill naturally
   at ~95px wide × 140px tall — no per-slot width override needed.      */
body.prehistory-battle .battle-col[data-loc-id="100"] {
  flex: 0 0 397px;
  width: 397px;
}

/* Three symmetric 192 / 336 / 192px sections:
   top (opp band):    192px — Neanderthal portrait + face-down deck pile
   middle (board):    flex:1 = 720 − 192 − 192 = 336px gameboard
   bottom (player band): 192px — Lucy portrait + player hand + HUD buttons
   Height 192px = card height (166px) + 26px breathing room, matching the
   standard game ratio (210px band, 184px card → 26px breathing room).    */
body.prehistory-battle .battle-opp-hand    { height: 192px; padding-top: 0; }
body.prehistory-battle .battle-player-hand { height: 192px; padding-top: 0; }

/* Slot rows: standard Arcadium 3-location height (140px).
   336px board − 2×140px rows − 2×6px gaps = 44px for the location strip.
   padding:0 — base CSS flex:1 slots fill the 397px column naturally.   */
body.prehistory-battle .battle-slots-opp,
body.prehistory-battle .battle-slots-player {
  height: 140px;
  padding: 0;
}

/* The Camp background — same ::before pattern as the standard
   locations (loc IDs 1-6). Source asset: images/locations/prehistorycamp.jpg
   z-index MUST be -1 (not 0): with isolation:isolate on .battle-col
   the stacking order puts flex children (card slots) at step 3 and
   positioned elements with z-index≥0 at step 6, which would paint
   the background image on top of every played card. -1 keeps it
   behind flex children at step 2. */
.battle-col[data-loc-id="100"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/prehistorycamp.jpg') center / cover no-repeat;
  z-index: -1;
  opacity: 0.72;
}

/* Location strip: fills leftover board space between the two slot rows.
   With 336px board, 140px slot rows, 2×6px gaps → ~44px for this strip.
   max-height:80px caps it if the board is ever taller (safety guard).
   width/align-self no longer needed — column IS 397px, strip fills it. */
body.prehistory-battle .battle-location {
  flex: 1 1 auto;
  max-height: 80px;
  border-color: transparent;
  box-shadow: none;
}

/* Remove purple occupied-slot border on played cards */
body.prehistory-battle .battle-card-slot.occupied {
  border-color: transparent;
}

/* Neanderthal avatar: top-right corner of the 192px opp band, mirroring
   Lucy's bottom-left placement. Equal inner+outer padding:
   (192 − 120) / 2 = 36px → top:36px; right:36px. */
body.prehistory-battle .battle-avatar-opponent {
  top:   36px;
  right: 36px;
}
body.prehistory-battle .battle-avatar-opponent .battle-avatar-frame {
  width:  120px;   /* its own 192px band: keeps the full-size portrait */
  height: 120px;
}

/* Flip the portrait image so Neanderthal faces LEFT (toward the board).
   Only the <img> is flipped — the circular frame stays unflipped so the
   gold ring and shadow are not mirrored. */
body.prehistory-battle .battle-avatar-opponent .battle-avatar-frame img {
  transform: scaleX(-1);
}

/* Hide ability text on The Camp (spec: "No ability text"). The .battle-loc-name
   still shows so the player sees "The Camp" centered on the tile. */
body.prehistory-battle .battle-loc-ability { display: none; }

/* Hide CC numerals on every card surface (spec: "Capital Cost numbers
   are hidden on all cards in this battle. Only the IP number is shown.") */
body.prehistory-battle .db-overlay-cc { display: none; }

/* Top-left box: no override. The turn row and the CARDS TO PLAY ticker render
   exactly as in capital battles (SOG.board.updateHeader). */

/* Lucy avatar hidden until Phase E pops her in. .adv-active is added
   by Phase E's coaching kickoff.
   Position: bottom-left corner of the 192px player band, matching Neanderthal.
   Equal inner+outer padding: (192 − 120) / 2 = 36px → bottom:36px; left:36px. */
body.prehistory-battle .battle-avatar-ally {
  bottom: 36px;
  left:   36px;
  opacity: 0;
  transform: scale(0.3);
  transform-origin: center bottom;
  transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
body.prehistory-battle .battle-avatar-ally.adv-active {
  opacity: 1;
  transform: scale(1);
}

/* Pre-coaching arrival window: hide hand, deck pile, opp hand, the
   bottom-right HUD (RESET + END TURN), and the top-left Turn counter.
   Phase E removes the `prehistory-pre-coaching` body class and GSAP
   animates each element from its off-screen starting position into
   place. Using `visibility: hidden` (not display:none) so the
   bounding rects exist for the slide-in delta calculation. */
body.prehistory-battle.prehistory-pre-coaching .battle-player-hand,
body.prehistory-battle.prehistory-pre-coaching .battle-opp-hand,
body.prehistory-battle.prehistory-pre-coaching .battle-hud-bottomright,
body.prehistory-battle.prehistory-pre-coaching .battle-hud-topleft {
  visibility: hidden;
}

/* IP overlay: 1 unit smaller font and thinner stroke in the Neanderthal
   battle so the numeral doesn't overpower the card art at this card size. */
body.prehistory-battle .db-overlay-ip {
  font-size: 21cqw;
  top: calc(3cqw + 2px);
  text-shadow:
    -1px -1px 0 #fff,  1px -1px 0 #fff,
    -1px  1px 0 #fff,  1px  1px 0 #fff;
}

/* IP gold ring injected during the "See that number?" coaching beat.
   JS creates a <div.adv-ip-ring> directly on #sog-stage (bypassing the
   card's overflow:hidden) and positions it via getBoundingClientRect().
   border-radius:50% makes it a circle; z-index sits above hand cards. */
.adv-ip-ring {
  position: absolute;
  border-radius: 50%;
  border: 4px solid #f8d000;
  box-shadow: 0 0 10px 3px rgba(248, 208, 0, 0.55),
              inset 0 0 6px 1px rgba(248, 208, 0, 0.15);
  pointer-events: none;
  z-index: 9000;
}

/* ────────────────────────────────────────────────────────────────
   Phase F additions: End Turn pulse, result screens, completed node
   ──────────────────────────────────────────────────────────────── */

/* End Turn button pulse used on turn 1 to draw attention after the
   player makes their first play (spec step 8). JS adds .adv-pulse
   and removes it once the player clicks End Turn. */
@keyframes adv-button-pulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--snes-yellow),
                          4px 4px 0 #111; }
  50%      { box-shadow: 0 0 0 2px var(--snes-yellow),
                          0 0 18px 6px rgba(248, 208, 0, 0.75),
                          4px 4px 0 #111; }
}
.btn-end-turn.adv-pulse:not([disabled]) {
  animation: adv-button-pulse 0.85s ease-in-out infinite;
}

/* ── Post-battle dim overlay (win card-reveal sequence) ────────
   Sits inside #sog-stage (moved there by JS) so it scales with the
   stage transform. Covers the gameboard while the card rises. */
#adv-post-battle-dim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.80);
  z-index: 5000;
  pointer-events: none;
}

/* Card reveal container — centred flex column on stage */
#adv-card-reveal {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 5100;
  pointer-events: auto;
}

/* Battle popup must sit above the card-acquisition overlay (z-index 5100)
   when it's triggered from the card reveal screen. z-index: 200 (the base)
   is buried under the dim (5000) and card-reveal (5100) layers because
   #screen-battle has no stacking context of its own. */
#battle-popup-backdrop.visible {
  z-index: 5200;
}

/* Card acquisition wrapper — sized container for the img + IP overlay.
   container-type:inline-size makes cqw units resolve against card width
   so .db-overlay-ip scales exactly as it does on in-game hand cards.  */
#adv-card-reveal-card-wrap {
  position: relative;
  width: 320px;
  container-type: inline-size;
  cursor: pointer;
  transition: transform 0.15s ease;   /* hover scale runs on the whole card (art + IP/CC badges) */
}
#adv-card-reveal-card-wrap:hover {
  transform: scale(1.02);             /* scale the wrapper so the IP/CC badges enlarge WITH the art */
}

/* Card acquisition image — fills wrapper; sizing/cursor live on wrapper */
#adv-card-reveal-img {
  width: 100%;
  height: auto;
  border-radius: 4px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.75),
              0 0 0 2px rgba(212, 170, 80, 0.5);
  display: block;
  transition: box-shadow 0.2s ease, transform 0.15s ease;
}
#adv-card-reveal-card-wrap:hover #adv-card-reveal-img {
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.75),
              0 0 0 3px rgba(248, 208, 0, 0.85);
  /* scale now lives on the wrapper so the IP/CC badges scale too */
}

/* ✕ close button on the card's top-right corner (44px hit area, 40px circle),
   centred just outside the corner so it clears the IP number. Same as
   clicking outside the card. Hidden until the reveal takes clicks (.is-live,
   set by _wireCardAcquisitionInteractions). One radial gradient for the
   circle and its ring (no border-radius border); the ✕ is two CSS bars. */
#adv-card-reveal-close {
  --close-ring: #f3e6c4;
  position: absolute;
  top: -26px;
  right: -26px;
  z-index: 3;
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  cursor: pointer;
  background: radial-gradient(circle closest-side,
    rgba(18, 10, 4, 0.96) calc(100% - 5px), var(--close-ring) calc(100% - 4.5px),
    var(--close-ring) calc(100% - 2.5px), rgba(0, 0, 0, 0) calc(100% - 1.5px));
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.7));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.12s ease;
}
#adv-card-reveal-close.is-live { opacity: 1; pointer-events: auto; }
#adv-card-reveal-close::before,
#adv-card-reveal-close::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 18px;
  height: 3px;
  margin: -1.5px 0 0 -9px;
  border-radius: 1px;
  background: var(--close-ring);
}
#adv-card-reveal-close::before { transform: rotate(45deg); }
#adv-card-reveal-close::after  { transform: rotate(-45deg); }
#adv-card-reveal-close:hover { --close-ring: #f8d000; transform: scale(1.08); }
#adv-card-reveal-close:focus-visible { outline: 2px solid #f8d000; outline-offset: 2px; border-radius: 50%; }
/* Hovering the ✕ is not hovering the card: no card lift / gold card ring. */
#adv-card-reveal-card-wrap:has(#adv-card-reveal-close:hover) { transform: none; }
#adv-card-reveal-card-wrap:has(#adv-card-reveal-close:hover) #adv-card-reveal-img {
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.75), 0 0 0 2px rgba(212, 170, 80, 0.5);
}

/* "New Card Acquired" banner — pixel-art gold ribbon above the card */
#adv-card-reveal-banner {
  font-family: var(--font);
  font-size: 20px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #1a0a04;
  background: linear-gradient(90deg,
    transparent 0%,
    #f8d000     10%,
    #f8d000     90%,
    transparent 100%);
  padding: 7px 40px;
  margin-bottom: 14px;
  border-top:    2px solid #c8a800;
  border-bottom: 2px solid #c8a800;
  white-space: nowrap;
  /* entrance handled inline by JS transition */
}

/* Result screens (victory / defeat) — fullscreen overlay above the
   battle. Uses the same .result-wrap parchment panel as the Arcadium
   result screen, centred by this fixed backdrop. */
.adv-result {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.78);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font);
  animation: adv-result-fadein 0.35s ease-out;
}
@keyframes adv-result-fadein {
  from { opacity: 0; }
  to   { opacity: 1; }
}
/* Single-row result-locs: first-child AND last-child — give all four
   corners the same 2px radius (rather than having :last-child win and
   removing the top-corner radius set by :first-child). */
.adv-result .result-loc-row:first-child:last-child {
  border-radius: 2px;
}

/* Completed-node treatment: gold checkmark badge overlaid on the
   Prehistory node once the battle is won. Sits above the node image,
   below the location label. Phase F adds .overworld-node-complete
   on entry to the overworld after a victory.
   At the node's BOTTOM-RIGHT corner, clear of its art: the node box IS the
   trimmed art, so the badge sits just outside its right edge (2px gap) with
   its bottom level with the art's base, the same on every node. A node can
   move it with its own --badge-x/--badge-y (the badge's centre). It is
   inside the node, so it is counter-scaled by the node's scale (--node-s,
   set by overworld.js) to stay 24px on screen. */
.overworld-node.overworld-node-complete::before {
  content: '\2713';   /* ✓ */
  position: absolute;
  left: var(--badge-x, calc(100% + 14px / var(--node-s, 1)));
  top:  var(--badge-y, calc(100% - 12px / var(--node-s, 1)));
  transform: translate(-50%, -50%) scale(calc(1 / var(--node-s, 1)));
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* One radial gradient: yellow fill + 2px dark ring (no border-radius
     border — see .db-pick::before for the cross artifact that caused). */
  background: radial-gradient(circle closest-side,
    var(--snes-yellow) calc(100% - 2.5px), #1a0a04 calc(100% - 2px),
    #1a0a04 calc(100% - 0.75px), rgba(26, 10, 4, 0) 100%);
  color: #1a0a04;
  font-family: var(--font);
  font-size: 15px;
  font-weight: bold;
  /* bevel, glow, and a small cast shadow under the overworld's one sun
     (front-left: shadows fall up and to the right — see SUN in overworld.js) */
  filter: drop-shadow(0 2px 0 #000) drop-shadow(0 0 4px rgba(248, 208, 0, 0.5)) drop-shadow(3px -3px 2px rgba(0, 0, 0, 0.35));
  z-index: 3;
  pointer-events: none;
}
/* The East Africa signpost wears its ✓ ON the sign board, right of the
   plaque — beside the post it read as floating in empty grass. */
.overworld-node[data-id="egypt-signpost"] { --badge-x: 74%; --badge-y: 41%; }


/* ════════════════════════════════════════════════════════════════
   DECK BUILDER TUTORIAL — spotlight overlay
   Fires on first-time deck-builder entry (and replays via the "?"
   icon) until the player ships a complete 15-card deck.
   ════════════════════════════════════════════════════════════════ */

/* "?" help icon in the deck-builder header — gold circular button
   sitting inline to the left of #db-counter. Distinct enough from
   the counter that it doesn't read as part of the "15 / 15" number. */
.db-help-icon {
  width: 28px;
  height: 28px;
  margin-right: 0;
  border-radius: 50%;
  border: 2px solid var(--snes-yellow);
  background: transparent;
  color: var(--snes-yellow);
  font-family: var(--font);
  font-size: 16px;
  font-weight: bold;
  line-height: 24px;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.15s, color 0.15s;
}
.db-help-icon:hover {
  background: var(--snes-yellow);
  color: #2a1608;
}


/* Spotlight cutout: four dim rectangles arranged around the target
   (top / right / bottom / left). The cutout is the negative space
   between them, so the spotlighted element — and anything that opens
   over it like the ability popup — renders at its natural z-index
   with no manipulation. Each rect eats clicks on its dim area; the
   cutout passes clicks straight through to the underlying element. */
.db-tut-dim {
  position: fixed;
  background: rgba(0, 0, 0, 0.72);
  z-index: 9000;
  pointer-events: auto;
  display: none;
  /* Smooth transitions when the cutout moves between targets. */
  transition: top 220ms ease, left 220ms ease,
              width 220ms ease, height 220ms ease;
}
.db-tut-dim.visible { display: block; }

#db-tut-frame {
  position: fixed;
  pointer-events: none;
  border: 3px solid var(--snes-yellow);
  border-radius: 4px;
  box-shadow:
    0 0 18px rgba(248, 208, 0, 0.55),
    inset 0 0 8px rgba(248, 208, 0, 0.20);
  z-index: 9101;
  display: none;
  transition: top 220ms ease, left 220ms ease,
              width 220ms ease, height 220ms ease;
}
#db-tut-frame.visible { display: block; }

/* Skip button: modest weight, bottom-right corner, always above
   the overlay so it's clickable throughout the flow. */
#db-tut-skip {
  position: fixed;
  bottom: 18px;
  right: 18px;
  padding: 6px 14px;
  border: 2px solid #8a6a30;
  background: rgba(20, 12, 6, 0.85);
  color: #c8a060;
  font-family: var(--font);
  font-size: 12px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border-radius: 3px;
  cursor: pointer;
  z-index: 9200;
  opacity: 0.7;
  display: none;
  transition: opacity 0.15s;
}
#db-tut-skip.visible { display: block; }
#db-tut-skip:hover { opacity: 1; color: var(--snes-yellow); border-color: var(--snes-yellow); }

/* Position Lucy's dialogue box centred horizontally near the bottom
   of the viewport while the deck-builder tutorial is active. The
   element (#tut-box) is the same one the home-screen intro uses;
   the base rule already centres it via translateX(-50%) and sizes
   it up to 985px wide. This override:
     - keeps the horizontal centring (no transform: none)
     - pins it near the bottom (so the card grid above stays readable)
     - shrinks the width cap to ~650px (~25% wider than the previous
       520px cap; comfortable on Chromebook 1366×768 without dominating)
     - compresses internal padding to keep total height ~15% shorter */
#tut-box.db-tut-positioned {
  position: fixed;
  bottom: 32px;
  left: 50%;
  transform: translateX(-50%);
  top: auto;
  right: auto;
  width: 900px;
  /* Pin the box to a stable height so the perceived size doesn't
     change between 1-line and 2-line dialogues. Wider 900px width
     makes the longest dialogue wrap to a single line, so 188px is
     enough headroom for portrait + text + click-to-continue hint. */
  min-height: 188px;
  z-index: 9200;
}
/* Tighter inner spacing + smaller dialogue font on the deck-builder
   variant so the box reads as a smaller, less intrusive prompt.
   20px font (down from 24px) lets the longest single-line dialogue
   fit at 900px wide without wrapping, which keeps the height stable. */
#tut-box.db-tut-positioned .tut-portrait {
  width: 116px;
}
#tut-box.db-tut-positioned #tut-text {
  font-size: 20px;
  padding: 6px 14px;
  line-height: 1.15;
}
#tut-box.db-tut-positioned #tut-hint {
  padding: 0 14px 6px;
}


/* ═══════════════════════════════════════════════════════════════════
   LOCATION NAMEPLATE — clickable affordance
   .battle-loc-info--clickable is added by buildLocationTile when the
   location popup feature is available.
═══════════════════════════════════════════════════════════════════ */
.battle-loc-info--clickable {
  cursor: pointer;
  transition: filter 0.15s ease;
  border-radius: 3px;
}
.battle-loc-info--clickable:hover {
  filter: brightness(1.18);
}
.battle-loc-info--clickable:active {
  filter: brightness(0.9);
}

/* ═══════════════════════════════════════════════════════════════════
   LOCATION POPUP OVERLAY + PANEL
   Dark-wood parchment theme matching the battle card popup.
   Animates in via .active — opacity fade + scale from 0.87 → 1.
═══════════════════════════════════════════════════════════════════ */

/* Full-screen dimmed backdrop */
#location-popup-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 10, 2, 0.75);
  z-index: 950;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.28s ease-out;
  /* Click on overlay itself closes popup (wired in JS) */
}
#location-popup-overlay.active {
  opacity: 1;
}

/* Popup panel */
.location-popup {
  position: relative;
  width: 480px;
  max-width: 92vw;
  padding: 22px 20px 18px;
  background:
    repeating-linear-gradient(
      0deg,
      transparent 0px, transparent 6px,
      rgba(0, 0, 0, 0.10) 6px, rgba(0, 0, 0, 0.10) 7px
    ),
    linear-gradient(180deg,
      #2a1608 0%,
      #3a200c 50%,
      #2a1608 100%
    );
  border: 2px solid #d4aa50;
  border-radius: 6px;
  box-shadow:
    0 0 0 3px #1a0c04,
    0 0 0 6px #6a4418,
    0 0 0 7px #1a0c04,
    inset 0 0 28px rgba(60, 30, 0, 0.55);
  transform: scale(0.87);
  transition: transform 0.28s ease-out;
}
#location-popup-overlay.active .location-popup {
  transform: scale(1);
}

/* Close (×) button — top-right corner */
.location-popup-close {
  position: absolute;
  top: 8px;
  right: 10px;
  background: none;
  border: none;
  color: #c8a060;
  font-size: 18px;
  cursor: pointer;
  line-height: 1;
  padding: 2px 5px;
  transition: color 0.15s;
}
.location-popup-close:hover { color: #f8d000; }

/* Side labels ("OPPONENT 5" / "YOU 7") */
.location-popup-side-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 11px;
  color: #c8a060;
  letter-spacing: 0.08em;
  padding: 0 4px 4px;
}
.location-popup-side-total {
  font-size: 15px;
  color: #e8c060;
  font-weight: bold;
}

/* Row of contributor thumbnails */
.location-popup-contributors {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  min-height: 72px;
  padding: 6px 4px;
}
/* Individual card thumbnail */
.location-popup-thumb {
  display: flex;
  flex-direction: column;
  align-items: center;
  cursor: pointer;
  width: 52px;
  outline: none;
}
.location-popup-thumb-img {
  width: 48px;
  height: 58px;
  background-size: cover;
  background-position: center top;
  border-radius: 3px;
  border: 1px solid #6a4418;
  transition: border-color 0.12s;
}
.location-popup-thumb:hover .location-popup-thumb-img,
.location-popup-thumb:focus .location-popup-thumb-img {
  border-color: #f8d000;
}
.location-popup-thumb-ip {
  font-size: 13px;
  color: #f8d000;
  font-weight: bold;
  margin-top: 3px;
  line-height: 1;
}

/* Enlarged location nameplate strip */
.location-popup-nameplate {
  border-top: 1px solid rgba(180, 130, 40, 0.55);
  border-bottom: 1px solid rgba(180, 130, 40, 0.55);
  text-align: center;
  padding: 10px 8px;
  margin: 4px 0;
}
.location-popup-name {
  font-size: 20px;
  color: #e8c060;
  text-shadow: 2px 2px 0 #000, 0 0 8px rgba(220, 170, 60, 0.30);
  line-height: 1.2;
}
.location-popup-abilitytext {
  font-size: 10px;
  color: #a88040;
  margin-top: 5px;
  line-height: 1.3;
}


/* ================================================================
   ADVENTURE MODE HUD — Phase H1
   Bottom bar: 1280×96 px, pinned inside #sog-stage.
   Three zones: LEFT portrait | CENTER deck slots + music | RIGHT util.
   z-index 150: above map overlay (z30), below travel transition (z200)
   and dialogue boxes (z9999).
   ================================================================ */

/* ── Outer bar ───────────────────────────────────────────────── */
#adv-hud {
  /* Hidden by default; CSS shows it when data-screen === "overworld" */
  display: none;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 120px;
  flex-direction: row;
  align-items: stretch;
  z-index: 150;

  /* Natural wood — warm boards with soft, slightly irregular long grain running
     along the bar (two overlaid grain layers with different periods so the lines
     don't read as a regular stripe), gentle tonal banding, and a top-lit sheen. */
  background:
    /* fine grain layer A */
    repeating-linear-gradient(0deg,
      rgba(0, 0, 0, 0)        0px,
      rgba(0, 0, 0, 0)        6px,
      rgba(38, 20, 6, 0.07)   7px,
      rgba(0, 0, 0, 0)        9px),
    /* fine grain layer B (different period → quasi-irregular) */
    repeating-linear-gradient(0deg,
      rgba(255, 226, 180, 0.025) 0px,
      rgba(255, 226, 180, 0.025) 1px,
      rgba(0, 0, 0, 0)           11px),
    /* broad tonal bands for natural colour variation */
    linear-gradient(0deg,
      rgba(90, 55, 22, 0.10) 0%,
      rgba(0, 0, 0, 0.00)    50%,
      rgba(70, 42, 16, 0.10) 100%),
    /* warm base, top-lit → darker at the bottom */
    linear-gradient(180deg, #6e4119 0%, #5a3414 42%, #482a0f 78%, #3c2209 100%);
  border-top: 3px solid #d4aa50;
  box-shadow:
    inset 0 2px 0 rgba(248, 220, 80, 0.12),
    0 -2px 14px rgba(0, 0, 0, 0.55);
  font-family: var(--font);
}

/* Show when the overworld screen is active */
body[data-screen="overworld"] #adv-hud {
  display: flex;
}

/* ── Map area: constrain to 600 px (720 − 120 HUD) ───────────────
   Restricts the regional map image and its overlay (nodes, character,
   exit zones) to the space above the HUD bar. The travel transition
   and fog overlays are intentionally NOT constrained — they cover the
   full stage so the HUD is cleanly obscured during loading/fog events.
   Percentage-based coordinates for nodes, spawn points, and walk paths
   remain accurate because they scale relative to the new 600 px height. */
body[data-screen="overworld"] #overworld-map,
body[data-screen="overworld"] #overworld-overlay {
  height: calc(100% - 120px);   /* 720 - 120 = 600 px */
}

/* ── LEFT group: avatar+name · focus/textbook · gold coin ────────
   Anchored to the left edge. Children spaced by margins (no flex gap) so
   focus + gold collapse cleanly to width 0 in dialogue mode. */
#adv-hud-left {
  flex-shrink: 0;
  display: flex;
  flex-direction: row;
  align-items: center;
}

/* ── Portrait zone — avatar + static player title stacked ──────── */
#adv-hud-portrait {
  width: 120px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  /* Transparent so the HUD's wood texture runs continuously behind the
     portrait (no separate brown panel around the frame). */
  background: transparent;
  cursor: pointer;
  transition: background 0.15s;
}
#adv-hud-portrait:hover {
  /* Subtle warm highlight over the wood on hover. */
  background: radial-gradient(ellipse at 50% 35%, rgba(212, 170, 80, 0.16) 0%, transparent 70%);
}
#adv-hud-portrait img {
  width: 84px;
  height: 84px;
  object-fit: cover;
  object-position: center top;
  border: 2px solid #d4aa50;
  border-radius: 3px;
  box-shadow:
    inset 0 0 0 1px rgba(248, 220, 80, 0.18),
    0 2px 6px rgba(0, 0, 0, 0.65);
  display: block;
}

/* Static player title (default "Explorer"); SOG.HUD.setName() can feed it. */
#adv-hud-player-name {
  font-family: var(--font);
  font-size: 11px;
  font-weight: bold;
  letter-spacing: 0.06em;
  color: rgba(243, 213, 116, 0.95);
  text-transform: uppercase;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
  line-height: 1;
  white-space: nowrap;
}

/* ── Focus column — fills the full bar height: the big FOCUS word fills
   the space above the (thin, HUD-centred) bar, and the textbook fills the
   space below. Label + textbook share equal flex so the bar stays centred. */
#adv-hud-focus-col {
  flex-shrink: 0;
  margin-left: 16px;
  align-self: stretch;
  width: 168px;   /* widened so the left group ≈ the right group (balance) */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 6px 0;
}
/* FOCUS word — grows to fill the top space, large. */
.adv-hud-focus-label {
  flex: 1 1 0;
  min-height: 0;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font);
  font-size: 22px;
  font-weight: bold;
  letter-spacing: 0.07em;
  color: rgba(212, 170, 80, 0.9);
  text-transform: uppercase;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  line-height: 1;
}
/* Thin bar — sits centred in the HUD. */
.adv-hud-focus-track {
  flex-shrink: 0;
  width: 100%;
  height: 9px;
  border: 1px solid rgba(212, 170, 80, 0.5);
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.4);
  overflow: hidden;
}
.adv-hud-focus-fill {
  height: 100%;
  width: 72%;   /* static placeholder level */
  background: linear-gradient(180deg, #6fcf5a 0%, #3fae2e 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
/* Textbook — placeholder for a future learning-check that boosts focus.
   Shares equal flex with the FOCUS word (so the bar stays centred) and fills
   the bottom space; aspect-ratio keeps it square so the (4096px) source can't
   claim its natural width and blow out the column. */
#adv-hud-textbook {
  flex: 1 1 0;
  min-height: 0;
  min-width: 0;        /* Firefox: without this the img's auto min-width resolves to
                          its intrinsic (4096px) width and, via aspect-ratio, refuses
                          to shrink — overflowing the column and shoving FOCUS/bar out
                          of place. Chrome/Safari clamp it anyway; Firefox needs this. */
  height: auto;
  width: auto;
  aspect-ratio: 1 / 1;
  max-width: 150px;
  max-height: 100%;    /* hard cap to the column so it can never blow out vertically */
  object-fit: contain;
  filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.5));
  user-select: none;
  display: block;
}

/* Focus-gate beacon: pulsing gold halo on the book button while Focus is 0 and
   the player has hit the gate. drop-shadow follows the book's alpha shape, so the
   glow hugs the icon (not a rectangle). Added/removed via .adv-hud-textbook--halo
   (SOG.HUD.showFocusHalo / refreshFocus). */
@keyframes adv-hud-textbook-halo {
  0%, 100% {
    filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.5))
            drop-shadow(0 0 6px rgba(232, 192, 96, 0.9))
            drop-shadow(0 0 10px rgba(232, 192, 96, 0.6));
  }
  50% {
    filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.5))
            drop-shadow(0 0 14px rgba(240, 205, 110, 1))
            drop-shadow(0 0 24px rgba(240, 200, 110, 0.85));
  }
}
#adv-hud-textbook.adv-hud-textbook--halo {
  cursor: pointer;
  animation: adv-hud-textbook-halo 1.1s ease-in-out infinite;
}

/* ── Gold — coin with the balance overlaid in its centre (white) ── */
#adv-hud-gold {
  position: relative;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Coin is taller than the 120px bar — anchor it to the bottom so it overflows
     into the map. Nudged down slightly (the visible coin face has generous
     transparent padding, so it won't clip). */
  align-self: flex-end;
  margin-bottom: -1px;
}
/* Coin 25% bigger again (116→145px); overflows the bar top. */
#adv-hud-gold-coin {
  width: 145px;
  height: 145px;
  object-fit: contain;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55));
  user-select: none;
  display: block;
}
#adv-hud-gold-num {
  position: absolute;
  left: 50%;
  top: 50%;
  /* The coin face centre sits ~3% below the image centre, so nudge the number
     down to sit in the middle of the visible coin. */
  transform: translate(-50%, calc(-50% + 4px));
  font-family: var(--font);
  font-size: 37px;
  font-weight: bold;
  color: #ffffff;
  letter-spacing: 0.01em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85), 0 0 3px rgba(120, 70, 10, 0.9);
  pointer-events: none;
}
/* Triple-digit (100+) totals drop 2px so the wider number still fits the coin. */
#adv-hud-gold-num.gold-triple {
  font-size: 35px;
}

/* ── MIDDLE: dynamic region name (BIG); also hosts the dialogue overlay
   (position: relative set in the State B block above). ──────────── */
#adv-hud-center {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 16px;
}
#adv-hud-region {
  /* Absolutely centred on the WHOLE bar (independent of the left/right groups'
     widths) so the region name is dead-centre horizontally on screen. */
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 1;
  font-family: var(--font);
  font-size: 38px;
  font-weight: bold;
  letter-spacing: 0.10em;
  color: #f0d99a;
  text-transform: uppercase;
  text-shadow: 0 3px 4px rgba(0, 0, 0, 0.65), 0 0 2px #5a3a08;
  line-height: 1;
  white-space: nowrap;
  text-align: center;
}

/* ── RIGHT group: deck card-back (→ deck builder) · Options icon ── */
#adv-hud-util {
  flex-shrink: 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-end;
  /* Per-item margins (not a uniform gap): the coin has ~36px of transparent
     padding on its right, so the deck is pulled in to keep the VISUAL coin→deck
     gap equal to the deck→options gap. */
  padding: 0 10px;
}
#adv-hud-deck    { margin-left: -8px; }   /* coin → deck (compensates coin padding) */
#adv-hud-btn-options { margin-left: 24px; }  /* deck → options */

/* Card-back deck button — merges the old deck slot + Deck Builder button.
   Click opens the deck builder; the active deck name shows underneath. */
#adv-hud-deck {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  cursor: pointer;
}
.adv-hud-deck-back {
  height: 86px;
  width: auto;
  border: 2px solid #d4aa50;
  border-radius: 4px;
  box-shadow:
    inset 0 0 0 1px rgba(248, 220, 80, 0.18),
    0 2px 6px rgba(0, 0, 0, 0.6);
  display: block;
  transition: transform 0.12s, box-shadow 0.12s, border-color 0.12s;
}
#adv-hud-deck:hover .adv-hud-deck-back {
  transform: translateY(-2px);
  border-color: #f6d873;
  box-shadow:
    inset 0 0 0 1px rgba(248, 220, 80, 0.30),
    0 4px 10px rgba(0, 0, 0, 0.6);
}
#adv-hud-deck-name {
  font-family: var(--font);
  font-size: 9px;
  font-weight: bold;
  letter-spacing: 0.05em;
  color: rgba(243, 213, 116, 0.95);
  text-transform: uppercase;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
  line-height: 1;
  max-width: 88px;
  text-align: center;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
/* Locked state — greyed out + non-interactive until the deck builder unlocks
   (after the first Gilgamesh win + marketplace visit). Keeps the player from
   being distracted by it early in adventure mode. */
#adv-hud-deck.adv-hud-deck-locked {
  cursor: default;
  pointer-events: none;
  filter: grayscale(1) brightness(0.55);
  opacity: 0.5;
}
#adv-hud-deck.adv-hud-deck-locked #adv-hud-deck-name {
  color: rgba(200, 200, 200, 0.6);
}

/* Options — unlabeled icon settings button. */
#adv-hud-btn-options {
  flex-shrink: 0;
  width: 80px;
  height: 80px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  /* opacity is listed too: this rule comes after the shared HUD fade
     (#adv-hud-btn-options { transition: opacity 0.25s } above) and would
     otherwise replace it, so the button snapped out in dialogue mode instead
     of fading with gold + deck. */
  transition: opacity 0.25s ease, transform 0.12s, filter 0.12s;
}
#adv-hud-btn-options img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.5));
  display: block;
}
#adv-hud-btn-options:hover { transform: scale(1.06); }
#adv-hud-btn-options:hover img { filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.6)) brightness(1.08); }
#adv-hud-btn-options:active { transform: scale(0.97); }

/* End Adventure Mode HUD — Phase H1 */

/* ─────────────────────────────────────────────────────────────────
   Per-card REVEAL presentation (flavor only — see js/game/reveal-fx.js).
   Each class is added to a .battle-card-slot during reveal and self-removes.
   Cards without these classes are completely unaffected.
   ───────────────────────────────────────────────────────────────── */

/* Fire (29): warm illuminate pulse that flares then settles back to rest. */
@keyframes revealFxIlluminate {
  0%   { filter: brightness(1);   box-shadow: none; }
  30%  { filter: brightness(1.65); box-shadow: 0 0 20px 7px rgba(255, 168, 56, 0.9); }
  100% { filter: brightness(1);   box-shadow: none; }
}
.battle-card-slot.reveal-fx-illuminate {
  animation: revealFxIlluminate 0.85s ease-out;
  z-index: 6;
}

/* Fire (29) embers: a handful of glowing particles that rise from the card's
   CENTRE, drift slightly OUTWARD as they rise (per-particle randomized angle),
   flicker, and fade. The LAYER is anchored at the card centre; each
   .reveal-fx-ember carries randomized custom props set in reveal-fx.js
   spawnEmbers() — --rise (how high), --dx (outward drift, +/-), --dur (speed),
   --delay (stagger), --peak (max opacity) — driving the rise+drift+fade envelope.
   Its .reveal-fx-ember-core is the glowing dot doing a fast opacity/scale flicker;
   nested opacity MULTIPLIES, so the flicker rides on top of the fade envelope.
   Tuning knobs: ember COUNT / COLORS / size / all random ranges live in
   spawnEmbers(); the envelope shape + start/end scale live in the keyframes here. */
.battle-card-slot .reveal-fx-ember-layer {
  position: absolute;
  left: 50%;
  top: 50%;                       /* embers emanate from the card centre */
  width: 0;
  height: 0;
  pointer-events: none;
  z-index: 10;                    /* above the card face + the illuminate glow */
}
.reveal-fx-ember {
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
  will-change: transform, opacity;
  /* rise + drift + fade; `both` holds the faded-out end state until cleanup */
  animation: revealFxEmberRise var(--dur, 0.85s) ease-out var(--delay, 0s) 1 both;
}
.reveal-fx-ember-core {
  border-radius: 50%;
  /* fast flicker (period set inline per-ember); alternate = gentle pulse */
  animation: revealFxEmberFlicker 0.15s ease-in-out infinite alternate;
}
@keyframes revealFxEmberRise {
  0%   { transform: translate(-50%, -50%) scale(0.55); opacity: 0; }
  18%  { opacity: var(--peak, 1); }
  100% {
    transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% - var(--rise, 60px))) scale(0.85);
    opacity: 0;
  }
}
@keyframes revealFxEmberFlicker {
  0%   { opacity: 0.55; transform: scale(0.82); }
  100% { opacity: 1;    transform: scale(1.05); }
}

/* Shared neighbor-border glow — the BORDERS of adjacent cards glow, then fade.
   Mostly an INSET glow so it hugs the target card's border and does NOT bleed
   across the slot gap onto the source card beside it; a small tight outset adds a
   touch of bloom. The COLOUR is factored into CSS variables so multiple cards can
   reuse the SAME keyframe with their own colour:
     • Domesticated Animal (32) — green (the original look, unchanged)
     • Enkidu (44)              — warm amber/bronze
   Each card's handler adds exactly one of the colour classes below. */
@keyframes revealFxNeighborGlow {
  0%   { box-shadow: inset 0 0 0 0    var(--ng-inset-off), 0 0 0 0   var(--ng-out-off); }
  30%  { box-shadow: inset 0 0 12px 2px var(--ng-inset-on),  0 0 6px 1px var(--ng-out-on); }
  100% { box-shadow: inset 0 0 0 0    var(--ng-inset-off), 0 0 0 0   var(--ng-out-off); }
}
.battle-card-slot.reveal-fx-neighbor-glow,
.battle-card-slot.reveal-fx-neighbor-glow-enkidu {
  animation: revealFxNeighborGlow 0.85s ease-out;
  z-index: 6;
}
/* Domesticated Animal — green (identical to the original) */
.battle-card-slot.reveal-fx-neighbor-glow {
  --ng-inset-on:  rgba(150, 240, 150, 0.95);
  --ng-inset-off: rgba(150, 240, 150, 0);
  --ng-out-on:    rgba(120, 220, 120, 0.5);
  --ng-out-off:   rgba(120, 220, 120, 0);
}
/* Enkidu — warm amber/bronze (distinct from DA's green) */
.battle-card-slot.reveal-fx-neighbor-glow-enkidu {
  --ng-inset-on:  rgba(255, 170, 60, 0.95);
  --ng-inset-off: rgba(255, 170, 60, 0);
  --ng-out-on:    rgba(235, 130, 45, 0.55);
  --ng-out-off:   rgba(235, 130, 45, 0);
}

/* Neanderthal (34): small drop-into-place settle (drops a few px and lands). */
@keyframes revealFxDropIn {
  0%   { transform: translateY(-10px); }
  70%  { transform: translateY(2px); }
  100% { transform: translateY(0); }
}
.battle-card-slot.reveal-fx-dropin {
  animation: revealFxDropIn 0.42s cubic-bezier(0.34, 1.4, 0.64, 1);
}

/* Ziggurat (45): "struck bell" ring-out — a DAMPED oscillation. The card swings
   (pivoting at the top, like a hanging bell) and sways side-to-side with steadily
   DECREASING amplitude, then settles to rest — a single strike that rings out, not
   a sustained/looping shake. The decay lives in the keyframe amplitudes (6px/2.2°
   down to 0). Tuning knobs: peak amplitude (the 8% keyframe), how fast it decays
   (the falloff across keyframes), and the 1.1s duration. */
@keyframes revealFxZigguratRing {
  0%   { transform: translateX(0)      rotate(0deg); }
  8%   { transform: translateX(-6px)   rotate(-2.2deg); }
  19%  { transform: translateX(5px)    rotate(1.8deg); }
  30%  { transform: translateX(-3.6px) rotate(-1.4deg); }
  42%  { transform: translateX(2.6px)  rotate(1.0deg); }
  55%  { transform: translateX(-1.7px) rotate(-0.65deg); }
  68%  { transform: translateX(1.0px)  rotate(0.4deg); }
  82%  { transform: translateX(-0.5px) rotate(-0.18deg); }
  100% { transform: translateX(0)      rotate(0deg); }
}
.battle-card-slot.reveal-fx-ziggurat-ring {
  animation: revealFxZigguratRing 1.1s ease-out;
  transform-origin: center top;   /* swing from the top, like a hanging bell */
  z-index: 6;
}

/* Domesticated Animal (32) + Enkidu (44) "howl" — both sfx are a wolf howl, so the
   card REARS its head UP: pivoting on its BOTTOM-LEFT corner it tilts back/up (like
   a wolf raising its snout to howl at the moon), HOLDS the pose, then lowers back to
   rest. Shared by both cards. Tuning knobs: peak tilt (the -21° keyframe), how long
   it holds up (the 26%→68% plateau), and the 1.8s duration. */
@keyframes revealFxHowl {
  0%   { transform: rotate(0deg); }
  16%  { transform: rotate(-18deg); }   /* raise head up */
  26%  { transform: rotate(-21deg); }   /* peak */
  68%  { transform: rotate(-18deg); }   /* sustained howl (head held up) */
  100% { transform: rotate(0deg); }     /* lower back down to rest */
}
.battle-card-slot.reveal-fx-howl {
  animation: revealFxHowl 1.8s ease-in-out;
  transform-origin: left bottom;   /* pivot on the BOTTOM-LEFT corner */
  z-index: 7;
}
/* …and the mirror: pivots on the bottom-RIGHT corner, so the head tilts toward
   the LEFT — used for a howl aimed at the slot on the left. (The left-pivot
   keyframe above tilts the head toward the RIGHT.) */
@keyframes revealFxHowlRight {
  0%   { transform: rotate(0deg); }
  16%  { transform: rotate(18deg); }
  26%  { transform: rotate(21deg); }
  68%  { transform: rotate(18deg); }
  100% { transform: rotate(0deg); }
}
.battle-card-slot.reveal-fx-howl-right {
  animation: revealFxHowlRight 1.8s ease-in-out;
  transform-origin: right bottom;  /* pivot on the BOTTOM-RIGHT corner */
  z-index: 7;
}

/* Tool (26): "hammer swing" — rotate upright → full horizontal pivoting on the
   bottom-right corner (the strike), then rebound/overshoot back to upright.
   IMPACT (full horizontal) is the 50% keyframe; reveal-fx.js times the SFX, the
   draw, and the drawn-card pull-in to that 50% mark (500ms into the 1s anim). */
@keyframes revealFxToolSwing {
  0%   { transform: rotate(0deg);   animation-timing-function: ease-in; }
  12%  { transform: rotate(-12deg); animation-timing-function: ease-in;  }  /* wind-up back */
  50%  { transform: rotate(90deg);  animation-timing-function: ease-out; }  /* IMPACT — full horizontal */
  64%  { transform: rotate(72deg);  animation-timing-function: ease-in-out; } /* rebound */
  80%  { transform: rotate(-9deg);  animation-timing-function: ease-in-out; } /* overshoot past upright */
  92%  { transform: rotate(4deg); }
  100% { transform: rotate(0deg); }                                        /* settle */
}
.battle-card-slot.reveal-fx-tool-swing {
  transform-origin: 100% 100%;   /* bottom-right corner pivot */
  animation: revealFxToolSwing 1s;
  z-index: 7;
}

/* The card Tool draws "pulls in" — rises from below with a scale-up overshoot,
   landing on the hammer strike (reveal-fx.js applies this at the impact beat). */
@keyframes revealFxToolDrawIn {
  0%   { transform: translateY(40px) scale(0.55); opacity: 0; }
  55%  { transform: translateY(-6px) scale(1.08); opacity: 1; }
  100% { transform: translateY(0)    scale(1);    opacity: 1; }
}
.battle-hand-card.reveal-fx-tool-draw-in {
  animation: revealFxToolDrawIn 0.45s cubic-bezier(0.34, 1.4, 0.64, 1);
  z-index: 5;
}

/* Cave Art (30): a caveman ARM holding charcoal pops in over the card's face and
   "scribbles" (a subtle wandering jitter + slight rotation) while caveart.m4a
   plays, then fades out (see js/game/reveal-fx.js). No marks are drawn — the
   motion implies it. The PNG's charcoal/drawing tip is ~40%/51% of the image; we
   anchor that point to the card's centre-slightly-high and pivot the wiggle there.
   Tuning knobs: width (arm size), left/top (the drawing spot on the card), the
   translate base + deltas in the keyframes (scribble amount), the 0.32s animation
   (scribble speed), and the JS fallback duration / sfx 'ended' (overall length). */
.battle-card-slot .reveal-fx-caveart-arm {
  position: absolute;
  left: 50%;
  top: 38%;                       /* anchor: card centre, slightly above middle */
  width: 165%;                    /* arm size relative to the card */
  height: auto;
  transform-origin: 40% 51%;      /* the charcoal / drawing tip */
  pointer-events: none;
  z-index: 9;
  opacity: 1;                     /* pops in instantly — no fade-in */
  transition: opacity 0.45s ease;
  filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.5));
  animation: revealFxCaveArtScribble 0.32s ease-in-out infinite;
}
.battle-card-slot .reveal-fx-caveart-arm.reveal-fx-caveart-arm-out {
  opacity: 0;
}
/* The base translate aligns the charcoal tip (~40%/51% of the PNG) to the anchor;
   the small per-keyframe deltas are the scribble (wander + slight rotation). */
@keyframes revealFxCaveArtScribble {
  0%   { transform: translate(-40%, -51%) rotate(0deg); }
  20%  { transform: translate(-43%, -53%) rotate(-2.5deg); }
  40%  { transform: translate(-37%, -49%) rotate(2deg); }
  60%  { transform: translate(-42%, -52%) rotate(-1.5deg); }
  80%  { transform: translate(-38%, -50%) rotate(2.5deg); }
  100% { transform: translate(-40%, -51%) rotate(0deg); }
}

/* Tribe (36): reactive "happy hop" — a small double-bounce upward, fired each
   time Tribe gains bonus IP from a card played at its location (see abilities.js
   tribeReactBounce → SOG.RevealFx.reactBounce). Self-removing so it re-triggers
   on each subsequent bonus. Tuning: hop height (-14px) and duration (0.45s). */
@keyframes revealFxBounce {
  0%   { transform: translateY(0); }
  28%  { transform: translateY(-14px); }
  52%  { transform: translateY(0); }
  70%  { transform: translateY(-6px); }
  100% { transform: translateY(0); }
}
.battle-card-slot.reveal-fx-bounce {
  animation: revealFxBounce 0.45s cubic-bezier(0.3, 0.7, 0.4, 1);
  z-index: 6;
}

/* Farmer (39): an onion that POPS UP from the card's CENTRE and DISSIPATES as it
   rises (see reveal-fx.js handler 39 + the revealFxOnionPop keyframes). The <img>
   is centred on the card; the keyframe pops it in with a slight scale overshoot,
   floats it upward, and fades it out — then JS removes the element. Tuning knobs:
   width (onion size), the translateY at 100% (rise height), the animation duration
   (pop+fade speed), and the opacity/scale stops (pop snappiness vs fade). */
/* Scribe (40) stamping: ONE travelling stamp (fixed-position so it floats above
   the whole board, independent of any slot's clipping) presses onto each target
   card; a cuneiform MARK is left inside the card for ~markMs then fades. The JS
   (reveal-fx.js scribeStampSequence) drives position/timing via inline styles;
   these rules only set the look. Tuning of timing lives in abilities.js (the opts
   passed to scribeStampSequence) and in the JS; sizes/shadows are tuned here. */
/* Soldier (42) charge: a spear (fixed-position so it flies over the whole board)
   travels from the Soldier to the chosen target and back; the struck card shakes
   on impact. JS (reveal-fx.js soldierCharge) drives position/rotation/timing via
   inline styles — these rules only set the look. Tuning of timing/rotation lives
   in soldierCharge's opts; size/shadow here. */
/* The Soldier card itself charges (a fixed-position clone); the spear is ATTACHED
   to it at the leading edge, pointing at the target. */
.reveal-fx-soldier-flyer {
  z-index: 9998;                  /* above the board */
  will-change: left, top, transform;
  filter: drop-shadow(0 8px 12px rgba(0, 0, 0, 0.6));   /* lifted-card elevation */
  border-radius: 8px;
}
/* Chariot (48) arrow — a fixed-position projectile flung at the target on arrival;
   slide/rotate/dissolve driven by reveal-fx.js inline styles. */
.reveal-fx-chariot-arrow {
  position: fixed;
  width: 150px;                   /* arrow size (knob) */
  height: auto;
  pointer-events: none;
  z-index: 9999;                  /* above the board */
  will-change: left, top, transform, opacity;
  filter: drop-shadow(0 4px 7px rgba(0, 0, 0, 0.65));
}
/* Phoenicians (49) merge — the card clones into a fixed flyer that slides over the
   target and dissolves (slide/fade driven by reveal-fx.js inline styles). */
.reveal-fx-phoenicians-fly {
  z-index: 9998;                  /* above the board, in front of the target's face */
  will-change: left, top, transform, opacity;
  filter: drop-shadow(0 8px 12px rgba(0, 0, 0, 0.6));
  border-radius: 8px;
}
.reveal-fx-soldier-spear {
  position: absolute;             /* child of the charging card */
  width: 180px;                   /* spear size (knob) — long enough to lead the charge */
  height: auto;
  pointer-events: none;
  z-index: 1;                     /* in front of the card face */
  filter: drop-shadow(0 4px 7px rgba(0, 0, 0, 0.65));
}
@keyframes revealFxSoldierHit {
  0%   { transform: translate(0, 0); }
  15%  { transform: translate(-8px, 4px); }
  35%  { transform: translate(8px, -4px); }
  55%  { transform: translate(-6px, 3px); }
  75%  { transform: translate(5px, -2px); }
  100% { transform: translate(0, 0); }
}
.battle-card-slot.reveal-fx-soldier-hit {
  animation: revealFxSoldierHit 0.34s ease-in-out;
  z-index: 6;
}

/* Canals (41) water border — PERSISTENT, STATE-DRIVEN (added/removed by
   evaluateContinuous, NOT a one-shot animation). A blue stream cycles around the
   border of every card Canals is CURRENTLY boosting, and is removed the moment the
   boost stops. The ring is a conic gradient masked to the card's edge; animating its
   start angle 0deg->360deg sweeps the bright band around the perimeter like flowing
   water. (@property lets the angle animate; browsers without it show a static ring.) */
@property --canals-angle { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.battle-card-slot.canals-water::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 2px;
  padding: 3px;                          /* water-ring thickness (knob) */
  background: conic-gradient(from var(--canals-angle),
              rgba(70, 170, 235, 0.10), #2aa8e6, #9becff, #2aa8e6, rgba(70, 170, 235, 0.10));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  animation: canalsWaterFlow 2.6s linear infinite;   /* flow speed (knob) */
  pointer-events: none;
  z-index: 7;
}
@keyframes canalsWaterFlow { to { --canals-angle: 360deg; } }

/* The Scribe card itself becomes the stamp: a fixed-position clone that lifts out
   of its slot and presses onto each target (driven by reveal-fx.js inline styles). */
.reveal-fx-scribe-flyer {
  z-index: 9999;                  /* above the board */
  will-change: left, top, transform;
  filter: drop-shadow(0 8px 12px rgba(0, 0, 0, 0.6));   /* lifted-card elevation */
  border-radius: 8px;
}
.battle-card-slot .reveal-fx-scribe-mark {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 104%;                    /* mark size relative to the card (knob; was 80%, +30%) */
  height: auto;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 8;                     /* on the card face, beneath the pressing card */
  opacity: 0.95;
  transition: opacity 0.26s ease;
  /* Invert the (black) cuneiform art to WHITE so it reads on the card; a dark
     drop-shadow keeps it legible on light cards too. */
  filter: invert(1) drop-shadow(0 1px 2px rgba(0, 0, 0, 0.7));
}
.battle-card-slot .reveal-fx-scribe-mark.reveal-fx-scribe-mark-out {
  opacity: 0;
}

.battle-card-slot .reveal-fx-onion {
  position: absolute;
  left: 50%;
  top: 50%;                       /* sits on the card centre */
  width: 82%;                     /* onion size relative to the card (50% bigger) */
  height: auto;
  pointer-events: none;
  z-index: 9;                     /* above the card face */
  opacity: 0;
  transform: translate(-50%, -50%);
  transform-origin: 50% 50%;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.45));
  animation: revealFxOnionPop 1.25s ease-out forwards;
}
@keyframes revealFxOnionPop {
  0%   { transform: translate(-50%, -50%)  scale(0.6);  opacity: 0; }   /* small, hidden */
  14%  { transform: translate(-50%, -58%)  scale(1.05); opacity: 1; }   /* pop in (overshoot) */
  55%  { transform: translate(-50%, -78%)  scale(1.02); opacity: 1; }   /* linger visible, slow rise */
  100% { transform: translate(-50%, -122%) scale(0.9);  opacity: 0; }   /* rise + dissipate */
}

/* Rosetta Stone (58): the SOURCE card — whatever sits in slot 0 — glows
   purplish-pink while it is being transcribed, marking "this is the card being
   copied". The hue is deliberately unused elsewhere: Ramses is gold, Narmer red,
   Kente orange, the continuous-mod ring cyan, and the IP cues blue.

   TWO CLASSES on purpose. The base class carries the transition and a FULLY
   TRANSPARENT drop-shadow of the same structure; `.is-lit` carries the lit values.
   Toggling `.is-lit` therefore fades the glow up and back down through one
   interpolation — transitioning to `filter: none` instead would be relying on
   none-interpolation and tends to snap. Duration is owned by the animation, which
   adds `.is-lit` at its start and drops it at its end. */
.battle-card-slot.reveal-fx-rosetta-source {
  transition: filter 0.3s ease-out;
  filter: drop-shadow(0 0 0 rgba(232, 121, 233, 0))
          drop-shadow(0 0 0 rgba(168, 66, 208, 0));
}
.battle-card-slot.reveal-fx-rosetta-source.is-lit {
  filter: drop-shadow(0 0 8px rgba(232, 121, 233, 0.95))
          drop-shadow(0 0 20px rgba(168, 66, 208, 0.60));
}

/* Rosetta Stone (58): the scribe's hand that inscribes the transcribed text.
   Body-level fixed (a hand is larger than the card, and .battle-card-slot is
   overflow:hidden), so all positioning and motion belong to reveal-fx.js
   (rosettaTranscribe); this is only the drop shadow that seats it on the card. */
.reveal-fx-scribe-hand {
  filter: drop-shadow(0 4px 7px rgba(0, 0, 0, 0.55));
  user-select: none;
}

/* The SOURCE card shown at the slot just before the bandages go on — the "who is
   coming back" beat, shared by the Priest revival and Book of the Dead. Sits above
   the (hidden) Mummy face and below the strap layer, so the straps build over it.
   Opacity is GSAP's; this only positions it. */
.battle-card-slot .reveal-fx-wrap-source {
  position: absolute;
  inset: 0;
  z-index: 19;
  pointer-events: none;
}

/* Book of the Dead (66): the card under judgment — a body-level flyer carrying the
   real card face, so it is FACE UP for both sides. Lifted off the board with a
   heavier shadow than a slot card, since it is being held up to be read. All
   motion, rotation and the flicker belong to reveal-fx.js (bookJudgment). */
.reveal-fx-judgment-card {
  border-radius: 4px;
  box-shadow: 0 14px 26px rgba(0, 0, 0, 0.66), 0 3px 7px rgba(0, 0, 0, 0.5);
  will-change: transform, opacity;
}

/* Sphinx (64): grains of sand shedding off the card as it rises out of the dune.
   Pale tan/ochre and much finer than Pyramid's dirt clods (which are dark browns at
   roughly twice the size) — the two particle effects sit next to each other in the
   same Egypt set, so they are kept clearly distinct. Slightly irregular rather than
   round; motion is GSAP's (sandCascade). */
/* Akhenaten (77) — "Forsaken Gods": ONE reddish-purple pulse when his discard
   count rises (or when he reveals with a count already standing). One-shot: the
   class is stripped after AKH_PULSE_MS in reveal-fx so it re-triggers on the next
   discard. Deliberately a box-shadow + brightness pulse, not an animated
   multi-layer text-shadow — the Narmer lesson: text-shadow cannot be composited
   and pulsing one costs frames every time it runs. */
@keyframes reveal-fx-akhenaten-pulse-kf {
  0%   { box-shadow: 0 0 0 0 rgba(158, 46, 122, 0);
         filter: brightness(1); }
  28%  { box-shadow: 0 0 18px 6px rgba(158, 46, 122, 0.85),
                     0 0 34px 12px rgba(112, 28, 74, 0.55);
         filter: brightness(1.22) saturate(1.15); }
  100% { box-shadow: 0 0 0 0 rgba(158, 46, 122, 0);
         filter: brightness(1); }
}

.reveal-fx-akhenaten-pulse {
  animation: reveal-fx-akhenaten-pulse-kf 900ms ease-out;
  z-index: 3;
}

/* Imhotep (65) — the sand-sculpted Pyramid.
   .reveal-fx-sand-form is the card-shaped outline the pour gathers into; its child
   .reveal-fx-sand-fill is the sand rising from the base (GSAP animates the height).
   The repeating stripe gives the mass a grainy, settled read rather than a flat
   block. Both are body-level fixed flyers, positioned inline by reveal-fx. */
.reveal-fx-sand-form {
  border: 2px solid rgba(196, 154, 82, 0.95);
  border-radius: 2px;
  /* The drop shadow is what separates a sand-coloured block from the beige
     location art behind it — without it the form reads as a smudge. */
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55),
              0 0 12px rgba(214, 178, 110, 0.45),
              inset 0 0 10px rgba(120, 92, 48, 0.35);
  background: rgba(40, 28, 12, 0.55);
  overflow: hidden;
}

.reveal-fx-sand-fill {
  background:
    repeating-linear-gradient(-8deg,
      rgba(0, 0, 0, 0.06) 0px, rgba(0, 0, 0, 0.06) 2px,
      rgba(255, 255, 255, 0.05) 2px, rgba(255, 255, 255, 0.05) 5px),
    linear-gradient(180deg,
      rgba(238, 216, 168, 0.96) 0%,
      rgba(214, 184, 124, 0.96) 45%,
      rgba(170, 134, 78, 0.96) 100%);
  box-shadow: inset 0 3px 6px rgba(255, 246, 214, 0.5);
}

.reveal-fx-sand-grain {
  border-radius: 45% 55% 50% 50%;
  background: radial-gradient(circle at 38% 32%,
    rgba(238, 216, 168, 0.98) 0%,
    rgba(214, 184, 124, 0.95) 55%,
    rgba(178, 142, 84, 0.88) 100%);
  box-shadow: 0 0 2px rgba(196, 164, 108, 0.6);
}

/* Ra (63): the sun-glow on the card being drawn up into him. Orange-gold — warmer
   and more orange than the capital indicator's pure gold (#ffd700), so "the sun has
   taken this card" never reads as "you gained capital". Motion belongs to
   reveal-fx.js (raAbsorb); this is the light. */
.reveal-fx-ra-card {
  border-radius: 4px;
  box-shadow: 0 12px 22px rgba(0, 0, 0, 0.6);
  will-change: transform, opacity, filter;
}
.reveal-fx-ra-card.reveal-fx-ra-sunglow {
  animation: revealFxRaSun 1.15s ease-out 1 forwards;
}
@keyframes revealFxRaSun {
  0%   { filter: drop-shadow(0 0 2px  rgba(255, 190, 80, 0.5)); }
  30%  { filter: drop-shadow(0 0 12px rgba(255, 176, 32, 1))
                 drop-shadow(0 0 30px rgba(255, 122, 0, 0.85)); }
  100% { filter: drop-shadow(0 0 18px rgba(255, 176, 32, 1))
                 drop-shadow(0 0 44px rgba(255, 122, 0, 0.95)); }
}

/* Hieroglyphics (62): a momentary red flash on a card the moment it GAINS the
   aura. Deliberately not persistent — Narmer's red glow marks an ongoing state,
   this marks an event, and they share the hue on purpose (both are "an Egyptian
   aura is acting on this card").

   `filter` rather than box-shadow: a boosted card has contMod > 0, so Anim.setGlow
   already owns its boxShadow for the cyan continuous ring. Duration is tied to the
   sting — keep in step with HIERO_PULSE_MS in reveal-fx.js. */
.battle-card-slot.reveal-fx-hiero-pulse {
  animation: revealFxHieroPulse 1.25s ease-out 1;
}
@keyframes revealFxHieroPulse {
  0%   { filter: drop-shadow(0 0 0   rgba(240, 64, 48, 0)); }
  18%  { filter: drop-shadow(0 0 10px rgba(245, 80, 64, 1))
                 drop-shadow(0 0 24px rgba(200, 30, 24, 0.8)); }
  55%  { filter: drop-shadow(0 0 8px  rgba(240, 64, 48, 0.85))
                 drop-shadow(0 0 18px rgba(200, 30, 24, 0.55)); }
  100% { filter: drop-shadow(0 0 0   rgba(240, 64, 48, 0)); }
}

/* Egyptian Priest (71): linen straps that wrap the slot as a Mummy is revived.
   The layer sits INSIDE .battle-card-slot, which is overflow:hidden — deliberately,
   so the straps' overhanging ends are trimmed at the card edges and they read as
   bound around the card rather than floating over it. Position, angle, thickness
   and all motion are set per-strap by reveal-fx.js (mummyWrapReveal); these rules
   are only the material. */
.reveal-fx-wrap-layer {
  position: absolute;
  inset: 0;
  z-index: 20;
  pointer-events: none;
}
.reveal-fx-strap {
  position: absolute;
  left: 50%;
  width: 190%;                    /* overhangs both edges; the slot clips the ends */
  transform-origin: 50% 50%;
  border-radius: 2px;
  /* Off-white linen: warm bone tones with a soft weave banding across the width. */
  background:
    repeating-linear-gradient(90deg,
      rgba(255, 255, 255, 0.06) 0px,
      rgba(255, 255, 255, 0.06) 2px,
      rgba(0, 0, 0, 0.05) 2px,
      rgba(0, 0, 0, 0.05) 4px),
    linear-gradient(180deg,
      rgba(243, 236, 220, 0.97) 0%,
      rgba(226, 214, 190, 0.97) 45%,
      rgba(198, 184, 158, 0.97) 100%);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
/* Closes the slivers left between straps so "fully covered" is literally true
   before the dissolve. Faded in by GSAP at the end of the wrap. */
.reveal-fx-wrap-seal {
  position: absolute;
  inset: 0;
  opacity: 0;
  background: linear-gradient(180deg,
    rgba(238, 230, 212, 0.55) 0%,
    rgba(214, 202, 178, 0.62) 100%);
}

/* Pyramid (57): dirt thrown up as it erupts from the ground. Dry earth browns,
   irregular via border-radius rather than perfect circles so they read as clods
   and not as more water droplets. Motion is GSAP's (dirtBurst). */
.reveal-fx-dirt-clod {
  border-radius: 40% 55% 45% 60%;
  background: radial-gradient(circle at 35% 30%,
    rgba(150, 112, 72, 0.98) 0%,
    rgba(110, 78, 48, 0.95) 50%,
    rgba(72, 50, 30, 0.9) 100%);
  box-shadow: 0 0 3px rgba(60, 42, 24, 0.7);
}

/* ── KUSH (78-87) flourishes ──────────────────────────────────────────────
   Flyers below are CLONES of real card elements (a slot or a hand card), so they
   keep .battle-card-slot / .battle-hand-card and the container-type that makes
   the cqw CC/IP badges resolve; these rules only add the in-flight look.
   Position, size and z-index are set inline by the FX. */

/* Piye's copy budding off him (piyeBubbleCopy): a soap-film rim + lift shadow. */
.reveal-fx-piye-bubble {
  box-shadow: 0 0 0 2px rgba(140, 210, 255, 0.55), 0 12px 28px rgba(0, 0, 0, 0.6);
  filter: saturate(1.1) brightness(1.05);
  border-radius: 6px;
}
/* A card in flight between a deck pile and a slot / hand (deckCardToHand,
   deckCardToSlot). */
.reveal-fx-deck-fly {
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.65);
}
/* The face-down flyer's back fills its clone (Trade Network's replacement
   arriving face down). Later than .battle-card-back, so these win. */
.reveal-fx-card-back-fly {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  border-radius: inherit;
}

/* The Iron Furnace (87): the quick pop on ignite (ironFurnaceIgnite; sparks are
   the shared spawnEmbers layer). */
.battle-card-slot.reveal-fx-furnace-pop {
  animation: revealFxFurnacePop 0.46s cubic-bezier(0.3, 0.7, 0.4, 1);
  z-index: 6;
}
@keyframes revealFxFurnacePop {
  0%   { transform: translateY(0)     scale(1); }
  30%  { transform: translateY(-16px) scale(1.06); }
  60%  { transform: translateY(0)     scale(1); }
  80%  { transform: translateY(-5px); }
  100% { transform: translateY(0); }
}
/* The red flame burning UNDER each boosted Labor card for the clip's duration.
   Appended to the slot (clipped to the card); screen-blended so it reads as fire
   on top of the art rather than a red block. Removed by the FX when the clip ends. */
.battle-card-slot .reveal-fx-furnace-flame {
  position: absolute;
  left: 4%;
  right: 4%;
  bottom: -2%;
  height: 44%;
  pointer-events: none;
  z-index: 9;
  background: radial-gradient(ellipse at 50% 100%,
    rgba(255, 214, 90, 0.95) 0%,
    rgba(255, 112, 30, 0.90) 26%,
    rgba(222, 32, 20, 0.78) 54%,
    rgba(120, 0, 0, 0) 78%);
  filter: blur(1.5px);
  mix-blend-mode: screen;
  transform-origin: 50% 100%;
  animation: revealFxFurnaceFlame 0.28s ease-in-out infinite alternate;
}
@keyframes revealFxFurnaceFlame {
  0%   { transform: scaleY(0.82) scaleX(1.04); opacity: 0.8; }
  100% { transform: scaleY(1.12) scaleX(0.96); opacity: 1; }
}

/* The nugget struck out of the Nubian Gold Mines (nubianGoldEmerge). Same
   throwaway-particle contract as .reveal-fx-dirt-clod above: position/size/z-index
   are set inline by the FX, this rule owns only the look. Irregular ore silhouette
   rather than a disc so it reads as raw gold, not a coin. */
.reveal-fx-gold-nugget {
  border-radius: 46% 58% 42% 62% / 55% 44% 60% 45%;
  background: radial-gradient(circle at 32% 28%,
    #fff6cf 0%,
    #f3cf5e 34%,
    #d1a02c 66%,
    #8a6410 100%);
  box-shadow: 0 0 10px rgba(247, 208, 96, 0.85),
              0 0 22px rgba(214, 160, 40, 0.5),
              inset -2px -2px 4px rgba(96, 68, 12, 0.55);
}

/* The OUTGOING number in an IP badge swap (ipBadgeSwap). A clone of the badge
   that keeps the badge's own geometry — it is given the same .db-overlay-ip class
   so it sits exactly where the real number was — then falls away while the new
   value drops in. Motion and fade are GSAP's; this only detaches it from layout
   so the real badge is not pushed around while it falls. */
.db-overlay-ip.reveal-fx-ip-old {
  pointer-events: none;
  z-index: 12;
}

/* Farmer — EGYPT (55) PHASE 2: the onion that falls onto the card which took the
   +1. Unlike the Phase 1 pop this is a BODY-LEVEL fixed flyer positioned from the
   card's rect, because .battle-card-slot is overflow:hidden and would clip a drop
   that starts above the card. Motion, opacity and the final hard cut all belong to
   GSAP in farmerOnionBite — this rule is only the look. */
.reveal-fx-onion-bite {
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.55));
}

/* ================================================================
   OPTIONS PANEL — shared overlay (overworld + battle). Clones the
   card-popup/backdrop look; hosts the relocated music widget.
   ================================================================ */
.options-backdrop { z-index: 9000; }   /* above the HUD, below result scoreboards */

.options-panel {
  width: 560px;
  max-width: 92vw;
  height: 540px;               /* fixed — the box stays one size across both tabs.
                                  Raised from 460px when the Gameplay section landed:
                                  Sounds + Gameplay overflowed by ~76px, pushing a
                                  brand-new setting below the fold. Still well under
                                  max-height (86vh). Raise again if a third section
                                  is added — measure #opt-main-view scrollHeight. */
  max-height: 86vh;
  padding: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;            /* clip the scroll + bottom bar to the rounded frame */
  text-align: left;
}
/* Header row: Home (absolute top-left) · "Settings" (center) · ✕ (top-right). */
.options-home-btn {
  position: absolute;
  top: 12px;
  left: 14px;
  z-index: 2;
  padding: 7px 14px;
  font-family: var(--font, monospace);
  font-size: 14px;
  color: #f3e6c4;
  background: #5a3418;
  border: 2px solid #8a5a26;
  border-radius: 5px;
  box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000;
  cursor: pointer;
}
.options-home-btn:hover  { background: #6e4220; border-color: #d4aa50; color: #e8c060; }
.options-home-btn:active { transform: translateY(2px); box-shadow: 0 1px 0 #1a0c04, 0 2px 0 #000; }

/* "Back to Map" (forfeit) — battle-context only (shown by JS, replacing the close
   ✕ in the top-right corner). Compact SNES parchment button, mirroring the Home
   button's corner placement, in a warmer red-brown to read as a "leave the
   battle" action. */
.options-map-corner {
  position: absolute;
  top: 12px;
  right: 14px;
  z-index: 2;
  padding: 7px 14px;
  font-family: var(--font, monospace);
  font-size: 14px;
  color: #f3e6c4;
  background: #6a2d1c;
  border: 2px solid #a85a36;
  border-radius: 5px;
  box-shadow: 0 3px 0 #2a0c04, 0 4px 0 #000;
  cursor: pointer;
}
.options-map-corner:hover  { background: #803726; border-color: #e0a060; color: #ffd890; }
.options-map-corner:active { transform: translateY(2px); box-shadow: 0 1px 0 #2a0c04, 0 2px 0 #000; }

/* Top toggle — one joined button (two halves) that flips the panel's view.
   Sits on its own row BELOW the absolute Home (top-left) and Back-to-Map / ✕
   (top-right) corner buttons, so the extra top padding clears them. */
.options-tabs {
  flex: 0 0 auto;
  display: flex;
  justify-content: center;
  padding: 60px 18px 12px;
}
.options-toggle {
  display: inline-flex;
  padding: 0;
  border: 2px solid #8a5a26;
  border-radius: 6px;
  overflow: hidden;
  background: #3a200c;
  box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000;
  cursor: pointer;
  font-family: var(--font, monospace);
}
.options-toggle:active { transform: translateY(2px); box-shadow: 0 1px 0 #1a0c04, 0 2px 0 #000; }
.options-toggle-seg {
  padding: 8px 22px;
  font-size: 16px;
  color: #c9b48a;
  background: transparent;
}
.options-toggle-seg + .options-toggle-seg { border-left: 2px solid #6a4418; }   /* divider between halves */
.options-toggle-seg.is-active { color: #1a0c04; background: #d4aa50; }            /* highlighted current view */
.options-toggle:hover .options-toggle-seg:not(.is-active) { color: #e8c060; }

.options-scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 4px 22px 14px;
}

/* Sections */
.options-section { margin-bottom: 16px; }
.options-section-title {
  font-family: var(--font, monospace);
  font-size: 18px;
  color: #e8c060;
  text-transform: uppercase;
  letter-spacing: 1px;
  text-shadow: 2px 2px 0 #000;                     /* chunky SNES drop-shadow — matches .rules-popup-title */
  border-bottom: 1px solid rgba(212, 170, 80, 0.40);
  padding-bottom: 6px;
  margin-bottom: 12px;
}

/* Volume sliders */
.options-slider-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 14px 0;
}
.options-slider-label {
  flex: 0 0 96px;
  font-family: var(--font, monospace);
  font-size: 20px;
  color: #f3e6c4;
  text-shadow: 1px 1px 0 #000;                     /* match .rules-popup-body cream body text */
}
.options-slider {
  flex: 1 1 auto;
  accent-color: #d4aa50;
  height: 8px;
}
.options-vol-num {
  flex: 0 0 44px;
  text-align: right;
  font-family: var(--font, monospace);
  font-size: 18px;
  color: #e8c060;
  text-shadow: 1px 1px 0 #000;
}

/* ── ON/OFF setting row (Gameplay section) ─────────────────────────────
   Same three-column rhythm as .options-slider-row — label · control · read-out
   — so Sounds and Gameplay align down the panel. The label column is wider here
   because these settings are named, not one-word levels. */
.options-toggle-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 14px 0;
}
.options-toggle-row .options-slider-label {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.options-toggle-sub {
  font-size: 13px;
  color: rgba(243, 230, 196, 0.50);
  text-shadow: none;
}

/* The switch — a bronze track with a sliding knob, in the panel's palette. */
.options-switch {
  flex: 0 0 auto;
  position: relative;
  width: 58px;
  height: 28px;
  padding: 0;
  border: 2px solid #6a4418;
  border-radius: 0;                 /* pixel-perfect, matches the rest of the UI */
  background: #241206;
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.60);
  cursor: pointer;
  transition: background 0.13s ease, border-color 0.13s ease;
}
.options-switch:hover { border-color: #d4aa50; }
.options-switch.is-on {
  background: #5a3418;
  border-color: #d4aa50;
}
.options-switch-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  background: #8a6a34;
  box-shadow: 0 2px 0 #1a0c04;
  transition: left 0.13s cubic-bezier(0.22, 1, 0.36, 1), background 0.13s ease;
}
.options-switch.is-on .options-switch-knob {
  left: 32px;
  background: #e8c060;
}

/* ── How-to-Play SLIDESHOW (the How-to-Play tab's view) ─────────────────── */
.options-slideshow {
  flex: 1 1 auto;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 6px 22px 16px;
}
/* Reserved image area — drop a slide image in later (slide.image → background). */
.slideshow-image {
  align-self: center;       /* centered; narrower than full width */
  width: auto;
  height: 160px;
  aspect-ratio: 16 / 9;     /* 16:9 image window */
  max-width: 100%;
  flex: 0 0 auto;
  border-radius: 6px;
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  margin-bottom: 12px;
}
.slideshow-image.is-placeholder {
  background-color: rgba(212, 170, 80, 0.06);
  border: 2px dashed rgba(212, 170, 80, 0.40);
}
.slideshow-body {
  flex: 1 1 auto;
  font-family: var(--font, monospace);
  font-size: 18px;
  line-height: 1.6;
  color: #f3e6c4;
  text-shadow: 1px 1px 0 #000;
  text-align: center;
  padding: 0 6px;
}
.slideshow-nav {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 14px;
}
.slideshow-arrow {
  width: 40px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: #f3e6c4;
  background: #5a3418;
  border: 2px solid #8a5a26;
  border-radius: 5px;
  box-shadow: 0 3px 0 #1a0c04, 0 4px 0 #000;
  cursor: pointer;
}
.slideshow-arrow:hover:not(:disabled)  { background: #6e4220; border-color: #d4aa50; color: #e8c060; }
.slideshow-arrow:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 #1a0c04, 0 2px 0 #000; }
.slideshow-arrow:disabled { opacity: 0.3; cursor: default; }
.slideshow-dots { display: flex; align-items: center; gap: 8px; }
.slideshow-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(212, 170, 80, 0.30);
  border: 1px solid rgba(212, 170, 80, 0.55);
}
.slideshow-dot.is-active { background: #e8c060; border-color: #f0d28a; }

/* Bottom music bar (Settings tab only) */
.options-music-bar {
  flex: 0 0 auto;
  border-top: 2px solid rgba(212, 170, 80, 0.45);
  background: rgba(0, 0, 0, 0.28);
  padding: 9px 16px 11px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.options-music-credit {
  font-family: var(--font, monospace);
  font-size: 14px;
  color: #c9b48a;
  letter-spacing: 0.3px;
  text-align: center;
  min-height: 16px;
}
/* The panel has its own track title + transport buttons (driven by SOG.music). */
.options-music-title {
  font-family: var(--font, monospace);
  font-size: 16px;
  color: #e8c060;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  text-shadow: 1px 1px 0 #000;
  text-align: center;
}
.options-music-controls { display: flex; align-items: center; gap: 16px; margin-top: 2px; }
.options-music-btn {
  background: transparent;
  border: none;
  color: #e8c060;
  font-size: 19px;
  cursor: pointer;
  padding: 4px 6px;
  line-height: 1;
}
.options-music-btn:hover  { color: #fff; }
.options-music-btn:active { transform: translateY(1px); }

/* Corner music widget: retired from battle/overworld (the Options gear covers
   those), but RESTORED on the home + deck-builder screens, which have no gear. */
#music-ctrl { display: none; }
body[data-screen="home"] #music-ctrl,
body[data-screen="deckbuilder"] #music-ctrl { display: flex; }
/* Deck builder: the widget sits bottom-LEFT, in the free space under the
   filters, so it no longer covers the cards. 16px matches the column's padding.
   (Home keeps it bottom-right.) */
body[data-screen="deckbuilder"] #music-ctrl { left: 16px; right: auto; }

/* …and it is dressed to match the filter column: a play button shaped like
   the sort buttons and a gold volume slider. No box and no label of its own. */
body[data-screen="deckbuilder"] #music-ctrl {
  bottom: 14px;
  width: 286px;              /* the column's inner width: lines up with the search box */
  min-width: 0;
  box-sizing: border-box;
  gap: 7px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
body[data-screen="deckbuilder"] .music-controls { gap: 10px; }
body[data-screen="deckbuilder"] .music-ctrl-btn {
  width: 36px;
  height: 30px;
  box-sizing: border-box;
  padding: 0;
  font-size: 12px;
  color: #f0cf6c;
  background: rgba(8, 4, 1, 0.7);
  border: 2px solid rgba(120, 90, 40, 0.6);
  border-radius: 2px;
  transition: background 0.1s, border-color 0.1s, color 0.1s;
}
body[data-screen="deckbuilder"] .music-ctrl-btn:hover {
  color: #fff5d8;
  border-color: #d4aa50;
  text-shadow: none;
}
body[data-screen="deckbuilder"] .music-volume-slider {
  height: 6px;
  margin-left: 0;
  background: rgba(8, 4, 1, 0.85);
  border: 1px solid rgba(180, 130, 40, 0.65);
}
body[data-screen="deckbuilder"] .music-volume-slider::-webkit-slider-thumb {
  width: 14px;
  height: 14px;
  background: #f0cf6c;
  border: 1px solid #2a1608;
  box-shadow: 0 0 4px rgba(212, 170, 80, 0.5);
}
body[data-screen="deckbuilder"] .music-volume-slider::-moz-range-thumb {
  width: 14px;
  height: 14px;
  background: #f0cf6c;
  border: 1px solid #2a1608;
  box-shadow: 0 0 4px rgba(212, 170, 80, 0.5);
}

/* (Battle Options gear is now styled via .battle-icon-strip .btn-hud-icon.) */

/* ══════════════════════════════════════════════════════════════════
   NARMER ADVANCE BATTLE (body.narmer-battle) — advance-gate lock
   affordance. Purely visual: the rule itself is enforced in the play
   predicate (board.js isAdvanceUnlocked); sog-adventure-narmer.js
   toggles these classes from the same predicate. Scoped to the
   narmer-battle body class so no other battle is affected.
══════════════════════════════════════════════════════════════════ */
body.narmer-battle .battle-slots-player { position: relative; }

/* Player-side lock: grey the player's slot row… */
body.narmer-battle .battle-col.advance-locked-player .battle-slots-player .battle-card-slot {
  opacity: 0.35;
  filter: grayscale(0.85);
}
/* …and float a 🔒 hint naming the unlock condition over it. */
body.narmer-battle .battle-col.advance-locked-player .battle-slots-player::after {
  content: '🔒 ' attr(data-lock-hint);
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 5;
  pointer-events: none;
  font-family: 'CTGalbite', 'Courier New', monospace;
  font-size: 13px;
  line-height: 1.35;
  text-align: center;
  color: #f3e6c4;
  text-shadow: 1px 1px 0 #000;
  background: rgba(26, 12, 4, 0.85);
  border: 2px solid #d4aa50;
  border-radius: 8px;
  padding: 5px 10px;
  max-width: 90%;
}

/* AI-side lock: a subtle grey on Narmer's row so the symmetric rule reads. */
body.narmer-battle .battle-col.advance-locked-ai .battle-slots-opp .battle-card-slot {
  opacity: 0.55;
  filter: grayscale(0.6);
}

/* Narmer battle column art (loc ids 111-113 exist only in that battle; the
   body scope keeps them inert everywhere else). User-supplied Egypt art. */
body.narmer-battle .battle-col[data-loc-id="111"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/loweregypt.jpeg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}
body.narmer-battle .battle-col[data-loc-id="112"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/memphis.jpeg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}
body.narmer-battle .battle-col[data-loc-id="113"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/upperegypt.jpeg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

/* ── Hyksos invasion column art (loc ids 131-133 exist only in that battle;
   the body scope keeps them inert everywhere else). Same shape as Narmer's
   block above — the tile background is CSS, not the location's `image` field,
   which feeds popups/thumbnails only. Both must name the same file: this rule
   draws the tile, LOC_ART in js/sog-adventure-hyksos.js draws the popup.

   ALL THREE ARE REAL ART — no placeholders. Note the UNDERSCORES in the two new
   filenames (nile_delta, aswan_cataract): the server is character- and
   case-sensitive, so a hyphen or a collapsed name 404s. ── */
body.hyksos-battle .battle-col[data-loc-id="131"]::before {   /* The Nile Delta */
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/nile_delta.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}
body.hyksos-battle .battle-col[data-loc-id="132"]::before {   /* Thebes */
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/thebes.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}
body.hyksos-battle .battle-col[data-loc-id="133"]::before {   /* Aswan Cataract */
  content: '';
  position: absolute;
  inset: 0;
  background: url('../images/locations/aswan_cataract.jpg') center / cover no-repeat;
  opacity: 0.5;
  z-index: -1;
}

/* Hyksos (67) — the crossing flyer. A body-level fixed clone of the card,
   sliding from its own slot to the opponent's side (reveal-fx hyksosLiftOff /
   hyksosCrossing). The shadow is the whole point: it lifts the card off the
   board for the length of the roll so the travel reads as a card CROSSING
   rather than two slots redrawing. Positioning is inline; only the lift is here. */
.reveal-fx-hyksos-fly {
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.65);
  filter: brightness(1.06);
}

/* ── Join links + student logins (teacher dashboard) ───────────────────── */
#td-roster-section {
  flex: 2;
}
/* The label input keeps a usable width in the narrower classes column; the
   buttons wrap onto the next line when there isn't room beside it. */
.td-class-label-input {
  flex: 1 1 120px;
}
/* The link wraps onto its own full-width line under the class row's controls
   so a long URL never squeezes the label input or the buttons. */
.td-class-row {
  flex-wrap: wrap;
}
.td-join-link {
  flex-basis: 100%;
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 12px;
  color: var(--text-dim);
}
.td-join-link-url {
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 12px;
  color: var(--text-white);
  word-break: break-all;
}

/* Passphrases stay hidden behind this until clicked — a roster is often on a
   projector, and every one of these is a working student login. */
.td-reveal-btn {
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 11px;
  padding: 3px 8px;
  background: var(--bg-btn);
  border: 2px solid var(--border-mid);
  border-radius: 3px;
  color: var(--text-dim);
  cursor: pointer;
}
.td-reveal-btn:hover {
  color: var(--snes-yellow);
  border-color: var(--snes-yellow);
}
.td-pass-cell {
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
}

/* Separator line above an alternative action (e.g. Continue with Google). */
.account-flow-or {
  margin-top: 12px;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 12px;
  color: var(--text-dim);
  text-align: center;
}

/* Account-flow steps can carry three wide buttons (CREATE TEACHER ACCOUNT /
   CONTINUE WITH GOOGLE / BACK), which run off the modal's right edge in the
   base single-row layout — .popup-actions .btn-snes sets flex-shrink: 0, so
   they overflow rather than shrink. Wrapping keeps every button whole and
   inside the box at any width; steps with one or two buttons are unaffected.
   The chooser's own :has(#af-teacher) grid above still wins for that step. */
#account-flow-actions {
  flex-wrap: wrap;
  justify-content: center;
}
#account-flow-actions .btn-snes {
  max-width: 100%;
  box-sizing: border-box;
}

/* ════════════════════════════════════════════════════════════════════════
   Teacher & student onboarding (js/teacher-onboard.js)
   ════════════════════════════════════════════════════════════════════════ */

/* Home corner links (top right): Log in / name, Dashboard, Join a class,
   Teachers. Small and quiet until hovered — the centre of the home screen
   stays title + tagline + I'M READY. */
.home-corner {
  position: absolute;
  top: 18px;
  right: 26px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 22px;
}
.home-corner-link {
  background: none;
  border: none;
  padding: 4px 0;
  /* Same face, colour and shadow as the home byline; yellow on hover. */
  font-family: var(--font);
  font-size: 15px;
  letter-spacing: 0.06em;
  color: #b48ad4;
  text-shadow: 1px 1px 0 #000;
  cursor: pointer;
  transition: color 0.15s ease;
}
.home-corner-link:hover,
.home-corner-link:focus-visible {
  color: var(--snes-yellow);
  text-shadow: 1px 1px 0 #000;
  text-decoration: underline;
  text-underline-offset: 3px;
  outline: none;
}
.account-code-input {
  font-family: 'Source Sans 3', Arial, Helvetica, sans-serif;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.tcl-nolink { margin-top: 6px; font-size: 14px; color: var(--text-dim); line-height: 1.4; }
.tcl-nolink strong { color: var(--text-white); }

/* Slim teacher banner across the top of the stage. */
.teacher-banner {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -110%);
  z-index: 900;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 7px 10px 7px 18px;
  background: rgba(10, 12, 40, 0.92);
  border: 2px solid var(--snes-yellow);
  border-top: none;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 15px;
  color: var(--text-white);
  white-space: nowrap;
  transition: transform 0.25s ease;
  pointer-events: none;
}
.teacher-banner.visible { transform: translate(-50%, 0); pointer-events: auto; }
.teacher-banner-go {
  background: var(--snes-yellow);
  color: #10102a;
  border: none;
  padding: 5px 12px;
  font-family: var(--font);
  font-size: 12px;
  cursor: pointer;
}
.teacher-banner-close {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
.teacher-banner-close:hover { color: var(--text-white); }


/* Account-flow additions. */
.account-adult-row { margin: 4px 0 12px; font-size: 14px; }
.account-google-btn { display: block; width: 100%; margin: 4px 0; }
.account-flow-steps { margin: 8px 0 10px 20px; padding: 0; line-height: 1.5; }

/* Class-link screen (after signup, and LINK & QR in the dashboard). */
.teacher-classlink { background: rgba(0, 0, 14, 0.6); z-index: 1200; }
.tcl-modal {
  width: 82%;
  max-height: 88%;
  box-sizing: border-box;
  padding: 20px 28px 22px;
  background: var(--bg-dialog);
  border: 3px solid var(--border-bright);
  box-shadow: 0 0 0 3px var(--border-dark), 0 0 0 6px var(--border-mid), 0 0 0 7px var(--border-dark);
  color: var(--text-white);
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.tcl-header { display: flex; align-items: center; justify-content: space-between; border-bottom: 2px solid var(--border-mid); padding-bottom: 12px; }
.tcl-title { font-family: var(--font); font-size: 22px; color: var(--snes-yellow); }
.tcl-header .btn-snes { font-size: 11px; padding: 8px 14px; }
.tcl-loading { font-size: 16px; padding: 30px 0; text-align: center; }
.tcl-grid { display: flex; gap: 28px; align-items: flex-start; }
.tcl-left { flex: 1; min-width: 0; }
.tcl-right { flex-shrink: 0; }
.tcl-qr { width: 250px; height: 250px; background: #fff; padding: 6px; box-sizing: border-box; }
.tcl-qr svg { width: 100%; height: 100%; display: block; }
.tcl-label { display: block; font-size: 13px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.06em; margin: 10px 0 4px; }
.tcl-linkrow { display: flex; gap: 8px; }
.tcl-link {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  font-size: 16px;
  background: #0a0c22;
  color: var(--text-white);
  border: 2px solid var(--snes-yellow);
}
.tcl-linkrow .btn-snes { font-size: 13px; padding: 8px 18px; }
.tcl-code { margin-top: 10px; font-size: 18px; }
.tcl-code strong { font-family: 'Source Sans 3', Arial, Helvetica, sans-serif; font-weight: 700; color: var(--snes-yellow); letter-spacing: 0.14em; font-size: 24px; }
.tcl-steps { margin: 12px 0 4px 22px; padding: 0; font-size: 16px; line-height: 1.6; }
.tcl-fields { display: grid; grid-template-columns: 1fr 1fr; column-gap: 14px; }
.tcl-fields .tcl-label { grid-row: 1; }
.tcl-input { margin: 0; }
.tcl-actions { display: flex; gap: 10px; justify-content: flex-end; }
.tcl-actions .btn-snes { font-size: 13px; padding: 10px 18px; }

/* Projector view: fills the stage (and the screen, when the browser allows). */
.teacher-projector {
  position: absolute;
  inset: 0;
  z-index: 2000;
  display: none;
  align-items: center;
  justify-content: center;
  gap: 6%;
  background: #ffffff;
  color: #111;
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
}
.teacher-projector.visible { display: flex; }
.teacher-projector:fullscreen { width: 100vw; height: 100vh; }
.tpj-qr { height: 78%; aspect-ratio: 1 / 1; }
.tpj-qr svg { width: 100%; height: 100%; display: block; }
.tpj-side { display: flex; flex-direction: column; gap: 10px; }
.tpj-line { font-size: 30px; }
.tpj-line strong { font-weight: 700; }
.tpj-small { font-size: 22px; color: #555; }
/* Plain, unambiguous glyphs for a code read off a projector (the pixel font's
   4 reads as a Y). */
.tpj-code { font-family: 'Source Sans 3', Arial, Helvetica, sans-serif; font-weight: 700; font-size: 110px; letter-spacing: 0.1em; color: #111; }
.teacher-projector-close {
  position: absolute;
  top: 14px;
  right: 18px;
  background: none;
  border: 2px solid #999;
  color: #555;
  font-size: 26px;
  width: 44px;
  height: 44px;
  cursor: pointer;
}

/* Student login card: floats over the game, never blocks it. */
.login-card-float {
  position: absolute;
  right: 20px;
  bottom: 140px;
  z-index: 1100;
  width: 330px;
  box-sizing: border-box;
  padding: 14px 18px 16px;
  background: var(--bg-dialog);
  border: 3px solid var(--snes-yellow);
  box-shadow: 0 0 0 3px var(--border-dark), 0 8px 24px rgba(0, 0, 0, 0.5);
  color: var(--text-white);
  font-family: var(--font-ui, 'Source Sans 3', sans-serif);
  display: none;
}
.login-card-float.visible { display: block; }
.lcf-title { font-family: var(--font); color: var(--snes-yellow); font-size: 15px; margin-bottom: 10px; }
.lcf-row { display: flex; justify-content: space-between; gap: 10px; font-size: 14px; margin: 4px 0; }
.lcf-row span { color: var(--text-dim); }
.lcf-row strong { font-size: 16px; letter-spacing: 0.02em; word-break: break-all; text-align: right; }
.lcf-hint { font-size: 12px; color: var(--text-dim); margin: 10px 0; line-height: 1.4; }
.login-card-float .btn-snes { font-size: 12px; padding: 7px 16px; }

/* Printable login cards (dashboard → PRINT LOGIN CARDS). The container lives
   outside the stage; only it prints while body.printing-login-cards is set. */
#login-cards-print { display: none; }
@media print {
  body.printing-login-cards * { visibility: hidden !important; }
  body.printing-login-cards #login-cards-print,
  body.printing-login-cards #login-cards-print * { visibility: visible !important; }
  body.printing-login-cards #login-cards-print {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 10mm;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    padding: 8mm;
    box-sizing: border-box;
    background: #fff;
  }
  .login-card {
    border: 1.5px dashed #444;
    padding: 6mm;
    break-inside: avoid;
    font-family: Arial, Helvetica, sans-serif;
    color: #000;
  }
  .login-card-title { font-weight: 700; font-size: 13pt; margin-bottom: 3mm; }
  .login-card-row { display: flex; justify-content: space-between; font-size: 11pt; margin: 1.5mm 0; }
  .login-card-row strong { font-family: 'Courier New', monospace; font-size: 12pt; }
  .login-card-qr { width: 34mm; height: 34mm; margin: 3mm auto 1mm; }
  .login-card-qr svg { width: 100%; height: 100%; }
  .login-card-hint { font-size: 8.5pt; text-align: center; color: #333; }
}

/* Sign-up: "Teacher accounts are for adults. Privacy & account deletion" and
   the Privacy overlay it opens above the sign-up modal (js/account-ui.js). */
.account-privacy-line { margin: -6px 0 12px 22px; font-size: 14px; color: var(--text-dim); font-family: var(--font-ui, 'Source Sans 3', sans-serif); }
.account-privacy-line a { color: var(--snes-yellow); }
#privacy-peek-backdrop { z-index: 9500; }
.privacy-peek { max-width: 720px; }
.privacy-peek-body { max-height: 460px; overflow-y: auto; font-family: var(--font-ui, 'Source Sans 3', sans-serif); font-size: 17px; line-height: 1.5; text-align: left; }
.privacy-peek-body h2 { font-family: var(--font); color: var(--snes-yellow); font-size: 18px; margin: 0 0 10px; }
.privacy-peek-body p { margin: 0 0 10px; }
.privacy-peek-body a { color: var(--snes-yellow); }

/* ════════════════════════════════════════════════════════════
   SCRIPTED FIRST NEANDERTHAL BATTLE — system callouts & guides
   (js/sog-adventure-prehistory.js, "SCRIPTED FIRST BATTLE").
   One instruction style, deliberately unlike the characters' parchment
   speech bubbles: dark slate, a yellow edge, clean sans-serif.
   Everything lives in #snap-layer inside the stage, pointer-events none,
   so it never gets in the way of a drag.
   ════════════════════════════════════════════════════════════ */
#snap-layer {
  position: absolute;
  inset: 0;
  z-index: 9000;
  pointer-events: none;
  user-select: none;   /* quick repeated taps must not select callout text */
  -webkit-user-select: none;
}
.snap-callout {
  position: absolute;
  max-width: 300px;
  padding: 10px 14px 10px 16px;
  background: rgba(10, 22, 36, 0.96);
  border: 2px solid #f8d000;
  border-left-width: 6px;
  border-radius: 8px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.6);
  color: #fff;
  font-family: 'Source Sans 3', Arial, Helvetica, sans-serif;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.25;
  animation: snap-callout-in 0.25s ease-out;
}
@keyframes snap-callout-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.snap-callout--instr { max-width: 330px; }   /* clears Lucy's portrait at the left */
.snap-callout--oneline { max-width: none; white-space: nowrap; }   /* a short hint kept on one line */
body.snap-guiding #battle-hover-popup { visibility: hidden !important; }
.snap-callout-sub {
  margin-top: 4px;
  font-size: 15px;
  font-weight: 600;
  color: #9fe8e8;
}
.snap-callout-tap {
  margin-top: 6px;
  font-size: 13px;
  font-weight: 700;
  color: #f8d000;
  letter-spacing: 0.04em;
  animation: snap-tap-blink 1.2s ease-in-out infinite;
}
@keyframes snap-tap-blink { 50% { opacity: 0.45; } }
/* Arrow toward the anchor (--arrow-x / --arrow-y keep it on target after clamping). */
.snap-callout::after {
  content: '';
  position: absolute;
  width: 0; height: 0;
  border: 9px solid transparent;
}
.snap-callout--free::after { display: none; }
.snap-callout--top::after    { top: 100%;  left: var(--arrow-x, 50%); margin-left: -9px; border-top-color: #f8d000; }
.snap-callout--bottom::after { bottom: 100%; left: var(--arrow-x, 50%); margin-left: -9px; border-bottom-color: #f8d000; }
.snap-callout--left::after   { left: 100%; top: var(--arrow-y, 50%); margin-top: -9px; border-left-color: #f8d000; }
.snap-callout--right::after  { right: 100%; top: var(--arrow-y, 50%); margin-top: -9px; border-right-color: #f8d000; }

/* Pinned goal, top centre. */
.snap-goal {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  padding: 6px 16px;
  background: rgba(10, 22, 36, 0.92);
  border: 2px solid #f8d000;
  border-radius: 999px;
  color: #fff;
  font-family: 'Source Sans 3', Arial, Helvetica, sans-serif;
  font-size: 17px;
  font-weight: 700;
  white-space: nowrap;
}

/* Drag guide: a translucent copy of the card rides a pointing hand to the slot. */
.snap-guide-ghost {
  position: absolute;
  left: 0; top: 0;
  border-radius: 6px;
  background-size: cover;
  background-position: center;
  box-shadow: 0 0 0 2px #f8d000, 0 8px 18px rgba(0, 0, 0, 0.55);
}
.snap-guide-hand {
  position: absolute;
  left: 0; top: 0;
  margin: -16px 0 0 -26px;   /* the fingertip, not the box corner, sits on the point */
  filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.6));
}
@keyframes snap-target-pulse {
  0%, 100% { box-shadow: inset 0 0 0 3px rgba(64, 224, 224, 0.9), 0 0 10px 2px rgba(64, 224, 224, 0.45); }
  50%      { box-shadow: inset 0 0 0 3px rgba(64, 224, 224, 1),   0 0 22px 8px rgba(64, 224, 224, 0.75); }
}
.battle-card-slot.snap-target,
.battle-card-slot.snap-target-soft {
  animation: snap-target-pulse 1.1s ease-in-out infinite;
  border-radius: 6px;
}

/* The choice card not taken leaves the hand. */
.battle-hand-card.snap-choice-gone {
  opacity: 0 !important;
  transform: translateY(30px) scale(0.85) !important;
  transition: opacity 0.5s ease, transform 0.5s ease;
  pointer-events: none;
}

/* Location score: count-up pulse, and the finale's surge. */
@keyframes snap-score-pulse {
  0%, 100% { transform: scale(1);   text-shadow: 1px 1px 4px rgba(0,0,0,0.95), 0 0 10px rgba(0,0,0,0.85); }
  50%      { transform: scale(1.45); text-shadow: 0 0 12px rgba(64,224,224,0.95), 0 0 24px rgba(64,224,224,0.7); }
}
.battle-loc-score-player.snap-score-pulse { animation: snap-score-pulse 0.32s ease-in-out infinite; }
@keyframes snap-score-surge {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.9); text-shadow: 0 0 18px #40e0e0, 0 0 36px #40e0e0; }
  100% { transform: scale(1); }
}
.battle-loc-score-player.snap-score-surge { animation: snap-score-surge 0.8s ease-out 2; }

.snap-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.snap-arc  { fill: none; stroke: #f8d000; stroke-width: 4; stroke-linecap: round; }
.snap-arc-label {
  fill: #f8d000;
  font-family: 'Source Sans 3', Arial, Helvetica, sans-serif;
  font-size: 22px;
  font-weight: 800;
  text-anchor: middle;
  paint-order: stroke;
  stroke: #000;
  stroke-width: 4px;
}

/* The Cave Art "what if": the guide's copy stays in Fire's slot, dashed. */
.snap-guide-ghost--landed {
  outline: 3px dashed #f8d000;
  outline-offset: 2px;
  box-shadow: 0 0 18px 4px rgba(248, 208, 0, 0.5);
}
/* "+1" popping over a card Cave Art boosts (or would have). */
.snap-plus {
  position: absolute;
  transform: translate(-50%, -50%);
  color: #f8d000;
  font-family: 'Source Sans 3', Arial, Helvetica, sans-serif;
  font-size: 34px;
  font-weight: 800;
  text-shadow: 0 0 4px #000, 0 2px 0 #000, 0 0 14px rgba(248, 208, 0, 0.8);
  animation: snap-plus-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes snap-plus-pop {
  from { opacity: 0; transform: translate(-50%, -20%) scale(0.4); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
/* The score while it shows the imagined Cave Art total. */
.battle-loc-score-player.snap-score-whatif { color: var(--snes-yellow); }

/* A card under discussion (Megalith, Tribe). */
@keyframes snap-spotlight {
  0%, 100% { box-shadow: 0 0 0 3px #f8d000, 0 0 14px 4px rgba(248, 208, 0, 0.55); }
  50%      { box-shadow: 0 0 0 4px #f8d000, 0 0 30px 12px rgba(248, 208, 0, 0.85); }
}
.battle-card-slot.snap-spotlight {
  animation: snap-spotlight 1s ease-in-out infinite;
  border-radius: 6px;
  position: relative;
  z-index: 30;
}

/* Finger-sized tap areas (~44 px) on small controls students meet, without
   changing how they look: an invisible hit area extends past the edges. */
/* (.popup-close-x is already position:absolute, which anchors its hit area.) */
.home-corner-link,
.music-ctrl-btn,
.teacher-banner-close,
.teacher-banner-go { position: relative; }
.home-corner-link::before,
.popup-close-x::before,
.music-ctrl-btn::before,
.teacher-banner-close::before,
.teacher-banner-go::before {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: max(100%, 44px);
  height: max(100%, 44px);
  transform: translate(-50%, -50%);
}

/* Touch-only devices (no hover at all): the map's hover-only labels — place
   names and exit boxes ("To Mesopotamia →") — show all the time, since a tap
   there already walks or travels. (Hidden Sahara exits have no label: still
   hidden.) Touch laptops keep hover: they have a trackpad. */
@media (hover: none) {
  .overworld-node .overworld-node-label { opacity: 1; }
  .overworld-exit { border-color: rgba(255, 215, 0, 0.35); }
  .overworld-exit .overworld-exit-label { opacity: 1; }
}

/* ════════════════════════════════════════════════════════════
   ÖTZI BATTLE — interjections (js/otzi-lessons.js) and order badges
   (js/game/order-badges.js). Callouts reuse the Neanderthal battle's
   .snap-callout / .snap-goal / .snap-arc styles.
   ════════════════════════════════════════════════════════════ */
#otzi-layer,
#order-badge-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}
#otzi-layer { z-index: 9000; }
#order-badge-layer { z-index: 2; }   /* inside #screen-battle: above the hand strip + resting hand cards (z 1), below a hovered card (z 100) */
/* Shared callout layers (js/game/callouts.js): fades. */
.callout-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
  z-index: 9000;
}
.callout-layer .snap-callout,
.callout-layer .snap-svg,
.otzi-final-banner { transition: opacity 0.35s ease; }
.callout-fading { opacity: 0 !important; }

/* Order badges: the action's number, centred under the card inside the dark
   hand strip, so it never covers a card. */
.order-badge {
  position: absolute;
  box-sizing: border-box;
  transform: translateX(-50%);
  width: 17px;
  height: 17px;
  /* One radial gradient: fill + 1.5px gold ring (no border-radius border —
     see .db-pick::before for the cross artifact that caused). */
  --ob-fill: rgba(10, 22, 36, 0.95);
  --ob-ring: #f8d000;
  background: radial-gradient(circle closest-side,
    var(--ob-fill) calc(100% - 2px), var(--ob-ring) calc(100% - 1.5px),
    var(--ob-ring) calc(100% - 0.5px), rgba(0, 0, 0, 0) 100%);
  color: #f8d000;
  font-family: 'Source Sans 3', Arial, Helvetica, sans-serif;
  font-size: 12px;
  font-weight: 800;
  line-height: 17px;
  text-align: center;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
  animation: order-badge-in 0.2s ease-out;
}
@keyframes order-badge-in { from { opacity: 0; } to { opacity: 1; } }
/* A queued move: the ring is dashed — a conic stripe under the fill, both
   clipped to the circle. */
.order-badge--move {
  background:
    radial-gradient(circle closest-side, var(--ob-fill) calc(100% - 2px), rgba(0, 0, 0, 0) calc(100% - 1.5px)),
    repeating-conic-gradient(var(--ob-ring) 0deg 22.5deg, rgba(0, 0, 0, 0) 22.5deg 45deg);
  -webkit-mask: radial-gradient(circle closest-side, #000 calc(100% - 0.5px), rgba(0, 0, 0, 0) 100%);
          mask: radial-gradient(circle closest-side, #000 calc(100% - 0.5px), rgba(0, 0, 0, 0) 100%);
}
.order-badge--waiting { opacity: 0.45; }
@keyframes order-badge-lit {
  0%   { filter: drop-shadow(0 0 0 rgba(248, 208, 0, 0)); }
  40%  { filter: drop-shadow(0 0 6px rgba(248, 208, 0, 0.9)); }
  100% { filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6)); }
}
.order-badge--lit {
  opacity: 1;
  --ob-fill: #f8d000;
  color: #1a0a04;
  animation: order-badge-lit 0.6s ease-out;
}

/* FINAL TURN banner (every attempt until Ötzi is beaten). */
.otzi-final-banner {
  position: absolute;
  left: 50%;
  top: 34%;
  transform: translate(-50%, -50%);
  padding: 14px 36px 16px;
  background: rgba(10, 22, 36, 0.94);
  border: 3px solid #f8d000;
  border-radius: 12px;
  text-align: center;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.7);
  animation: otzi-banner-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes otzi-banner-in {
  from { opacity: 0; transform: translate(-50%, -50%) scale(0.6); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
.otzi-final-title {
  font-family: var(--font);
  font-size: 40px;
  color: #f8d000;
  letter-spacing: 0.08em;
  text-shadow: 2px 2px 0 #000;
}
.otzi-final-line {
  margin-top: 4px;
  font-family: 'Source Sans 3', Arial, Helvetica, sans-serif;
  font-size: 22px;
  font-weight: 700;
  color: #fff;
}

/* Score glow: the player's score at a location glows light blue while ahead,
   dims while behind (updated on every score change). */
.battle-loc-score-player.otzi-ahead {
  text-shadow: 0 0 8px rgba(64, 224, 224, 0.95), 0 0 18px rgba(64, 224, 224, 0.75), 1px 1px 3px #000;
}
.battle-loc-score-player.otzi-behind { opacity: 0.5; }
