/* Phase D: competition-scoped season analysis. */
.competition-lab { padding-bottom: 80px; }
.competition-lab-header {
  min-height: 230px; display: flex; align-items: end; justify-content: space-between; gap: 32px;
  padding: 34px 0 40px; border-top: 1px solid var(--border-subtle); border-bottom: 4px solid var(--text-primary);
}
/* The header switches to `flex-direction: column; align-items: start` below
   920px, which makes children shrink-to-fit at max-content and lets a long
   headline exceed the container. Cap them at the container width. */
.competition-lab-header > div { min-width: 0; max-width: 100%; }
.competition-lab-header h1 { max-width: 930px; margin: 8px 0 4px; font-size: clamp(44px, 6vw, 76px); line-height: .96; }
.competition-lab-header p { margin: 14px 0 0; color: var(--text-secondary); font-size: 16px; }
.lab-scope-count { min-width: 150px; padding-left: 20px; border-left: 1px solid var(--border-subtle); text-align: right; }
.lab-scope-count strong { display: block; color: var(--brand-accent); font-size: 58px; line-height: .9; }
.lab-scope-count span { display: block; margin-top: 9px; color: var(--text-secondary); font-size: 13px; text-transform: uppercase; }

/* Sticks under the masthead, not under the top of the window: at top:0 it stuck
   behind the masthead, which is sticky too and 88px tall, so all a reader ever
   saw of the filters they were meant to keep was the last few pixels of their
   bottom edge. --masthead-height is measured, so this holds when the bar
   reflows to two rows on a narrow screen. */
.lab-filter-shell {
  position: sticky; top: var(--masthead-height); z-index: 15; display: grid; grid-template-columns: repeat(7, minmax(120px, 1fr));
  gap: 0; margin: 20px 0 0; padding: 0; background: var(--surface-raised); border: 1px solid var(--border-subtle);
  box-shadow: var(--elevation-sticky);
}
.lab-filter-shell label, .lab-player-controls label, .lab-player-controls > div { min-width: 0; display: grid; gap: 6px; padding: 11px 12px; background: var(--surface-base); }
.lab-filter-shell label { border-right: 1px solid var(--border-subtle); border-bottom: 1px solid var(--border-subtle); }
.lab-filter-shell label > span, .lab-player-controls label > span, .lab-player-controls > div > span {
  color: var(--text-secondary); font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
}
.lab-filter-shell .control, .lab-player-controls .control {
  width: 100%; min-width: 0; min-height: 44px; padding: 8px 30px 8px 9px; color: var(--text-primary);
  background-color: var(--surface-raised); border: 1px solid var(--border-strong); font-size: 14px; text-transform: none;
}
.lab-player-controls input.control { padding-right: 9px; }

.lab-match-selector { margin-top: 12px; background: var(--surface-raised); border: 1px solid var(--border-subtle); }
.lab-match-selector-head { min-height: 58px; display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 8px 13px 8px 18px; border-bottom: 1px solid var(--border-subtle); }
.lab-match-selector-head strong, .lab-match-selector-head span { display: block; }
.lab-match-selector-head strong { font-size: 15px; }
.lab-match-selector-head span { margin-top: 3px; color: var(--text-secondary); font-size: 12px; }
.lab-match-selector-head button { min-height: 44px; padding: 8px 14px; color: var(--text-primary); background: var(--surface-sunken); border: 1px solid var(--border-strong); font-size: 13px; font-weight: 800; }
.lab-match-selector-head button:hover { border-color: var(--brand-accent); }
.lab-match-chips { display: flex; overflow-x: auto; background: var(--surface-raised); scrollbar-color: var(--border-subtle) var(--surface-raised); }
.lab-match-chips > button {
  position: relative; min-width: 224px; min-height: 68px; display: grid; grid-template-columns: 30px minmax(0,1fr) 26px;
  gap: 9px; align-items: center; padding: 9px 12px; color: var(--text-secondary); background: var(--surface-base); border: 0; border-right: 1px solid var(--border-subtle); text-align: left;
}
.lab-match-chips > button::after { content: ''; position: absolute; inset: auto 0 0; height: 3px; background: transparent; }
.lab-match-chips > button.active { color: var(--text-primary); background: var(--surface-sunken); }
.lab-match-chips > button.active::after { background: var(--brand-primary); }
.lab-match-chips strong, .lab-match-chips small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lab-match-chips strong { font-size: 14px; }
.lab-match-chips small { margin-top: 4px; color: var(--text-secondary); font-size: 12px; }

.lab-sample-warning, .lab-evidence, .lab-method {
  display: grid; grid-template-columns: auto minmax(0,1fr); gap: 8px 18px; align-items: center;
  margin-top: 12px; padding: 13px 17px; color: var(--text-secondary); background: var(--surface-raised); border: 1px solid var(--border-subtle); font-size: 13px;
}
.lab-sample-warning strong { color: var(--warning-text); text-transform: uppercase; }
.lab-tabs { display: flex; gap: 2px; margin: 28px 0 20px; border-bottom: 1px solid var(--border-subtle); overflow-x: auto; }
.lab-tabs a { min-width: max-content; min-height: 50px; display: grid; place-items: center; padding: 0 20px; color: var(--text-secondary); border-bottom: 3px solid transparent; font-size: 14px; font-weight: 850; }
.lab-tabs a:hover, .lab-tabs a.active { color: var(--text-on-accent); background: var(--surface-sunken); border-color: var(--brand-accent); }
.lab-view { display: grid; gap: 18px; }

/* Waiting for a panel inside the page, rather than for the page. The content
   stays exactly where it is and is veiled: swapping it for a loading screen
   collapsed the document, which dropped the scroll offset and threw the reader
   to the top and back again for a fetch that takes a moment. The sweep is the
   only thing that moves. */
.lab-view.is-busy { position: relative; }
.lab-view.is-busy > * { pointer-events: none; }
.lab-view.is-busy::after {
  content: ''; position: absolute; inset: -4px; z-index: 6;
  background-color: color-mix(in srgb, var(--surface-base) 62%, transparent);
  background-image: linear-gradient(100deg, transparent 34%, color-mix(in srgb, var(--text-primary) 9%, transparent) 50%, transparent 66%);
  background-size: 220% 100%; background-repeat: no-repeat;
  animation: lab-busy-sweep 1.15s ease-in-out infinite;
}
@keyframes lab-busy-sweep { from { background-position: 130% 0; } to { background-position: -130% 0; } }
@media (prefers-reduced-motion: reduce) { .lab-view.is-busy::after { animation: none; } }

.lab-summary-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 1px; background: var(--border-subtle); border: 1px solid var(--border-subtle); }
.lab-summary-grid article { min-width: 0; min-height: 142px; display: grid; align-content: center; padding: 18px; background: var(--surface-raised); }
.lab-summary-grid article > span { color: var(--text-secondary); font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.lab-summary-grid article > strong { margin: 11px 0 8px; font-size: clamp(24px, 2.3vw, 34px); font-variant-numeric: tabular-nums; white-space: nowrap; }
.lab-summary-grid article > strong i { margin: 0 3px; color: var(--text-secondary); font-size: .46em; font-style: normal; }
.lab-coverage { color: var(--text-secondary); font-size: 12px; }
.lab-panel { min-width: 0; background: var(--surface-raised); border: 1px solid var(--border-subtle); }
.lab-panel-head, .formation-analysis-head { min-height: 82px; display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 15px 18px; border-bottom: 1px solid var(--border-subtle); }
.lab-panel-head span, .formation-analysis-head span { color: var(--brand-accent); font-size: 12px; font-weight: 850; letter-spacing: .08em; text-transform: uppercase; }
/* Display headings are set in caps across the site — .editorial-heading,
   .section-head and .panel-title all are. The lab panels were the exception. */
.lab-panel-head h2, .formation-analysis-head h2 { margin: 4px 0 0; font-size: 24px; text-transform: uppercase; letter-spacing: -.01em; }
.lab-match-selector-head strong { text-transform: uppercase; letter-spacing: .04em; }
.lab-panel-head > small { max-width: 390px; color: var(--text-secondary); font-size: 12px; text-align: right; }
.lab-trend { display: grid; }
.lab-trend > a { min-height: 74px; display: grid; grid-template-columns: 34px 34px minmax(180px,.75fr) 50px minmax(280px,1fr); gap: 13px; align-items: center; padding: 9px 16px; color: var(--text-primary); border-top: 1px solid var(--border-subtle); }
.lab-trend > a:first-child { border-top: 0; }
.lab-trend > a:hover { background: var(--surface-sunken); }
.lab-trend > a > i { color: var(--text-secondary); font-size: 12px; font-style: normal; }
.lab-trend-result { width: 30px; height: 30px; display: grid; place-items: center; color: var(--text-on-accent); border: 1px solid var(--border-subtle); font-size: 13px; font-weight: 900; }
.lab-trend-result.win { background: var(--success-surface); }.lab-trend-result.draw { background: var(--interactive-disabled); }.lab-trend-result.loss { background: var(--danger-surface); }
.lab-trend strong, .lab-trend small { display: block; }.lab-trend small { margin-top: 4px; color: var(--text-secondary); font-size: 12px; }
.lab-trend > a > b { font-size: 21px; font-variant-numeric: tabular-nums; }
/* Each metric is a duel: two values with the split between them drawn. Printed
   as "2.20:1.19" the pair asked the reader to know that this page is always
   Basel first — and the archive two clicks away orders the same figure home
   first. The side is the colour the rest of the app already gives it (app.js
   paints team 9931 --team-home and everyone else --team-away on every pitch and
   momentum chart), so nothing new has to be learnt and the row stays one line
   per metric. The bar answers "who was better" before either number is read.
   Red and blue as marks; their text-safe siblings for the numerals, per §1.3. */
.lab-trend dl { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; margin: 0; background: var(--border-subtle); }
.lab-trend dl div { padding: 9px 11px; background: var(--surface-sunken); }
.lab-trend dt { color: var(--text-secondary); font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.lab-trend dd { display: flex; align-items: center; gap: 9px; margin: 7px 0 0; }
.lab-trend dd b { min-width: 34px; font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; }
.lab-trend dd b:first-child { color: var(--brand-accent); }
.lab-trend dd b:last-child { color: var(--info-text); text-align: right; }
.lab-duel-bar { flex: 1; min-width: 20px; height: 7px; background: var(--team-away); }
.lab-duel-bar > i { display: block; width: var(--basel-share); height: 100%; background: var(--team-home); box-shadow: 1px 0 0 var(--surface-sunken); }
.lab-trend dd.lab-duel-empty { color: var(--text-muted); font-size: 15px; }

/* Stated once for the panel, not once per row: the rows carry the colour. It
   takes the rows' own track list so the two names sit at the ends of the block
   they describe — the left value is Basel's on every bar below. */
.lab-trend-key { display: grid; grid-template-columns: 34px 34px minmax(180px,.75fr) 50px minmax(280px,1fr); gap: 13px; padding: 9px 16px; border-bottom: 1px solid var(--border-subtle); }
/* Both names share the last cell — grid-row keeps auto-placement from putting
   the second one on a line of its own. */
.lab-trend-key > span { grid-column: -2; grid-row: 1; display: flex; align-items: center; gap: 7px; color: var(--text-secondary); font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.lab-trend-key > span:last-child { justify-self: end; }
.lab-trend-key > span::before { content: ''; width: 11px; height: 11px; background: var(--team-away); }
.lab-trend-key > span:first-child::before { background: var(--team-home); }
.lab-overview-columns { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.lab-record-row { min-height: 58px; display: grid; grid-template-columns: minmax(130px,1fr) 100px 120px 90px; gap: 10px; align-items: center; padding: 8px 16px; border-top: 1px solid var(--border-subtle); font-size: 13px; }
.lab-record-row:first-of-type { border-top: 0; }.lab-record-row span { color: var(--text-secondary); }.lab-record-row b { text-align: right; }
.lab-empty { padding: 20px; color: var(--text-secondary); }

.formation-analysis-head > strong { font-size: 15px; }
.formation-analysis-grid { display: grid; grid-template-columns: minmax(0,1.45fr) minmax(380px,.55fr); gap: 18px; padding: 18px; }
.lab-formation-pitch { background: var(--pitch-surface); }.lab-formation-pitch svg { width: 100%; }
.formation-analysis-grid aside { min-width: 0; display: grid; align-content: start; gap: 14px; }
.formation-shape-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; margin: 0; background: var(--border-subtle); border: 1px solid var(--border-subtle); }
.formation-shape-stats > div { min-height: 82px; display: grid; align-content: center; padding: 12px; background: var(--surface-sunken); }
.formation-shape-stats dt { color: var(--text-secondary); font-size: 12px; text-transform: uppercase; }.formation-shape-stats dd { margin: 6px 0 0; font-size: 20px; font-weight: 850; }
/* Shape tab. The formation switcher sits in the side column, where the page
   already has the room: pinning it over the top of the page took a band of
   height from every screen to serve a control used once a visit. It is also
   the comparison — a formation's record and its shape are on its own row. */
.shape-view { gap: 14px; }
.shape-lens { margin: 0; }
.shape-lens p { flex: 1; min-width: 220px; margin: 0; color: var(--text-secondary); font-size: 13px; }
.shape-formations { padding: 0; overflow: hidden; }
.shape-formations > .panel-title { margin: 0; padding: 14px 16px; border-bottom: 1px solid var(--border-subtle); }
.shape-formations > .panel-title h3 { margin: 0; font-size: 16px; }
.shape-formations > button {
  width: 100%; display: grid; grid-template-columns: minmax(0,1fr) auto; gap: 2px 10px; align-items: baseline;
  padding: 11px 16px; color: var(--text-secondary); background: var(--surface-raised); border: 0;
  border-top: 1px solid var(--border-subtle); text-align: left; font-variant-numeric: tabular-nums;
}
.shape-formations > .panel-title + button { border-top: 0; }
.shape-formations > button:hover { background: var(--surface-sunken); }
.shape-formations > button.active { background: var(--surface-sunken); box-shadow: inset 3px 0 var(--brand-primary); }
.shape-formations strong { color: var(--text-primary); font-size: 16px; }
.shape-formations b { color: var(--text-primary); font-size: 13px; }
.shape-formations small, .shape-formations em { grid-column: 1 / -1; font-size: 12px; font-style: normal; }
.shape-formations em { color: var(--text-muted); }
.shape-no-heatmaps { color: var(--text-muted); }
.shape-slot .shirt { font-size: 1.9px; }
.shape-prompt { margin: 0; padding: 14px 16px; color: var(--text-secondary); background: var(--surface-sunken); border: 1px solid var(--border-subtle); font-size: 13px; line-height: 1.55; }
.shape-slot-list { max-height: 430px; overflow-y: auto; border: 1px solid var(--border-subtle); }
.shape-slot-list > button { width: 100%; min-height: 57px; display: grid; grid-template-columns: 38px minmax(0,1fr) auto; gap: 9px; align-items: center; padding: 7px 10px; color: var(--text-primary); background: var(--surface-raised); border: 0; border-top: 1px solid var(--border-subtle); text-align: left; }
.shape-slot-list > button:first-child { border-top: 0; }
.shape-slot-list > button:hover, .shape-slot-list > button.active { background: var(--surface-sunken); box-shadow: inset 3px 0 var(--brand-accent); }
.shape-slot-list b, .shape-slot-badge { width: 32px; height: 32px; display: grid; place-items: center; color: var(--text-on-accent); background: var(--brand-primary); border-radius: 50%; font-size: 11px; font-weight: 900; }
.shape-slot-list span { min-width: 0; }
.shape-slot-list strong, .shape-slot-list small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shape-slot-list small { margin-top: 3px; color: var(--text-secondary); font-size: 12px; }
.shape-slot-list em { color: var(--text-secondary); font-size: 12px; font-style: normal; font-variant-numeric: tabular-nums; }
.shape-slot-focus h4 { min-height: 30px; display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 16px 0 8px; color: var(--text-secondary); font-size: 12px; letter-spacing: .06em; text-transform: uppercase; }
.shape-slot-focus h4 button { padding: 5px 11px; color: var(--text-secondary); background: var(--surface-sunken); border: 1px solid var(--border-subtle); font-size: 12px; font-weight: 800; letter-spacing: 0; text-transform: none; }
.shape-slot-focus h4 button:hover { border-color: var(--brand-accent); }
.shape-slot-focus h4 button.active { color: var(--text-primary); border-color: var(--brand-primary); }
.shape-pairs { width: 100%; margin-top: 10px; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
.shape-pairs th { color: var(--text-secondary); font-weight: 800; text-align: right; }
.shape-pairs th:first-child, .shape-pairs td:first-child { text-align: left; }
.shape-pairs th, .shape-pairs td { padding: 6px 8px; border-bottom: 1px solid var(--border-subtle); text-align: right; }
/* Two of these three labels wrap in the rail's width; reserving the second
   line keeps the three values on one baseline instead of stepping down. */
.shape-slot-focus .focus-numbers { margin: 18px 0 4px; }
.shape-slot-focus .focus-numbers dt { min-height: 32px; }
.shape-slot-focus .spatial-method-note { margin-bottom: 0; }
.shape-layer-note { margin: 13px 0 0; padding: 10px 12px; color: var(--text-secondary); background: var(--surface-sunken); border-left: 3px solid var(--brand-primary); font-size: 13px; }
.shape-occupants { display: grid; gap: 1px; margin: 0; background: var(--border-subtle); border: 1px solid var(--border-subtle); }
.shape-occupants > button { min-height: 52px; display: grid; grid-template-columns: 30px minmax(0,1fr) auto; gap: 9px; align-items: center; padding: 6px 10px; color: var(--text-primary); background: var(--surface-raised); border: 0; text-align: left; }
.shape-occupants > button:hover, .shape-occupants > button.active { background: var(--surface-sunken); box-shadow: inset 3px 0 var(--brand-accent); }
.shape-occupants span { min-width: 0; }
.shape-occupants strong, .shape-occupants small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shape-occupants small { margin-top: 2px; color: var(--text-secondary); font-size: 12px; }
/* The swatch says which of the two densities on the pitch is his. */
.shape-occupants > button > i { width: 13px; height: 13px; border-radius: 50%; background: var(--player-colour); }
.shape-games { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }
.shape-games > button { min-height: 54px; display: grid; gap: 2px; padding: 7px 11px; color: var(--text-secondary); background: var(--surface-sunken); border: 1px solid var(--border-subtle); text-align: left; font-size: 12px; }
.shape-games > button:hover { border-color: var(--brand-accent); }
.shape-games > button.active { color: var(--text-primary); border-color: var(--brand-primary); box-shadow: inset 0 -3px var(--brand-primary); }
.shape-games strong { font-size: 13px; }.shape-games em { color: var(--text-muted); font-style: normal; }
/* The slot's on-ball group. Same three-up figures as the spatial ones above it,
   because in a 380px rail a second layout would be a second design, not a second
   subject; the heading and the note under it say which feed it came from. */
.shape-slot-focus .player-ladder { margin-top: 10px; }
.shape-slot-focus .player-ladder li { grid-template-columns: minmax(7rem, max-content) 1fr max-content; gap: 8px; }
.shape-slot-focus .player-ladder-name { font-size: 12px; }

/* The formation's own on-ball card, in the column under the pitch — which was
   empty from the method note down to the foot of the aside. */
.formation-onball { display: grid; gap: 14px; margin-top: 18px; padding: 18px; background: var(--surface-raised); border: 1px solid var(--border-subtle); }
/* Three fixed columns is phase-c's rule for a rail 380px wide holding 18px
   figures. These are 27px and "211/306" is nine characters, so on a phone the
   third of a column it gets is narrower than the number in it: auto-fit wraps to
   two columns instead of printing 211/306 into 3,656 m. */
.formation-onball .focus-numbers { grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); margin: 0; }
.formation-onball .focus-numbers dd { font-size: 27px; font-family: var(--font-display); font-weight: 800; }
/* The total is the figure; per match is the reading that makes two shapes
   comparable. Block, or the second number runs on from the first as one string. */
.formation-onball .focus-numbers dd small { display: block; margin-top: 5px; color: var(--text-muted); font-family: var(--font-body); font-size: 12px; font-weight: 400; }
.formation-onball .spatial-method-note { margin: 0; }
.formation-onball-tables { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); gap: 18px; }
/* Without this a table wider than its share pushes the column open and prints
   over the one beside it — grid items do not shrink below their content. */
.formation-onball-tables > div { min-width: 0; overflow-x: auto; }
.formation-onball-tables h4 { margin: 0 0 8px; color: var(--text-secondary); font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
/* phase-a.css:387 puts a 680px floor under every .data-table, which is right for
   the wide season tables it was written for and 200px more than a column of this
   card. These two hold four short columns and fit their share. */
.formation-onball-tables .data-table { min-width: 0; width: 100%; border-collapse: collapse; font-size: 13px; font-variant-numeric: tabular-nums; }
.formation-onball-tables .data-table th { padding: 7px 8px; font-size: 11px; }
.formation-onball-tables .data-table td { padding: 7px 8px; }
.formation-onball-tables .data-table small { display: block; margin-top: 2px; color: var(--text-muted); font-size: 11px; }

.shape-exits { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.shape-exits button, .shape-exits a { min-height: 40px; display: inline-flex; align-items: center; padding: 6px 13px; color: var(--text-primary); background: var(--surface-sunken); border: 1px solid var(--border-strong); font-size: 13px; font-weight: 700; }
.shape-exits button:hover, .shape-exits a:hover { border-color: var(--brand-accent); }
.spatial-legend button { min-height: 32px; padding: 4px 10px; color: var(--text-secondary); background: var(--surface-sunken); border: 1px solid var(--border-subtle); font-size: 12px; font-weight: 700; }
.spatial-legend button.active { color: var(--text-primary); border-color: var(--brand-primary); }

.lab-player-controls { display: grid; grid-template-columns: minmax(175px,1fr) auto 165px 165px minmax(190px,1fr); gap: 1px; background: var(--border-subtle); border: 1px solid var(--border-subtle); }
.lab-player-controls .segmented-control button { min-height: 44px; }
.lab-evidence { grid-template-columns: auto auto minmax(240px,1fr); margin: 0; background: var(--surface-raised); border-color: var(--border-subtle); }
.lab-evidence strong { color: var(--text-on-accent); font-size: 14px; }.lab-evidence span { color: var(--text-secondary); }.lab-evidence p { margin: 0; color: var(--text-secondary); text-align: right; }
.players-dashboard .table-frame-scroll { max-width: 100%; background: var(--surface-raised); border: 1px solid var(--border-subtle); }
.lab-player-table { min-width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; font-variant-numeric: tabular-nums; }
/* Abbreviated headings and a tighter row: 27 metrics across full-length titles
   made a table nobody could take in. The full title lives on the abbr. */
.lab-player-table th, .lab-player-table td { min-width: 76px; height: 44px; padding: 6px 9px; border-right: 1px solid var(--border-subtle); border-bottom: 1px solid var(--border-subtle); text-align: right; vertical-align: middle; white-space: nowrap; }
.lab-player-table th abbr { border: 0; text-decoration: none; cursor: help; }
.lab-player-table th { position: sticky; top: 0; z-index: 3; min-height: 58px; color: var(--text-secondary); background: var(--surface-sunken); }
.lab-player-table th button { width: 100%; min-height: 44px; padding: 6px 0; color: inherit; background: transparent; border: 0; font-size: 12px; font-weight: 850; text-align: right; white-space: normal; }
.lab-player-table th button:hover, .lab-player-table th button.active { color: var(--text-on-accent); }
.lab-player-table th > small { display: block; color: var(--text-muted); font-size: 12px; font-weight: 500; }
.lab-player-table .sticky-player { position: sticky; left: 0; z-index: 2; min-width: 225px; max-width: 225px; text-align: left; background: var(--surface-raised); box-shadow: var(--elevation-sticky-column); }
.lab-player-table th.sticky-player { z-index: 5; background: var(--surface-sunken); }.lab-player-table th.sticky-player button { text-align: left; }
.lab-player-cell { display: grid; grid-template-columns: 36px minmax(0,1fr); gap: 10px; align-items: center; }.lab-player-cell span { min-width: 0; }.lab-player-cell strong, .lab-player-cell small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.lab-player-cell strong { font-size: 14px; }.lab-player-cell small { margin-top: 3px; color: var(--text-secondary); font-size: 12px; }
.lab-player-table td > strong { font-size: 14px; }.lab-player-table td > small { display: block; margin-top: 3px; color: var(--text-secondary); font-size: 12px; }.metric-missing, .metric-na { color: var(--text-muted); }.metric-na { font-size: 12px; text-transform: uppercase; }

.season-spatial-workspace { gap: 16px; }.season-spatial-workspace .spatial-controls { margin: 0; }
.season-spatial-roster { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); background: var(--surface-raised); border: 1px solid var(--border-subtle); gap: 0; }
.season-spatial-roster > button { position: relative; min-width: 0; min-height: 64px; display: grid; grid-template-columns: 34px minmax(0,1fr); gap: 9px; align-items: center; padding: 8px 10px; color: var(--text-primary); background: var(--surface-raised); border: 0; border-right: 1px solid var(--border-subtle); border-bottom: 1px solid var(--border-subtle); text-align: left; }
.season-spatial-roster > button:hover, .season-spatial-roster > button.active { background: var(--surface-overlay); box-shadow: inset 3px 0 var(--brand-accent); }.season-spatial-roster span { min-width: 0; }.season-spatial-roster strong, .season-spatial-roster small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.season-spatial-roster strong { font-size: 13px; }.season-spatial-roster small { margin-top: 3px; color: var(--text-secondary); font-size: 12px; }.season-spatial-roster i { position: absolute; top: 5px; right: 5px; width: 20px; height: 20px; display: grid; place-items: center; color: var(--surface-base); background: var(--player-colour); border-radius: 50%; font-size: 12px; font-style: normal; font-weight: 900; }
/* The order the squad is read in belongs beside the squad, not up in the
   analysis controls: it changes the list and nothing else. */
.roster-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: -10px; }
.roster-head h3 { margin: 0; font-family: var(--font-display); font-size: 15px; letter-spacing: .06em; text-transform: uppercase; }
.roster-sort button { min-height: 36px; padding: 5px 13px; font-size: 12px; }

/* One player, one pitch per match, small enough to hold side by side. */
.spatial-match-strip { padding: 20px; }
.spatial-match-strip > .panel-title { margin: 0 0 14px; }
/* auto-fit, so three matches spread into readable pitches instead of huddling
   at the minimum beside three empty tracks; the cap stops one match from
   becoming a second full-width pitch under the one it is a detail of. */
.spatial-match-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(236px, 348px)); justify-content: start; gap: 12px; }
.spatial-match-card { min-width: 0; display: grid; gap: 9px; padding: 11px; color: var(--text-primary); background: var(--surface-sunken); border: 1px solid var(--border-subtle); text-align: left; }
.spatial-match-card:hover { border-color: var(--brand-accent); }
.spatial-match-card.active { border-color: var(--brand-primary); box-shadow: inset 0 -3px var(--brand-primary); }
/* An unchosen match stays legible — it is still evidence, and it is the thing
   being clicked. It reads as out of the panel, not as unavailable. */
.spatial-match-card:not(.active) { background: var(--surface-raised); }
.spatial-match-card:not(.active) .spatial-mini-pitch { opacity: .55; }
.spatial-match-head, .spatial-match-foot { min-width: 0; display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.spatial-match-head strong { overflow: hidden; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }
.spatial-match-head small, .spatial-match-foot b, .spatial-match-foot em { color: var(--text-secondary); font-size: 12px; font-style: normal; font-weight: 500; white-space: nowrap; }
.spatial-mini-pitch { display: block; background: var(--pitch-surface); }
.spatial-mini-pitch svg { display: block; width: 100%; }
/* The mean dot's label and the corridor caption are sized for the big pitch;
   at a third of the width they are a smear across the goalmouth. */
.spatial-mini-pitch text, .spatial-mini-pitch .spatial-centroid { display: none; }

.spatial-scope-note { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin: 14px 0 0; padding: 10px 13px; color: var(--info-on-subtle); background: var(--info-subtle); border: 1px solid var(--border-subtle); font-size: 13px; }
.spatial-scope-note button { min-height: 34px; padding: 4px 12px; color: var(--text-primary); background: var(--surface-overlay); border: 1px solid var(--border-strong); font-size: 12px; font-weight: 700; }
.spatial-scope-note button:hover { border-color: var(--brand-accent); }

.lab-included-matches { overflow: hidden; }.lab-included-matches h3 { margin: 0; padding: 15px; font-size: 17px; }.lab-included-matches a { min-height: 52px; display: flex; align-items: center; justify-content: space-between; gap: 15px; padding: 8px 13px; color: var(--text-primary); border-top: 1px solid var(--border-subtle); font-size: 13px; }.lab-included-matches a:hover { background: var(--surface-sunken); }.lab-included-matches b { color: var(--text-secondary); font-size: 12px; }

.coverage-summary { grid-template-columns: repeat(6, 1fr); }.lab-coverage-table { min-width: 1080px; }.lab-coverage-table td:first-child a { color: var(--text-primary); }.lab-coverage-table td:first-child strong, .lab-coverage-table td:first-child small { display: block; }.lab-coverage-table td:first-child small { margin-top: 4px; color: var(--text-secondary); font-size: 12px; }
.availability-mark { display: inline-flex; min-height: 28px; align-items: center; padding: 3px 8px; border: 1px solid var(--border-subtle); font-size: 12px; font-weight: 800; }.availability-mark.yes { color: var(--success-text); background: var(--success-subtle); border-color: var(--pitch-border); }.availability-mark.no { color: var(--text-muted); background: var(--neutral-subtle); }
.lab-method { grid-template-columns: 150px minmax(0,1fr); background: var(--surface-raised); border-color: var(--border-subtle); }.lab-method p { margin: 0; color: var(--text-secondary); line-height: 1.6; }

@media (max-width: 1240px) {
  .lab-filter-shell { grid-template-columns: repeat(4, 1fr); position: static; }
  .lab-summary-grid, .coverage-summary { grid-template-columns: repeat(3, 1fr); }
  .lab-player-controls { grid-template-columns: 1fr 1fr 1fr; }.lab-player-search { grid-column: span 2; }
  .season-spatial-roster { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 920px) {
  .competition-lab-header { min-height: 210px; align-items: start; flex-direction: column; justify-content: end; }.lab-scope-count { padding: 0; border: 0; text-align: left; }.lab-scope-count strong { display: inline; margin-right: 8px; font-size: 36px; }.lab-scope-count span { display: inline; }
  .lab-filter-shell { grid-template-columns: repeat(2, 1fr); }
  .lab-overview-columns, .formation-analysis-grid { grid-template-columns: 1fr; }
  .lab-trend > a, .lab-trend-key { grid-template-columns: 30px 34px minmax(150px,1fr) 44px; }.lab-trend dl { grid-column: 3 / -1; width: 100%; }.lab-trend-key > span { grid-column: 3 / -1; }
  .lab-evidence { grid-template-columns: 1fr; }.lab-evidence p { text-align: left; }
  .season-spatial-roster { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 620px) {
  .competition-lab-header h1 { font-size: 42px; }.competition-lab-header p { font-size: 14px; }
  .lab-filter-shell { grid-template-columns: 1fr 1fr; }.lab-filter-shell label { padding: 9px; }
  .lab-match-selector-head { align-items: start; }.lab-match-chips > button { min-width: 205px; }
  .lab-tabs a { padding: 0 14px; }
  .lab-summary-grid, .coverage-summary { grid-template-columns: 1fr 1fr; }.lab-summary-grid article { min-height: 118px; padding: 13px; }.lab-summary-grid article > strong { font-size: 24px; }
  .lab-panel-head { align-items: start; flex-direction: column; }.lab-panel-head > small { text-align: left; }
  /* Three tracks, not four: the index is hidden at this width, so a four-track
     list shifted every cell one column left and squeezed the fixture into the
     badge's 32px. */
  .lab-trend > a, .lab-trend-key { grid-template-columns: 32px minmax(110px,1fr) 46px; padding: 10px 8px; }.lab-trend dl { grid-column: 1 / -1; }.lab-trend > a > i { display: none; }.lab-trend-key > span { grid-column: 1 / -1; }
  .lab-record-row { grid-template-columns: minmax(110px,1fr) 85px 70px; }.lab-record-row span:nth-of-type(2) { display: none; }
  .formation-analysis-grid { padding: 10px; }.formation-analysis-head { align-items: start; flex-direction: column; }.formation-shape-stats { grid-template-columns: 1fr 1fr; }
  .shape-games > button { flex: 1 1 100%; }
  .lab-player-controls { grid-template-columns: 1fr 1fr; }.lab-player-search { grid-column: 1 / -1; }.lab-player-table .sticky-player { min-width: 190px; max-width: 190px; }
  .season-spatial-roster { grid-template-columns: 1fr; }.season-spatial-workspace .spatial-controls { padding: 10px; }
  .lab-method { grid-template-columns: 1fr; }
}

/* --- Shot team switch ----------------------------------------------------- */

/* Three equal plates across the row rather than three words in a corner: the
   control is the first decision on the tab and the space was going unused. */
.shot-team-switch {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
  flex: 1;
}

.shot-team-switch button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 52px;
  padding: var(--space-2) var(--space-3);
  background: var(--surface-sunken);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  color: var(--text-secondary);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}

.shot-team-switch button:hover { background: var(--surface-overlay); }

.shot-team-switch button.active {
  color: var(--text-on-accent);
  background: var(--brand-secondary);
  border-color: var(--brand-secondary);
}

.shot-team-switch button i {
  font-style: normal;
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.shot-team-switch .identity-image { width: 26px; height: 26px; flex: none; }
.shot-team-switch .identity-image img { width: 100%; height: 100%; object-fit: contain; }

/* --- Attempt stepper ------------------------------------------------------ */

/* One control, not two buttons with a number loose between them: a single
   bordered group with the count in the middle, the same segmented shape the
   filters use. It also has to hold together in a narrow cell — as a plain flex
   row the fixed-width buttons still shrank, which is how "3 / 26" ended up
   broken over three lines beside two slivers. Nothing here may shrink. */
.shot-stepper {
  flex: none;
  display: flex;
  align-items: stretch;
  margin-inline-start: var(--space-3);
  background: var(--surface-sunken);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  overflow: hidden;
}

.shot-stepper button {
  flex: none;
  width: 36px;
  min-height: 0;
  height: 36px;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--text-primary);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}

.shot-stepper button:hover:not([disabled]) { background: var(--surface-overlay); }
.shot-stepper button[disabled] { color: var(--interactive-disabled); cursor: not-allowed; }
.shot-stepper span {
  flex: none;
  min-width: 62px;
  display: grid;
  place-items: center;
  padding: 0 var(--space-2);
  border-inline: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

@media (max-width: 640px) {
  .shot-team-switch button span { display: none; }
  .shot-team-switch button { min-height: 48px; }
}
