/*
 * Score, fixture, ladder and match-detail components.
 *
 * Built entirely on the tokens in /theme.css - no colour, radius or spacing
 * value is invented here. A page is a stack of panels; a panel holds rows,
 * tables or a chart; nothing else.
 */

/* =============================================================== the panel */

.panel {
    margin: 0 0 var(--gap-5);
    padding: var(--gap-4) var(--gap-5) var(--gap-5);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

/* A round of matches is already structured - a labelled band per day, a card
   per match - so framing it puts a box around a box. The heading stays, the
   frame goes, and the cards sit on the ground where they read as the content
   of the page rather than the contents of a container. */
.panel.is-plain {
    padding: 0;
    background: none;
    border: 0;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

.panel.is-plain > .panel-head {
    margin-bottom: var(--gap-3);
}

.panel-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--gap-2) var(--gap-4);
    margin-bottom: var(--gap-4);
}

.panel-head h2 {
    margin: 0;
}

.panel-sub {
    flex-basis: 100%;
    margin: 0;
    font-size: 0.82rem;
    color: var(--text-mute);
}

.panel > .score-board:last-child,
.panel > .ladder-scroll:last-child {
    margin-bottom: 0;
}

.note {
    margin: 0 0 var(--gap-5);
    padding: var(--gap-3) var(--gap-4);
    border-radius: var(--r);
    background: var(--surface);
    border: 1px solid var(--line);
    font-size: 0.9rem;
    color: var(--text-mute);
}

.table-scroll {
    overflow-x: auto;
}

/* ============================================================ match cards */

.score-board {
    display: grid;
    gap: var(--gap-4);
    margin: 0 0 var(--gap-5);
}

.score-board .match-day:first-child .match-day-heading {
    margin-top: 0;
}

.score-board.is-single {
    max-width: 560px;
}

/* A day is a labelled band, not a floating caption: the rule carries the eye
   across the width the matches occupy, so a single Thursday game reads as a day
   with one match in it rather than a card that lost its neighbour. */
.match-day-heading {
    display: flex;
    align-items: center;
    gap: var(--gap-3);
    margin: var(--gap-3) 0 0;
    font-size: 0.7rem;
    font-weight: 750;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-mute);
}

.match-day-heading::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--line);
}

/* Two across on a wide screen. One match stretched over a full desktop column
   puts a hundred empty pixels between a team and its own score. */
.match-day {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(430px, 100%), 1fr));
    gap: var(--gap-2);
}

.match-day-heading {
    grid-column: 1 / -1;
}

/* The app's layout, and the only one: names on their own line, the badge and
   the score under each, then a centred state flanked by one progress track per
   half while the match is live. */
.match-card {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    grid-template-areas:
        "home-name  vs away-name"
        "home-score vs away-score"
        "status     status status"
        "venue      venue  venue";
    align-items: center;
    column-gap: var(--gap-3);
    row-gap: var(--gap-1);
    padding: 0.85rem 1rem;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--r);
    color: inherit;
    transition: background 0.15s ease, border-color 0.15s ease;
}

a.match-card:hover {
    background: var(--surface-3);
    border-color: var(--line-2);
    color: inherit;
}

.score-line {
    display: flex;
    align-items: center;
    gap: var(--gap-2);
    min-width: 0;
}

.score-line[data-side="home"] { grid-area: home-score; }

.score-line[data-side="away"] {
    grid-area: away-score;
    flex-direction: row-reverse;
}

/* A card is the widest thing on a scores page and its job is to be read at a
   glance, so the club and the score take the room that is there. */
.match-team {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    min-width: 0;
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.match-team[data-side="home"] { grid-area: home-name; }

.match-team[data-side="away"] {
    grid-area: away-name;
    flex-direction: row-reverse;
}

.match-team.is-winner {
    color: var(--text);
}

/* Always in the markup, shown only for the winner, so scores.js settles a
   result by toggling one class rather than building an element. */
.win-tick {
    display: none;
}

.match-team.is-winner .win-tick {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.15em;
    height: 1.15em;
    border-radius: 50%;
    background: var(--brand);
    color: var(--on-brand);
    font-size: 0.7em;
    font-weight: 800;
    line-height: 1;
}

.match-vs {
    grid-area: vs;
    align-self: center;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-mute);
}

.score-value {
    font-size: 2.6rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.05;
    color: var(--text-dim);
}

.match-card .team-badge {
    width: 38px;
    height: 38px;
}

.score-line.is-winner .score-value {
    color: var(--text);
}

.match-middle {
    grid-area: status;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--gap-1);
    min-width: 0;
    margin-top: var(--gap-2);
}

.match-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border-radius: var(--r-sm);
    background: var(--surface-3);
    font-size: 0.75rem;
    font-weight: 650;
    color: var(--text-dim);
    white-space: nowrap;
}

.match-pill.is-live {
    background: var(--live-wash);
    color: var(--live);
}

.live-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--live);
    animation: pulse 1.8s ease-in-out infinite;
}

@keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.3; }
}

@media (prefers-reduced-motion: reduce) {
    .live-dot { animation: none; }
}

.match-progress {
    flex: 1 1 0;
    min-width: 0;
    height: 3px;
    border-radius: 2px;
    background: var(--line-2);
    overflow: hidden;
}

.match-progress span {
    display: block;
    height: 100%;
    background: var(--live);
    transition: width 0.4s ease;
}

.match-venue {
    grid-area: venue;
    margin: var(--gap-1) 0 0;
    font-size: 0.75rem;
    color: var(--text-mute);
    text-align: center;
}


/* ============================================================== match hero */

/* The match page's header is the card at scoreboard scale: the same home-left,
   away-right hierarchy, the same centred state with a progress track per half,
   with the stage, day and ground on one micro-caps line above. */
.match-hero {
    margin: 0 0 var(--gap-5);
    padding: var(--gap-4) var(--gap-5) var(--gap-5);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

.match-hero-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.25rem 0.4rem;
    margin: 0 0 var(--gap-4);
    text-align: center;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-mute);
}

.match-hero-dot {
    color: var(--line-2);
}

/* The frame runs the width of the page, like every other panel; the scoreboard
   inside it does not. Stretched to the full measure it would put the width of a
   hand between a club and its own score. */
.match-card.is-hero {
    max-width: 820px;
    margin-inline: auto;
    padding: 0;
    background: none;
    border: 0;
    column-gap: var(--gap-5);
}

.match-card.is-hero:hover {
    background: none;
}

.is-hero .match-team {
    font-size: 1.4rem;
    font-weight: 750;
}

.match-card.is-hero .team-badge {
    width: 56px;
    height: 56px;
}

.is-hero .score-line {
    gap: var(--gap-3);
}

.is-hero .score-value {
    font-size: clamp(2.4rem, 6vw, 3.4rem);
}

.is-hero .match-middle {
    margin-top: var(--gap-4);
}

/* The state pill carries a kick-off time before the match starts, and there is
   no score pair beside it to compete with, so it takes the space instead.
   Keyed on data-status, which scores.js rewrites the moment the match starts. */
.match-card.is-hero[data-status="upcoming"] .match-pill {
    padding: 0.3rem 1rem;
    border-radius: var(--r);
    font-size: 1.35rem;
    font-weight: 750;
    letter-spacing: -0.02em;
    color: var(--text);
}

/* ==================================================== competition switcher */

.comp-switch {
    display: flex;
    gap: var(--gap-1);
    margin-bottom: var(--gap-4);
    padding: var(--gap-1);
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    overflow-x: auto;
    scrollbar-width: none;
    width: fit-content;
    max-width: 100%;
}

.comp-switch::-webkit-scrollbar {
    display: none;
}

.comp-chip {
    padding: 0.35rem 0.9rem;
    border-radius: var(--r-pill);
    font-size: 0.85rem;
    font-weight: 650;
    color: var(--text-dim);
    white-space: nowrap;
}

a.comp-chip:hover {
    background: var(--surface-3);
    color: var(--text);
}

.comp-chip[aria-current] {
    background: var(--brand);
    color: var(--on-brand);
}

/* ========================================================= local navigation */

.section-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin: 0 0 var(--gap-5);
}

.section-nav a,
.section-nav span {
    padding: 0.4rem 0.85rem;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    color: var(--text-dim);
    font-size: 0.85rem;
    font-weight: 650;
}

.section-nav a:hover {
    background: var(--surface-2);
    border-color: var(--line-2);
    color: var(--text);
}

.section-nav [aria-current] {
    background: var(--brand-wash);
    border-color: var(--brand-edge);
    color: var(--text);
}

/* The previous / index / next row an injected club-page block carries, where
   there is no room for the season's whole stage rail. */
.round-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: var(--gap-4);
}

.round-step {
    padding: 0.35rem 0.8rem;
    border-radius: var(--r-pill);
    background: var(--surface-2);
    border: 1px solid var(--line);
    color: var(--text-dim);
    font-size: 0.82rem;
    font-weight: 650;
}

.round-step[rel="next"] {
    margin-left: auto;
}

.round-step:hover {
    background: var(--surface-3);
    border-color: var(--line-2);
    color: var(--text);
}

.round-step.is-index {
    color: var(--accent);
}

/* The stage bar: every round of the season as a real link on one rail, with a
   step either side of it. One control rather than the two stacked rows this
   used to be - a wall of bordered chips above a separate previous/next row -
   because they answer the same question. The rail scrolls, and scores.js
   centres the current stage in it on load; the mask tells the eye there is
   more of the season in both directions. */
.stage-bar {
    display: flex;
    align-items: center;
    gap: var(--gap-2);
    width: fit-content;
    max-width: 100%;
    margin: 0 0 var(--gap-5);
    padding: 0.3rem;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
}

.stage-step {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    color: var(--text-dim);
    font-size: 0.95rem;
    line-height: 1;
}

.stage-step:hover {
    background: var(--surface-3);
    color: var(--text);
}

/* Present but inert at the ends of the season, so the rail keeps its width and
   the chips do not shuffle sideways between one round and the next. */
.stage-step.is-end {
    opacity: 0.25;
    pointer-events: none;
}

.stage-track {
    display: flex;
    gap: 0.2rem;
    flex: 0 1 auto;
    min-width: 0;
    /* Inner padding wider than the mask, so the first and last stage can scroll
       clear of the fade instead of being read through it. */
    padding-inline: 0.85rem;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    mask-image: linear-gradient(to right, transparent 0, #000 0.7rem, #000 calc(100% - 0.7rem), transparent 100%);
}

.stage-track::-webkit-scrollbar {
    display: none;
}

.stage-track a,
.stage-track span {
    flex: 0 0 auto;
    padding: 0.35rem 0.8rem;
    border-radius: var(--r-pill);
    color: var(--text-dim);
    font-size: 0.85rem;
    font-weight: 650;
    white-space: nowrap;
    scroll-snap-align: center;
}

.stage-track a:hover {
    background: var(--surface-3);
    color: var(--text);
}

.stage-track [aria-current] {
    background: var(--brand);
    color: var(--on-brand);
}

.season-picker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    margin: 0 0 var(--gap-3);
}

.season-picker-label {
    margin-right: var(--gap-1);
    color: var(--text-mute);
    font-size: 0.72rem;
    font-weight: 750;
    text-transform: uppercase;
    letter-spacing: 0.1em;
}

.season-picker a,
.season-picker [aria-current] {
    padding: 0.3rem 0.75rem;
    border-radius: var(--r-pill);
    color: var(--text-dim);
    font-size: 0.82rem;
    font-weight: 700;
}

.season-picker a {
    border: 1px solid var(--line);
}

.season-picker a:hover {
    background: var(--surface-2);
    border-color: var(--line-2);
    color: var(--text);
}

.season-picker [aria-current] {
    background: var(--brand-wash);
    box-shadow: inset 0 0 0 1px var(--brand-edge);
    color: var(--text);
}

/* ============================================================ score centre */

/* The same column the round pages use, so a card is the same card here and the
   container query resolves to the same club name in both places. */
.score-centre-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(400px, 100%), 1fr));
    gap: var(--gap-3);
}

.score-centre-groups {
    display: grid;
    gap: var(--gap-5);
}

.score-centre-context {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.45rem;
    margin: 0 0 var(--gap-2);
}

.score-centre-context h3 {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    margin: 0;
    font-size: 0.76rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-mute);
}

.score-centre-context a {
    color: var(--accent);
}

.score-centre-context h3 span::before {
    content: "·";
    margin-right: 0.45rem;
    color: var(--text-mute);
}

.score-centre-more {
    font-size: 0.82rem;
    font-weight: 650;
    white-space: nowrap;
}

.score-centre-day {
    margin: var(--gap-3) 0 0;
}

.score-centre-day:first-of-type {
    margin-top: 0;
}

/* The same labelled band the round pages use. */
.score-centre-day h4 {
    display: flex;
    align-items: center;
    gap: var(--gap-3);
    margin: 0 0 var(--gap-2);
    font-size: 0.7rem;
    font-weight: 750;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-mute);
}

.score-centre-day h4::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--line);
}

.panel-link {
    margin: var(--gap-3) 0 0;
    font-size: 0.9rem;
    font-weight: 650;
}

/* ==================================================================== byes */

.bye-grid {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap-2);
}

.bye-tile {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.3rem 0.7rem 0.3rem 0.35rem;
    border-radius: var(--r-pill);
    background: var(--surface-2);
    border: 1px solid var(--line);
    color: var(--text-dim);
    font-size: 0.82rem;
}

.bye-tile:hover {
    background: var(--surface-3);
    border-color: var(--line-2);
    color: var(--text);
}

/* ================================================================== ladder */

.ladder-scroll {
    overflow-x: auto;
    margin: 0 0 var(--gap-5);
}

table.ladder {
    width: 100%;
    min-width: 660px;
    border-collapse: collapse;
}

table.ladder th,
table.ladder td {
    padding: 0.6rem 0.4rem;
    text-align: center;
    font-size: 0.88rem;
    color: var(--text-dim);
}

table.ladder thead th {
    padding-bottom: 0.5rem;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-mute);
    border-bottom: 1px solid var(--line-2);
}

table.ladder tbody tr {
    border-bottom: 1px solid var(--line);
}

table.ladder tbody tr:hover {
    background: var(--surface-2);
}

/* The eighth line is the only structural fact a ladder carries beyond order,
   so it is the only row that gets a rule of its own. */
table.ladder tbody tr.is-finals-cut {
    border-bottom: 2px solid var(--line-2);
}

table.ladder tbody tr.is-live {
    background: var(--live-wash);
}

.ladder-position {
    width: 2.4rem;
    font-weight: 700;
    color: var(--text-mute);
}

tr.is-top-four .ladder-position {
    color: var(--brand);
}

table.ladder thead th.ladder-team-head {
    text-align: left;
    padding-left: var(--gap-2);
}

.ladder-team {
    display: flex;
    align-items: center;
    gap: var(--gap-2);
    text-align: left;
    font-weight: 650;
    color: var(--text);
    white-space: nowrap;
}

.ladder-team a {
    color: inherit;
}

.ladder-team a:hover {
    color: var(--brand-bright);
}

.ladder-points {
    font-weight: 800;
    color: var(--text);
}

.ladder-move {
    width: 2.6rem;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--text-mute);
}

.ladder-move.is-up { color: var(--brand); }
.ladder-move.is-down { color: var(--loss); }

.ladder-form {
    padding-left: var(--gap-3) !important;
}

.ladder-team .live-dot {
    margin-left: 0.3rem;
}

/* ============================================================ form and rank */

.form-guide {
    display: inline-flex;
    gap: 2px;
    vertical-align: middle;
}

.form-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 17px;
    height: 17px;
    border-radius: 4px;
    font-size: 0.62rem;
    font-weight: 800;
    color: var(--on-brand);
}

.form-pill.is-w { background: var(--brand); }
.form-pill.is-l { background: var(--loss); color: #1A0505; }
.form-pill.is-d { background: var(--warn); color: #17110A; }

.form-strip {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap-2);
}

.form-result {
    display: grid;
    justify-items: center;
    gap: var(--gap-1);
    flex: 1 1 92px;
    min-width: 92px;
    max-width: 150px;
    padding: var(--gap-3) var(--gap-2);
    border-radius: var(--r);
    background: var(--surface-2);
    border: 1px solid var(--line);
}

.form-round {
    font-size: 0.66rem;
    font-weight: 650;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--text-mute);
    white-space: nowrap;
}

.form-score {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--text);
}

.form-letter {
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: 0.06em;
}

.form-result.is-w .form-letter { color: var(--brand); }
.form-result.is-l .form-letter { color: var(--loss); }
.form-result.is-d .form-letter { color: var(--warn); }

.standing-figures {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: var(--gap-2);
}

.standing-figures > div {
    display: grid;
    gap: 0.1rem;
    padding: var(--gap-3) var(--gap-2);
    border-radius: var(--r);
    background: var(--surface-2);
    border: 1px solid var(--line);
    text-align: center;
}

.standing-figures .standing-rank {
    background: var(--brand-wash);
    border-color: var(--brand-edge);
}

.standing-value {
    font-size: 1.35rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--text);
}

.standing-rank .standing-value {
    color: var(--brand-bright);
}

.standing-label {
    font-size: 0.66rem;
    font-weight: 650;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-mute);
}

.standing-form {
    display: flex;
    align-items: center;
    gap: var(--gap-2);
    margin-top: var(--gap-4);
    color: var(--text-dim);
}

.next-line,
.live-lede {
    color: var(--text-dim);
}

/* =================================================================== tabs */

.match-tabs {
    margin-bottom: var(--gap-5);
}

.tab-radio {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.tab-strip {
    display: flex;
    gap: 0.15rem;
    margin-bottom: var(--gap-5);
    border-bottom: 1px solid var(--line);
}

.tab-strip label {
    padding: 0.6rem 1.1rem;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    font-size: 0.92rem;
    font-weight: 650;
    color: var(--text-mute);
    cursor: pointer;
    user-select: none;
}

.tab-strip label:hover {
    color: var(--text-dim);
}

/* The checked segment marks its own label and hides every panel but its own,
   by position rather than by id, so the match page and the ladder share one set
   of rules. A fourth segment anywhere needs a fourth line in each block. */
.tab-radio:nth-of-type(1):checked ~ .tab-strip label:nth-child(1),
.tab-radio:nth-of-type(2):checked ~ .tab-strip label:nth-child(2),
.tab-radio:nth-of-type(3):checked ~ .tab-strip label:nth-child(3) {
    color: var(--text);
    border-bottom-color: var(--brand);
}

.tab-radio:nth-of-type(1):focus-visible ~ .tab-strip label:nth-child(1),
.tab-radio:nth-of-type(2):focus-visible ~ .tab-strip label:nth-child(2),
.tab-radio:nth-of-type(3):focus-visible ~ .tab-strip label:nth-child(3) {
    outline: 2px solid var(--brand);
    outline-offset: -2px;
}

.tab-radio:nth-of-type(1):checked ~ .tab-panels > .tab-panel:not(:nth-child(1)),
.tab-radio:nth-of-type(2):checked ~ .tab-panels > .tab-panel:not(:nth-child(2)),
.tab-radio:nth-of-type(3):checked ~ .tab-panels > .tab-panel:not(:nth-child(3)) {
    display: none;
}

/* The ladder's three readings sit inside one panel, so its strip needs less air
   under it than the match page's, which separates whole panels. */
.ladder-tabs .tab-strip {
    margin-bottom: var(--gap-4);
}

.tab-panel > .ladder-scroll:last-child {
    margin-bottom: 0;
}

.tab-note {
    margin: var(--gap-3) 0 0;
    font-size: 0.82rem;
    color: var(--text-mute);
}

/* ============================================================== score worm */

.worm-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap-4);
    margin-bottom: var(--gap-3);
    font-size: 0.82rem;
    color: var(--text-dim);
}

.worm-key {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.worm-swatch {
    width: 10px;
    height: 10px;
    border-radius: 3px;
}

.worm-frame {
    display: flex;
    gap: var(--gap-2);
}

.worm-axis {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    height: 200px;
    min-width: 1.75rem;
    font-size: 0.68rem;
    color: var(--text-mute);
    text-align: right;
}

.worm-plot {
    position: relative;
    flex: 1;
    min-width: 0;
}

/* Stretched to the page width, so nothing inside it may be text: the strokes
   opt out of scaling and the labels live in HTML alongside. */
/* Sunk into the panel rather than raised out of it: on a lit ground a chart
   reads as a well, and the team fills need a dark field to keep their hue. */
.worm-chart {
    display: block;
    width: 100%;
    height: 200px;
    border-radius: var(--r-sm);
    background: rgba(0, 0, 0, 0.22);
}

.worm-line {
    stroke: var(--text);
    stroke-width: 2.5;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

.worm-zero {
    stroke: var(--line-2);
    stroke-width: 1;
    stroke-dasharray: 5 5;
    vector-effect: non-scaling-stroke;
}

.worm-half {
    stroke: var(--line-2);
    stroke-width: 1;
    stroke-dasharray: 3 3;
    vector-effect: non-scaling-stroke;
}

.worm-ticks {
    position: relative;
    height: 1.1rem;
    margin-top: var(--gap-1);
}

.worm-ticks span {
    position: absolute;
    transform: translateX(-50%);
    font-size: 0.68rem;
    color: var(--text-mute);
}

.worm-ticks span:first-child {
    transform: none;
}

/* =========================================================== scoring events */

.events {
    list-style: none;
    border: 1px solid var(--line);
    border-radius: var(--r);
    overflow: hidden;
}

.event {
    display: grid;
    grid-template-columns: 3rem 22px 1fr auto;
    align-items: center;
    gap: var(--gap-3);
    padding: 0.6rem 0.85rem;
    background: var(--surface-2);
    border-left: 3px solid var(--line-2);
}

.event + .event {
    border-top: 1px solid var(--line);
}

.event-minute {
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--text-mute);
}

.event-badge {
    display: flex;
}

.event-detail {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.event-player {
    font-size: 0.92rem;
    font-weight: 650;
    color: var(--text);
}

.event-type {
    font-size: 0.75rem;
    color: var(--text-mute);
}

.event-score {
    font-size: 0.92rem;
    color: var(--text-mute);
    white-space: nowrap;
}

.event-score b {
    color: var(--text);
}

/* ================================================== tables inside a match */

.player-blocks,
.lineup-blocks {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--gap-5);
}

.player-block h3,
.lineup-block h3 {
    display: flex;
    align-items: center;
    gap: var(--gap-2);
    margin-bottom: var(--gap-3);
    font-size: 0.92rem;
    color: var(--text);
}

.period-table,
.player-table {
    width: 100%;
    border-collapse: collapse;
}

.period-table th,
.period-table td,
.player-table th,
.player-table td {
    padding: 0.55rem 0.4rem;
    text-align: center;
    font-size: 0.88rem;
    color: var(--text-dim);
}

.period-table thead th,
.player-table thead th {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-mute);
    border-bottom: 1px solid var(--line-2);
}

.period-table tbody tr,
.player-table tbody tr {
    border-bottom: 1px solid var(--line);
}

.period-team,
.player-name {
    display: flex;
    align-items: center;
    gap: var(--gap-2);
    text-align: left;
    font-weight: 650;
    color: var(--text);
    white-space: nowrap;
}

.player-name {
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
}

/* ============================================================== team stats */

.team-stats-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--gap-4);
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--text);
}

.team-stats-head > span {
    display: inline-flex;
    align-items: center;
    gap: var(--gap-2);
}

.team-stat-list {
    list-style: none;
    display: grid;
    gap: var(--gap-4);
}

.team-stat {
    display: grid;
    grid-template-columns: 3rem 1fr 3rem;
    align-items: center;
    gap: var(--gap-2);
}

.team-stat-value {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text);
}

.team-stat-value:first-child { text-align: left; }
.team-stat > .team-stat-value:nth-child(3) { text-align: right; }

.team-stat-label {
    text-align: center;
    font-size: 0.78rem;
    color: var(--text-mute);
}

/* A hairline of the track between the two sides, so the split is legible even
   where both clubs draw in the same colour. The gap is a flex gap and each side
   is only in the markup when it has something to show, so a nil count takes no
   width and leaves no stub. */
.team-stat-bar {
    grid-column: 1 / -1;
    display: flex;
    gap: 3px;
    height: 5px;
    border-radius: 3px;
    overflow: hidden;
    background: var(--line);
}

.team-stat-bar span {
    display: block;
    height: 100%;
    border-radius: 3px;
}

/* ================================================================= lineups */

.lineup-block h4 {
    margin: var(--gap-4) 0 var(--gap-2);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-mute);
}

.lineup-list {
    list-style: none;
}

.lineup-list li {
    display: grid;
    grid-template-columns: 1.75rem 1fr auto;
    align-items: baseline;
    gap: var(--gap-2);
    padding: 0.3rem 0;
    font-size: 0.88rem;
    color: var(--text-dim);
    border-bottom: 1px solid var(--line);
}

.lineup-list li:last-child {
    border-bottom: 0;
}

.shirt {
    font-size: 0.76rem;
    font-weight: 700;
    color: var(--text-mute);
}

.lineup-name {
    color: var(--text);
}

/* =============================================================== fact grid */

.fact-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--gap-2);
}

.fact-grid > div {
    padding: var(--gap-3) var(--gap-4);
    border-radius: var(--r);
    background: var(--surface-2);
    border: 1px solid var(--line);
}

.fact-grid dt {
    margin-bottom: 0.15rem;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-mute);
}

.fact-grid dd {
    font-size: 0.92rem;
    color: var(--text);
}

/* Match detail follows the app's InfoRow treatment: one fact per line, with
   the label above its value and a divider separating adjacent rows. Keep the
   multi-column fact grid for season summaries and ladder notes. */
.match-info-list > div {
    padding: var(--gap-2) 0;
}

.match-info-list > div + div {
    border-top: 1px solid var(--line);
}

.match-info-list dt {
    margin-bottom: 0.15rem;
    font-size: 0.76rem;
    font-weight: 650;
    color: var(--text-mute);
}

.match-info-list dd {
    font-size: 0.92rem;
    color: var(--text);
}

/* ========================================================= injected blocks */

.live-heading {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--gap-3);
    margin-bottom: var(--gap-4);
}

.live-heading h2 {
    margin: 0;
}

.live-flag {
    display: inline-block;
    margin-left: var(--gap-2);
    padding: 0.1rem 0.5rem;
    border-radius: var(--r-sm);
    background: var(--live-wash);
    color: var(--live);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    vertical-align: middle;
}

.live-more {
    font-size: 0.85rem;
    font-weight: 650;
    white-space: nowrap;
}

.team-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap-3);
    margin-bottom: var(--gap-4);
}

/* ============================================================= the app row */

.app-note {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-4) var(--gap-5);
    margin: var(--gap-6) 0 var(--gap-5);
    padding: var(--gap-4) var(--gap-5);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
}

.app-note img {
    width: 44px;
    height: 44px;
    border-radius: 10px;
    flex-shrink: 0;
}

.app-note-lead {
    display: flex;
    align-items: center;
    gap: var(--gap-4);
    flex: 1 1 320px;
    min-width: 0;
}

.app-note-copy {
    min-width: 0;
}

.app-note-copy h2 {
    margin-bottom: 0.15rem;
    font-size: 0.95rem;
}

.app-note-copy p {
    margin: 0;
    font-size: 0.85rem;
    color: var(--text-mute);
}

.app-note .store-badges {
    flex: 0 0 auto;
    gap: var(--gap-3);
}

/* Apple's badge fills its image. Google's bakes a transparent margin into all
   four edges, so at a matched image height it draws a third smaller than
   Apple's. Each anchor is the size of the visible badge and crops what the file
   puts around it, which is what keeps the two the same height and the gap
   between them even. */
.app-note .store-badge {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 40px;
    overflow: hidden;
}

.app-note .store-badge img {
    display: block;
    flex-shrink: 0;
    height: 40px;
    width: auto;
    margin: 0;
    border-radius: 0;
}

.app-note .google-play-badge {
    width: 134px;
}

.app-note .google-play-badge img {
    height: 60px;
    max-width: none;
}

/* ========================================================== the match page */

/* Generated score pages use the site's standard measure. This keeps their
   parent-return link aligned with the content whether the reader is at the
   competition, season, round or match level. */
main > .breadcrumbs,
main > article.wide {
    max-width: var(--page);
    margin-inline: auto;
}

article.wide.match-page > .score-board.is-single {
    margin-inline: auto;
}

article.wide.team-page .score-board.is-single {
    max-width: none;
}

/* ================================================================ utility */

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ============================================================= responsive */

@media (max-width: 640px) {
    .panel {
        padding: var(--gap-4);
        border-radius: var(--r);
    }

    .panel.is-plain {
        padding: 0;
    }

    .match-card {
        padding: 0.75rem 0.85rem;
    }

    .match-team { font-size: 1.02rem; }
    .score-value { font-size: 2.15rem; }

    .match-card .team-badge {
        width: 32px;
        height: 32px;
    }

    .match-hero {
        padding: var(--gap-4) var(--gap-3) var(--gap-4);
    }

    /* A separator that ends a wrapped line is punctuation pointing at nothing;
       the gap does the separating once the line breaks. */
    .match-hero-meta {
        gap: 0.1rem 0.7rem;
    }

    .match-hero-dot {
        display: none;
    }

    .match-card.is-hero {
        padding: 0;
        column-gap: var(--gap-3);
    }

    .is-hero .match-team { font-size: 1.1rem; }
    .is-hero .score-value { font-size: 2.6rem; }

    .match-card.is-hero .team-badge {
        width: 42px;
        height: 42px;
    }

    .event {
        grid-template-columns: 2.5rem 22px 1fr auto;
        gap: var(--gap-2);
    }

    .worm-chart,
    .worm-axis { height: 160px; }

    .tab-strip label {
        flex: 1;
        text-align: center;
        padding: 0.6rem 0.4rem;
        font-size: 0.88rem;
    }
}

@media (max-width: 430px) {
    .match-card .team-badge {
        width: 28px;
        height: 28px;
    }
}
