.match-detail-screen {
  display: flex; flex-direction: column; gap: 16px;
  padding-top: 4px;
  width: 100%; max-width: 1100px; margin: 0 auto;
}
/* CollapseCards gives every host child a 100% basis and puts chips at order:-1; these two opt out
   of both so the back button keeps its width and stays above the chip row. */
.match-detail-screen.cc-host > .md-back { flex: 0 0 auto; }
.match-detail-screen.cc-host > .md-back,
.match-detail-screen.cc-host > .md-header { order: -2; }

/* Three lines: verdict — how it ended — when · the ratings · the setup badges. */
.md-header {
  display: flex; flex-direction: column;
  gap: 8px;
  padding: 8px 0 12px;
  border-bottom: 1px solid var(--border-color);
}
/* `baseline`, not centre: the reason is set beside a 1.7rem title and must sit on its line. */
.md-header-line {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 4px 10px;
}
.md-title {
  font-size: 1.7rem; font-weight: 700;
  color: var(--ink); margin: 0; line-height: 1.2;
}
.md-title strong { color: var(--bronze-2); font-weight: 800; }
/* Plain ink: the title beside it already carries the outcome colour. */
.md-reason-text {
  font-size: 1.05rem; font-weight: 600;
  color: var(--ink-2);
}
.md-dash { color: var(--ink-3); }
.md-when { color: var(--ink-2); font-size: 0.86rem; white-space: nowrap; }

/* The rating line: name, standing, swing — reader (or winner) first. */
.md-elo-line {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px 12px;
  font-size: 0.95rem;
}
.md-elo-side {
  display: inline-flex; align-items: center; gap: 8px;
  min-width: 0;
}
.md-elo-name {
  color: var(--ink); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* Tabular so the two standings line up whatever the digit count. */
.md-elo-val {
  color: var(--ink-2); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.md-elo-vs {
  color: var(--ink-3); font-size: 0.8rem;
  text-transform: uppercase; letter-spacing: 0.06em;
}
.md-header-win  .md-title { color: var(--accent-green); }
.md-header-loss .md-title { color: var(--accent-red); }
.md-header-draw .md-title { color: var(--bronze-2); }

.md-card {
  background: var(--bg-card); border: 1px solid var(--border-color);
  border-radius: 10px; padding: 14px 16px;
  display: flex; flex-direction: column; gap: 12px;
}
.md-card-eyebrow {
  font-size: 0.72rem; font-weight: 700;
  color: var(--bronze-2); text-transform: uppercase; letter-spacing: 0.6px;
}
/* The setup badges, third line. Variants only: geometry is THE pill primitive's (theme.css). */
.md-header-facts {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px;
}
/* One surface up: the primitive's --bg-2 fill is the card fill, so an unraised pill is invisible. */
.md-header-facts .pill { background: var(--bg-3); }
.md-header-facts .pill.md-pill-rated {
  color: var(--bronze-2);
  background: color-mix(in srgb, var(--bronze-2) 12%, var(--bg-3));
  border-color: color-mix(in srgb, var(--bronze-2) 30%, transparent);
}
.md-pill-unrated { color: var(--ink-3); }
/* A key/value badge: the key stays muted so the ANSWER is what the eye picks out of the strip. */
.md-pill-fact { color: var(--ink); gap: 5px; }
.md-pill-k { color: var(--ink-3); font-weight: 700; }

.md-delta {
  font-weight: 700; font-variant-numeric: tabular-nums;
  font-size: 0.92rem;
  padding: 2px 10px; border-radius: 999px;
  border: 1px solid currentColor;
  background: color-mix(in srgb, currentColor 12%, transparent);
  white-space: nowrap;
}
.md-delta-up   { color: var(--accent-green); }
.md-delta-down { color: var(--accent-red); }
.md-delta-zero { color: var(--ink-2); }

/* No card chrome of its own — the two army cards are the frames. */
.md-armies-section {
  display: flex; flex-direction: column; gap: 12px;
}
/* Must clear the collapse control, absolute at top 8 and 30px tall, or the caret overhangs the
   right army card's corner. */
.md-armies-section > .md-card-eyebrow {
  display: flex; align-items: center;
  min-height: 30px; padding-right: 34px;
}
.md-armies-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 768px) {
  .md-armies-grid { grid-template-columns: 1fr; }
}
.md-armies-empty {
  text-align: center; color: var(--ink-3);
  font-size: 0.88rem; padding: 8px 0;
}

.md-army-card {
  background: var(--bg-card); border: 1px solid var(--border-color);
  border-radius: 10px; padding: 14px 16px;
  display: flex; flex-direction: column; gap: 12px;
  position: relative;
}
/* I27: --eval-* may decorate but never DISTINGUISH — the pair is 1.07:1 to a red-green dichromat,
   and the card's own heading is what names whose army it is. Mine/theirs, NOT seat. */
.md-army-card-mine { border-top: 3px solid var(--eval-mine); }
.md-army-card-them { border-top: 3px solid var(--eval-them); }
.md-army-card-self {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--bronze-2) 35%, transparent);
}

.md-army-header { display: flex; flex-direction: column; gap: 4px; }
.md-army-name {
  font-size: 1.05rem; font-weight: 700; color: var(--ink); margin: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.md-army-spec-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
}
.md-army-spec {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--bronze-2); font-weight: 600;
}
.md-army-status {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.5px;
  font-weight: 600;
  padding: 2px 8px; border-radius: 999px;
  border: 1px solid currentColor;
  background: color-mix(in srgb, currentColor 10%, transparent);
}
.md-army-status-killed   { color: var(--accent-red); }
.md-army-status-survived { color: var(--accent-green); }

.md-army-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 4px;
}
.md-army-unit {
  display: grid; grid-template-columns: 22px 1fr auto;
  align-items: center; gap: 8px;
  padding: 4px 8px; border-radius: 6px;
  background: var(--bg-input);
  font-size: 0.9rem;
}
.md-army-unit-icon  { font-size: 1rem; }
.md-army-unit-name  { color: var(--ink-2); }
.md-army-unit-count { color: var(--bronze-2); font-weight: 700; font-variant-numeric: tabular-nums; }
.md-army-list-empty {
  margin: 0; color: var(--ink-3); font-style: normal; font-size: 0.88rem;
  padding: 8px 4px; text-align: center;
  border: 1px dashed var(--border-color); border-radius: 6px;
}

.md-army-stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 6px; font-size: 0.82rem;
  border-top: 1px solid var(--border-color); padding-top: 10px;
}
.md-army-stat {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  text-align: center;
}
.md-army-stat-label { font-size: 0.66rem; color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.4px; }
.md-army-stat-value { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.md-stat-lost .md-army-stat-value { color: var(--accent-red); }
@media (max-width: 480px) {
  .md-army-stats { grid-template-columns: repeat(2, 1fr); }
}


.md-replay-layout {
  display: grid;
  /* Two parts: the board column and the log. */
  grid-template-columns: minmax(280px, 1.4fr) minmax(260px, 1fr);
  grid-template-areas: "board log";
  gap: 16px;
  align-items: start;
}
.md-replay-rail,
.md-replay-board-main { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.md-replay-tools { display: flex; align-items: center; gap: 8px; }
/* Empty while analysis is off; without this the rail's gap would still reserve a strip. */
#md-an-mount:empty { display: none; }
/* The board column holds the board AND its rail, side by side. The rail's width is RESERVED
   whether or not analysis is open, so toggling the panel never moves or resizes the board — the
   board is what a review is read from and it must hold still. */
.md-replay-board-col {
  grid-area: board;
  /* 280px, not less: below it "Answer for the defender:" and its three choices cannot share a
     line, and the panel grows a row. 240 and 260 buy nothing — the wrap point is 280. */
  display: grid; grid-template-columns: minmax(0, 1fr) 280px;
  gap: 16px; align-items: start;
}
.md-replay-log { grid-area: log; }
/* Stacked (<=1024px — phones AND tablets, portrait or landscape) the log is a fixed-height block
   below the board. On desktop it is the
   right COLUMN of the replay grid, so it fills the row the board column establishes instead
   of stopping at an arbitrary 420px and leaving the rest of the column empty. `align-self`
   overrides the grid's `align-items: start`, which is what the board column still wants. */
.md-replay-log .log-scroll { max-height: 420px; }
@media (min-width: 1025px) {
  .md-replay-log { align-self: stretch; position: relative; min-height: 0; }
  /* OUT OF FLOW on purpose. The row height must come from the BOARD column (board + eval
     bar + scrubber); an in-flow scroller with no max-height contributes its own content
     height instead, so a 50-ply log would stretch the row and leave the board short. */
  .md-replay-log .log-scroll {
    position: absolute; inset: 0;
    max-height: none;
  }
}
/* Positioning context for the shared action wheel (#acpop-root is absolute); without it the
   wheel resolves against some ancestor and lands off the board. */
.md-replay-board { position: relative; }
/* Board + coordinate gutters. The letter row and number column are grid tracks of the
   FRAME, so they stay aligned with the cells at any width without a second size source. */
.md-rp-frame {
  display: grid;
  grid-template-columns: 1.35em minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) 1.15em;
  gap: 2px;
  width: 100%;
  max-width: 544px;
  margin: 0 auto;
}
.md-rp-axis {
  display: grid;
  font-size: 0.6rem; font-weight: 600;
  color: var(--ink-3);
  line-height: 1;
  user-select: none;
}
.md-rp-axis i {
  display: flex; align-items: center; justify-content: center;
  font-style: normal;
}
.md-rp-axis-left   { grid-template-rows: repeat(var(--md-rp-n, 16), 1fr); }
.md-rp-axis-bottom { grid-column: 2; grid-template-columns: repeat(var(--md-rp-n, 16), 1fr); }

/* Rows declared explicitly, else they size to content and cells go non-square. */
/* position:relative anchors the trail overlay (.trail-arrows-container, board.css) and the
   annotation layer. */
.md-rp-board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--md-rp-n, 16), 1fr);
  grid-template-rows: repeat(var(--md-rp-n, 16), 1fr);
  width: 100%;
  aspect-ratio: 1;
  border: 1px solid var(--bronze-deep);
  border-radius: 4px;
  overflow: hidden;
}
/* Pips, costs and swords counter-rotate so they stay upright when the board turns. */
.md-rp-piece .unit-pip,
.md-rp-cell .cell-cost,
.md-rp-cell .cell-battle { transform: rotate(var(--piece-counter-rotate, 0deg)); }

/* Clicking a log line scrubs to that moment; plies ahead of the marker are dimmed. */
.md-ply-row { cursor: pointer; }
.md-ply-row:hover { background: var(--bg-hover); }
.md-ply-row:focus-visible { outline: 2px solid var(--bronze); outline-offset: -2px; }
.md-ply-ahead { opacity: 0.45; }

/* The overlay's own z-index is 3, under .cell-battle at 4; a review board is read ply by ply, so
   the arrow that names the ply must not be broken by a sword glyph sitting on its path. */
.md-rp-board > .trail-arrows-container { z-index: 6; }
/* board.css sizes the tick off --cell-size, which this board does not set. Scoped here so it
   wins on specificity, not on the shared calc() happening to be invalid. */
.md-rp-cell .confirm-tick { font-size: 0.85em; }
/* The mini-board has no --cell-size, so the live rule's calc() sizing collapses here. */
.md-rp-cell .cell-battle { font-size: 0.95em; line-height: 1; }
.md-rp-cell .cell-battle-corner { font-size: 0.6em; top: 0; right: 1px; }

/* The bar itself is THE shared component (evalBarHtml). Only the frame is review-specific:
   drop the fused play-column borders and the play-screen gutter offsets, which exist to line
   the track up with the live board's coordinate gutter. */
.md-rp-eval { width: 100%; max-width: 544px; margin: 0 auto; padding-left: 1.35em; }
.md-rp-eval .eval-wrap { background: none; border: 0; }
.md-rp-eval .eval-ends,
.md-rp-eval .eval-bar-h { margin-left: 0; margin-right: 0; }
.md-rp-eval .eval-bar-h { height: 12px; border-radius: 3px; }

.md-rp-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1;
  min-width: 0;
  min-height: 0;
  font-style: normal;
  /* background === terrain color; halo hides sub-pixel seams */
  box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.15) inset;
}
.md-rp-piece { display: flex; width: 82%; aspect-ratio: 1; height: auto; }
.md-rp-piece .unit-pip { width: 100%; height: 100%; border-width: 1px; }
.md-rp-pinned { opacity: 0.55; }

/* Glyph re-scoped here because .piece-glyph sizes off --cell-size, which the mini-board doesn't set. */
.md-rp-piece .piece-glyph { font-size: clamp(9px, 1.7vw, 18px); }
.md-rp-piece .piece-glyph.is-label { font-size: clamp(7px, 1.2vw, 12px); }
.md-rp-piece .unit-pip.piece-skin-flat,
.md-army-unit-icon .unit-pip.piece-skin-flat { border-color: var(--pc-edge); box-shadow: none; }
.md-army-unit-icon .piece-glyph { font-size: 0.82em; }
.md-replay-scrub {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  width: 100%; max-width: 520px; margin: 0 auto;
}
.md-replay-scrub input[type="range"] { flex: 1 1 auto; min-width: 0; accent-color: var(--bronze-2); }
/* Its own line under the slider: beside it the label was a third element competing for width,
   and it is a readout rather than a control. */
.md-replay-label {
  flex: 1 1 100%; text-align: center;
  color: var(--ink-2); font-size: 0.82rem; white-space: nowrap;
}
/* Analysis: the review board becomes playable for BOTH sides. Legality comes from the server,
   so these classes only DRAW what it returned — they never decide anything. */
.btn-md-analysis.is-active { background: color-mix(in srgb, var(--gold) 22%, var(--bg-2)); border-color: var(--gold); }
.md-rp-cell.md-rp-sel { box-shadow: inset 0 0 0 2px var(--gold); }
/* The destination dot marks a legal cell only where no figure does — `md-rp-priced` is set
   wherever the cost badge stands, and the dot would sit behind the digit. */
.md-rp-cell.md-rp-move:not(.md-rp-priced)::after {
  content: ''; position: absolute; width: 26%; aspect-ratio: 1; border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 55%, transparent);
}
.md-rp-cell.md-rp-target { box-shadow: inset 0 0 0 2px var(--porphyry-2); }
/* The prompt rings are THE shared pair (board.css) — same classes and same colour, restated at
   (0,2,0) because `.md-rp-cell`'s own seam halo is an equal-specificity box-shadow in THIS file
   and would otherwise overwrite the ring. Width is re-pinned too: the shared rule sizes it off
   --cell-size, which this board does not set. */
.md-rp-cell.cell-response-anchor,
.md-rp-cell.cell-response-source {
  --resp-ring-w: 2px;
  box-shadow: inset 0 0 0 var(--resp-ring-w) var(--porphyry);
}
/* Clicking the anchor collapses the wheel; the rest of the board is inert during a prompt. */
.md-rp-cell.cell-response-anchor { cursor: pointer; }
/* THE live board's cost badges (board.css), re-sized: the mini-board sets no --cell-size, so every
   calc() in those rules is invalid and the whole declaration is dropped. Corner placement per
   rotation stays with board.css, whose [data-rotation] selectors already cover this board. */
.md-rp-cell .cell-cost { font-size: clamp(8px, 1.3vw, 14px); }
.md-rp-cell .cell-cost-attack {
  min-width: 11px; height: 11px; padding: 0 2px;
  border-radius: 6px; font-size: clamp(7px, 1vw, 10px);
}
/* A COLUMN in the rail; the mobile block below turns it back into a wrapping row. */
.md-analysis-bar {
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  width: 100%; font-size: 0.78rem;
}
.md-analysis-bar .btn { white-space: normal; }
.md-analysis-bar.is-busy { opacity: 0.6; }
.md-an-note { color: var(--ink-2); }
.md-an-err { color: var(--porphyry-2); }
/* The line's price, tabular so it does not jitter as steps are added. */
.md-an-spent {
  color: var(--bronze-2); font-variant-numeric: lining-nums tabular-nums;
  font-size: 0.82rem; white-space: nowrap;
}
.md-an-acts { display: flex; flex-wrap: wrap; gap: 6px; }
/* Icon-only: square, so three of them sit on one line even in a 200px rail. */
.md-an-ico {
  flex: 0 0 auto; min-width: 0;
  width: 34px; height: 32px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.md-an-ico svg { width: 17px; height: 17px; display: block; }
.md-replay-empty { color: var(--ink-3); font-size: 0.85rem; padding: 8px; }
.log-entry.md-ply-current { background: color-mix(in srgb, var(--bronze-2) 12%, var(--bg-1)); }
@media (max-width: 1024px) {
  /* Stacked: one column, the whole rail under the board — so the buttons land under the
     scrubber and the panel under them, the same order as the desktop rail. */
  .md-replay-layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "board" "log";
  }
  .md-replay-board-col { grid-template-columns: minmax(0, 1fr); }
  /* LEFT, both of them. Once the rail is under the board its width is the whole card, so
     without this the buttons and the panel each pick their own edge and the two disagree. */
  .md-replay-rail { align-items: flex-start; }
  /* The SAME cap and centring as .md-rp-frame, so the rail's left edge lands exactly where the
     board's number gutter starts. Below 544px both are full width and the point is moot; above
     it the board centres, and without this the rail stayed at the card edge instead. */
  .md-replay-rail { width: 100%; max-width: 544px; margin: 0 auto; }
  .md-replay-tools,
  .md-analysis-bar { align-self: flex-start; width: 100%; }
  /* Back to a wrapping row: full width is no longer scarce, and a column of one-per-line buttons
     is a long scroll. min-width:0 lets a button shrink instead of overflowing the card. */
  .md-analysis-bar { flex-direction: row; align-items: center; justify-content: flex-start; flex-wrap: wrap; }
  .md-an-note, .md-an-err, .md-an-spent { flex: 1 1 100%; }
  .md-an-acts { flex: 1 1 100%; }
  /* :not() excludes the icon buttons — fixed width at every size. Only worded buttons stretch. */
  .md-analysis-bar .btn:not(.md-an-ico) { flex: 1 1 auto; min-width: 0; }
  /* The scrubber carries six controls; at `flex: 1 1 auto` the slider claims the leftover width
     and pushes the rest past the card. A small basis makes it the thing that yields. */

  .md-replay-scrub { gap: 8px; }
  .md-replay-scrub input[type="range"] { flex: 1 1 80px; }
}
