/* ==========================================================================
   Actions tab — Sofascore on-ball actions.

   Colour rules follow Design.md: every value is a token, never a literal.
   Outcome is carried by hue *and* by opacity/width, so completion is not
   read by colour alone.

   This file loads last, so anything here overrides every sheet before it.
   Two things it must not get wrong, both learned the hard way:

   RADIUS. The scale is the three tokens of Design.md 5.4 and nothing else. An
   earlier cut reached for --radius-2 and --radius-3, which do not exist in
   tokens.css, so each fell through to a hard-coded 8px or 12px — exactly the
   light-theme radii 5.4 retires.

   PADDING. v2.css:88 makes .card transparent with no horizontal padding, but
   phase-a.css:98 loads *after* it and restores the filled, bordered, 24px card
   that the site actually renders. Reading v2 alone and matching it stripped the
   side padding from these panels while leaving the border in place, which put
   every heading hard against the frame. Cards here are boxes: padding on all
   four sides, --space-6, same as .card-pad.
   ========================================================================== */

.actions-tab {
  display: grid;
  gap: var(--space-8);
}

/* --- The right rail -------------------------------------------------------
   The tab answers a dozen separate questions down a dozen screens, so it gets
   the index the analysis has (styled in phase-a.css). Everything that steers
   the tab lives in the one lane: what is in it, then what it is filtered by,
   then which side — read top to bottom, in the order a reader needs them.
   The docks were floating in the window's corner, which put them across the
   index at the top of the tab, where the index has not stuck yet and runs the
   full height of the column. In the rail they cannot collide with it. */
.actions-flow {
  display: grid;
  gap: var(--space-8);
  min-width: 0;
}
.actions-flow > * { min-width: 0; }
.actions-flow > section[id] { scroll-margin-top: var(--sticky-top); }

.actions-rail { min-width: 0; display: grid; gap: var(--space-4); align-content: start; }

@media (min-width: 1120px) {
  /* The sections are one grid item and the rail is the other, both in row one,
     which is what lets the rail stick for the length of the tab. See the note
     on .analysis-flow for why `grid-row: 1 / -1` cannot do this. */
  .actions-tab.with-index {
    /* Out to the window's edge, beside the dock rather than stranded 200px
       inside the frame, and the figures take the room that opens up. See the
       note on .analysis-workspace. */
    --rail-pull: max(0px, (100vw - min(1500px, 100vw - 56px) - 2 * var(--space-6)) / 2);
    grid-template-columns: minmax(0, 1fr) 232px;
    column-gap: var(--space-8);
    margin-right: calc(-1 * var(--rail-pull));
    align-items: start;
  }
  .actions-tab.with-index > .actions-flow { grid-column: 1; grid-row: 1; }
  .actions-tab.with-index > .actions-rail {
    grid-column: 2;
    grid-row: 1;
    position: sticky;
    top: var(--sticky-top);
    align-self: start;
    max-height: calc(100vh - var(--sticky-top) - var(--space-6));
    overflow-y: auto;
    padding-left: var(--space-2);
  }
  /* In the rail it is part of the column, not a thing floating over the page. */
  .actions-rail .action-dock-stack {
    position: static;
    inset: auto;
    justify-items: stretch;
  }
  .actions-rail .action-filter-dock { max-width: none; }
  /* Three across the column, so the switch reads as one control the width of
     the lane rather than as buttons parked at its left edge. */
  .actions-rail .action-team-dock button { flex: 1; min-width: 44px; }
}

/* Panels that carry a heading but no .card-pad in the markup. Without this they
   inherit .card's border and none of its padding. */
.action-map-card,
.action-player-table,
.action-channel-card,
.action-moments-card { padding: var(--space-6); }

.loading-inline {
  display: grid;
  justify-items: center;
  gap: var(--space-3);
  padding: var(--space-8);
  color: var(--text-muted);
}

/* The tab's small caps. One definition, so every label across the tab is the
   same size, weight and tracking as the rest of the site's metadata. */
.action-team-figures span,
.territory-key,
.action-stat-source,
.action-stat-grid span,
.action-player-table .data-table th button {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}

/* --- Team strip --------------------------------------------------------- */

.action-team-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: var(--space-8);
}

/* A card, like every other panel on the page: filled and bordered per
   phase-a.css:98, square per Design.md 5.4. */
.action-team-card {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-6);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
}

.action-team-card header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.action-team-card header strong {
  font-size: 17px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-primary);
}

.action-team-figures {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}

.action-team-figures > div {
  display: grid;
  gap: var(--space-1);
}

.action-team-figures span { color: var(--text-muted); }

.action-team-figures strong {
  font-family: var(--font-display);
  font-size: 42px;
  font-weight: 800;
  line-height: .9;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.action-team-figures small {
  font-size: 12px;
  color: var(--text-muted);
}

/* Territory: defensive -> attacking third, left to right. */
.territory-bar {
  display: flex;
  height: var(--space-6);
  overflow: hidden;
  background: var(--surface-sunken);
}

.territory-bar i {
  display: grid;
  place-items: center;
  min-width: 0;
  font-style: normal;
  transition: width var(--motion-base) var(--motion-ease);
}

.territory-bar b {
  font-size: 12px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.territory-bar .third-defensive { background: var(--surface-overlay); color: var(--text-secondary); }
.territory-bar .third-middle { background: var(--brand-secondary); color: var(--text-on-accent); }
.territory-bar .third-attacking { background: var(--brand-primary); color: var(--text-on-accent); }

.territory-key {
  display: flex;
  justify-content: space-between;
  color: var(--text-muted);
}

/* --- Controls ----------------------------------------------------------- */

/* Five dropdowns on one line, in place of thirty-one buttons across six rows.
   The controls were taller than the map they controlled. */
.action-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--space-3);
  margin-block: var(--space-4);
}

.action-select { display: grid; gap: var(--space-1); min-width: 0; }

.action-select > span {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.action-select select { min-width: 11rem; }

/* --- Player picker -------------------------------------------------------- */

/* The squad sits open in the side column: as a closed disclosure it read as a
   caption and nobody found the names behind it. */
.action-picker {
  display: grid;
  gap: var(--space-3);
  align-content: start;
  padding: var(--space-4);
  min-width: 0;
}

.action-picker > .panel-title { align-items: flex-start; }
.action-picker > .panel-title h3 { font-size: 16px; }
.action-picker > .panel-title span { color: var(--text-muted); font-size: 12px; }

.action-picker-body {
  display: grid;
  gap: var(--space-4);
  max-height: 30rem;
  overflow-y: auto;
  min-width: 0;
}

.action-picker-team h4 {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.action-picker-team ul { margin: 0; padding: 0; list-style: none; display: grid; }

.action-picker-team button {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: 36px;
  padding: var(--space-1) var(--space-2);
  background: none;
  border: 0;
  color: var(--text-secondary);
  font: inherit;
  font-size: 13px;
  text-align: start;
  cursor: pointer;
}

/* The face is a <span> too, so this has to exclude it or it gets stretched into
   an ellipse by the name's flex: 1. */
.action-picker-team button > span:not(.identity-image) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.action-picker-team button i { font-style: normal; font-variant-numeric: tabular-nums; color: var(--text-muted); font-size: 12px; }
.action-picker-team button:hover { background: var(--surface-overlay); }

/* Picked players wear the same blue plate as every other active filter. */
.action-picker-team button.on {
  color: var(--text-on-accent);
  background: var(--brand-secondary);
}
.action-picker-team button.on i { color: var(--text-on-accent); opacity: .8; }

/* --- The pitch ---------------------------------------------------------- */

/* Capped so the whole pitch, its direction line and its legend sit inside one
   screen. At full column width the map ran past the fold, and a map you have to
   scroll to see the far end of cannot be read as one shape — which is the only
   reason to draw it. The cap is on width because the pitch is a fixed 105:68,
   so height follows; 62vh leaves room for the controls above and legend below
   on a laptop, and the 880px ceiling stops it stretching on a wide monitor. */
.action-pitch svg {
  display: block;
  width: 100%;
  max-width: min(880px, calc(62vh * 105 / 68));
  height: auto;
  margin-inline: auto;
}

.action-layer line {
  stroke-width: .45;
  fill: none;
  stroke-linecap: round;
}

/* Nine hundred passes drawn at full strength is a hairball, not a map. With
   nobody selected the layer is thinned so density reads as texture; picking a
   player brings it back to full weight. */
.action-pitch.crowded .action-layer { opacity: .42; }
.action-pitch.crowded .action-layer line { stroke-width: .28; }
.action-pitch.crowded .action-layer circle { r: .5; }
.action-pitch.focused .action-layer line { stroke-width: .6; }

.action-layer circle {
  stroke: none;
}

.action-mark.complete line { stroke: var(--success-text); }
.action-mark.complete circle { fill: var(--success-text); }

/* Incomplete is dimmer as well as differently hued, so the distinction
   survives for a reader who cannot separate the two colours. */
.action-mark.incomplete line { stroke: var(--brand-accent); stroke-dasharray: 1.5 1.2; }
.action-mark.incomplete circle { fill: var(--brand-accent); }
.action-mark.incomplete { opacity: .75; }

.action-mark.progressive line { stroke-width: .75; }
.action-mark.key-pass line { stroke: var(--player-4); stroke-width: .9; }
.action-mark.key-pass circle { fill: var(--player-4); }
.action-mark.cross line { stroke-dasharray: 2.5 1; }

.action-mark.defensive circle,
.action-mark.dribbles circle { r: 1.1; }

.action-mark:hover line { stroke-width: 1.1; }

.action-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  font-size: 12px;
  color: var(--text-secondary);
  margin-block-start: var(--space-4);
}

.action-legend i {
  display: inline-block;
  width: var(--space-6);
  height: 3px;
  margin-inline-end: var(--space-2);
  vertical-align: middle;
}

/* --- Territory ----------------------------------------------------------- */

.action-territory-card { padding: var(--space-6); display: grid; gap: var(--space-4); }

/* The cells are the surface, so the pitch fill underneath them is not needed;
   leaving it in tinted every ramp step green. */
.territory-pitch, .flow-pitch { background: var(--surface-sunken); }

/* A hairline of surface between cells. Without it adjacent steps of the same
   ramp merge into one blob and the grid stops being readable as a grid. */
.territory-cell {
  stroke: var(--surface-sunken);
  stroke-width: .25;
}

.territory-cell.basel-1 { fill: var(--territory-basel-1); }
.territory-cell.basel-2 { fill: var(--territory-basel-4); }
.territory-cell.basel-3 { fill: var(--territory-basel-5); }
.territory-cell.basel-4 { fill: var(--territory-basel-6); }
.territory-cell.basel-5 { fill: var(--territory-basel-5); }
.territory-cell.basel-6 { fill: var(--territory-basel-6); }
.territory-cell.opponent-1 { fill: var(--territory-opponent-1); }
.territory-cell.opponent-2 { fill: var(--territory-opponent-4); }
.territory-cell.opponent-3 { fill: var(--territory-opponent-5); }
.territory-cell.opponent-4 { fill: var(--territory-opponent-6); }
.territory-cell.opponent-5 { fill: var(--territory-opponent-5); }
.territory-cell.opponent-6 { fill: var(--territory-opponent-6); }
.territory-cell.even { fill: var(--territory-even); }

/* The pitch markings have to sit above the fills or they vanish under them. */
.territory-pitch .pitch-lines { stroke: var(--overlay-strong); }
.territory-layer { mix-blend-mode: normal; }

.territory-legend i { height: 12px; width: var(--space-6); }
.action-legend .legend-basel-4 { background: var(--territory-basel-6); }
.action-legend .legend-opponent-4 { background: var(--territory-opponent-6); }
.action-legend .legend-even { background: var(--territory-even); }

.territory-multiples {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: var(--space-6);
}

.territory-multiples.two-up { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }
.territory-multiples.one-up { grid-template-columns: minmax(0, 26rem); margin-block-start: var(--space-6); }

.territory-small { margin: 0; display: grid; gap: var(--space-2); }

.territory-small figcaption {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.territory-small figcaption b { color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* Small multiples carry no max-height cap: they are already small, and the
   shared cap would shrink four pitches to thumbnails. */
.territory-small .action-pitch svg { max-width: none; }

/* --- Flow ----------------------------------------------------------------- */

/* Each side wears its own half of the diverging ramp. The route map this
   replaced painted both teams in Basel red, so the opponent's panel claimed
   to be Basel. */
/* Constant, thin. The shaft says direction and nothing else. */
.flow-vector line { fill: none; stroke-linecap: butt; stroke-width: .55; }
.zone-grid { fill: none; stroke: var(--overlay-line); stroke-width: .2; }
.flow-vector.basel line, .flow-vector.basel circle { stroke: var(--territory-basel-5); fill: var(--territory-basel-5); }
.flow-vector.opponent line, .flow-vector.opponent circle { stroke: var(--territory-opponent-5); fill: var(--territory-opponent-5); }
.flow-vector circle { stroke: none; opacity: .8; }
.vector-head.basel path { fill: var(--territory-basel-5); }
.vector-head.opponent path { fill: var(--territory-opponent-5); }

/* --- Progression: the ladder and the origin grid -------------------------- */

.action-progression-card { padding: var(--space-6); }

/* Which column is whose. Without it the two sides of a diverging figure are
   two anonymous bars and the reader has to guess. */
.ladder-head {
  display: grid;
  grid-template-columns: 1fr max-content 1fr;
  align-items: center;
  gap: var(--space-4);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.ladder-head span:first-child { display: flex; align-items: center; gap: var(--space-2); }
.ladder-head span:last-child { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); }

.progression-ladder {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-1);
}

.progression-ladder button {
  display: grid;
  grid-template-columns: 1fr max-content 1fr;
  align-items: center;
  gap: var(--space-4);
  width: 100%;
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  background: none;
  border: 0;
  border-radius: var(--radius-control);
  color: inherit;
  font: inherit;
  cursor: pointer;
  text-align: start;
}

.progression-ladder button:hover { background: var(--surface-overlay); }
.progression-ladder li.on button { background: var(--surface-overlay); box-shadow: inset 0 0 0 1px var(--border-strong); }

.ladder-name {
  font-size: 13px;
  font-weight: 700;
  text-align: center;
  min-width: 11ch;
}

/* Basel reads outwards from the centre label, the opponent inwards, so the two
   sides meet at the line they crossed rather than at the page edge. */
.ladder-figure {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.ladder-figure.basel { flex-direction: row; }
.ladder-figure.opponent { flex-direction: row-reverse; }

.ladder-figure b {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  min-width: 8ch;
  text-align: end;
}

.ladder-figure.opponent b { text-align: start; }
.ladder-figure b em { color: var(--text-muted); font-style: normal; font-size: 12px; }

/* Kept sits against the centre label on both sides: the eye compares the solid
   blocks against each other, and the faded remainder is what it cost. */
.ladder-figure.basel .ladder-bar { justify-content: flex-end; }
.ladder-figure.opponent .ladder-bar { flex-direction: row-reverse; justify-content: flex-end; }

.ladder-figure.basel .kept { background: var(--territory-basel-6); }
.ladder-figure.basel .lost { background: var(--territory-basel-6); opacity: .3; }
.ladder-figure.opponent .kept { background: var(--territory-opponent-6); }
.ladder-figure.opponent .lost { background: var(--territory-opponent-6); opacity: .3; }

.action-legend .legend-kept { background: var(--text-secondary); height: 12px; }
.action-legend .legend-lost { background: var(--text-secondary); height: 12px; opacity: .3; }

.progression-origins-title { margin-block-start: var(--space-4); }
.progression-origins-title h4 { margin: 0; font-size: 15px; }

/* Three lanes by three thirds, drawn at pitch proportions so it reads as a
   pitch rather than as a table that happens to have nine cells.
   Given the whole column each grid ran to 700px across and half a screen tall,
   which is a lot of room for nine numbers. The tracks are sized to the pitches
   now rather than the pitches to the tracks — and capping them alone was worse
   than doing nothing, because the width came off the pitches and went straight
   into empty card beside them. The reading of the figure moves into that space
   instead, which takes it off the bottom of the card as well. */
.origin-multiples {
  grid-template-columns: repeat(auto-fit, minmax(0, 19rem));
  justify-content: start;
  gap: var(--space-6) var(--space-8);
}

/* The ladder and the origins answer the same question from two sides — which
   line was broken, and from where — so they sit beside each other rather than
   one under the other. The card was two full-width figures stacked, which is
   what made this section as long as the map it filters. */
.progression-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) max-content;
  gap: var(--space-6) var(--space-8);
  align-items: start;
}
.progression-lines, .progression-origins { min-width: 0; display: grid; gap: var(--space-3); align-content: start; }
.progression-origins .progression-origins-title { margin-block-start: 0; }

/* Four numbers under the pitches: what the two figures beside them cannot say
   in one place. */
.progression-facts { margin: var(--space-2) 0 0; display: grid; gap: 1px; background: var(--border-subtle); border: 1px solid var(--border-subtle); }
.progression-facts > div { display: grid; grid-template-columns: minmax(0, 1fr) 5.5rem 5.5rem; gap: var(--space-2); align-items: baseline; padding: var(--space-2) var(--space-3); background: var(--surface-raised); }
.progression-facts dt { color: var(--text-secondary); font-size: 13px; }
.progression-facts dd { margin: 0; color: var(--text-primary); font-size: 13.5px; font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; }
.progression-facts .facts-head { background: var(--surface-sunken); }
.progression-facts .facts-head dd {
  overflow: hidden; color: var(--text-muted); font-size: 12px; font-weight: 800;
  letter-spacing: .08em; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap;
}

/* The method note, folded away behind the `?` in the heading. */
.note-toggle {
  flex: none; width: 26px; min-height: 26px; height: 26px; margin-inline-start: var(--space-3); padding: 0;
  color: var(--text-secondary); background: var(--surface-sunken);
  border: 1px solid var(--border-strong); border-radius: var(--radius-round);
  font-size: 13px; font-weight: 800; line-height: 1;
}
.note-toggle:hover, .note-toggle[aria-expanded="true"] { color: var(--text-on-accent); background: var(--surface-overlay); border-color: var(--brand-accent); }
.action-progression-card > .spatial-method-note { margin-block: 0 var(--space-4); }

@media (max-width: 1240px) {
  .progression-row { grid-template-columns: minmax(0, 1fr); }
}

/* Both pitches on one line inside a max-content track: auto-fit has no width
   to fit against in there and collapses to a single column, which stacked them
   and made the card taller than it was before any of this. */
@media (min-width: 901px) {
  .progression-origins .origin-multiples { grid-template-columns: repeat(2, 16.5rem); }
}



.origin-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  aspect-ratio: 105 / 68;
  gap: 2px;
  background: var(--surface-sunken);
  padding: 2px;
  border-radius: var(--radius-control);
}

.origin-cell {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 2px;
  border: 0;
  border-radius: var(--radius-control);
  background: var(--surface-sunken);
  color: var(--text-muted);
  font: inherit;
  cursor: pointer;
  padding: var(--space-1);
}

.origin-cell b { font-size: 13px; font-variant-numeric: tabular-nums; }
.origin-cell small { font-size: 11px; font-variant-numeric: tabular-nums; opacity: .85; }
.origin-cell[disabled] { cursor: default; }
/* Two rings, dark then light. A single ring in one colour disappears into
   whichever end of the ramp happens to be behind it, and these cells run from
   near-white to near-black. */
.origin-cell:not([disabled]):hover { box-shadow: inset 0 0 0 1px var(--surface-raised), inset 0 0 0 3px var(--interactive-hover); }
.origin-cell.on { box-shadow: inset 0 0 0 1px var(--surface-raised), inset 0 0 0 3px var(--text-primary); }

/* Each side's half of the territory ramp, one step per shade. Straight through
   rather than the mapping .territory-cell uses above, which sends steps 4, 5
   and 6 to shades 6, 5 and 6 — on a cell carrying a number that would print a
   larger figure on a lighter cell than a smaller one.

   Ink flips with the fill, because these cells carry text the ones above do
   not: the four pale steps take dark ink and the two dark steps light, and
   every pair clears 4.5:1 (Design.md 4.3) — the worst is 4.82:1 on step 4. */
.origin-cell.basel-1 { background: var(--territory-basel-1); color: var(--text-on-inverse); }
.origin-cell.basel-2 { background: var(--territory-basel-2); color: var(--text-on-inverse); }
.origin-cell.basel-3 { background: var(--territory-basel-3); color: var(--text-on-inverse); }
.origin-cell.basel-4 { background: var(--territory-basel-4); color: var(--text-on-inverse); }
.origin-cell.basel-5 { background: var(--territory-basel-5); color: var(--text-on-accent); }
.origin-cell.basel-6 { background: var(--territory-basel-6); color: var(--text-on-accent); }
.origin-cell.opponent-1 { background: var(--territory-opponent-1); color: var(--text-on-inverse); }
.origin-cell.opponent-2 { background: var(--territory-opponent-2); color: var(--text-on-inverse); }
.origin-cell.opponent-3 { background: var(--territory-opponent-3); color: var(--text-on-inverse); }
.origin-cell.opponent-4 { background: var(--territory-opponent-4); color: var(--text-on-inverse); }
.origin-cell.opponent-5 { background: var(--territory-opponent-5); color: var(--text-on-accent); }
.origin-cell.opponent-6 { background: var(--territory-opponent-6); color: var(--text-on-accent); }

.progression-drill {
  margin: 0;
  font-size: 13px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.progression-drill.hint { color: var(--text-muted); }
.progression-drill.on { color: var(--text-primary); }

/* --- Colour by line ------------------------------------------------------ */

/* Position colour replaces outcome colour rather than joining it — one mark
   cannot mean "completed" and "midfielder" in the same hue. Width still carries
   progression and the dashes still carry crosses, so nothing is lost by the
   swap. The darker pitch is not decoration: the palette was validated for 3:1
   contrast against --pitch-surface, and the lighter --pitch-surface-alt does
   not reach it. */
.action-pitch.colour-line { background: var(--pitch-surface); }

.action-pitch.colour-line .action-mark line,
.action-pitch.colour-line .action-mark circle { stroke: none; }
.action-pitch.colour-line .action-mark.line-gk line { stroke: var(--line-gk); }
.action-pitch.colour-line .action-mark.line-def line { stroke: var(--line-def); }
.action-pitch.colour-line .action-mark.line-mid line { stroke: var(--line-mid); }
.action-pitch.colour-line .action-mark.line-att line { stroke: var(--line-att); }
.action-pitch.colour-line .action-mark.line-unknown line { stroke: var(--text-muted); }
.action-pitch.colour-line .action-mark.line-gk circle { fill: var(--line-gk); }
.action-pitch.colour-line .action-mark.line-def circle { fill: var(--line-def); }
.action-pitch.colour-line .action-mark.line-mid circle { fill: var(--line-mid); }
.action-pitch.colour-line .action-mark.line-att circle { fill: var(--line-att); }
.action-pitch.colour-line .action-mark.line-unknown circle { fill: var(--text-muted); }

/* Outcome no longer owns hue here, so it is carried by the dash alone. */
.action-pitch.colour-line .action-mark.incomplete line { stroke-dasharray: 1.5 1.2; }
.action-pitch.colour-line .action-mark.key-pass line { stroke-width: 1; }

.action-legend .legend-line-gk { background: var(--line-gk); }
.action-legend .legend-line-def { background: var(--line-def); }
.action-legend .legend-line-mid { background: var(--line-mid); }
.action-legend .legend-line-att { background: var(--line-att); }
.action-legend .legend-line-unknown { background: var(--text-muted); }

.action-legend .legend-complete { background: var(--success-text); }
.action-legend .legend-incomplete { background: var(--brand-accent); opacity: .75; }
.action-legend .legend-progressive { background: var(--success-text); height: 5px; }
.action-legend .legend-key { background: var(--player-4); height: 5px; }

/* --- Player table ------------------------------------------------------- */

.action-player-table .data-table th button {
  background: none;
  border: 0;
  color: var(--text-muted);
  font-family: inherit;
  cursor: pointer;
  padding: 0;
}

.action-player-table .data-table th button.active,
.action-player-table .data-table th button:hover {
  color: var(--interactive-hover);
}

/* Tighter than the shared table. Thirty-two rows of twelve columns is a
   reference table, read by scanning down a column, and every row of padding is
   a row of players pushed off the screen. The 44px target on the name button
   still sets the floor, so this stays reachable by touch. */
.actions-tab .data-table { font-size: 14px; }
.actions-tab .data-table th { padding: var(--space-2) var(--space-3); font-size: 12px; }
.actions-tab .data-table td { padding: var(--space-1) var(--space-3); }

.action-player-table .data-table td {
  font-variant-numeric: tabular-nums;
}

.action-player-pick {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
  width: 100%;
  min-height: 44px;
}

.action-player-pick span {
  display: grid;
}

.action-player-pick small {
  color: var(--text-muted);
  font-size: 12px;
}

.action-player-table tr.selected {
  background: var(--surface-overlay);
}

.action-player-pick:hover strong {
  color: var(--interactive-hover);
}

/* --- What the map says -------------------------------------------------- */

.action-says-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: var(--space-8);
}

.action-says header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--text-primary);
}

.action-says header strong {
  font-size: 17px;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.action-says ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Ruled rows, the same way the season brief and the archive list read. The
   left-hand accent bar this replaced belonged to no other list on the site. */
.action-says li {
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--border-subtle);
  font-size: 16px;
  line-height: 1.5;
  color: var(--text-secondary);
}

.action-says li strong { color: var(--text-primary); }

/* --- Map beside its index ----------------------------------------------- */

/* The list is what makes the map readable, so the two sit together rather than
   the list being a section the reader has to scroll to and lose the pitch. */
.action-map-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(16rem, 21rem);
  gap: var(--space-8);
  align-items: start;
}

/* Highlighting one ball has to suppress the other 1,454, or the marks that
   matter are lost in what they were picked out of. */
.action-pitch.has-highlight .action-layer > :not(.highlighted) { opacity: .12; }
.action-mark.highlighted line { stroke-width: 1.1; }
.action-mark.highlighted circle { r: 1.4; }

/* Compact strip under the map: scan it sideways, pick one, the pitch answers. */
/* Nested inside the map card, so it takes none of the standalone padding. */
.action-moments-card.compact {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-5);
  padding: var(--space-4) 0 0;
  border-top: 1px solid var(--border-subtle);
}

.action-moments-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.action-moments-head h4 {
  margin: 0;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.action-moments-head .ghost-button { margin-inline-start: auto; }
.action-moments-meta { font-size: 12px; color: var(--text-muted); margin-inline-start: auto; }

.action-moment-groups { flex-wrap: wrap; }

/* --- Who did it ----------------------------------------------------------- */

/* Denser than the whole-match table below and capped in height: this is a
   ranking you read the top of, and at ten rows it must not push the map off
   the screen it was opened to explain. */
.who-table { font-size: 13px; }
.who-table td { font-variant-numeric: tabular-nums; }
.who-table .action-player-pick { min-height: 36px; }
.who-table em { font-style: normal; color: var(--text-muted); font-size: 12px; }
.who-table td:last-child { color: var(--text-muted); }
.who-table th button {
  background: none;
  border: 0;
  color: var(--text-muted);
  font: inherit;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding: 0;
  cursor: pointer;
}
.who-table th button.active,
.who-table th button:hover { color: var(--interactive-hover); }

.who-empty { margin: 0; color: var(--text-muted); font-size: 13px; }
.who-more { justify-self: start; }

/* --- One player's ladder -------------------------------------------------- */

/* The rungs themselves are in phase-c.css: the Shape tab draws the same figure
   for a lineup slot, so it cannot live inside one tab's sheet. What stays here is
   the card's headline. */

/* The card's headline, at the size the card's own measurements deserve. 34px
   rather than the 42px of a team figure: this is one man inside a panel, not the
   side's total across a card of its own. Three fixed columns, so the note under
   each figure wraps in its own column instead of dragging the figure beside it
   wider. */
.player-ladder-figures {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
  margin-block-end: var(--space-5);
  max-width: 34rem;
}

.player-ladder-figures > div { display: grid; gap: var(--space-1); align-content: start; }

.player-ladder-figures span {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.player-ladder-figures strong {
  font-family: var(--font-display);
  font-size: 34px;
  font-weight: 800;
  line-height: .9;
  font-variant-numeric: tabular-nums;
}

/* The scope of the figure above it, not decoration: the rungs count line
   crossings and these count balls, so a reader who takes 16/22 for the sum of a
   column has been misled by the layout. */
.player-ladder-figures small {
  font-size: 12px;
  line-height: 1.3;
  color: var(--text-muted);
}

.action-moments-card.compact .action-moment-list {
  display: flex;
  gap: var(--space-2);
  margin: 0;
  padding: 0 0 var(--space-2);
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* Without this the row expands the card instead of scrolling, and it takes
     the whole page wide enough to push the squad's action counts off-screen. */
  min-width: 0;
}
.action-moments-card.compact .action-moment-list > li { flex: 0 0 auto; }
.action-moments-card.compact .action-moment-list button {
  display: grid;
  grid-template-columns: auto;
  gap: 2px;
  width: auto;
  min-width: 11rem;
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm, 4px);
  background: var(--surface-sunken);
}
.action-moments-card.compact .moment-player { font-size: 13px; font-weight: 700; }
.action-moments-card.compact .moment-player small { display: inline; margin-inline-start: var(--space-2); }
.action-moments-card.compact .moment-route,
.action-moments-card.compact .moment-length,
.action-moments-card.compact .moment-outcome { font-size: 11px; }
.action-moments-card.compact .moment-length { display: inline; margin-inline-end: var(--space-2); }
.action-moments-card.compact .moment-outcome { display: inline; }

.action-moment-list {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 26rem;
  overflow-y: auto;
}

.action-moment-list button {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-1) var(--space-3);
  width: 100%;
  min-height: 44px;
  padding: var(--space-3) var(--space-2);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border-subtle);
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.action-moment-list button:hover,
.action-moment-list button.selected { background: var(--surface-overlay); }

.moment-player { font-size: 16px; font-weight: 700; color: var(--text-primary); }
.moment-player small { display: block; font-weight: 400; color: var(--text-muted); font-size: 12px; }
.moment-route,
.moment-length { font-size: 13px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.moment-length { text-align: end; }
.moment-outcome { font-size: 12px; font-weight: 700; text-align: end; }
.moment-outcome.complete { color: var(--success-text); }
.moment-outcome.incomplete { color: var(--brand-accent); }

/* --- Channels ----------------------------------------------------------- */

.action-channel-card { display: grid; gap: var(--space-4); }

.action-channel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
  gap: var(--space-8);
}

.action-channel-table header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding-bottom: var(--space-3);
  margin-block-end: var(--space-3);
  border-bottom: 1px solid var(--text-primary);
}

.action-channel-table header strong {
  font-size: 17px;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.action-channel-table .data-table td { font-variant-numeric: tabular-nums; }
.action-channel-table .data-table td small {
  display: block;
  color: var(--text-muted);
  font-size: 12px;
}

/* --- Player statistics -------------------------------------------------- */

.action-stat-source {
  margin: var(--space-6) 0 var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-muted);
}

/* The ladder and the territory map side by side. Both are about 400px of
   height and neither is wider than half this card, so stacked they cost a
   screen to say two things that fit on one. The map keeps a fixed column: a
   pitch that grows with the viewport stops being comparable with the pitch in
   the tab beside it. */
.player-stat-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 26rem);
  gap: var(--space-8);
  align-items: start;
}

/* Level with the ladder's own heading, rather than a block-start that pushed the
   pitch below it. */
.player-stat-split .territory-multiples.one-up {
  grid-template-columns: minmax(0, 1fr);
  margin-block-start: 0;
}

/* A reference table, not a scoreboard: label at the left, figure at the right,
   a hairline under each pair. Auto-fit here, where a fixed six columns was
   right for the 27px version — a row is one line high, so a label that wraps
   costs nothing beside it, and the widest ("Progressive carrying distance") sets
   a 16rem floor that keeps every label to at most two lines. */
.action-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: 0 var(--space-8);
}

.action-stat-grid > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
}

.action-stat-grid span {
  color: var(--text-muted);
  line-height: 1.3;
}

/* The figure never breaks: "0 m" split across two lines put the unit under the
   number and the row out of line with the three beside it. */
.action-stat-grid strong {
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Stacked below this, not at the 1100px the rest of the tab uses: at 1024 — the
   narrowest laptop the site is checked at — the pair still leaves the ladder a
   470px column, which is a bar long enough to read, and holds the card at 796px
   where stacking it costs 1089. */
@media (max-width: 1000px) {
  .player-stat-split { grid-template-columns: minmax(0, 1fr); }
  .player-stat-split .territory-multiples.one-up { grid-template-columns: minmax(0, 26rem); }
}

@media (max-width: 900px) {
  .action-map-layout { grid-template-columns: minmax(0, 1fr); }
  .action-moment-list { max-height: 18rem; }
}

@media (max-width: 640px) {
  .action-team-figures { grid-template-columns: repeat(2, 1fr); }
  .action-controls { gap: var(--space-2); }
  .player-ladder-figures { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); }
  .player-ladder-figures strong { font-size: 27px; }
  .action-map-card,
  .action-player-table,
  .action-channel-card,
  .action-moments-card,
  .action-team-card { padding: var(--space-4); }
}

/* --- The corner dock ------------------------------------------------------ */

/* Fixed bottom-right rather than sticky top: the masthead is already sticky and
   88px tall, and a second bar under it eats the top of every map on a laptop.
   Bottom-right also puts it under the thumb on a phone.
   The stack is what the corner is: the team filter at the bottom, and anything
   that has to travel with the reader piled above it. */
.action-dock-stack {
  position: fixed;
  inset: auto var(--space-6) var(--space-6) auto;
  z-index: 40;
  display: grid;
  justify-items: end;
  gap: var(--space-2);
}

/* --- What the map is filtered by ------------------------------------------ */

/* Every pick is made screens above the map it narrows — the dropdowns over the
   map, the roster beside it, the ladder and the grid in the section before it.
   None of them are on screen by the time the reader is reading the marks, so
   each pick keeps a line here, shortest useful name first and the way out of it
   at the end. One plate for the set: five separate floating boxes in a corner
   is a pile, not a panel. */
.action-filter-dock {
  display: grid;
  gap: 1px;
  max-width: min(19rem, calc(100vw - var(--space-12)));
  padding: 1px;
  background: var(--border-subtle);
  border: 1px solid var(--brand-accent);
  box-shadow: var(--elevation-sticky);
}

.filter-chip {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-1) var(--space-1) var(--space-3);
  background: var(--surface-raised);
}

.drill-mark { flex: none; width: 24px; height: 16px; }
.drill-mark .pitch { fill: var(--surface-sunken); stroke: var(--border-strong); stroke-width: .8; }
.drill-mark .thirds line { stroke: var(--border-strong); stroke-width: .5; opacity: .8; }
.drill-mark .on { fill: var(--brand-accent); }
.drill-mark.line .ball { fill: none; stroke: var(--text-secondary); stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round; }
.drill-mark.line .crossed { stroke: var(--brand-accent); stroke-width: 1.2; }
.filter-chip .identity-image { flex: none; }

.filter-chip .chip-copy { min-width: 0; display: grid; }
.filter-chip strong {
  overflow: hidden;
  color: var(--text-primary);
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.filter-chip small { color: var(--text-muted); font-size: 12px; }

.filter-chip button {
  flex: none;
  width: 30px;
  min-height: 30px;
  height: 30px;
  margin-inline-start: auto;
  padding: 0;
  color: var(--text-secondary);
  background: var(--surface-sunken);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  font-size: 17px;
  line-height: 1;
}
.filter-chip button:hover { color: var(--text-on-accent); background: var(--surface-overlay); border-color: var(--brand-accent); }

.action-team-dock {
  display: flex;
  gap: var(--space-1);
  padding: var(--space-2);
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  box-shadow: var(--elevation-sticky);
}

.action-team-dock button {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: var(--surface-sunken);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  color: var(--text-secondary);
  cursor: pointer;
}

.action-team-dock button:hover { background: var(--surface-overlay); }

/* Same blue plate as the in-page filters, so "selected" means one thing on
   this tab wherever the control happens to be. */
.action-team-dock button.active {
  color: var(--text-on-accent);
  background: var(--brand-secondary);
  border-color: var(--brand-secondary);
}

.action-team-dock button i {
  font-size: 12px;
  font-style: normal;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.action-team-dock .identity-image { width: 26px; height: 26px; }
.action-team-dock .identity-image img { width: 100%; height: 100%; object-fit: contain; }

/* Only while the docks float, which is below the width where the rail exists:
   in the rail they are in flow and take their own room. */
@media (max-width: 1119px) {
  .actions-tab { padding-bottom: calc(44px + var(--space-12)); }
  .actions-tab.is-filtered { padding-bottom: calc(44px + 96px + var(--space-12)); }
}

@media (max-width: 640px) {
  .action-dock-stack { inset: auto var(--space-3) var(--space-3) auto; }
  .action-filter-dock { max-width: calc(100vw - var(--space-8)); }
}

.territory-multiples.one-up.wide { grid-template-columns: minmax(0, 880px); }
