/* Cricket Scores — component layer.
 *
 * Everything the views actually render: controls, cards, score rows, tables,
 * forms, states and the admin tables. Colours come from tokens.css only, and
 * text drawn on a fill uses the matching `--on-*` / `*-text` token so every pair
 * is one of the measured, passing combinations.
 */

/* ------------------------------------------------------------- 0. icons */

/* The sprite is geometry definitions only; a `<symbol>` never renders on its own. */
.icon-sprite {
  display: none;
}

/*
 * One drawing rule for the whole set. `fill`, `stroke`, `stroke-width` and the
 * line joins are inherited into the `<use>` shadow tree, so a symbol carries
 * geometry alone and `currentColor` follows the text the icon sits in. A shape
 * that needs to be filled (the dots on `info` and `alert`) says so on itself,
 * because a presentation attribute beats an inherited value, and `pause` sets its
 * own width for the two strokes to read as a pause rather than a pair of hairlines.
 */
.icon {
  flex: none;
  width: 1.1em;
  height: 1.1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: -0.16em;
}

/* Filled variants: an outline glyph turns solid without a second symbol, so a
 * scripted state change (`app.js` toggles the button class) needs no markup swap. */
.icon--filled,
.star__button--on .icon,
.follow__button--on .icon {
  fill: currentColor;
}

.icon--sm {
  width: 0.95em;
  height: 0.95em;
}

.icon--md {
  width: 1.3em;
  height: 1.3em;
}

.icon--lg {
  width: 1.7em;
  height: 1.7em;
}

/* Large icons carry a lighter stroke, or they read heavier than the text beside them. */
.icon--xl {
  width: 2.4em;
  height: 2.4em;
  stroke-width: 1.5;
}

/* An icon and its label on one baseline, for the spans that carry both. */
.with-icon {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}

/*
 * The few places that size a glyph in px rather than em, because the furniture
 * around it has a fixed height and must not grow with the text scale. These have
 * to live after `.icon` — with equal specificity the later rule wins, so a size
 * declared in base.css for the shell's own marks would be overridden here.
 */
.brand__mark {
  width: 30px;
  height: 30px;
}

.star__button .icon {
  width: 17px;
  height: 17px;
}

.datebar__arrow .icon,
.competition__chevron .icon,
.theme-toggle .icon {
  width: 18px;
  height: 18px;
}

.datebar__pin .icon {
  width: 16px;
  height: 16px;
}

/* ------------------------------------------------------------ 1. controls */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--control-h);
  padding: 0 var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--r-full);
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-size: var(--fs-2);
  font-weight: var(--fw-bold);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}

.button:hover {
  background: var(--accent-hover);
  color: var(--on-accent-hover);
}

.button--secondary {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border-strong);
}

.button--secondary:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.button--quiet {
  background: transparent;
  color: var(--text);
  border-color: var(--border-strong);
  font-weight: var(--fw-medium);
}

.button--quiet:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.button--danger {
  background: transparent;
  color: var(--danger-text);
  border-color: var(--danger-border);
}

.button--danger:hover {
  background: var(--danger-soft);
  color: var(--danger-text);
}

.button:disabled,
.button[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}

.chip {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-h-sm);
  padding: 0 var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  background: var(--surface);
  color: var(--text-muted);
  font-size: var(--fs-1);
  font-weight: var(--fw-medium);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}

.chip:hover {
  border-color: var(--border-strong);
  color: var(--text);
}

.chip--on,
.chip[aria-current="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  font-weight: var(--fw-bold);
}

.segmented {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  background: var(--surface-sunken);
}

.segmented__option {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font: inherit;
  font-size: var(--fs-2);
  font-weight: var(--fw-medium);
  min-height: var(--control-h-sm);
  padding: 0 var(--sp-4);
  border: 0;
  border-radius: var(--r-full);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.segmented__option:hover {
  color: var(--text);
  background: var(--surface-hover);
}

.segmented__option[aria-pressed="true"] {
  background: var(--accent);
  color: var(--on-accent);
  font-weight: var(--fw-bold);
}

/* ------------------------------------------------- 2. form controls */

select,
input[type="number"],
input[type="text"],
input[type="email"],
input[type="search"] {
  font: inherit;
  font-size: var(--fs-2);
  min-height: var(--control-h);
  padding: 0 var(--sp-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text);
  /* Native checkbox/radio/select accents follow the theme instead of staying
     browser blue. */
  accent-color: var(--accent);
}

select:focus-visible,
input:focus-visible {
  border-color: var(--focus);
}

input[type="checkbox"] {
  width: 1.05rem;
  height: 1.05rem;
  margin: 0;
  accent-color: var(--accent);
}

.form {
  display: grid;
  gap: var(--sp-5);
  max-width: 44rem;
}

.form fieldset {
  display: grid;
  gap: var(--sp-2);
  min-width: 0;
  margin: 0;
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
}

.form legend {
  padding: 0 var(--sp-2);
  background: var(--surface);
  font-size: var(--fs-1);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--text-muted);
}

.form__row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--sp-4);
}

.form__row label,
.form__field {
  display: grid;
  gap: var(--sp-1);
  font-size: var(--fs-1);
  color: var(--text-muted);
}

.form__field input {
  max-width: 12rem;
}

.form--inline,
.filters__form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin: var(--sp-3) 0;
  font-size: var(--fs-2);
}

.checkbox {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-1) 0;
  font-size: var(--fs-2);
  color: var(--text);
}

.push-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-2);
}

.filters {
  display: grid;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}

.filters__row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/* --------------------------------------------------------- 3. cards & badges */

.card {
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-1);
}

.match-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  overflow: hidden;
}

/*
 * One 3px state bar for cards, match rows and feed items: drawn here on
 * `::before`, so a state colour is one `background` token rather than a border in
 * one family and a pseudo-element in another. `tests/theme.test.ts` keeps all
 * three families on this rule and every tone on it at 3:1 or better.
 */
.match-card::before,
.match-row::before,
.feed__item::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--border-strong);
}

.match-card--live::before {
  background: var(--live);
}

.match-card--break::before {
  background: var(--break);
}

.match-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-3);
}

.match-card__competition {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.match-card__series {
  font-size: var(--fs-1);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  text-decoration: none;
  color: var(--text-muted);
}

.match-card__series:hover {
  color: var(--text);
}

.match-card__label {
  font-size: var(--fs-1);
  color: var(--text-subtle);
}

.match-card__title {
  margin: 0;
  font-size: var(--fs-4);
  letter-spacing: -0.01em;
}

.match-card__title a {
  text-decoration: none;
}

.match-card__title a:hover {
  text-decoration: underline;
}

.match-card__outcome {
  margin: 0;
  font-size: var(--fs-2);
}

.scorelines {
  display: grid;
  gap: 0;
}

.scoreline {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-2) 0;
  border-top: 1px solid var(--border);
}

.scoreline:first-child {
  border-top: 0;
}

.scoreline--batting .scoreline__name {
  font-weight: var(--fw-bold);
}

.scoreline__team {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  min-width: 0;
}

.scoreline__name {
  font-size: var(--fs-4);
}

.scoreline__flag {
  font-size: var(--fs-1);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent-text);
}

.scoreline__score {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
}

.score {
  font-size: var(--fs-6);
  font-weight: var(--fw-bold);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.overs {
  font-size: var(--fs-1);
}

.match-card__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
}

.match-card__meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  font-size: var(--fs-2);
  color: var(--text-muted);
}

.match-card__updated {
  font-size: var(--fs-1);
  font-variant-numeric: tabular-nums;
}

.match-card__coverage {
  margin-top: var(--sp-2);
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-tight);
  flex: none;
  min-height: var(--sp-6);
  padding: 0 var(--sp-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-full);
  background: var(--surface);
  font-size: var(--fs-1);
  font-weight: var(--fw-medium);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  white-space: nowrap;
  color: var(--text-muted);
}

.badge__glyph {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: currentColor;
}

.badge--live {
  color: var(--accent-text);
  border-color: var(--accent-border);
  background: var(--accent-soft);
}

/* Interrupted play differs by shape as well as hue, so the state survives
   greyscale and colour-blind viewing. */
.badge--break {
  color: var(--warn-text);
  border-color: var(--warn-border);
  background: var(--warn-soft);
}

.badge--break .badge__glyph {
  border-radius: 1px;
}

.badge--done .badge__glyph {
  background: transparent;
  border: 2px solid currentColor;
}

.freshness {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0;
  font-size: var(--fs-2);
  color: var(--text-muted);
}

.freshness--stale {
  color: var(--warn-text);
}

.freshness__text {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}

.freshness--stale .freshness__text {
  font-weight: var(--fw-bold);
}

.freshness__hint {
  font-size: var(--fs-1);
}

.coverage {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  font-size: var(--fs-1);
  color: var(--text-muted);
}

.coverage__cadence,
.coverage__alerts {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-tight);
}

.coverage__pill {
  padding: 1px var(--sp-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-full);
  color: var(--text);
  font-weight: var(--fw-medium);
  white-space: nowrap;
}

.coverage__pill--priority {
  border-color: var(--accent-border);
  background: var(--accent-soft);
  color: var(--accent-text);
}

.coverage__pill--uncovered {
  border-style: dashed;
  color: var(--text-subtle);
}

.follow {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
}

.follow__button {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font: inherit;
  font-size: var(--fs-2);
  font-weight: var(--fw-bold);
  min-height: var(--control-h);
  padding: 0 var(--sp-5);
  border: 1px solid var(--accent);
  border-radius: var(--r-full);
  background: transparent;
  color: var(--accent-text);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.follow__button:hover {
  background: var(--accent-soft);
}

.follow__button--on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.follow__button--on:hover {
  background: var(--accent-hover);
  color: var(--on-accent-hover);
}

.follow__hint {
  max-width: 30ch;
  font-size: var(--fs-1);
}

/* Both push glyphs are in the markup; the same attribute the script flips picks
 * one, so the icon and the label can never disagree. */
[data-push-toggle] .push-icon--off {
  display: none;
}

[data-push-toggle][data-push-enabled="true"] .push-icon--off {
  display: block;
}

[data-push-toggle][data-push-enabled="true"] .push-icon--available {
  display: none;
}

/* ------------------------------------------------------------ 4. match page */

.match-header {
  position: sticky;
  top: var(--topbar-h);
  z-index: 10;
  display: grid;
  gap: var(--sp-3);
  margin-bottom: var(--sp-6);
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-2);
}

/* Pinned state, toggled by app.js once the card is stuck under the top bar.
   Collapsed to the live score so it does not bury the rail underneath. */
.match-header.is-stuck {
  gap: var(--sp-1);
  padding: var(--sp-2) var(--sp-4);
  box-shadow: var(--shadow-3);
}

.match-header.is-stuck .match-header__top,
.match-header.is-stuck .match-header__meta,
.match-header.is-stuck .freshness,
.match-header.is-stuck .coverage,
.match-header.is-stuck .match-header__status {
  display: none;
}

.match-header.is-stuck .match-header__team {
  padding: 0;
  border-top: 0;
}

/* The pinned card shows the score only: keeping the overs line doubled its
   height and let it spill past the collapsed box. */
.match-header.is-stuck .match-header__overs {
  display: none;
}

.match-header.is-stuck .match-header__name,
.match-header.is-stuck .match-header__score {
  font-size: var(--fs-4);
}

.match-header__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}

.match-header__back {
  font-size: var(--fs-1);
  font-weight: var(--fw-medium);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  text-decoration: none;
  color: var(--text-muted);
}

.match-header__back:hover {
  color: var(--text);
}

/* One team per row at every width. Two columns put the left team's score
   directly beside the right team's name, which read as the wrong score. */
.match-header__scores {
  display: grid;
  gap: 0;
}

.match-header__team {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "name score" "name overs";
  align-items: baseline;
  column-gap: var(--sp-4);
  padding: var(--sp-2) 0;
  border-top: 1px solid var(--border);
}

.match-header__team:first-child {
  border-top: 0;
  padding-top: 0;
}

.match-header__name {
  grid-area: name;
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  min-width: 0;
  font-size: var(--fs-4);
  font-weight: var(--fw-medium);
}

/* Dotted leader between the team and its score. On a full-width card the two
   are otherwise a screen apart and stop reading as one line. */
.match-header__name::after {
  content: "";
  flex: 1 1 var(--sp-6);
  min-width: var(--sp-4);
  align-self: center;
  border-bottom: 1px dotted var(--border-strong);
}

.match-header__score {
  grid-area: score;
  font-size: var(--fs-6);
  font-weight: var(--fw-bold);
  letter-spacing: -0.02em;
  text-align: right;
}

.match-header__overs {
  grid-area: overs;
  font-size: var(--fs-1);
  text-align: right;
}

.match-header__status {
  margin: 0;
  font-size: var(--fs-2);
  font-weight: var(--fw-bold);
}

.match-header__meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: var(--fs-1);
  color: var(--text-muted);
}

.match-body {
  display: grid;
  gap: var(--sp-6);
}

.match-tabs {
  display: flex;
  gap: var(--sp-1);
  margin-bottom: var(--sp-4);
  border-bottom: 1px solid var(--border);
}

.match-tabs__tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-2);
  font-weight: var(--fw-medium);
  text-decoration: none;
  color: var(--text-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.match-tabs__tab:hover {
  color: var(--text);
  background: var(--surface-hover);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
}

.match-tabs__tab--on {
  color: var(--text);
  font-weight: var(--fw-bold);
  border-bottom-color: var(--accent);
}

.innings-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}

.scorecard__team {
  margin: var(--sp-4) 0 var(--sp-2);
}

/* --------------------------------------------------------------- 5. tables */

.table-wrap {
  margin-bottom: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow-x: auto;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-2);
}

.table caption {
  padding: var(--sp-3) var(--sp-4);
  text-align: left;
  font-size: var(--fs-1);
  color: var(--text-muted);
}

.table th,
.table td {
  padding: var(--sp-3) var(--sp-4);
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}

.table thead th {
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--border-strong);
  font-size: var(--fs-1);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-subtle);
}

.table tbody tr:last-child td {
  border-bottom: 0;
}

.table tbody tr:hover td {
  background: var(--surface-hover);
}

.table tbody tr.row--current td {
  background: var(--accent-soft);
}

.table .num {
  /* Numeric columns shrink to their content so a count never floats a screen
     away from the label it belongs to. */
  width: 1%;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.table--select select {
  min-height: var(--control-h-sm);
}

.table--card td {
  vertical-align: baseline;
}

/* ------------------------------------------------------------------ 6. facts */

.facts {
  display: grid;
  gap: 0;
  margin: 0 0 var(--sp-4);
  border-top: 1px solid var(--border);
}

.facts__row {
  display: grid;
  grid-template-columns: minmax(8rem, 12rem) minmax(0, 1fr);
  gap: var(--sp-4);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border);
}

.facts dt {
  font-size: var(--fs-2);
  color: var(--text-muted);
}

.facts dd {
  margin: 0;
  font-size: var(--fs-2);
  font-weight: var(--fw-medium);
}

/* ------------------------------------------------------------------- 7. feed */

.feed {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-2);
}

.feed__item {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0 var(--sp-4);
  /* The 2px keeps the text at the 19px inset the old 3px left border gave it now
     that the bar is an overlay inside a 1px border, as it is on cards. */
  padding: var(--sp-3) var(--sp-4) var(--sp-3) calc(var(--sp-4) + 2px);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  overflow: hidden;
  font-size: var(--fs-2);
}

.feed__item--wicket::before {
  background: var(--accent);
}

/* Milestones take the accent's on-surface form, not its border tint: the tint is
   under the 3:1 bar threshold in both appearances (tests/theme.test.ts). */
.feed__item--batter_fifty::before,
.feed__item--batter_hundred::before {
  background: var(--accent-text);
}

.feed__item--break_started::before {
  background: var(--break);
}

/* The kind glyph sits inside the title, which keeps the item's two-track grid
 * (and the stamp's pinned trailing column) exactly as `tests/theme.test.ts` reads it. */
.feed__title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: var(--fw-bold);
}

.feed__detail {
  grid-column: 1 / -1;
  font-size: var(--fs-1);
}

/*
 * Placed explicitly, because auto-placement cannot reach the trailing track: the
 * detail is declared `1 / -1` and precedes the stamp in the markup, which would
 * strand the stamp in a third row with the `auto` track 0px wide.
 * `tests/theme.test.ts` pins both declarations.
 */
.feed__time {
  grid-row: 1;
  grid-column: 2;
  font-size: var(--fs-1);
  font-variant-numeric: tabular-nums;
}

.disclosure {
  margin-bottom: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
}

.disclosure summary {
  cursor: pointer;
  font-size: var(--fs-2);
  font-weight: var(--fw-bold);
}

.disclosure[open] summary {
  margin-bottom: var(--sp-2);
}

.link-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-2);
  font-size: var(--fs-2);
}

/* ------------------------------------------------------------ 8. empty states */

.empty {
  margin-bottom: var(--sp-5);
  padding: var(--sp-6);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-1);
}

.empty__icon {
  display: block;
  margin-bottom: var(--sp-3);
  color: var(--text-subtle);
}

.empty--error .empty__icon {
  color: var(--danger-text);
}

.empty h2 {
  font-size: var(--fs-4);
}

.empty p:last-child {
  margin-bottom: 0;
}

.empty--error {
  border-color: var(--danger-border);
  background: var(--danger-soft);
}

.empty--error h2 {
  color: var(--danger-text);
}

.expectation {
  margin: var(--sp-2) 0 0;
  padding-left: var(--sp-3);
  border-left: 3px solid var(--border-strong);
  font-size: var(--fs-1);
  color: var(--text-muted);
}

.expectation--priority {
  border-left-color: var(--accent);
}

.expectation--uncovered {
  border-left-color: var(--danger);
}

.followed {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.followed__alerts {
  margin-top: var(--sp-1);
  padding: var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-sunken);
}

.followed__alerts h3 {
  font-size: var(--fs-2);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-subtle);
}

.followed__alerts p {
  font-size: var(--fs-1);
  margin-bottom: var(--sp-1);
}

/* ------------------------------------------------------------------ 9. admin */

.meter {
  height: var(--sp-2);
  margin: var(--sp-3) 0;
  border-radius: var(--r-full);
  background: var(--surface-sunken);
  overflow: hidden;
}

.meter__fill {
  height: 100%;
  border-radius: var(--r-full);
  background: var(--accent);
}

.meter__fill--econ {
  /* `--break` rather than `--warn`: the fill sits on the sunken track, where the
     lighter amber measures 2.46:1. */
  background: var(--break);
}

.meter__fill--halted {
  background: var(--danger);
}

.log {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-2);
  font-size: var(--fs-2);
}

.log__item {
  display: grid;
  grid-template-columns: 5.5rem 11rem 7rem minmax(0, 1fr);
  gap: var(--sp-4);
  align-items: baseline;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
}

.log__item--not_configured {
  border-left: 3px solid var(--danger);
}

.log__item--ok {
  border-left: 3px solid var(--accent);
}

.log__endpoint,
.log__kind,
.log__time {
  font-size: var(--fs-1);
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.log__message {
  font-size: var(--fs-1);
}

/* -------------------------------------------------- 10. scores directory */

.scores {
  display: grid;
  gap: var(--sp-6);
}

.scores__side {
  display: grid;
  gap: var(--sp-5);
  align-content: start;
  /* Grid items default to min-width:auto, which lets the search row push past
     its fixed rail column and overlap the match list. */
  min-width: 0;
}

.scores__side > *,
.scores__main {
  min-width: 0;
}

.scores__live-summary {
  margin: calc(-1 * var(--sp-3)) 0 var(--sp-2);
  font-size: var(--fs-2);
  color: var(--text-muted);
}

.scores__live-summary strong {
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
}

.scores__note {
  max-width: 68ch;
  margin-top: var(--sp-6);
  font-size: var(--fs-1);
  color: var(--text-muted);
}

.side-search {
  display: flex;
  gap: var(--sp-2);
  margin: 0;
}

.side-search input[type="search"] {
  flex: 1;
  min-width: 0;
  padding-inline: var(--sp-4);
  border-radius: var(--r-full);
}

.side-search__go {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font: inherit;
  font-size: var(--fs-2);
  font-weight: var(--fw-medium);
  min-height: var(--control-h);
  padding: 0 var(--sp-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-full);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}

.side-search__go:hover {
  background: var(--surface-hover);
}

.side-nav {
  display: grid;
  gap: var(--sp-1);
}

.side-nav__title {
  display: flex;
  align-items: center;
  /* The disclosure chevron is pushed right by its own `margin-left: auto`, because
     the icon and the label now sit together at the start of the row. */
  justify-content: flex-start;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-1);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--text-subtle);
  cursor: pointer;
  list-style: none;
}

.side-nav__title::-webkit-details-marker {
  display: none;
}

.side-nav__title::after {
  content: "›";
  margin-left: auto;
  font-size: var(--fs-4);
  line-height: 1;
  transform: rotate(90deg);
  transition: transform var(--dur-fast) var(--ease);
}

.side-nav:not([open]) > .side-nav__title::after {
  transform: rotate(0deg);
}

.side-nav__title:hover {
  color: var(--text);
  background: var(--surface-hover);
}

.side-nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
  min-width: 0;
}

.side-nav__list li {
  min-width: 0;
}

.side-nav__link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  min-width: 0;
  padding: 0.45rem var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-2);
  text-decoration: none;
  color: var(--text-muted);
}

.side-nav__link:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.side-nav__link--on {
  background: var(--accent-soft);
  color: var(--text);
  font-weight: var(--fw-bold);
  box-shadow: inset 2px 0 0 var(--accent);
}

.side-nav__name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.side-nav__count {
  flex: none;
  font-size: var(--fs-1);
  font-variant-numeric: tabular-nums;
}

.side-nav__hint {
  margin: 0;
  padding-inline: var(--sp-3);
  font-size: var(--fs-1);
}

/* ---------------------------------------------------------------- date bar */

.datebar {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin-bottom: var(--sp-5);
  padding: var(--sp-1) var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  background: var(--surface);
  box-shadow: var(--shadow-1);
}

.datebar__live {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-tight);
  flex: none;
  min-height: var(--control-h-sm);
  padding: 0 var(--sp-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-full);
  font-size: var(--fs-1);
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-decoration: none;
  color: var(--text-muted);
}

.datebar__live:hover {
  color: var(--text);
  border-color: var(--text-subtle);
}

.datebar__live--on {
  color: var(--accent-text);
  border-color: var(--accent-border);
  background: var(--accent-soft);
}

.datebar__dot {
  width: var(--sp-2);
  height: var(--sp-2);
  border-radius: 50%;
  background: currentColor;
}

.datebar__live--on .datebar__dot {
  animation: live-pulse 1.6s ease-in-out infinite;
}

.datebar__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--control-h-sm);
  height: var(--control-h-sm);
  border-radius: 50%;
  font-size: var(--fs-5);
  line-height: 1;
  text-decoration: none;
  color: var(--text-muted);
}

.datebar__arrow:hover {
  color: var(--text);
  background: var(--surface-hover);
}

.datebar__label {
  flex: 1 1 auto;
  min-width: 0;
  text-align: center;
  font-size: var(--fs-2);
  font-weight: var(--fw-bold);
}

.datebar__today,
.datebar__pin {
  display: inline-flex;
  align-items: center;
  flex: none;
  gap: var(--sp-1);
  padding: 0 var(--sp-3);
  font-size: var(--fs-1);
  font-weight: var(--fw-medium);
  text-decoration: none;
  color: var(--text-muted);
}

.datebar__today:hover {
  color: var(--text);
}

@keyframes live-pulse {
  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.3;
  }
}

/* --------------------------------------------------------- competitions */

.competitions {
  display: grid;
  gap: var(--sp-6);
}

.competition {
  display: grid;
  gap: var(--sp-3);
}

.competition__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--border);
}

.competition__link {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  text-decoration: none;
}

.competition__name {
  font-size: var(--fs-4);
  font-weight: var(--fw-bold);
  letter-spacing: -0.01em;
}

.competition__link:hover .competition__name {
  text-decoration: underline;
}

.competition__sub {
  font-size: var(--fs-1);
  font-weight: var(--fw-medium);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-subtle);
}

.competition__chevron {
  flex: none;
  line-height: 1;
  color: var(--text-subtle);
  transition: transform var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.competition__head:hover .competition__chevron {
  color: var(--accent-text);
  transform: translateX(2px);
}

.competition__list {
  display: grid;
  gap: var(--sp-2);
}

.competition--collapsible {
  gap: 0;
}

.competition--collapsible .competition__head {
  padding-bottom: 0;
  border-bottom: 0;
}

.competition__details {
  min-width: 0;
}

.competition__summary {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--control-h-sm);
  padding: 0 var(--sp-2);
  border-radius: var(--r-sm);
  color: var(--text-muted);
  font-size: var(--fs-1);
  font-weight: var(--fw-medium);
  cursor: pointer;
  list-style: none;
}

.competition__summary::-webkit-details-marker {
  display: none;
}

.competition__summary::before {
  content: "›";
  width: 1em;
  color: var(--text-subtle);
  font-size: var(--fs-4);
  line-height: 1;
  transition: transform var(--dur-fast) var(--ease);
}

.competition__details[open] > .competition__summary::before {
  transform: rotate(90deg);
}

.competition__summary:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.competition__details[open] > .competition__list {
  margin-top: var(--sp-2);
}

.series-line {
  display: block;
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-2);
}

/* ------------------------------------------------------------ match rows */

.match-row {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}

/* No bar until the row has a state; the geometry is the shared bar rule. */
.match-row::before {
  background: transparent;
}

.match-row:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-1);
}

.match-row--live {
  border-color: var(--accent-border);
}

.match-row--live::before {
  background: var(--live);
}

.match-row--break {
  border-color: var(--warn-border);
}

.match-row--break::before {
  background: var(--break);
}

/* Stretched link: the row is clickable, the star still sits above it. The focus
   ring is drawn here, so keyboard focus outlines the whole row. */
.match-row__link {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.match-row__link:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
  border-radius: var(--r-md);
}

.match-row__body {
  position: relative;
  z-index: 0;
  display: grid;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4) var(--sp-3) var(--sp-5);
}

.match-row__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-right: calc(var(--control-h-sm) + var(--sp-1)); /* clear of the star */
  font-size: var(--fs-1);
  color: var(--text-subtle);
}

.match-row__format {
  min-width: 0;
  font-weight: var(--fw-medium);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.match-row__dates {
  flex: none;
  font-variant-numeric: tabular-nums;
}

.match-row__status {
  display: flex;
  align-items: center;
  gap: var(--gap-tight);
  margin: 0;
  font-size: var(--fs-2);
  font-weight: var(--fw-bold);
}

/* A glyph as well as a hue: circle for play, square for an interruption. */
.match-row__status::before {
  content: "";
  flex: none;
  width: var(--sp-2);
  height: var(--sp-2);
  border-radius: 50%;
  background: currentColor;
}

.match-row__status--live {
  color: var(--accent-text);
}

.match-row__status--break {
  color: var(--warn-text);
}

.match-row__status--break::before {
  border-radius: 1px;
}

.match-row__status--done,
.match-row__status--upcoming {
  color: var(--text-muted);
}

.match-row__status--done::before {
  background: transparent;
  border: 2px solid currentColor;
}

.match-row__teams {
  display: grid;
  gap: var(--sp-2);
  margin-top: var(--sp-1);
}

.match-row__team {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--sp-3);
}

.match-row__glyph {
  display: inline-flex;
  align-self: center;
  color: var(--accent-text);
}

.match-row__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.match-row__team--batting .match-row__name {
  font-weight: var(--fw-bold);
}

.match-row__score {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: flex-end;
  gap: 0 var(--gap-tight);
  text-align: right;
  white-space: nowrap;
}

.match-row__runs {
  font-size: var(--fs-4);
  font-weight: var(--fw-bold);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

/* Overs sit under the runs rather than being strung into them, so a two-innings
   score stops reading as one long parenthesised number. */
.match-row__overs {
  flex-basis: 100%;
  font-size: var(--fs-1);
  font-weight: var(--fw-normal);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.match-row__note {
  margin: 0;
  font-size: var(--fs-1);
}

.match-row__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-1);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
  font-size: var(--fs-1);
  color: var(--text-muted);
}

.match-row__foot .coverage {
  font-size: var(--fs-1);
}

.match-row__foot .match-card__updated {
  margin-left: auto;
}

.star {
  position: absolute;
  top: var(--sp-2);
  right: var(--sp-2);
  z-index: 2;
}

.star__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-h-sm);
  height: var(--control-h-sm);
  padding: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  background: transparent;
  color: var(--text-subtle);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}

.star__button:hover {
  color: var(--accent-text);
  border-color: var(--border);
  background: var(--surface-hover);
}

.star__button--on {
  color: var(--accent-text);
}

.delivery {
  flex: none;
  width: 15px;
  height: 15px;
}

/* ------------------------------------------------- 11. widths and print */

@media (min-width: 40rem) {
  .match-body {
    grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr);
    align-items: start;
  }

  .match-body__aside {
    position: sticky;
    top: calc(var(--topbar-h) + var(--sp-4));
  }
}

@media (min-width: 60rem) {
  .scores {
    grid-template-columns: var(--rail) minmax(0, 1fr);
    align-items: start;
  }

  .scores__side {
    position: sticky;
    top: calc(var(--topbar-h) + var(--sp-5));
  }
}

/* Phones: scores first. A fourteen-row competition rail above the list would
   bury the thing the visitor came for. */
@media (max-width: 59.99rem) {
  .scores__main {
    order: -1;
  }
}

/*
 * Narrow phones. Every `max-width: 26rem` override in this file lives in this one
 * block, so the phone layout can be read in one place instead of three.
 *
 * - The date is the one thing the date bar exists to tell you, so the fixed parts
 *   give up their padding and the label may take a second line. It used to keep
 *   `nowrap` with an ellipsis and rendered "Fri 2…" at 319px, clipped rather than
 *   merely tight.
 * - The rail is the full column width here, so a long competition name gets a
 *   second line instead of being elided to "Afghanistan vs Bangladesh in U…". The
 *   desktop rail keeps its single-line ellipsis, where the name competes with the
 *   match count in a fixed 16rem column.
 * - The score column is `auto`, so with a two-innings score it used to take the
 *   whole row and squeeze the team name track to 0px — the name vanished rather
 *   than merely tightening. Here the name gets a floor and both the name and the
 *   score may take a second line instead of being cut. The match-header leader is
 *   dropped: it was reserving width the name needed.
 */
@media (max-width: 26rem) {
  .datebar {
    gap: 2px;
    padding: var(--sp-1) var(--sp-1);
  }

  .datebar__live {
    gap: 0.3rem;
    padding: 0 var(--sp-2) 0 var(--sp-3);
  }

  .datebar__arrow {
    width: 1.75rem;
    height: 1.75rem;
    font-size: var(--fs-4);
  }

  .datebar__label {
    line-height: var(--lh-snug);
    text-wrap: balance;
  }

  .side-nav__name {
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
  }

  .match-row__team {
    grid-template-columns: auto minmax(5.5rem, 1fr) auto;
  }

  .match-row__name {
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
  }

  .match-row__score,
  .match-row__runs {
    white-space: normal;
  }

  .match-header__name::after {
    display: none;
  }
}

@media (max-width: 34rem) {
  .facts__row,
  .log__item {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-1);
  }
}

@media (max-width: 30rem) {
  .shell__main {
    padding-inline: var(--sp-3);
  }

  .page__head h1 {
    font-size: var(--fs-6);
  }

  .score,
  .match-header__score {
    font-size: var(--fs-5);
  }

  /* Stacked scorecard: the header row carries the label instead of a top bar. */
  .table--card thead {
    display: none;
  }

  .table--card,
  .table--card tbody,
  .table--card tr,
  .table--card td {
    display: block;
  }

  .table--card tr {
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--border);
  }

  .table--card tr:last-child {
    border-bottom: 0;
  }

  /* A fixed label column, with values starting at one shared edge. Ragged
     right-aligned values read worse than a clean second column, and a badge in
     a cell no longer gets stretched between the two edges. */
  .table--card td {
    display: flex;
    align-items: baseline;
    gap: var(--sp-3);
    padding: 2px 0;
    border: 0;
    white-space: normal;
  }

  .table--card td::before {
    content: attr(data-label);
    flex: none;
    width: var(--label-col);
    font-size: var(--fs-1);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-subtle);
  }

  .table--card td .tag {
    flex: none;
    margin-left: 0;
    white-space: nowrap;
  }

  /* In the stacked view every value shares one left edge, so the desktop
     "right-align the numbers" rule is dropped rather than left to fight the
     fixed label column. */
  .table--card .num {
    width: auto;
    text-align: left;
  }
}

/* Score change flash: subtle, motion-safe and non-essential. */
@keyframes score-flash {
  from {
    background: var(--accent-soft);
  }

  to {
    background: transparent;
  }
}

.score--changed,
.match-row__runs.score--changed {
  animation: score-flash 1.2s ease-out;
}

@media (forced-colors: active) {
  .match-row,
  .datebar,
  .chip,
  .badge,
  .coverage__pill,
  .card,
  .empty,
  .table-wrap,
  .form fieldset,
  .side-nav__link--on {
    border-color: CanvasText;
  }
}

@media print {
  .scores__side,
  .datebar,
  .star,
  .follow,
  .filters,
  .match-tabs {
    display: none;
  }

  .match-header {
    position: static;
    box-shadow: none;
  }
}
