/* ─── DEFENDERS OF HOGWARTS — shared styles ────────────────────────────────
 * Mobile-first. Primary target is the Galaxy Fold 7: ~344–360px folded and
 * ~660–770px unfolded. Desktop is the third case, not the first.
 */

:root {
  /* Wizarding palette — MinaLima "Defenders of Hogwarts": midnight indigo lit
     from above by candlelight, aged-gold foil, warm-parchment ink, a wisp of
     Dark-Arts aubergine. */
  --bg:        #0b0a14;
  --bg-2:      #14121f;
  --panel:     #1a1730;
  --panel-2:   #221d3a;
  --line:      #3a3358;
  --ink:       #f0ead8;   /* warm parchment, not cold white */
  --ink-dim:   #a99fc4;
  --gold:      #d9af53;   /* aged gold — primary accent */
  --gold-soft: #f4d98a;   /* foil highlight */
  --gold-deep: #a67c2e;   /* foil shadow */
  --edge:      rgba(217,175,83,.22); /* gold hairline for ornament */
  --accent:    #d9af53; /* in-game primary CTA tone (audit M1: was undefined, so
                           #action-bar button.primary rendered transparent) */
  --gryffindor:#7f0909;
  --hufflepuff:#e0a83a;
  --ravenclaw: #1b2a5e;
  --slytherin: #1a472a;
  --dark:      #7b4fb0;   /* Dark Arts purple */
  --danger:    #c0392b;
  --ok:        #3aa76a;
  --radius:    10px;
  /* An old-spellbook serif for titles; body stays a clean sans. Both are system
     stacks — no web font, so nothing to fetch and nothing to break the CSP. */
  --font-display: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Palatino, Georgia, "Times New Roman", serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  /* Candlelight from above, a breath of magic from below, over midnight. */
  background:
    radial-gradient(1200px 620px at 50% -12%, rgba(217,175,83,.10), transparent 62%),
    radial-gradient(900px 900px at 50% 118%, rgba(123,79,176,.14), transparent 60%),
    var(--bg);
  background-attachment: fixed;
  color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 15px;
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3, .brand, .auth-card h1 { font-family: var(--font-display); letter-spacing: .3px; }

/* Half of the Fold 7 scroll fix (see public/js/board.js). 100dvh bounds the
 * column to the VISIBLE viewport; 100vh includes the strip behind the URL bar,
 * which makes an overlay panel taller than the screen and unscrollable. */
html.mobile, html.mobile body {
  height: 100dvh;
  overflow: hidden;
}

a { color: var(--gold); }
button, input, select, textarea { font: inherit; color: inherit; }

button {
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: var(--radius);
  padding: 9px 14px;
  cursor: pointer;
  /* 44px minimum touch target — anything smaller is a miss on a folded phone. */
  min-height: 44px;
}
button:hover:not(:disabled) { background: #2c3452; }
button:disabled { opacity: .45; cursor: not-allowed; }
/* Foil: a vertical gold gradient with a soft top highlight reads as struck
   metal rather than a flat swatch. */
button.primary {
  background: linear-gradient(180deg, var(--gold-soft), var(--gold) 55%, var(--gold-deep));
  border-color: var(--gold-deep);
  color: #2a2103; font-weight: 700;
  text-shadow: 0 1px 0 rgba(255,255,255,.25);
}
button.primary:hover:not(:disabled) { background: linear-gradient(180deg, #fbe6a6, var(--gold-soft) 55%, var(--gold)); }
button.danger  { background: var(--danger); border-color: var(--danger); }
button.ghost   { background: transparent; }

input, select, textarea {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 12px;
  width: 100%;
  min-height: 44px;
}

/* ─── APP SHELL ─────────────────────────────────────────────────────────── */
.app { display: flex; flex-direction: column; height: 100dvh; }

header.topbar {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  background: linear-gradient(180deg, #221c39, #130f22);
  /* a thin gold rule under the header, like foil on a book cover */
  border-bottom: 1px solid var(--gold-deep);
  box-shadow: 0 1px 0 var(--edge), 0 2px 12px rgba(0,0,0,.4);
  flex: 0 0 auto;
}
header.topbar .brand { font-size: 17px; text-shadow: 0 1px 2px rgba(0,0,0,.5); }
/* The brand doubles as the game title in game.html, and a long table name was
 * shoving the right-hand buttons off a 344px screen. Let it truncate instead —
 * min-width:0 is what actually allows a flex child to shrink below its content. */
header.topbar .brand {
  font-weight: 700; color: var(--gold); letter-spacing: .3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0; flex: 0 1 auto;
}
header.topbar .spacer { flex: 1; }
header.topbar button { flex: 0 0 auto; padding: 6px 10px; min-height: 38px; }
/* Folded Fold 7 (~344px): every topbar control must stay on screen. The
   roles pill is the least informative element there — drop it and tighten
   the button chrome instead of losing a button off the edge. */
@media (max-width: 430px) {
  header.topbar { gap: 4px; padding: 8px 6px; }
  header.topbar button { padding: 5px 6px; }
  header.topbar .pill { display: none; }
}

.badge {
  display: none; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 9px; background: var(--danger);
  font-size: 11px; font-weight: 700; margin-left: 4px;
}

.rank { color: var(--gold); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ─── LAYOUT ────────────────────────────────────────────────────────────── */
main.cols {
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  padding: 10px;
  overflow: hidden;
  min-height: 0;
}
@media (min-width: 640px)  { main.cols { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1100px) { main.cols { grid-template-columns: 1fr 1.2fr 1fr; } }

.col {
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--line);
  /* a faint gold seam along the top edge */
  border-top: 1px solid var(--edge);
  border-radius: var(--radius);
  display: flex; flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.col > h2 {
  margin: 0; padding: 11px 12px;
  font-family: var(--font-display);
  font-size: 15px; letter-spacing: .5px;
  color: var(--gold);
  background: linear-gradient(180deg, rgba(217,175,83,.06), transparent);
  border-bottom: 1px solid var(--edge);
  flex: 0 0 auto;
}

/* Every scrolling region carries touch-action:pan-y — the second half of the
 * Fold 7 fix. board.js's guard is the third. */
.scroll-region { flex: 1 1 auto; overflow-y: auto; touch-action: pan-y; padding: 8px; min-height: 0; }

.empty { color: var(--ink-dim); padding: 16px; text-align: center; font-size: 14px; }

/* ─── MOBILE TAB BAR (≤900px) ───────────────────────────────────────────── */
.tabbar { display: none; flex: 0 0 auto; border-top: 1px solid var(--line); background: var(--bg-2); }
.tabbar button { flex: 1; border: none; border-radius: 0; background: transparent; font-size: 13px; }
.tabbar button.active { background: var(--panel-2); color: var(--gold); box-shadow: inset 0 2px 0 var(--gold); }

@media (max-width: 900px) {
  .tabbar { display: flex; }
  main.cols { grid-template-columns: 1fr; }
  main.cols .col { display: none; }
  main.cols .col.active { display: flex; }
}

/* ─── CARDS / ROWS ──────────────────────────────────────────────────────── */
.row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px; margin-bottom: 8px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.row .grow { flex: 1; min-width: 0; }
.row .title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .sub { font-size: 12px; color: var(--ink-dim); }

/* ─── SEATS ─────────────────────────────────────────────────────────────── */
.seat {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; margin-bottom: 8px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  border-left: 5px solid var(--line);
  background: var(--panel-2);
}
.seat.gryffindor { border-left-color: var(--gryffindor); }
.seat.hufflepuff { border-left-color: var(--hufflepuff); }
.seat.ravenclaw  { border-left-color: var(--ravenclaw); }
.seat.slytherin  { border-left-color: var(--slytherin); }
.seat.dark_arts  { border-left-color: var(--dark); background: #191426; }
.seat .who { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seat .who.vacant { color: var(--ink-dim); font-style: italic; }
.seat .dot { width: 8px; height: 8px; border-radius: 50%; background: #555; flex: 0 0 auto; }
.seat .dot.on { background: var(--ok); }
.seat .ready { color: var(--ok); font-size: 18px; }
.seat button { min-height: 38px; padding: 6px 12px; }

/* ─── BOARD ─────────────────────────────────────────────────────────────── */
/* The frame owns gestures; touch-action is managed in JS by board.js so page
 * scroll survives at base zoom and panning takes over once zoomed. */
#board-frame {
  position: relative;
  flex: 1 1 auto;
  overflow: hidden;
  background: radial-gradient(ellipse at 50% 40%, #1b2136 0%, #0b0d14 75%);
  min-height: 220px;
}
#board-stage { transform-origin: 0 0; width: 100%; height: 100%; }

/* The board scan: sized to fit the frame, panned/zoomed by the stage
 * transform. Until it loads (or when the gitignored assets aren't built) the
 * placeholder shows through; .ok hides the placeholder via the sibling rule. */
#board-img {
  display: none; width: 100%; height: 100%;
  object-fit: contain; user-select: none; -webkit-user-drag: none;
}
#board-img.ok { display: block; }
/* The img lives inside #board-fit since M2, so the placeholder (a SIBLING of
 * the fit box) hides via :has once the scan has actually loaded. */
#board-img.ok ~ .board-placeholder,
#board-fit:has(> #board-img.ok) ~ .board-placeholder { display: none; }

/* The 3D table — a SIBLING of the stage so it never inherits the 2D pan/zoom
 * transform. game.js flips display between the two views. */
#board3d { display: none; position: absolute; inset: 0; }

.board-placeholder {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  flex-direction: column; gap: 8px; text-align: center;
  color: var(--ink-dim); padding: 24px;
}
.board-placeholder .big { font-size: 34px; }
.board-placeholder .note { max-width: min(34ch, 100%); font-size: 13px; }

/* Overlay panels live INSIDE the board frame — the exact arrangement that
 * caused the WWII scroll bug. They must stay in board.js's OVERLAY_SELECTOR. */
.overlay {
  position: absolute; left: 0; right: 0; bottom: 0;
  max-height: 55%;
  background: rgba(20, 24, 38, .97);
  border-top: 1px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  display: none; flex-direction: column;
  touch-action: pan-y;
}
.overlay.open { display: flex; }
.overlay > header {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-bottom: 1px solid var(--line);
  font-size: 13px; color: var(--ink-dim); flex: 0 0 auto;
}
.overlay > header .spacer { flex: 1; }
.overlay .body { overflow-y: auto; touch-action: pan-y; padding: 10px; min-height: 0; }

/* ─── CHAT ──────────────────────────────────────────────────────────────── */
.chat-line { padding: 5px 2px; font-size: 14px; line-height: 1.35; word-break: break-word; }
.chat-line b { color: var(--gold); }
.chat-line time { color: var(--ink-dim); font-size: 11px; margin-left: 6px; }
.chat-input { display: flex; gap: 6px; padding: 8px; border-top: 1px solid var(--line); flex: 0 0 auto; }
.chat-input input { flex: 1; }
.chat-input button { flex: 0 0 auto; }

/* ─── NOTIFICATIONS ─────────────────────────────────────────────────────── */
.notif {
  display: flex; gap: 8px; align-items: flex-start;
  padding: 9px 10px; border-bottom: 1px solid var(--line); font-size: 14px;
}
.notif.unread { background: #1e2340; }
.notif time { margin-left: auto; color: var(--ink-dim); font-size: 11px; white-space: nowrap; }

/* ─── MODALS ────────────────────────────────────────────────────────────── */
.modal-bg {
  position: fixed; inset: 0; background: rgba(0,0,0,.72);
  display: none; align-items: center; justify-content: center; padding: 14px; z-index: 60;
}
.modal-bg.open { display: flex; }
.modal {
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  width: 100%; max-width: 460px; max-height: 88dvh;
  display: flex; flex-direction: column; overflow: hidden;
}
.modal > header { padding: 12px 14px; border-bottom: 1px solid var(--line); font-weight: 600; }
.modal .body { padding: 14px; overflow-y: auto; touch-action: pan-y; }
.modal .foot { padding: 12px 14px; border-top: 1px solid var(--line); display: flex; gap: 8px; justify-content: flex-end; }
.field { margin-bottom: 12px; }
.field label { display: block; font-size: 12px; color: var(--ink-dim); margin-bottom: 5px; }
.field .hint { font-size: 12px; color: var(--ink-dim); margin-top: 5px; line-height: 1.4; }
.check { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.check input { width: auto; min-height: auto; }

/* ─── TOASTS ────────────────────────────────────────────────────────────── */
#toasts { position: fixed; left: 50%; transform: translateX(-50%); bottom: 16px; z-index: 100;
          display: flex; flex-direction: column; gap: 8px; pointer-events: none; width: min(92vw, 420px); }
.toast {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 11px 14px; font-size: 14px;
  box-shadow: 0 6px 24px rgba(0,0,0,.55);
  transition: opacity .3s, transform .3s;
}
.toast.out { opacity: 0; transform: translateY(8px); }

/* ─── UPDATE BAR (soft deploy prompt) ───────────────────────────────────────
 * A dismissible bottom bar shown when the server has redeployed. It never
 * reloads on its own — the player refreshes when convenient — so it must stay
 * clear of the mobile tab bar (safe-area + a little lift). */
#update-bar {
  position: fixed; z-index: 120;
  left: 50%; transform: translateX(-50%);
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  width: min(94vw, 460px);
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--gold-deep);
  border-radius: 12px;
  box-shadow: 0 0 0 1px var(--edge) inset, 0 10px 34px rgba(0,0,0,.6);
  animation: ub-rise .3s ease-out;
}
@keyframes ub-rise { from { opacity: 0; transform: translate(-50%, 12px); } to { opacity: 1; transform: translate(-50%, 0); } }
#update-bar .ub-msg { flex: 1; min-width: 0; font-size: 14px; color: var(--ink); }
#update-bar .ub-refresh { min-height: 38px; padding: 7px 14px; }
#update-bar .ub-x { min-height: 38px; padding: 7px 10px; color: var(--ink-dim); }
/* Above the mobile tab bar so it never covers the Games/Friends/Chat controls. */
@media (max-width: 900px) { #update-bar { bottom: calc(64px + env(safe-area-inset-bottom, 0px)); } }

/* ─── AUTH ──────────────────────────────────────────────────────────────── */
.auth-wrap { display: flex; align-items: center; justify-content: center; height: 100dvh; padding: 18px; }
.auth-card { width: 100%; max-width: 380px;
             background:
               radial-gradient(120% 90% at 50% -10%, rgba(217,175,83,.10), transparent 60%),
               linear-gradient(180deg, var(--panel-2), var(--panel));
             border: 1px solid var(--gold-deep);
             box-shadow: 0 0 0 1px var(--edge) inset, 0 18px 50px rgba(0,0,0,.55);
             border-radius: 14px; padding: 26px 24px; text-align: center; }
.auth-card .field { text-align: left; }
.auth-card h1 { margin: 0 0 2px; font-size: 27px; color: var(--gold);
                text-shadow: 0 1px 0 var(--gold-deep), 0 2px 6px rgba(0,0,0,.5); }
/* A hairline flourish under the title, like the rule on a spellbook page. */
.auth-card p.tag { margin: 8px auto 20px; color: var(--ink-dim); font-size: 13px; font-style: italic;
                   max-width: 240px; padding-top: 10px;
                   border-top: 1px solid var(--edge); }
.auth-card .err { color: #ff8a80; font-size: 13px; min-height: 18px; margin-top: 8px; }
.auth-card .switch { margin-top: 14px; text-align: center; font-size: 13px; color: var(--ink-dim); }

.pill { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11px;
        background: var(--panel-2); border: 1px solid var(--line); color: var(--ink-dim); }
.pill.hidden-mode { border-color: var(--dark); color: #c9a6ff; }

/* ─── M2: BOARD OVERLAY ─────────────────────────────────────────────────── */
/* #board-fit keeps the scan's aspect ratio; the SVG overlay is its sibling
 * child, both sized to the same box so polygon coords track the pixels. */
#board-stage { display: flex; align-items: center; justify-content: center; }
#board-fit {
  position: relative;
  aspect-ratio: 2408 / 1604;
  max-width: 100%; max-height: 100%;
  width: 100%;
}
#board-fit #board-img { position: absolute; inset: 0; width: 100%; height: 100%; }
#board-overlay { position: absolute; inset: 0; width: 100%; height: 100%; }

#board-overlay .area { fill: transparent; stroke: transparent; cursor: pointer; }
/* M5 polish: highlights breathe, pawns settle when the board redraws, the
   path dashes march. Pure CSS on recreated elements — the overlay rebuilds
   wholesale each render, so continuous keyframes (not transitions) are what
   actually shows. Cheap on the Fold 7: compositor-only properties. */
@keyframes hl-pulse { 0%, 100% { fill-opacity: .55; } 50% { fill-opacity: 1; } }
@keyframes pawn-settle { from { transform: scale(1.35); opacity: .2; } to { transform: scale(1); opacity: 1; } }
@keyframes dash-march { to { stroke-dashoffset: -20; } }
#board-overlay .area.hl { fill: rgba(80, 200, 120, .25); stroke: #59d98c; stroke-width: 4; animation: hl-pulse 1.4s ease-in-out infinite; }
#board-overlay .area.onpath { fill: rgba(120, 170, 255, .22); }
#board-overlay .area.push { fill: rgba(255, 140, 60, .3); stroke: #ff8c3c; stroke-width: 4; }
#board-overlay .path-preview {
  fill: none; stroke: #78aaff; stroke-width: 6; stroke-dasharray: 14 10;
  stroke-linecap: round; pointer-events: none;
  animation: dash-march .8s linear infinite;
}
#board-overlay .pawn { cursor: pointer; }
#board-overlay .pawn > circle,
#board-overlay .pawn > rect { animation: pawn-settle .22s ease-out; transform-box: fill-box; transform-origin: center; }
#board-overlay .pawn.selectable circle,
#board-overlay .pawn.selectable rect { filter: drop-shadow(0 0 6px #59d98c); }
#board-overlay .pawn.selected circle,
#board-overlay .pawn.selected rect { filter: drop-shadow(0 0 8px #fff); }
#board-overlay .pawn.stunned { opacity: .7; }
#board-overlay .stun-t { font-size: 18px; fill: #ff5c5c; text-anchor: middle; pointer-events: none; }
#board-overlay .da-pawn { fill: #24122e; stroke: #7d3fbf; stroke-width: 3; }
#board-overlay .token-c { fill: #d3a625; stroke: #7a5b10; stroke-width: 2; }
#board-overlay .token-t { font-size: 17px; font-weight: 700; fill: #2b2003; text-anchor: middle; pointer-events: none; }
#board-overlay .shield-t, #board-overlay .ror-t { font-size: 26px; text-anchor: middle; pointer-events: none; }
#board-overlay .shield-sub { font-size: 14px; text-anchor: middle; pointer-events: none; }

/* ─── M2: ACTION BAR ────────────────────────────────────────────────────── */
#action-bar {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  padding: 8px; border-top: 1px solid var(--line);
  min-height: 52px; font-size: 13px;
}
#action-bar:empty { display: none; }
#action-bar .hint { flex: 1 1 100%; color: var(--ink-dim); font-size: 12px; }
#action-bar button { min-height: 40px; }
#action-bar button.primary { background: var(--accent, var(--gold)); color: #08131f; font-weight: 700; }
#action-bar .grow { flex: 1; }

/* ─── M5: LIVE SIDE BOARD (the real scan + overlay) ─────────────────────── */
.sideboard { position: relative; }
.sideboard > img { width: 100%; display: block; border-radius: 10px; }
.sideboard > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.sideboard .sb-marker {
  fill: rgba(20, 8, 30, .55); stroke: #d9b45b; stroke-width: 6;
  animation: hl-pulse 1.6s ease-in-out infinite;
}
.sideboard .sb-marker-t { font-size: 44px; text-anchor: middle; fill: #ffd97a; pointer-events: none; }
.sideboard .sb-token { fill: rgba(10, 10, 14, .78); stroke: #b44; stroke-width: 4; }
.sideboard .sb-token-t { font-size: 30px; font-weight: bold; text-anchor: middle; fill: #f0e6d0; pointer-events: none; }

/* ─── M2: CARDS ─────────────────────────────────────────────────────────── */
.cardrow { display: flex; flex-wrap: wrap; gap: 8px; }
.gamecard {
  width: 96px; border-radius: 8px; overflow: hidden; position: relative;
  border: 2px solid transparent; cursor: pointer; background: #0d0f16;
  padding: 0;
}
.gamecard img { width: 100%; display: block; }
.gamecard.sel { border-color: #59d98c; box-shadow: 0 0 8px #59d98c; }
.gamecard.dim { opacity: .4; }
.gamecard .cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,.75); color: #fff; font-size: 10px; padding: 2px 4px;
  text-align: center;
}
/* 🔍 corner badge on every card tile: opens the real card image full-size
   without triggering the tile's own select action. */
.gamecard .zoombtn {
  position: absolute; top: 2px; right: 2px; z-index: 2;
  width: 26px; height: 26px; line-height: 26px; border-radius: 50%;
  background: rgba(0,0,0,.62); color: #fff; font-size: 13px;
  text-align: center; cursor: zoom-in;
}
.gamecard .zoombtn:active { background: rgba(0,0,0,.85); }

/* Full-size card viewer — tap anywhere to dismiss. */
#card-zoom {
  position: fixed; inset: 0; z-index: 90; display: none;
  background: rgba(3, 5, 9, .88);
  align-items: center; justify-content: center; flex-direction: column;
  padding: 12px; cursor: zoom-out;
}
#card-zoom.open { display: flex; }
#card-zoom img {
  max-width: 96vw; max-height: 84dvh; border-radius: 12px;
  box-shadow: 0 8px 40px rgba(0,0,0,.8);
}
#card-zoom .cz-name { color: #fff; font-size: 14px; margin-top: 10px; text-align: center; }

/* ─── M2: MODALS ────────────────────────────────────────────────────────── */
.modal-back {
  position: fixed; inset: 0; z-index: 60; display: none;
  background: rgba(5, 7, 12, .72);
  align-items: center; justify-content: center; padding: 14px;
}
.modal-back.open { display: flex; }
.modal {
  background: var(--panel, #141824); border: 1px solid var(--line);
  border-radius: 14px; padding: 16px; max-width: min(560px, 96vw);
  max-height: 88dvh; overflow-y: auto; touch-action: pan-y;
}
.modal h3 { margin: 0 0 10px; font-size: 16px; }
.modal .row-btns { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.modal .row-btns button { flex: 1 1 auto; min-height: 44px; }
.modal .note { color: var(--ink-dim); font-size: 12px; margin: 6px 0; }

/* ─── M2: STATUS PANEL ──────────────────────────────────────────────────── */
.stat-track { display: flex; gap: 3px; flex-wrap: wrap; margin: 4px 0; }
.stat-track .cell {
  width: 18px; height: 18px; border-radius: 4px; background: #232838;
  display: flex; align-items: center; justify-content: center; font-size: 10px;
}
.stat-track .cell.white { background: #4a4f60; }
.stat-track .cell.orange { background: #7a4a1c; }
.stat-track .cell.red { background: #6d2020; }
.stat-track .cell.marker { outline: 2px solid #ffd75e; }
.item-chips { display: flex; gap: 6px; flex-wrap: wrap; font-size: 12px; }
.item-chips .chip { background: #1a2030; border: 1px solid var(--line); border-radius: 10px; padding: 2px 8px; }
