/* The Relay — Grandmaster command dashboard.
 *
 * Loaded by index.html after style.css and scoped to `#view-leader` plus the
 * `gm-active` body class that show() toggles. Nothing here leaks into the
 * lobby or the play view: those keep style.css untouched. The dark palette
 * itself lives in style.css, shared with the result screen — see result.css.
 *
 * The shape is a command board, not a page of cards. A fixed bar across the
 * top, then a deck that fills the viewport: a rail of who-and-what-happened
 * down the left, the two live boards across the middle and right, and the perk
 * shop as one band beneath them. Panels that grow without limit — the roster,
 * the feed, the shop — scroll inside themselves so the deck keeps its shape.
 * Everything a Grandmaster only consults between decisions (the level race, the
 * coin ledger) sits below the fold on ordinary page scroll.
 *
 * Team colours deliberately reuse style.css's --alpha/--bravo rather than
 * inventing a dashboard-only pair, so a Grandmaster and their players read the
 * same team identity on every screen.
 */

/* The command view is wider than every other screen; .view's 720px cap is a
   player-screen rule, so override it here only. */
body.gm-active { background: var(--gm-bg); }
body.gm-active .topbar { display: none; }

#view-leader {
  display: flex;
  flex-direction: column;
  gap: var(--gm-gap);
  width: min(1780px, calc(100% - 28px));
  max-width: none;
  margin: 0 auto 24px;
  padding: 0;
  color: var(--gm-text);
  font-variant-numeric: tabular-nums;
}

/* One screen exactly — a ceiling as much as a floor. A fold that could only
   grow would push the shop along its bottom off the bottom of the monitor,
   which is the whole thing this layout exists to stop. dvh rather than vh
   because a phone counts its browser chrome as viewport and vh does not. */
.gm-fold {
  display: flex;
  flex-direction: column;
  gap: var(--gm-gap);
  min-height: 0;
  height: 100vh;
  height: 100dvh;
  padding: 14px 0;
}

#view-leader :focus-visible {
  outline: 3px solid var(--gm-yellow);
  outline-offset: 2px;
  border-radius: 4px;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Panels own their own scrolling, so the deck never grows a scrollbar of its
   own and the bar never leaves the top of the screen. */
.gm-scroll,
.gm-duel,
.gm-manual__rail {
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(122, 140, 255, 0.4) transparent;
}
.gm-scroll { flex: 1; }
.gm-scroll::-webkit-scrollbar,
.gm-duel::-webkit-scrollbar,
.gm-manual__rail::-webkit-scrollbar { width: 8px; height: 8px; }
.gm-scroll::-webkit-scrollbar-track,
.gm-duel::-webkit-scrollbar-track,
.gm-manual__rail::-webkit-scrollbar-track { background: transparent; }
.gm-scroll::-webkit-scrollbar-thumb,
.gm-duel::-webkit-scrollbar-thumb,
.gm-manual__rail::-webkit-scrollbar-thumb {
  background: rgba(122, 140, 255, 0.34);
  border-radius: 999px;
}
.gm-scroll::-webkit-scrollbar-thumb:hover { background: rgba(122, 140, 255, 0.55); }

/* --- icons ------------------------------------------------------------- */

/* Local CC0/ISC SVGs recoloured through a mask, so one file serves every
   accent instead of shipping a copy per colour. See assets/CREDITS.md. */
.gm-ic {
  display: inline-block;
  width: 20px;
  height: 20px;
  flex: none;
  background: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.gm-ic--lg { width: 26px; height: 26px; }
.gm-ic--sm { width: 16px; height: 16px; }

.gm-ic--crown { -webkit-mask-image: url("/static/assets/ui/crown.svg"); mask-image: url("/static/assets/ui/crown.svg"); }
.gm-ic--coin { -webkit-mask-image: url("/static/assets/ui/coin.svg"); mask-image: url("/static/assets/ui/coin.svg"); }
.gm-ic--shield { -webkit-mask-image: url("/static/assets/ui/shield.svg"); mask-image: url("/static/assets/ui/shield.svg"); }
.gm-ic--reflect { -webkit-mask-image: url("/static/assets/ui/reflect.svg"); mask-image: url("/static/assets/ui/reflect.svg"); }
.gm-ic--insurance { -webkit-mask-image: url("/static/assets/ui/insurance.svg"); mask-image: url("/static/assets/ui/insurance.svg"); }
.gm-ic--duel { -webkit-mask-image: url("/static/assets/ui/duel.svg"); mask-image: url("/static/assets/ui/duel.svg"); }
.gm-ic--warning { -webkit-mask-image: url("/static/assets/ui/warning.svg"); mask-image: url("/static/assets/ui/warning.svg"); }
.gm-ic--timer { -webkit-mask-image: url("/static/assets/ui/timer.svg"); mask-image: url("/static/assets/ui/timer.svg"); }
.gm-ic--offline { -webkit-mask-image: url("/static/assets/ui/connection-off.svg"); mask-image: url("/static/assets/ui/connection-off.svg"); }
.gm-ic--cleared { -webkit-mask-image: url("/static/assets/ui/cleared.svg"); mask-image: url("/static/assets/ui/cleared.svg"); }
.gm-ic--team { -webkit-mask-image: url("/static/assets/ui/team.svg"); mask-image: url("/static/assets/ui/team.svg"); }
.gm-ic--level { -webkit-mask-image: url("/static/assets/ui/level.svg"); mask-image: url("/static/assets/ui/level.svg"); }
.gm-ic--bomb { -webkit-mask-image: url("/static/assets/ui/bomb.svg"); mask-image: url("/static/assets/ui/bomb.svg"); }
.gm-ic--spectating { -webkit-mask-image: url("/static/assets/ui/spectating.svg"); mask-image: url("/static/assets/ui/spectating.svg"); }
.gm-ic--key { -webkit-mask-image: url("/static/assets/ui/key.svg"); mask-image: url("/static/assets/ui/key.svg"); }

.gm-ic--perk-freeze { -webkit-mask-image: url("/static/assets/perks/freeze.svg"); mask-image: url("/static/assets/perks/freeze.svg"); }
.gm-ic--perk-scramble { -webkit-mask-image: url("/static/assets/perks/scramble.svg"); mask-image: url("/static/assets/perks/scramble.svg"); }
.gm-ic--perk-clock-burn { -webkit-mask-image: url("/static/assets/perks/clock-burn.svg"); mask-image: url("/static/assets/perks/clock-burn.svg"); }
.gm-ic--perk-skim { -webkit-mask-image: url("/static/assets/perks/skim.svg"); mask-image: url("/static/assets/perks/skim.svg"); }
.gm-ic--perk-silence { -webkit-mask-image: url("/static/assets/perks/silence.svg"); mask-image: url("/static/assets/perks/silence.svg"); }
.gm-ic--perk-wobble { -webkit-mask-image: url("/static/assets/perks/wobble.svg"); mask-image: url("/static/assets/perks/wobble.svg"); }
.gm-ic--perk-static { -webkit-mask-image: url("/static/assets/perks/static.svg"); mask-image: url("/static/assets/perks/static.svg"); }
.gm-ic--perk-mirror { -webkit-mask-image: url("/static/assets/perks/mirror.svg"); mask-image: url("/static/assets/perks/mirror.svg"); }
.gm-ic--perk-blackout { -webkit-mask-image: url("/static/assets/perks/blackout.svg"); mask-image: url("/static/assets/perks/blackout.svg"); }
.gm-ic--perk-shield { -webkit-mask-image: url("/static/assets/perks/shield.svg"); mask-image: url("/static/assets/perks/shield.svg"); }
.gm-ic--perk-reflect { -webkit-mask-image: url("/static/assets/perks/reflect.svg"); mask-image: url("/static/assets/perks/reflect.svg"); }
.gm-ic--perk-insurance { -webkit-mask-image: url("/static/assets/perks/insurance.svg"); mask-image: url("/static/assets/perks/insurance.svg"); }
.gm-ic--perk-extend-wait { -webkit-mask-image: url("/static/assets/perks/extend-wait.svg"); mask-image: url("/static/assets/perks/extend-wait.svg"); }

.gm-ic--star { -webkit-mask-image: url("/static/assets/ui/star.svg"); mask-image: url("/static/assets/ui/star.svg"); }
.gm-ic--logo-knight { -webkit-mask-image: url("/static/assets/logos/knight.svg"); mask-image: url("/static/assets/logos/knight.svg"); }
.gm-ic--logo-rook { -webkit-mask-image: url("/static/assets/logos/rook.svg"); mask-image: url("/static/assets/logos/rook.svg"); }
.gm-ic--logo-bishop { -webkit-mask-image: url("/static/assets/logos/bishop.svg"); mask-image: url("/static/assets/logos/bishop.svg"); }
.gm-ic--logo-queen { -webkit-mask-image: url("/static/assets/logos/queen.svg"); mask-image: url("/static/assets/logos/queen.svg"); }
.gm-ic--logo-bow { -webkit-mask-image: url("/static/assets/logos/bow.svg"); mask-image: url("/static/assets/logos/bow.svg"); }
.gm-ic--logo-skull { -webkit-mask-image: url("/static/assets/logos/skull.svg"); mask-image: url("/static/assets/logos/skull.svg"); }
.gm-ic--logo-campfire { -webkit-mask-image: url("/static/assets/logos/campfire.svg"); mask-image: url("/static/assets/logos/campfire.svg"); }
.gm-ic--logo-tower { -webkit-mask-image: url("/static/assets/logos/tower.svg"); mask-image: url("/static/assets/logos/tower.svg"); }

/* One mark per game, keyed by the game id. `.gm-ic--game` on its own is the
   fallback a game gets before it has a mark of its own: a board, not a blank
   square, so an unregistered id degrades to something rather than nothing. */
.gm-ic--game { -webkit-mask-image: url("/static/assets/games/generic.svg"); mask-image: url("/static/assets/games/generic.svg"); }
.gm-ic--game-rewire { -webkit-mask-image: url("/static/assets/games/rewire.svg"); mask-image: url("/static/assets/games/rewire.svg"); }
.gm-ic--game-sweep { -webkit-mask-image: url("/static/assets/games/sweep.svg"); mask-image: url("/static/assets/games/sweep.svg"); }
.gm-ic--game-mirror_run { -webkit-mask-image: url("/static/assets/games/mirror_run.svg"); mask-image: url("/static/assets/games/mirror_run.svg"); }
.gm-ic--game-decant { -webkit-mask-image: url("/static/assets/games/decant.svg"); mask-image: url("/static/assets/games/decant.svg"); }
.gm-ic--game-echo { -webkit-mask-image: url("/static/assets/games/echo.svg"); mask-image: url("/static/assets/games/echo.svg"); }
.gm-ic--game-overprint { -webkit-mask-image: url("/static/assets/games/overprint.svg"); mask-image: url("/static/assets/games/overprint.svg"); }
.gm-ic--game-stackdrop { -webkit-mask-image: url("/static/assets/games/stackdrop.svg"); mask-image: url("/static/assets/games/stackdrop.svg"); }
.gm-ic--game-lane_shift { -webkit-mask-image: url("/static/assets/games/lane_shift.svg"); mask-image: url("/static/assets/games/lane_shift.svg"); }
.gm-ic--game-shadow_cast { -webkit-mask-image: url("/static/assets/games/shadow_cast.svg"); mask-image: url("/static/assets/games/shadow_cast.svg"); }
.gm-ic--game-threadline { -webkit-mask-image: url("/static/assets/games/threadline.svg"); mask-image: url("/static/assets/games/threadline.svg"); }
/* The bomb and the crown already exist in the UI set; a second copy under
   games/ would be the same shape maintained twice. */
.gm-ic--game-bomb_defuse { -webkit-mask-image: url("/static/assets/ui/bomb.svg"); mask-image: url("/static/assets/ui/bomb.svg"); }
.gm-ic--game-rps_duel { -webkit-mask-image: url("/static/assets/games/rps_duel.svg"); mask-image: url("/static/assets/games/rps_duel.svg"); }
.gm-ic--game-crown_duel { -webkit-mask-image: url("/static/assets/ui/crown.svg"); mask-image: url("/static/assets/ui/crown.svg"); }
.gm-ic--game-number_clash { -webkit-mask-image: url("/static/assets/games/number_clash.svg"); mask-image: url("/static/assets/games/number_clash.svg"); }
.gm-ic--game-bid_war { -webkit-mask-image: url("/static/assets/games/bid_war.svg"); mask-image: url("/static/assets/games/bid_war.svg"); }

/* --- command bar ------------------------------------------------------- */

.gm-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  flex: none;
  padding: 12px 18px;
  background: linear-gradient(180deg, var(--gm-panel-2), var(--gm-panel));
  border: 1px solid var(--gm-line);
  border-radius: var(--gm-radius-lg);
}

.gm-mark { display: inline-flex; align-items: center; gap: 8px; }
.gm-mark svg { width: 18px; height: 24px; color: var(--gm-yellow); }
.gm-mark span {
  font-family: "Arial Black", "Segoe UI Black", Impact, system-ui, sans-serif;
  font-weight: 900;
  font-size: 1.15rem;
  letter-spacing: 0.03em;
}

.gm-field {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  padding: 6px 14px;
  border: 1px solid var(--gm-line);
  border-radius: var(--gm-radius-sm);
  background: rgba(7, 9, 31, 0.5);
}
.gm-field__label {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gm-muted);
}
.gm-field__value { font-weight: 800; font-size: 1rem; letter-spacing: 0.08em; }

/* The team badge carries the team colour as a solid edge, not a whole fill. */
.gm-bar__team {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 8px 16px 8px 13px;
  border: 1px solid var(--gm-line);
  border-left: 4px solid var(--team-color, var(--gm-cyan));
  border-radius: var(--gm-radius-sm);
  background: rgba(7, 9, 31, 0.5);
}
.gm-bar__team h1 {
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: "Arial Black", "Segoe UI Black", Impact, system-ui, sans-serif;
  font-weight: 900;
  font-size: 1.2rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--team-color, var(--gm-text));
}
.gm-level {
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(122, 140, 255, 0.16);
  font-weight: 800;
  font-size: 0.85rem;
  white-space: nowrap;
}

/* Currency is the Grandmaster's resource, so it gets the loudest treatment. */
.gm-coin {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 20px;
  border: 2px solid var(--gm-yellow);
  border-radius: 999px;
  background: rgba(255, 210, 28, 0.1);
  color: var(--gm-yellow);
  font-weight: 900;
  font-size: 1.25rem;
}

/* One strip divided by hairlines, not a row of separate boxes: every slot is
   always here, so the bar never reflows and a glance lands where it did last
   time. An inactive slot dims rather than leaving. */
.gm-flags {
  display: flex;
  align-items: stretch;
  gap: 0;
  flex-wrap: wrap;
  list-style: none;
  margin: 0 0 0 auto;
  padding: 0;
  border: 1px solid var(--gm-line-soft);
  border-radius: var(--gm-radius-sm);
  background: rgba(7, 9, 31, 0.55);
  overflow: hidden;
}
.gm-flag {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  padding: 7px 14px;
  font-size: 0.78rem;
  line-height: 1.15;
}
.gm-flag > span { min-width: 0; }
.gm-flag__label,
.gm-flag__value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gm-flag + .gm-flag { border-left: 1px solid var(--gm-line-soft); }
.gm-flag__label {
  display: block;
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gm-muted);
}
.gm-flag__value { font-weight: 800; }
.gm-flag--off { color: var(--gm-muted); opacity: 0.5; }
.gm-flag--on { color: var(--gm-cyan); }
.gm-flag--good { color: var(--gm-green); }
.gm-flag--warn { color: var(--gm-amber); background: rgba(255, 166, 43, 0.12); }
.gm-flag--danger { color: var(--gm-red); background: rgba(255, 81, 101, 0.14); }

/* --- the deck ---------------------------------------------------------- */

.gm-deck {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(320px, 0.95fr) minmax(0, 2.2fr);
  /* A floor under the stage, not just a share of the slack. The shop is the
     one panel here that can scroll without losing anything — a board you can
     only see 200px of is no longer a board — so on a short screen the shop is
     what gives way. */
  grid-template-rows: auto minmax(300px, 1fr) auto;
  grid-template-areas:
    "rail opp"
    "rail stage"
    "rail perks";
  gap: var(--gm-gap);
}

.gm-rail {
  grid-area: rail;
  display: flex;
  flex-direction: column;
  gap: var(--gm-gap);
  min-height: 0;
}
/* The roster takes the slack; the feed keeps a floor so it cannot be squeezed
   out of existence, and the handoff is a fixed control that never scrolls. */
.gm-rail .gm-panel--team { flex: 1 1 auto; min-height: 190px; }
.gm-rail .gm-panel--feed { flex: 0 1 auto; min-height: 156px; }
.gm-rail .gm-panel--handoff { flex: none; }

/* Flex, not grid columns: when the duel or the bomb console is hidden the one
   left takes the whole stage back, with no empty column behind it. */
.gm-stage {
  grid-area: stage;
  display: flex;
  gap: var(--gm-gap);
  min-height: 0;
}
.gm-stage .gm-panel--duel { flex: 1 1 300px; min-width: 0; }
.gm-stage .gm-panel--bomb { flex: 1.6 1 430px; min-width: 0; }

.gm-panel--perks { grid-area: perks; }

/* Neither board is on the table: no duellists were fielded and no Defuser is
   seated. Nothing left wants the fold's height, so the deck stops stretching
   to fill a screen it has nothing to fill it with, and the shop rises to meet
   the scoreline instead of floating under an empty pane. */
#view-leader:has(#leader-duel-card[hidden]):has(#leader-bomb-card[hidden]) .gm-fold {
  height: auto;
}
#view-leader:has(#leader-duel-card[hidden]):has(#leader-bomb-card[hidden]) .gm-deck {
  grid-template-rows: min-content min-content minmax(0, 1fr);
}

/* Below the fold: consulted between decisions, not during them. */
.gm-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: var(--gm-gap);
  align-items: start;
}

.gm-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--gm-panel);
  border: 1px solid var(--gm-line);
  border-radius: var(--gm-radius-md);
  overflow: hidden;
}
.gm-panel__head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
  flex-wrap: wrap;
  padding: 11px 16px;
  border-bottom: 1px solid var(--gm-line-soft);
  background: linear-gradient(180deg, rgba(122, 140, 255, 0.09), transparent);
}
.gm-panel__head h2 {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.gm-panel__head .gm-spacer { flex: 1; }
.gm-panel__meta { font-size: 0.78rem; color: var(--gm-muted); font-weight: 700; }
.gm-panel__body { padding: 14px 16px 16px; min-height: 0; }
.gm-panel__note {
  margin: 0 0 12px;
  color: var(--gm-muted);
  font-size: 0.82rem;
}

/* Only the panels that carry live pressure get a coloured edge. */
.gm-panel--duel { border-color: rgba(138, 77, 255, 0.55); }
/* The game's name is as long as the game's name; the clock beside it is the
   thing that must never move, so the title gives way first. */
.gm-panel--duel .gm-panel__head { flex-wrap: nowrap; }
.gm-panel--duel .gm-panel__head h2 {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gm-panel--duel .gm-panel__meta { white-space: nowrap; }
.gm-panel--duel .gm-panel__head { color: var(--gm-violet); background: linear-gradient(180deg, rgba(138, 77, 255, 0.18), transparent); }
.gm-panel--bomb { border-color: rgba(255, 81, 101, 0.45); }
.gm-panel--bomb .gm-panel__head { color: var(--gm-red); background: linear-gradient(180deg, rgba(255, 81, 101, 0.16), transparent); }
/* Wraps onto its own line under the title rather than setting a width floor. */
#leader-bomb-sub { flex: 1 1 100%; min-width: 0; }
.gm-panel--handoff { border-color: rgba(255, 210, 28, 0.4); }
.gm-panel--handoff .gm-panel__head { color: var(--gm-yellow); }
.gm-panel--team .gm-panel__head { color: var(--gm-cyan); }

/* --- level race --------------------------------------------------------- */

.gm-panel--race .gm-panel__body { padding: 12px 16px 14px; }
.gm-panel__meta.is-ahead { color: var(--gm-green); }
.gm-panel__meta.is-behind { color: var(--gm-amber); }

.gm-race__row {
  display: grid;
  grid-template-columns: 34px minmax(96px, auto) 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 10px 0;
}
.gm-race__row + .gm-race__row { border-top: 1px solid var(--gm-line-soft); }

.gm-race__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  border: 1px solid var(--team-color);
  background: color-mix(in srgb, var(--team-color) 16%, transparent);
  color: var(--team-color);
}
.gm-race__logo .gm-ic { width: 22px; height: 22px; }

.gm-race__name {
  font-family: "Arial Black", "Segoe UI Black", Impact, system-ui, sans-serif;
  font-weight: 900;
  font-size: 0.95rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--team-color);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gm-race__stars {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Lit to the level the team has actually reached; the rest stay dim, so the
   two rows read as one shared scale and the gap is the lit difference. */
.gm-race__star { display: flex; opacity: 0.28; }
.gm-race__star .gm-ic { background: var(--gm-muted); }
.gm-race__star.is-on { opacity: 1; }
.gm-race__star.is-on .gm-ic { background: var(--team-color); }

.gm-race__level {
  font-weight: 900;
  font-size: 0.9rem;
  color: var(--gm-muted);
  white-space: nowrap;
}
/* Your own row is the one being read at a glance. */
.gm-race__row.is-mine .gm-race__level { color: var(--gm-text); }
.gm-race__row:not(.is-mine) { opacity: 0.86; }

/* --- roster ------------------------------------------------------------ */

/* One column set, shared by the header and every row, so the table stays a
   table. Changing it in one place moves both. */
.gm-panel--team { --roster-cols: 38px minmax(82px, 0.9fr) minmax(104px, 1fr) auto; }

.gm-roster__head {
  display: grid;
  grid-template-columns: var(--roster-cols);
  align-items: center;
  gap: 12px;
  flex: none;
  padding: 8px 16px;
  border-bottom: 1px solid var(--gm-line-soft);
  background: rgba(7, 9, 31, 0.45);
  font-size: 0.6rem;
  font-weight: 900;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gm-muted);
}
.gm-roster__head span:first-child { grid-column: 1 / span 2; }

#view-leader .leader-roster { list-style: none; margin: 0; padding: 0; }
#view-leader .leader-roster li {
  display: grid;
  grid-template-columns: var(--roster-cols);
  align-items: center;
  gap: 12px;
  padding: 9px 16px;
  border: 0;
  border-top: 1px solid var(--gm-line-soft);
  background: none;
}
#view-leader .leader-roster li:first-child { border-top: 0; }
#view-leader .leader-roster li.is-offline { opacity: 0.62; }

.gm-avatar {
  position: relative;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 2px solid var(--team-color, var(--gm-line));
  background: var(--gm-panel-2);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  flex: none;
}
.gm-avatar svg { width: 100%; height: 100%; display: block; }
/* An initial instead of a face, where the protocol gives a name and no id. */
.gm-avatar--initials {
  color: var(--team-color, var(--gm-text));
  background: color-mix(in srgb, var(--team-color, #7a8cff) 20%, var(--gm-panel-2));
  font-weight: 900;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
}
.gm-avatar--slot { border-style: dashed; }

.gm-who { min-width: 0; }
.gm-who__name {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 800;
  font-size: 0.92rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gm-who__name .gm-ic--offline { color: var(--gm-muted); }
.gm-who__role {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gm-cyan);
}
.gm-who__role.is-duelist { color: var(--gm-pink); }
.gm-who__role.is-defuser { color: var(--gm-red); }
/* This dashboard is the only place a rejoin code is ever sent, and a stranded
   player is asking for theirs over the noise of a room: set wide enough to
   read aloud without misreading, dim enough not to compete with the roster. */
.gm-who__code {
  margin-top: 2px;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  color: var(--gm-muted);
}
/* The one row where it earns its brightness: they are gone, and this is how
   they get back. */
.leader-roster li.is-offline .gm-who__code { color: var(--gm-yellow); }

.gm-assign {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: var(--gm-muted);
  font-size: 0.82rem;
  font-weight: 700;
}
.gm-assign .gm-ic--game { color: var(--gm-violet); }
/* Wrap rather than clip: "Rock Paper Sciss..." is a worse row than a name on
   two lines, and the game is half of what the row is telling you. */
.gm-assign span { min-width: 0; line-height: 1.25; }

/* Status pills: the strongest colour on the row, always with a text label. */
#view-leader .pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border: 1px solid var(--gm-line);
  border-radius: 999px;
  background: rgba(7, 9, 31, 0.6);
  color: var(--gm-muted);
  font-size: 0.68rem;
  font-weight: 900;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  white-space: nowrap;
}
#view-leader .pill.green {
  color: var(--gm-green);
  border-color: rgba(66, 219, 131, 0.6);
  background: rgba(66, 219, 131, 0.14);
}
#view-leader .pill.bonus {
  color: var(--gm-yellow);
  border-color: rgba(255, 210, 28, 0.6);
  background: rgba(255, 210, 28, 0.14);
}
#view-leader .pill.duel {
  color: var(--gm-pink);
  border-color: rgba(255, 79, 148, 0.6);
  background: rgba(255, 79, 148, 0.14);
}
#view-leader .pill.hidden-pill {
  color: var(--gm-muted);
  border-style: dashed;
  letter-spacing: 0.24em;
}

/* --- coin leaders ------------------------------------------------------- */

.gm-panel--coins { border-color: rgba(255, 210, 28, 0.3); }
.gm-panel--coins .gm-panel__head { color: var(--gm-yellow); }

.gm-coins { list-style: none; margin: 0; padding: 0; }
.gm-coin-row {
  display: grid;
  grid-template-columns: 20px 30px minmax(70px, auto) minmax(40px, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 10px 18px;
}
.gm-coin-row + .gm-coin-row { border-top: 1px solid var(--gm-line-soft); }

.gm-coin-rank {
  font-weight: 900;
  font-size: 0.8rem;
  color: var(--gm-muted);
  text-align: center;
}
.gm-coin-row.is-top .gm-coin-rank { color: var(--gm-yellow); }

.gm-coin-row .gm-avatar { width: 30px; height: 30px; }

.gm-coin-name {
  font-weight: 800;
  font-size: 0.92rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The bar is the spread at a glance; the number is still there for the exact
   figure, so the bar is never the only way to read it. */
.gm-coin-meter {
  height: 7px;
  border-radius: 999px;
  background: rgba(122, 140, 255, 0.16);
  overflow: hidden;
}
.gm-coin-meter__fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--gm-muted);
}
.gm-coin-row.is-top .gm-coin-meter__fill { background: var(--gm-yellow); }

.gm-coin-value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 900;
  font-size: 0.95rem;
  color: var(--gm-muted);
}
.gm-coin-row.is-top .gm-coin-value { color: var(--gm-yellow); }

/* --- opponent ---------------------------------------------------------- */

/* A scoreline you glance at, so it is a band in their colour rather than a
   panel with a body: it sits above the bomb console the way a header does. */
.gm-panel--opponent {
  grid-area: opp;
  align-self: start;
  flex: none;
  border-color: color-mix(in srgb, var(--team-color, #7a8cff) 55%, transparent);
}
#view-leader .leader-opponent { color: inherit; font-weight: inherit; }
.gm-opp {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 16px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--team-color, #7a8cff) 22%, transparent),
    transparent 70%
  );
}
.gm-opp .gm-spacer { flex: 1; }
.gm-opp__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  border: 1px solid var(--team-color, var(--gm-line));
  color: var(--team-color, var(--gm-text));
}
.gm-opp__logo .gm-ic { width: 19px; height: 19px; }
.gm-opp__label {
  font-size: 0.6rem;
  font-weight: 900;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gm-muted);
}
.gm-opp__name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: "Arial Black", "Segoe UI Black", Impact, system-ui, sans-serif;
  font-weight: 900;
  font-size: 1.15rem;
  text-transform: uppercase;
  color: var(--team-color, var(--gm-text));
}
.gm-opp__stat { color: var(--gm-muted); font-weight: 700; font-size: 0.85rem; }
.gm-opp__stat strong { color: var(--gm-text); }

/* --- duel watch -------------------------------------------------------- */

.gm-duel { display: flex; flex-direction: column; gap: 12px; flex: 1; }
.gm-duel .gm-panel__note {
  margin: 0 auto;
  max-width: 46ch;
  text-align: center;
}
#leader-duel-mount { min-height: 0; }

.gm-seats {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  width: 100%;
  max-width: 400px;
  margin: 0 auto;
}
.gm-seat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  min-width: 0;
  flex: 1 1 0;
}
.gm-seat .gm-avatar { width: 46px; height: 46px; font-size: 0.95rem; }
.gm-seat__name {
  font-weight: 800;
  font-size: 0.88rem;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.gm-seat__team {
  font-size: 0.62rem;
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--team-color, var(--gm-muted));
}
.gm-seats__vs {
  flex: none;
  font-family: "Arial Black", "Segoe UI Black", Impact, system-ui, sans-serif;
  font-weight: 900;
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  color: var(--gm-violet);
}

/* The duel games are another slice: their markup is theirs, and this only
   recolours what they draw so a light-theme card does not sit in a dark board.
   Nothing here changes a shape or a position the module chose. */
#view-leader .duel { color: var(--gm-text); }
#view-leader .duel-header {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
}
#view-leader .duel-hand {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 68px;
  min-height: 68px;
  border: 2px solid var(--gm-line);
  border-radius: var(--gm-radius-md);
  background: rgba(7, 9, 31, 0.65);
  font-size: 2.1rem;
}
/* Every duel renderer labels its seats "You"/"Opponent" or with the two names,
   directly under the hands. The strip above already says who is playing, in the
   same order, so this would be the same row twice — and for a Grandmaster,
   neither seat is "You". */
#view-leader .duel-name { display: none; }
#view-leader .duel-pips { color: var(--gm-violet); }
#view-leader .duel-versus { color: var(--gm-muted); }
#view-leader .duel-status,
#view-leader .duel-note,
#view-leader .duel-guide,
#view-leader .duel-sub { color: var(--gm-muted); }
#view-leader .duel-score { color: var(--gm-violet); }
#view-leader .duel-round { color: var(--gm-text); }
#view-leader .duel-move {
  background: var(--gm-panel-2);
  border-color: var(--gm-line);
  color: var(--gm-text);
}

.gm-panel__head .duel-clock { float: none; }
#view-leader .duel-clock {
  padding: 3px 10px;
  border-radius: var(--gm-radius-sm);
  background: rgba(138, 77, 255, 0.18);
  color: var(--gm-violet);
  font-weight: 900;
  font-size: 0.85rem;
}

/* --- bomb console ------------------------------------------------------ */

.gm-bomb__clockwrap { display: flex; align-items: center; gap: 8px; margin-left: auto; }
/* No deadline means no clock, and a lone label reads as a broken one. */
.gm-bomb__clockwrap:has(.bomb-clock[hidden]) { display: none; }
#view-leader .bomb-clock {
  padding: 3px 12px;
  border: 2px solid var(--gm-red);
  border-radius: var(--gm-radius-sm);
  background: rgba(255, 81, 101, 0.12);
  color: var(--gm-red);
  font-size: 1.25rem;
  font-weight: 900;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
}
#view-leader .bomb-clock.is-urgent { animation: gm-pulse 1s ease-in-out infinite; }
@keyframes gm-pulse { 50% { opacity: 0.45; } }

/* The manual draws at a fixed 590x440 and is scaled to fit; the rail and the
   arrows are this console's own chrome, built from the module's PAGES list so
   the manual itself keeps drawing exactly what it always drew. */
.gm-manual {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 10px;
  padding: 10px;
  background: #0a0e26;
  border-top: 1px solid var(--gm-line-soft);
}
.gm-manual__rail {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-self: stretch;
  flex: none;
  width: 118px;
}
.gm-page-tab {
  padding: 7px 10px;
  border: 1px solid var(--gm-line);
  border-radius: var(--gm-radius-sm);
  background: rgba(122, 140, 255, 0.08);
  color: var(--gm-muted);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1.2;
  text-align: left;
  cursor: pointer;
}
.gm-page-tab:hover { background: rgba(122, 140, 255, 0.2); color: var(--gm-text); }
.gm-page-tab.is-open {
  border-color: var(--gm-red);
  background: rgba(255, 81, 101, 0.16);
  color: #ffc6cd;
}
.gm-manual #leader-bomb-mount {
  position: relative;
  /* A floor, not a target: the console scales the page to whatever this cell
     ends up being, and a tall floor here would push it out of the fold. */
  min-height: 190px;
  color: var(--gm-text);
}
.gm-manual__nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  align-self: center;
}
.gm-manual__count {
  font-size: 0.72rem;
  font-weight: 900;
  color: var(--gm-muted);
  white-space: nowrap;
}
.gm-page-btn {
  width: 34px;
  height: 34px;
  border: 1px solid var(--gm-line);
  border-radius: var(--gm-radius-sm);
  background: rgba(122, 140, 255, 0.1);
  color: var(--gm-text);
  font: inherit;
  font-size: 1.2rem;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
}
.gm-page-btn:hover:not(:disabled) { background: rgba(122, 140, 255, 0.26); }
.gm-page-btn:disabled { opacity: 0.32; cursor: not-allowed; }

/* --- perk shop --------------------------------------------------------- */

.gm-panel--perks .gm-panel__body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 14px 14px;
}
.gm-perks { display: flex; flex-direction: column; gap: 12px; }

/* A coloured spine down the left of each band instead of a heading above it:
   the label is the edge of the row, so the cards start at the top of the panel
   and the two bands read as two rails rather than two lists. */
.gm-perks__group {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: 10px;
  align-items: stretch;
}
.gm-perks__label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: 0;
  padding: 8px 0;
  border-radius: var(--gm-radius-sm);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 0.66rem;
  font-weight: 900;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.gm-perks__group--attack .gm-perks__label {
  color: var(--gm-red);
  background: rgba(255, 81, 101, 0.14);
  border: 1px solid rgba(255, 81, 101, 0.4);
}
.gm-perks__group--defense .gm-perks__label {
  color: var(--gm-cyan);
  background: rgba(32, 212, 231, 0.12);
  border: 1px solid rgba(32, 212, 231, 0.4);
}
/* The mask rotates with the rail; turn it back so the glyph stays upright. */
.gm-perks__label .gm-ic { transform: rotate(90deg); }

/* One line per band. Nine attack perks across the shop is the shape the
   Grandmaster learns, so the cards share the width rather than wrapping into a
   different arrangement every time the panel resizes. */
#view-leader .perk-grid {
  display: flex;
  gap: 9px;
  align-items: stretch;
  overflow-x: auto;
  padding-bottom: 2px;
  scrollbar-width: thin;
}
#view-leader .perk-card {
  display: flex;
  flex-direction: column;
  gap: 7px;
  /* Equal shares of the band, so a wide shop spreads the cards out on its own.
     The floor only decides when the band gives up and scrolls sideways, and
     nine attack perks on one line is worth holding on to. */
  flex: 1 1 0;
  min-width: 96px;
  padding: 10px;
  margin: 0;
  border: 1px solid var(--gm-line);
  border-radius: var(--gm-radius-sm);
  background: var(--gm-panel-2);
  box-shadow: none;
}
#view-leader .perk-card.attack { border-top: 3px solid var(--gm-red); }
#view-leader .perk-card.defense { border-top: 3px solid var(--gm-cyan); }
#view-leader .perk-card.is-active { border-color: var(--gm-green); box-shadow: 0 0 0 1px rgba(66, 219, 131, 0.35); }

.perk-name {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 900;
  font-size: 0.82rem;
  line-height: 1.2;
}
.perk-name .gm-ic { width: 17px; height: 17px; }
.perk-card.attack .perk-name .gm-ic { color: var(--gm-red); }
.perk-card.defense .perk-name .gm-ic { color: var(--gm-cyan); }
#view-leader .perk-desc {
  color: var(--gm-muted);
  font-size: 0.72rem;
  line-height: 1.34;
  flex: 1;
}

/* The price is the button: the whole foot of the card, so there is one thing
   to press and the number on it is the number you spend. */
#view-leader .gm-buy {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  min-height: 32px;
  padding: 6px 10px;
  border: 1px solid rgba(255, 210, 28, 0.4);
  border-radius: 999px;
  background: rgba(255, 210, 28, 0.14);
  color: var(--gm-yellow);
  font-family: inherit;
  font-weight: 900;
  font-size: 0.86rem;
  cursor: pointer;
}
#view-leader .gm-buy:hover:not(:disabled) { background: rgba(255, 210, 28, 0.3); }
#view-leader .gm-buy:disabled { opacity: 0.4; cursor: not-allowed; }
#view-leader .gm-buy.is-on {
  border-color: rgba(66, 219, 131, 0.55);
  background: rgba(66, 219, 131, 0.16);
  color: var(--gm-green);
  opacity: 1;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

#view-leader select {
  width: 100%;
  min-height: 32px;
  padding: 5px 8px;
  border: 1px solid var(--gm-line);
  border-radius: var(--gm-radius-sm);
  background: var(--gm-bg);
  color: var(--gm-text);
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 700;
}

/* --- feed -------------------------------------------------------------- */

#view-leader .feed { padding: 0; color: var(--gm-muted); font-size: 0.82rem; }
#view-leader .feed li {
  border-top: 1px solid var(--gm-line-soft);
  line-height: 1.35;
}
#view-leader .feed li:first-child { border-top: 0; }

/* Stamp, mark, message. The time is first because the feed is read against a
   fuse and a duel clock, and its column is fixed so the messages line up. */
.gm-event {
  display: grid;
  grid-template-columns: auto 16px minmax(0, 1fr);
  align-items: baseline;
  gap: 9px;
  padding: 8px 16px;
}
.gm-event__time {
  font-size: 0.7rem;
  font-weight: 800;
  color: var(--gm-muted);
  opacity: 0.75;
  white-space: nowrap;
}
.gm-event .gm-ic { align-self: center; color: var(--gm-muted); }
.gm-event__text { min-width: 0; }
.gm-event--good .gm-ic { color: var(--gm-green); }
.gm-event--warn .gm-ic { color: var(--gm-amber); }
.gm-event--on .gm-ic { color: var(--gm-cyan); }
.gm-event--bonus .gm-ic { color: var(--gm-yellow); }
.gm-event--danger .gm-ic { color: var(--gm-red); }
#view-leader .feed li.fresh {
  color: var(--gm-text);
  font-weight: 700;
  background: rgba(255, 210, 28, 0.07);
}

/* --- handoff ----------------------------------------------------------- */

#view-leader .handoff-row {
  display: flex;
  gap: 9px;
  align-items: center;
  flex-wrap: wrap;
}
#view-leader .handoff-row select { flex: 1 1 150px; width: auto; }
.gm-warn {
  display: flex;
  gap: 9px;
  padding: 8px 10px;
  margin-bottom: 10px;
  border: 1px solid rgba(255, 166, 43, 0.45);
  border-radius: var(--gm-radius-sm);
  background: rgba(255, 166, 43, 0.1);
  color: #ffd9a1;
  font-size: 0.78rem;
  line-height: 1.35;
}
.gm-warn .gm-ic { color: var(--gm-amber); margin-top: 1px; }

#view-leader .gm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 38px;
  padding: 9px 16px;
  border: 0;
  border-radius: var(--gm-radius-sm);
  font-family: inherit;
  font-weight: 900;
  font-size: 0.82rem;
  cursor: pointer;
}
/* Yellow, not green: handing the seat over costs the recipient their clear. */
#view-leader .gm-btn--warn { background: var(--gm-yellow); color: #23180a; }
#view-leader .gm-btn--warn:hover { background: #ffdd4d; }

/* --- silence ----------------------------------------------------------- */

/* Jammed regions render *instead of* the data, never on top of it, so no
   stale roster state can sit underneath a translucent cover. */
.gm-jammed {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 120px;
  padding: 20px 16px;
  text-align: center;
  color: var(--gm-amber);
  font-weight: 900;
  font-size: 0.82rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background:
    repeating-linear-gradient(
      180deg, rgba(255, 166, 43, 0.07) 0 2px, transparent 2px 5px
    ),
    rgba(7, 9, 31, 0.6);
}

/* --- host control ------------------------------------------------------ */

/* Ending the session is administrative and destructive, so it sits apart from
   the perk controls rather than beside them. */
body.gm-active .host-live {
  position: static;
  /* style.css caps this at 200px for the floating player-screen control. */
  max-width: none;
  display: flex;
  justify-content: flex-end;
  width: min(1780px, calc(100% - 28px));
  margin: 0 auto 28px;
  padding: 0;
  background: none;
  box-shadow: none;
  border: 0;
}
body.gm-active .host-live .btn {
  width: auto;
  min-height: 40px;
  padding: 9px 18px;
  border: 1px solid rgba(255, 81, 101, 0.5);
  border-radius: var(--gm-radius-sm, 8px);
  background: rgba(255, 81, 101, 0.12);
  color: #ff8b98;
  font-size: 0.85rem;
  font-weight: 800;
  box-shadow: none;
}

/* --- responsive -------------------------------------------------------- */

/* The fold is a desktop shape. On anything that cannot hold it, the panels
   stop competing for a fixed height and the page scrolls as one — the deck
   keeps its arrangement for as long as the arrangement still helps. */
@media (max-width: 1279px), (max-height: 759px) {
  .gm-fold { height: auto; }
  .gm-deck {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    grid-template-areas: "opp" "stage" "rail" "perks";
  }
  .gm-rail { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); align-items: start; }
  .gm-rail .gm-panel--team,
  .gm-rail .gm-panel--feed { min-height: 0; }
  .gm-scroll { overflow-y: visible; max-height: none; }
  .gm-manual #leader-bomb-mount { min-height: 320px; }
}

@media (max-width: 1023px) {
  .gm-stage { flex-wrap: wrap; }
  .gm-perks__group { grid-template-columns: 26px minmax(0, 1fr); }
}

@media (max-width: 799px) {
  #view-leader { width: calc(100% - 20px); }
  body.gm-active .host-live { width: calc(100% - 20px); }
  .gm-bar { gap: 10px; padding: 12px; }
  /* Six chips will not fit across a phone, and a flex line that cannot shrink
     below its labels pushes the whole board sideways. Two fixed columns
     instead: every slot still has its place, and none of them sets a floor. */
  .gm-flags {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-left: 0;
    width: 100%;
  }
  .gm-flag + .gm-flag { border-left: 0; }
  .gm-flag:nth-child(even) { border-left: 1px solid var(--gm-line-soft); }
  .gm-flag:nth-child(n + 3) { border-top: 1px solid var(--gm-line-soft); }
  .gm-rail { grid-template-columns: minmax(0, 1fr); }
  /* No room for four columns, so the header stops describing the rows and
     goes away; each row lays its own cells out instead. The assigned game
     drops onto a second line rather than shrinking to nothing, and every cell
     is placed explicitly so the status pill cannot land on top of it. */
  .gm-roster__head { display: none; }
  #view-leader .leader-roster li {
    grid-template-columns: 38px minmax(0, 1fr) auto;
    row-gap: 5px;
  }
  #view-leader .leader-roster li > .gm-avatar { grid-column: 1; grid-row: 1 / span 2; }
  #view-leader .leader-roster li > .gm-who { grid-column: 2; grid-row: 1; }
  #view-leader .leader-roster li > .pill { grid-column: 3; grid-row: 1; }
  #view-leader .leader-roster li > .gm-assign { grid-column: 2 / -1; grid-row: 2; }
  #view-leader .perk-card { min-width: 132px; }
  .gm-manual { grid-template-columns: minmax(0, 1fr); }
  .gm-manual__rail { flex-direction: row; flex-wrap: nowrap; width: auto; overflow-x: auto; }
  /* The spacer exists to push the scoreline to the far end of a wide band.
     On a narrow one there is no far end: the name takes a line of its own and
     the stats wrap under it, rather than every item shrinking until the last
     one is clipped off the edge of the panel. */
  .gm-opp .gm-spacer { display: none; }
  .gm-opp { row-gap: 6px; }
  .gm-opp__name { flex: 1 0 100%; }
  .gm-opp__stat { flex: 0 0 auto; }
  /* The duel head holds its clock on one line on a desktop; on a phone there
     is no line to hold it on. */
  .gm-panel--duel .gm-panel__head { flex-wrap: wrap; }
  .gm-manual__nav { flex-direction: row; }
}

@media (prefers-reduced-motion: reduce) {
  #view-leader *, #view-leader *::before, #view-leader *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* --- staked duels: the Grandmaster answering ----------------------------- */

/* Gold rather than the duel panel's violet: this is a spend, and it reads with
   the coin board and the perk shop rather than with the fight it pays for. */
.gm-panel--stake { border-color: rgba(255, 210, 28, 0.4); }
.gm-panel--stake .gm-panel__head .gm-ic { color: var(--gm-yellow); }
.gm-panel--stake .stk__row { justify-content: flex-start; margin-top: 12px; }
.gm-panel--stake .stk__state { font-size: 0.85rem; color: var(--gm-muted); }
#leader-stake-ask { color: var(--gm-text); font-weight: 800; }
#leader-stake-clock { color: var(--gm-yellow); }
