/*
 * Components and page blocks.
 *
 * Written against tokens.css. No raw hex, no raw pixel value — if something
 * here wants a value the tokens do not have, the token file is where it goes.
 * This file defines no tokens, for the reason set out at the top of base.css.
 *
 * ---------------------------------------------------------------------------
 * THE TWO REGISTERS
 *
 * The bundled design data profiles a football club as block-based and
 * motion-driven, and a financial dashboard as dark and data-dense. This product
 * is both, and the split is by surface rather than a compromise between them:
 *
 *   Front door, blog, membership -> blocks. Big type, hard edges, room to
 *   breathe, one idea per screen. These are the pages advertising review looks
 *   at and the pages a stranger arrives on.
 *
 *   Board, fixture, results -> density. A board of four tall cards shows four
 *   games; the same screen as rows shows a dozen, and someone scanning for
 *   their fixture wants the dozen.
 *
 * Same components, same tokens, different spacing and different scale.
 */

/* ========================================================== team identity */

/*
 * A crest, or initials on a generated ground when the provider has no image.
 * The two colour stops come in as --c1/--c2 per instance — a per-club value,
 * not a design token, which is why they are inline.
 */
.crest {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  overflow: hidden;
  border-radius: 50%;
  background: var(--terrace);
  border: var(--border) solid var(--hairline);
  color: #fff;
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-variation-settings: 'wdth' var(--condensed);
  letter-spacing: var(--tracking-md);
  line-height: 1;
}
.crest img { width: 76%; height: 76%; object-fit: contain; }
.crest i { display: none; font-style: normal; }
/*
 * A face, not a badge. The provider's headshots are square portraits on a
 * light ground; set inside a crest they became a small square photo in a
 * dark ring, a picture in a frame. A face fills its circle, cropped from the
 * top so the head is never cut, with no ring round it.
 */
.crest-player { border: 0; background: var(--chalk-2); }
.crest-player img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 12%; }
.crest.noimg { background: linear-gradient(145deg, var(--c2, #3b82f6), var(--c1, #1e3a8a)); }
.crest.noimg i { display: block; }
.crest-xl { width: 76px; height: 76px; font-size: var(--text-xl); }
.crest-lg { width: 48px; height: 48px; font-size: var(--text-md); }
.crest-md { width: 34px; height: 34px; font-size: var(--text-xs); }
.crest-sm { width: 21px; height: 21px; font-size: 7px; }
/*
 * `crest-xs` was used by the board's competition mark from the day that column
 * was written, and never had a rule. Nothing looked wrong, because the sandbox
 * could not load the images and the initials fallback sized itself off its own
 * font. The moment real crests arrived, an unsized box took the image's
 * intrinsic width and a 20px league badge rendered at 72px straight through the
 * kick-off time and the team names.
 */
.crest-xs { width: 20px; height: 20px; font-size: 6px; }

/* A competition mark. Square-ish rather than round, so a league never reads as
   a club at the size where both appear in the same row. */
.mark {
  display: inline-grid;
  place-items: center;
  flex: none;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: var(--terrace);
  font-weight: var(--weight-bold);
  line-height: 1;
}
.mark img { width: 100%; height: 100%; object-fit: contain; }
.mark-xs { width: 18px; height: 18px; font-size: 7px; }
.mark-sm { width: 24px; height: 24px; font-size: 9px; }
.mark-md { width: 34px; height: 34px; font-size: 12px; }

/* ============================================================= form chips */

.chips { display: inline-flex; gap: 3px; vertical-align: middle; }
.chip {
  display: grid;
  place-items: center;
  width: 17px; height: 17px;
  border-radius: 3px;
  font-size: 9px;
  font-weight: var(--weight-bold);
  font-style: normal;
  line-height: 1;
  background: var(--terrace);
  color: var(--chalk-3);
}
.chip.w { background: rgba(61, 180, 104, 0.18); color: var(--won); }
.chip.d { background: rgba(123, 137, 150, 0.2); color: var(--void); }
.chip.l { background: rgba(203, 49, 49, 0.18); color: var(--lost); }

/* =================================================================== tags */

/*
 * A tag says what happened, never what we filed it under. The pick classes and
 * the confidence bands used to be on the page as coloured pills; they are our
 * taxonomy and a reader does not have it. See engine/src/vocabulary.ts.
 */
.tag {
  display: inline-flex;
  align-items: center;
  padding: 3px var(--space-3);
  border: var(--border) solid transparent;
  border-radius: var(--radius-sm);
  font-size: var(--text-2xs);
  font-weight: var(--weight-black);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}
.tag.won  { background: rgba(61, 180, 104, 0.16); color: var(--won); }
.tag.lost { background: rgba(203, 49, 49, 0.16); color: var(--lost); }
.tag.void { background: rgba(123, 137, 150, 0.16); color: var(--void); }
/*
 * A predicted eleven is a guess, and it is drawn with the same photographs and
 * the same confidence as a confirmed one. The only thing separating them was
 * the word "predicted" set in muted grey, which is not enough weight to stop a
 * reader treating twenty-two named players as fact.
 */
.tag.prov { background: rgba(245, 165, 36, 0.16); color: var(--warn); }
.tag.ok { background: rgba(47, 191, 113, 0.16); color: var(--won); }
.pending { color: var(--chalk-3); }

/* ================================================================ surfaces */

.panel {
  background: var(--stand);
  border: var(--border) solid var(--hairline);
  border-radius: var(--radius);
  padding: var(--space-7);
  box-shadow: var(--ring-inset);
}
.panel + .panel { margin-top: var(--space-5); }
.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin: 0 0 var(--space-5);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--chalk-2);
}
.panel-head span {
  font-weight: var(--weight-normal);
  color: var(--chalk-3);
  white-space: nowrap;
}

/*
 * An empty state says three things: what this is, why it is empty, and that
 * the emptiness is deliberate. Forty-four per cent of the board has no call on
 * it, and without that third part the page reads as broken rather than as
 * restrained.
 */
.empty-state {
  padding: var(--space-9) var(--space-7);
  text-align: center;
  background: var(--stand);
  border: var(--border) dashed var(--rule);
  border-radius: var(--radius);
}
.empty-state b {
  display: block;
  margin-bottom: var(--space-2);
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-size: var(--text-lg);
  letter-spacing: var(--tracking-xl);
  color: var(--chalk);
}
.empty-state span {
  display: block;
  max-width: 46ch;
  margin-inline: auto;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--chalk-2);
}

/* Skeletons, so a slow board does not flash an empty page at a reader. */
.skeleton {
  border-radius: var(--radius);
  background: linear-gradient(90deg, var(--stand) 25%, var(--terrace) 37%, var(--stand) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s var(--ease-in-out) infinite;
}
.skeleton-row { height: 78px; }
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }

/* ============================================================== the hero */

/*
 * Full-bleed photography with the matchup sitting on it.
 *
 * The previous version put the picture in a bounded plate BESIDE the type,
 * on the reasoning that a scrim over a bright photograph makes type
 * unreadable. That reasoning was right about the risk and wrong about the
 * answer: the fix is to shape the scrim, not to shrink the picture. Every
 * reference this is measured against fills the masthead with one photograph
 * and puts the fixture in the bottom-left corner of it, and a bounded plate
 * beside a column of text reads as a brochure.
 *
 * So: one image, edge to edge, with a scrim weighted left and down -- heaviest
 * exactly where the type sits and clear on the right where the subject is.
 */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-bottom: var(--border) solid var(--hairline);
}
.hero-media { position: absolute; inset: 0; z-index: -1; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; }
.hero-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right, var(--pitch) 0%, rgba(12, 11, 9, 0.92) 30%, rgba(12, 11, 9, 0.45) 68%, rgba(12, 11, 9, 0.6) 100%),
    linear-gradient(to top, var(--pitch) 0%, rgba(12, 11, 9, 0.4) 44%, rgba(12, 11, 9, 0.62) 100%);
}
/* No photograph: a built field rather than a blank stage. */
[data-shot="none"] .hero-media,
[data-shot="none"] .fx-hero-media,
[data-shot="none"] .band-shot,
[data-shot="none"] .venue-shot {
  background:
    radial-gradient(120% 92% at 16% 0%, rgba(122, 90, 248, 0.22), transparent 58%),
    radial-gradient(100% 80% at 88% 8%, rgba(240, 168, 104, 0.12), transparent 62%),
    var(--terrace);
}

.hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  align-items: end;
  gap: var(--space-9);
  min-height: clamp(460px, 56vw, 620px);
  padding-block: var(--space-9);
}
.hero-copy { align-self: end; }
@media (max-width: 1040px) {
  .hero-inner { grid-template-columns: minmax(0, 1fr); }
}
.hero-copy { max-width: 46ch; }
/*
 * The competition above the headline tie: a link, in the UI face. The crest
 * says which competition before the name is read; the occasion follows in
 * a quieter colour when there is one.
 */
.comp-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin: 0 0 var(--space-4);
  text-shadow: 0 1px 12px rgba(10, 10, 12, 0.9);
}
.comp-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--floodlight-hi);
  text-decoration: none;
}
.comp-link:hover span { text-decoration: underline; text-underline-offset: 3px; }
.comp-occasion { font-size: var(--text-sm); color: var(--chalk-2); }

/* The kick-off, as a chip. First thing the reference states, and the first
   thing anybody wants: is this on tonight. */
.timechip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  background: rgba(12, 11, 9, 0.66);
  backdrop-filter: blur(6px);
  border: var(--border) solid var(--hairline);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  color: var(--chalk);
  white-space: nowrap;
}
.timechip.soon { color: var(--sodium); }

/*
 * The fixture as two rows, crest then name -- not "A vs B" on one line.
 *
 * Stacked, the two clubs read as two entries on a card. Side by side with a
 * "vs" between them they read as a headline, which is what the last version
 * did, and a headline cannot also carry a crest at a size anyone can see.
 */
/* An h1 in the hero, so the browser's own heading margins have to go. */
.fx-stack { display: flex; flex-direction: column; gap: var(--space-4); margin: 0; font-weight: inherit; }
.fx-line { display: flex; align-items: center; gap: var(--space-4); min-width: 0; flex-wrap: wrap; }
.fx-line .name {
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-size: var(--text-hero);
  letter-spacing: var(--tracking-2xl);
  line-height: 1.05;
  font-variation-settings: 'wdth' var(--condensed);
  overflow-wrap: anywhere;
}
.hero-blurb {
  margin: var(--space-6) 0 var(--space-7);
  max-width: 44ch;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--chalk-2);
}
.hero-cta { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }

@media (max-width: 700px) {
  .hero-inner { min-height: 380px; padding-block: var(--space-7); }
  .hero-media::after {
    background:
      linear-gradient(to top, var(--pitch) 6%, rgba(12, 11, 9, 0.72) 46%, rgba(12, 11, 9, 0.3) 100%);
  }
  /* Two buttons, one row, equal widths. The primary alone stretched and the
     second sat under it at its own width, which read as two unrelated things. */
  .hero-cta { display: grid; grid-template-columns: 1fr 1fr; }
  .hero-cta .btn { width: 100%; justify-content: center; text-align: center; }
}

/* ========================================================== match centre */

/*
 * The panel on the photograph.
 *
 * Glass rather than a solid block: it has to sit ON the picture, not cover it,
 * or the photograph may as well not be there. The backdrop blur is what makes
 * small type legible over a stadium without a scrim heavy enough to kill the
 * image.
 */
.matchcentre {
  align-self: end;
  border: var(--border) solid var(--rule);
  border-radius: var(--radius);
  background: rgba(10, 10, 12, 0.62);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  overflow: hidden;
}
@supports not (backdrop-filter: blur(1px)) {
  .matchcentre { background: rgba(10, 10, 12, 0.92); }
}

.mc-block { padding: var(--space-5); border-top: var(--border) solid var(--hairline); }
.mc-block:first-child { border-top: 0; }
.mc-label {
  display: block;
  margin-bottom: var(--space-4);
  font-size: var(--text-2xs);
  font-weight: var(--weight-black);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--chalk-3);
}

/* The one moving thing on the site. */
.mc-clock { text-align: left; }
.mc-count {
  display: block;
  font-family: var(--display);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-black);
  font-size: var(--text-4xl);
  line-height: 0.92;
  color: var(--chalk);
}
.mc-count.live { color: var(--lost); font-size: var(--text-2xl); }

.mc-side {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  padding-block: var(--space-2);
}
.mc-side .chips { grid-column: 1 / -1; margin-top: 2px; }
.mc-name {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mc-pos {
  font-family: var(--display);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-black);
  font-size: var(--text-lg);
  color: var(--floodlight-hi);
}
.matchcentre .formbar { max-width: none; margin-bottom: 0; }
.matchcentre .formbar-keys { font-size: 10px; gap: var(--space-2); }
.matchcentre .formbar-keys b { font-size: var(--text-md); }

/* ====================================================== the next-match list */

/*
 * What is on next, as a fixture list: home on the left reading in to the
 * kick-off, away on the right reading out of it, one match to a line. It
 * replaced a sideways-scrolling row of cards that readers found confusing --
 * a list is how every football page prints fixtures, so nobody has to learn
 * it.
 */
.next-list {
  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--stand);
  border: var(--border) solid var(--hairline);
  border-radius: var(--radius);
}
.next-list li + li { border-top: var(--border) solid var(--hairline); }
.next-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4);
  color: inherit;
  text-decoration: none;
}
.next-row:hover { background: var(--terrace); }
.next-side {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}
.next-side.home { justify-content: flex-end; text-align: right; }
.next-name { min-width: 0; overflow-wrap: anywhere; line-height: 1.25; }
.next-side .crest { flex: none; }
.next-mid {
  flex: none;
  width: 72px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
.next-time {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-lg);
  line-height: 1;
}
.next-mid small { font-size: var(--text-2xs); color: var(--chalk-3); }
.next-mid .next-pick {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-weight: 600;
  color: var(--floodlight-hi);
}
.next-pick svg { width: 10px; height: 10px; fill: none; stroke: currentColor; stroke-width: 2.4; }
@media (max-width: 560px) {
  .next-row { padding-inline: var(--space-3); gap: var(--space-2); }
  .next-side { font-size: var(--text-xs); gap: var(--space-2); }
  .next-mid { width: 58px; }
}

/* ============================================================== the promo */

/*
 * The one block on the site that is a solid colour.
 *
 * The reference gives its newsletter band the club's own blue and a player cut
 * out of the background, and it is the only saturated thing on the page. Ours
 * sells the membership, which is the equivalent job, and it gets the accent for
 * the same reason: one block of colour on a dark page is an event.
 */
.promo {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: var(--space-7);
  border-radius: var(--radius-lg);
  background: linear-gradient(104deg, #4b2fd0 0%, var(--floodlight) 46%, #8f74ff 100%);
  color: #fff;
}
/* The chevron flight the reference runs under its copy. Drawn, not an asset. */
.promo::after {
  content: '';
  position: absolute;
  inset: 0 0 0 auto;
  width: 60%;
  z-index: -1;
  background-image: repeating-linear-gradient(
    115deg,
    rgba(255, 255, 255, 0.09) 0 2px,
    transparent 2px 26px
  );
}
.promo-aside {
  margin: 0 0 var(--space-3);
  font-size: var(--text-2xl);
  color: rgba(255, 255, 255, 0.88);
}
.promo h2 {
  margin: 0;
  font-family: var(--display);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-xl);
  line-height: var(--leading-snug);
}
.promo p {
  margin: var(--space-3) 0 var(--space-6);
  max-width: 46ch;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: rgba(255, 255, 255, 0.82);
}
.promo .btn-light { border-color: transparent; }
.promo-price { font-variant-numeric: tabular-nums; }

/* ========================================================= the side rail */

/*
 * A dense list down the right of the page.
 *
 * The reference runs news there, with a thumbnail and two lines of headline per
 * item, and the page would feel half-built without it. We have no newsroom, so
 * ours carries what a reader actually came for: the calls that are live now.
 */
.with-side {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--col-side);
  gap: var(--space-7);
  align-items: start;
}
@media (max-width: 1040px) { .with-side { grid-template-columns: minmax(0, 1fr); } }

.side-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin: 0 0 var(--space-4);
  font-family: var(--display);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-md);
}
.side-head a { font-family: var(--body); font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--chalk-3); }
.side-head a:hover { color: var(--chalk); }

.side-list { display: flex; flex-direction: column; }
.side-item {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-bottom: var(--border) solid var(--hairline);
  align-items: center;
}
.side-item:last-child { border-bottom: 0; }
.side-item:hover .side-sel { color: var(--floodlight-hi); }
/* Two crests overlapped, standing in for the reference's thumbnail. */
.side-thumb { display: flex; align-items: center; }
.side-thumb .crest { border: 2px solid var(--pitch); }
.side-thumb .crest + .crest { margin-left: -10px; }
.side-body { min-width: 0; }
.side-sel {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--leading-snug);
  transition: color var(--dur-fast) var(--ease-out);
}
.side-meta {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-top: 3px;
  font-size: var(--text-2xs);
  color: var(--chalk-3);
}
.side-meta b {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  color: var(--floodlight-hi);
}

/* ============================================================ the form bar */

/*
 * Won, drawn, lost as one segmented bar with the share written on it.
 *
 * The reference opens its results block with exactly this, and it says in one
 * glance what a column of results takes a paragraph to say. It is also the
 * honest shape for our own settled record: the losing segment is the same size
 * it is in the data, and it is never left off.
 */
.formbar { max-width: 560px; margin-bottom: var(--space-7); }
.formbar-track {
  display: flex;
  gap: 2px;
  height: 6px;
  border-radius: var(--radius-pill);
  overflow: hidden;
  background: var(--terrace);
}
.formbar-track i { display: block; height: 100%; }
.formbar-track i.w { background: var(--won); }
.formbar-track i.d { background: var(--void); }
.formbar-track i.l { background: var(--lost); }
.formbar-keys {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-3);
  font-size: var(--text-2xs);
  color: var(--chalk-3);
}
.formbar-keys b {
  font-family: var(--display);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-black);
  font-size: var(--text-lg);
  line-height: 1;
}
/* What the bar is counting. Without it the bar and the headline above look
   like two answers to the same question. */
.formbar-scope { margin: var(--space-3) 0 0; font-size: var(--text-2xs); color: var(--chalk-3); }
.formbar-keys .w b { color: var(--won); }
.formbar-keys .d b { color: var(--void); }
.formbar-keys .l b { color: var(--lost); }

/*
 * A head-to-head is a tally, not a verdict.
 *
 * The semantic palette says green is won and red is lost, so running a
 * meetings record through it painted one club's wins as a good outcome and the
 * other's as a bad one. Two sides of a rivalry get two neutral tones and the
 * draws sit between them.
 */
.formbar.neutral .formbar-track i.w { background: var(--floodlight); }
.formbar.neutral .formbar-track i.d { background: var(--chalk-3); }
.formbar.neutral .formbar-track i.l { background: var(--chalk); }
.formbar.neutral .formbar-keys .w b { color: var(--floodlight-hi); }
.formbar.neutral .formbar-keys .d b { color: var(--chalk-3); }
.formbar.neutral .formbar-keys .l b { color: var(--chalk); }

/* ========================================================== result rows */

/*
 * A played match: who, the score, and what it was.
 *
 * The competition and the round sit on their own line above in small muted
 * type, exactly as the reference does it, which is what lets the row itself
 * stay down to two clubs and a score.
 */
.played { display: flex; flex-direction: column; gap: var(--space-2); }
.played-row {
  padding: var(--space-4) var(--space-5);
  background: var(--stand);
  border: var(--border) solid var(--hairline);
  border-radius: var(--radius);
  transition: background var(--dur-fast) var(--ease-out);
}
.played-row:hover { background: var(--terrace); }
.played-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
  font-size: var(--text-2xs);
  color: var(--chalk-3);
}
.played-tie {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: var(--space-4);
  align-items: center;
}
.played-side { display: flex; align-items: center; gap: var(--space-3); min-width: 0; font-size: var(--text-sm); }
.played-side.away { flex-direction: row-reverse; text-align: right; }
.played-side > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.played-score {
  flex: none;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--terrace);
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-bold);
  font-size: var(--text-md);
  letter-spacing: 0.06em;
  white-space: nowrap;
}
/* The scoreline stays neutral. The mark beside the kick-off already says
   whether it went our way, and colouring the score as well says it twice --
   in a colour that means something else on a scoreboard. */
.played-score { background: var(--terrace); color: var(--chalk); }
.played-score.w,
.played-score.l { background: var(--terrace); color: var(--chalk); }

/* ================================================================ squad */

/*
 * The team sheet as a list: name, position, number.
 *
 * Three columns and nothing else. The reference runs its squad this way under
 * everything else on the page, and it is the right shape for a list nobody
 * reads top to bottom but everybody scans for one name.
 */
.squad { display: flex; flex-direction: column; }
.squad-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  gap: var(--space-4);
  align-items: center;
  padding: var(--space-3) 0;
  border-bottom: var(--border) solid var(--hairline);
  font-size: var(--text-sm);
}
.squad-row:last-child { border-bottom: 0; }
.squad-row .pos { font-size: var(--text-xs); color: var(--chalk-3); white-space: nowrap; }
.squad-row .no {
  text-align: right;
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  color: var(--chalk-3);
}
.squad-row .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ================================================================== trust */

/*
 * Four things that are true, under the masthead.
 *
 * Separated by hairlines rather than by an accent bar on each item: four
 * coloured bars in a row is decoration, and the one thing this strip must read
 * as is fact.
 */
.trust { border-bottom: var(--border) solid var(--hairline); background: var(--stand); }
.trust-inner {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  padding-block: 0;
}
.trust-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-6) var(--space-6) var(--space-6) 0;
  border-left: var(--border) solid var(--hairline);
  padding-left: var(--space-6);
}
.trust-item:first-child { border-left: 0; padding-left: 0; }
.trust-item b { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--chalk); }
.trust-item span { font-size: var(--text-xs); color: var(--chalk-3); line-height: var(--leading-snug); }
@media (max-width: 860px) {
  .trust-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .trust-item { padding: var(--space-5) var(--space-5); }
  .trust-item:nth-child(odd) { border-left: 0; padding-left: 0; }
  .trust-item:nth-child(n+3) { border-top: var(--border) solid var(--hairline); }
}
@media (max-width: 420px) {
  .trust-inner { grid-template-columns: minmax(0, 1fr); }
  .trust-item { border-left: 0; padding-left: 0; }
  .trust-item + .trust-item { border-top: var(--border) solid var(--hairline); }
}

/* =========================================================== league rail */

.rail { border-bottom: var(--border) solid var(--hairline); }
.rail-inner {
  max-width: var(--maxw);
  margin-inline: auto;
  padding: var(--space-4) var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  overflow-x: auto;
  scrollbar-width: none;
}
.rail-inner::-webkit-scrollbar { display: none; }
.rail-label {
  flex: none;
  padding-right: var(--space-4);
  margin-right: var(--space-1);
  border-right: var(--border) solid var(--rule);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--chalk-3);
  white-space: nowrap;
}
.rail-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  flex: none;
  padding: var(--space-2) var(--space-4) var(--space-2) var(--space-2);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--stand);
  font-size: var(--text-sm);
  color: var(--chalk-2);
  white-space: nowrap;
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.rail-item:hover { color: var(--chalk); border-color: var(--rule-firm); }
.rail-item b { color: var(--chalk); font-weight: var(--weight-medium); }
.rail-item .count {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  color: var(--floodlight-hi);
  font-variant-numeric: tabular-nums;
}

/* ============================================================ pick cards */

/*
 * The front-door card. One fixture, the call, the price, the book.
 *
 * Deliberately not: a rounded card on a gradient fill that lifts three pixels
 * and grows a soft grey shadow on hover. That combination is on every
 * generated landing page there is. This is a flat block with a hairline, and
 * the only thing that happens on hover is that the rule across its top turns
 * the accent colour — which also happens to be the one change that survives
 * `prefers-reduced-motion`.
 */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--space-4);
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-6);
  background: var(--stand);
  border: var(--border) solid var(--hairline);
  border-radius: var(--radius);
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.card::before {
  content: '';
  position: absolute;
  inset: -1px -1px auto -1px;
  height: 2px;
  border-radius: var(--radius) var(--radius) 0 0;
  background: transparent;
  transition: background var(--dur-normal) var(--ease-out);
}
.card:hover { background: var(--terrace); border-color: var(--rule); }
.card:hover::before { background: var(--floodlight); }
.card:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.card:focus-visible::before { background: var(--floodlight); }

.card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: var(--text-xs);
  color: var(--chalk-3);
}
.card-league { display: inline-flex; align-items: center; gap: var(--space-3); min-width: 0; }
.card-league > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card-kick { white-space: nowrap; font-variant-numeric: tabular-nums; }
.card-kick.soon { color: var(--sodium); font-weight: var(--weight-medium); }

/* Crest, "vs", crest — the shape every football site uses, because it reads at
   a glance where a stacked list of names does not. */
.vs { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: var(--space-3); align-items: start; }
.vs-side { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); text-align: center; min-width: 0; }
.vs-side > span {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--leading-snug);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.vs-mark {
  padding-top: 16px;
  font-family: var(--display);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--chalk-3);
}

/* ---------------------------------------------------- the call, as shown */

/*
 * Four things and no more: what the call is, what has to happen for it to
 * land, the price, and who is offering it. What used to be here instead — a
 * class tag, our probability, the bookmaker's implied one, and a confidence
 * meter — told a reader nothing about what they were being asked to believe.
 */
.card-pick {
  padding-top: var(--space-5);
  border-top: var(--border) solid var(--hairline);
}
.card-pick .sel,
.verdict .sel {
  display: block;
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-xl);
}
.card-pick .wins,
.verdict .wins {
  margin: var(--space-3) 0 0;
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--chalk-2);
}

.pick-meta,
.verdict-meta {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  color: var(--chalk-3);
}
.pick-meta .book { color: var(--chalk-2); }
.pick-meta .ret { margin-left: auto; font-variant-numeric: tabular-nums; }
.verdict-meta b { color: var(--chalk); }

/* The price. Display face at a condensed width, tabular figures, accent
   colour — the one number on the page a reader came for. */
.price {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-bold);
  font-size: var(--text-2xl);
  letter-spacing: var(--tracking-num);
  line-height: 1;
  color: var(--floodlight-hi);
}

.card-pick.none { display: block; }
.card-pick.none b {
  display: block;
  margin-bottom: var(--space-2);
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-size: var(--text-md);
  color: var(--chalk-2);
}
.card-pick.none span { font-size: var(--text-sm); line-height: var(--leading-snug); color: var(--chalk-3); }

.also { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.also-call {
  max-width: 100%;
  padding: var(--space-2) var(--space-4);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--terrace);
  font-size: var(--text-xs);
  color: var(--chalk-2);
  /* It was nowrap, which is fine for "Also: over 2.5" and not for "Moise Kean
     — knee, out until November": five of those in a row pushed the fixture
     page nine hundred pixels sideways on a phone. The reason a player is out
     is a sentence, so it is allowed to be one. */
  overflow-wrap: anywhere;
}
.also-call b { color: var(--chalk); font-weight: var(--weight-bold); font-variant-numeric: tabular-nums; }
.caveat { display: inline-block; margin-left: var(--space-1); font-style: normal; color: var(--warn); }

/* A closing line on the card, in words rather than an arrow. `Read the
   analysis →` is one of the four generated-page tells this codebase had live. */
.card-go {
  margin-top: auto;
  padding-top: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--chalk-3);
  transition: color var(--dur-fast) var(--ease-out);
}
.card:hover .card-go { color: var(--floodlight-hi); }

/* ========================================================= the board row */

/*
 * One game, one line.
 *
 * Column order is deliberate: when it kicks off, who is playing, what we
 * think, what it pays. The eye runs down the left edge to find the fixture and
 * the right edge to find the price; the reasoning sits between them, read only
 * once the game has been found.
 */
/*
 * The board is a table, not a stack of cards.
 *
 * Every row used to be its own bordered, rounded box with a gap under it, so a
 * three-hundred-game board was three hundred containers and the eye had to
 * re-enter each one. No book lays a board out that way. They group by
 * competition, draw one frame round the group, and separate the rows inside it
 * with a single rule -- denser, quieter, and it lets a reader run straight down
 * the price column without interruption.
 */
.league-block {
  background: var(--stand);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.league-block + .league-block { margin-top: var(--space-5); }

.league-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  background: var(--terrace);
  border-bottom: var(--border) solid var(--rule);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--chalk-2);
}
.league-head .count { margin-left: auto; color: var(--chalk-3); font-weight: var(--weight-medium); }

.row {
  display: grid;
  grid-template-columns: var(--col-when) minmax(0, 1.05fr) minmax(0, 1.45fr) var(--col-price);
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-3) var(--space-5);
  border-top: var(--border) solid var(--hairline);
  transition: background var(--dur-fast) var(--ease-out);
}
.league-block .row:first-of-type { border-top: 0; }
.row:hover { background: var(--terrace); }
.row:focus-visible { outline: none; box-shadow: var(--focus-ring); position: relative; z-index: 1; }

.row-when { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.row-time {
  white-space: nowrap;
  font-family: var(--display);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-black);
  font-size: var(--text-xl);
  letter-spacing: 0;
  line-height: 1;
}
.row-day {
  display: block;
  margin-top: 3px;
  font-size: var(--text-2xs);
  color: var(--chalk-3);
}

.row-teams { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.row-side {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}
.row-side > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/*
 * The goals, out at the right edge of the name column.
 *
 * `margin-left: auto` puts them against the column edge on both rows, which is
 * what makes them line up under each other -- a printed fixture list reads
 * down the goals, not across the row, and two numbers that do not share an
 * edge cannot be read that way.
 *
 * The winning side's number is the one that carries weight. A draw leaves both
 * at the quieter colour, which is the correct amount of emphasis for a draw.
 */
.row-goals {
  margin-left: auto;
  padding-left: var(--space-3);
  /* Geist, not the display face, and this is the one number on the site set
     that way. Big Shoulders is signage type and its 1 is very nearly a bare
     stroke -- fine in "22:15" where the context carries it, ambiguous as a
     single goal beside a club name. A scoreline has to be unmistakable. */
  font-family: var(--body);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-black);
  font-size: var(--text-lg);
  line-height: 1;
  color: var(--chalk-3);
}
.row-goals.won { color: var(--chalk); }

/*
 * The mark: whether the call landed.
 *
 * It sits where the price sits, because on a finished match that is what the
 * price has become. Squared, on its own surface, and coloured -- this is the
 * one place on the site where green and red mean exactly what a reader assumes
 * they mean, and dressing it down would be false modesty about a loss.
 */
.mark {
  display: inline-block;
  padding: var(--space-2) var(--space-3);
  border: var(--border) solid currentColor;
  border-radius: var(--radius-sm);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}
.mark.won  { color: var(--won); }
.mark.lost { color: var(--lost); }
.mark.back,
.mark.part { color: var(--void); }
.mark.none { color: var(--chalk-3); border-style: dashed; }

/* A finished match is a different kind of thing from one still to come, and
   the board should sort into the two before a word of it is read. */
.row.is-played { background: color-mix(in srgb, var(--stand) 55%, transparent); }
.row.is-played:hover { background: var(--stand); }

.row-call { min-width: 0; }
.row-sel {
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-size: var(--text-lg);
  letter-spacing: 0.01em;
  line-height: 1.2;
}
.row-wins {
  margin: 3px 0 0;
  font-size: var(--text-xs);
  line-height: var(--leading-snug);
  color: var(--chalk-3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.row-none { margin: 0; font-size: var(--text-sm); color: var(--chalk-3); }
.row-locked { margin: 0; font-size: var(--text-sm); color: var(--chalk-2); }

.row-price { text-align: right; min-width: 0; }

/*
 * The price column. Tabular figures are not a nicety here: proportional digits
 * make a column of odds unscannable, because 1.11 and 2.87 come out different
 * widths and the decimal points stop lining up — and a board that refreshes
 * every fifteen minutes jitters on every tick.
 */
/*
 * The price is a surface, not a caption.
 *
 * This is the single change that makes the page read as a betting product
 * rather than as an article about football. Every book in the world puts its
 * price in a bordered box that looks like it can be pressed -- bet365, Stake,
 * FanDuel, all of them -- because the price is the thing the page is FOR, and a
 * number set in coloured text beside a paragraph is a footnote.
 *
 * It is not a link and does not pretend to be one: the whole row is the link.
 * What the box buys is weight on the page.
 */
.odds-tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 76px;
  padding: var(--space-2) var(--space-4);
  background: var(--terrace);
  border: var(--border) solid var(--rule-firm);
  border-radius: var(--radius-sm);
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.row:hover .odds-tile,
.card:hover .odds-tile { background: var(--floodlight); border-color: var(--floodlight); }
.row:hover .odds-tile .odds,
.card:hover .odds-tile .odds { color: #fff; }

.odds {
  display: block;
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-black);
  font-size: var(--text-xl);
  letter-spacing: 0;
  line-height: 1;
  color: var(--floodlight-hi);
  transition: color var(--dur-fast) var(--ease-out);
}
.odds-book {
  display: block;
  margin-top: 3px;
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--chalk-3);
  white-space: nowrap;
}
/*
 * A price no book here is quoting.
 *
 * It is still shown -- the call is real and the number is what the market
 * thinks -- but it is drawn as an outline rather than a solid tile, and the
 * book name is replaced by "not here", so nobody goes looking for an account
 * they cannot open. The fixture page says which book it belongs to.
 */
/* The word "odds" beside every price: the owner's rule is that a price is
   never printed bare. Set small and quiet so the number still leads. */
.odds-tile { gap: var(--space-2); }
.odds-unit,
.price small {
  font-family: var(--body);
  font-variation-settings: normal;
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  color: var(--chalk-3);
}
.price small { margin-left: var(--space-2); }
.row:hover .odds-tile .odds-unit { color: var(--chalk); }

.odds-tile.away { background: transparent; border-style: dashed; }
.odds-tile.away .odds { color: var(--chalk-3); }
.row:hover .odds-tile.away { background: transparent; border-color: var(--chalk-3); }
.row:hover .odds-tile.away .odds { color: var(--chalk-2); }

.warnish { color: var(--warn); }

.odds-tile.locked { border-style: dashed; border-color: var(--floodlight-dim); background: transparent; }
.odds-locked {
  display: block;
  font-family: var(--display);
  font-weight: var(--weight-black);
  font-size: var(--text-xl);
  letter-spacing: 0.14em;
  line-height: 1;
  color: var(--floodlight);
}

/* ---------------------------------------------------------- live state */

/*
 * A match that is happening now says so, in red, with a dot that pulses.
 *
 * The board runs from six hours ago so today's games stay on it, and every one
 * of those was rendered with a kick-off time as though it had not happened yet.
 * On a three-hundred-match board that was a hundred and seventy-seven matches
 * lying about their state.
 */
.live-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--body);
  font-size: var(--text-2xs);
  font-weight: var(--weight-black);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--lost);
  white-space: nowrap;
}
.live-badge i {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  animation: ping 1.8s var(--ease-in-out) infinite;
}
.live-badge.done { color: var(--chalk-3); }
@keyframes ping {
  0%   { box-shadow: 0 0 0 0 rgba(203, 49, 49, 0.55); }
  70%  { box-shadow: 0 0 0 6px rgba(203, 49, 49, 0); }
  100% { box-shadow: 0 0 0 0 rgba(203, 49, 49, 0); }
}

/* A finished game recedes. A live one is marked by its badge and nothing else:
   red down the side of two thirds of the board reads as two hundred errors. */
.row.is-ft .row-sel { color: var(--chalk-2); }

@media (max-width: 760px) {
  /*
   * Back to content width on a phone: a fixed 124px reserved for the price on
   * a 358px row is a third of it spent on nothing.
   *
   * `.row-when` is a centred column on the desktop layout. The mobile rule set
   * `align-items: center` on top of that and never reset the direction, so the
   * kick-off and its day stacked and centred themselves in a column the full
   * width of the row — a 26px time floating in the middle of the card with
   * everything else hard left. It is a left-aligned line here.
   */
  .row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      'when  price'
      'teams price'
      'call  call';
    gap: var(--space-2) var(--space-4);
    padding: var(--space-4);
  }
  .row-when {
    grid-area: when;
    flex-direction: row;
    align-items: baseline;
    justify-content: flex-start;
    gap: var(--space-3);
  }
  .row-day { margin-top: 0; }
  .row-teams { grid-area: teams; }
  .row-call { grid-area: call; margin-top: var(--space-3); }
  .row-price { grid-area: price; align-self: start; text-align: right; }
  .odds { font-size: var(--text-lg); }
  .row-time { font-size: var(--text-lg); }
}

/* The end of a capped board. Quiet, and it says why rather than just stopping. */
.board-foot {
  margin: var(--space-6) 0 0;
  max-width: 54ch;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--chalk-3);
}

/* ============================================================ filter bar */

/*
 * Sticky under the header. On a board a hundred rows long, a filter that
 * scrolls away is a filter nobody uses twice.
 */
.filters {
  display: flex;
  align-items: center;
  gap: var(--tap-gap);
  flex-wrap: wrap;
}
.filters select {
  appearance: none;
  min-height: var(--tap);
  padding: var(--space-3) var(--space-8) var(--space-3) var(--space-5);
  background-color: var(--terrace);
  color: var(--chalk);
  border: var(--border) solid var(--rule-firm);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 4.5L6 8.5L10 4.5' stroke='%238d94a3' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
  background-size: 12px;
  /* "Prices in United Kingdom" is longer than the control on a phone, and a
     country name is not something to abbreviate in the markup -- it runs into
     the chevron in whatever language the reader has. Clip it instead. */
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.filters select:hover { border-color: var(--chalk-3); }
.filters select:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* Side by side on a phone rather than one wide and one narrow on two lines.
   They are a pair and they should look like one. */
@media (max-width: 620px) {
  .filters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
  .filters select { padding-inline: var(--space-4) var(--space-7); }
  /* The switch and the country run the full width; the two that pair up sit
     side by side. The switch was clipping "Everything" against a half-width
     cell, which is what a fixed inline-flex does inside a grid track. */
  .filters .seg,
  .filters .filter-wide { grid-column: 1 / -1; }
  /* Three states now, so three tracks. It was two, and the third wrapped onto
     a line of its own with half the control left empty beside it. */
  .filters .seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .filters .seg button {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding-inline: var(--space-2);
  }
  .seg button i { margin-left: 4px; }
}

.section.dense .section-head .display { font-size: var(--text-2xl); letter-spacing: var(--tracking-2xl); }

/*
 * A two-state switch, squared, sharing one trough.
 *
 * Not two pills and not a dropdown: this is the most-used control on the board
 * and it should read as a thing with a current position, which a select does
 * not at a glance.
 */
.seg {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  background: var(--terrace);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius-sm);
}
.seg button {
  min-height: 34px;
  padding: 0 var(--space-5);
  border-radius: 3px;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--chalk-3);
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.seg button:hover { color: var(--chalk); }
.seg button.on { background: var(--chalk); color: var(--pitch); font-weight: var(--weight-bold); }

/* ========================================================= feature band */

/*
 * The argument for the product, with a real paragraph of the writing next to
 * it. A claim about the analysis is worth less than a sample of it.
 */
.band { border-block: var(--border) solid var(--hairline); background: var(--stand); }
.band-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(var(--space-8), 5vw, var(--space-11));
  align-items: start;
  padding-block: clamp(var(--space-10), 7vw, var(--space-12));
}
@media (max-width: 900px) { .band-inner { grid-template-columns: minmax(0, 1fr); } }
/* No narrative clean enough to quote: one column, and the copy keeps a
   readable measure rather than stretching across the whole grid. */
.band-inner.solo { grid-template-columns: minmax(0, 1fr); }
.band-inner.solo > div { max-width: 62ch; }

/* The ground, as a bounded plate above the heading rather than a wash under
   it. It says which fixture the paragraph on the right came from. */
.band-shot {
  position: relative;
  aspect-ratio: 21 / 9;
  margin-bottom: var(--space-7);
  overflow: hidden;
  border: var(--border) solid var(--hairline);
  border-radius: var(--radius);
  background: var(--terrace);
}
.band-shot img { width: 100%; height: 100%; object-fit: cover; }
.band-lede { margin-top: var(--space-5); }

.points { list-style: none; margin: var(--space-8) 0 0; padding: 0; display: grid; gap: var(--space-6); }
.points li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.points .n {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-weight: var(--weight-bold);
  font-size: var(--text-md);
  font-variant-numeric: tabular-nums;
  color: var(--floodlight-hi);
  padding-top: 2px;
}
.points b { display: block; margin-bottom: 3px; font-size: var(--text-md); font-weight: var(--weight-medium); }
.points span { color: var(--chalk-2); font-size: var(--text-sm); line-height: var(--leading-normal); }

/* A sample of the writing, set as what it is: a pull quote. */
.reason {
  padding: var(--space-7);
  background: var(--terrace);
  border: var(--border) solid var(--hairline);
  border-left: 3px solid var(--floodlight);
  border-radius: var(--radius);
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--chalk);
  text-wrap: pretty;
}
.reason .qmeta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
  padding-bottom: var(--space-4);
  border-bottom: var(--border) solid var(--hairline);
  font-size: var(--text-sm);
  color: var(--chalk-3);
}
.qmeta b { color: var(--chalk); font-weight: var(--weight-medium); }
.qmeta .qlink {
  margin-left: auto;
  color: var(--floodlight-hi);
  font-weight: var(--weight-medium);
  white-space: nowrap;
}
.qmeta .qlink:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ======================================================== results strip */

.strip { border-bottom: var(--border) solid var(--hairline); }
.strip-inner {
  max-width: var(--maxw);
  margin-inline: auto;
  padding: var(--space-5) var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  overflow-x: auto;
  scrollbar-width: none;
}
.strip-inner::-webkit-scrollbar { display: none; }
.res {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  flex: none;
  padding: var(--space-2) var(--space-5) var(--space-2) var(--space-2);
  background: var(--stand);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  color: var(--chalk-2);
  white-space: nowrap;
}
.res-tie { min-width: 0; }
.res-mark { font-weight: var(--weight-bold); }
.res-mark.w { color: var(--won); }
.res-mark.l { color: var(--lost); }

/* ============================================================ stat band */

.statband { border-bottom: var(--border) solid var(--hairline); padding-block: clamp(var(--space-8), 5vw, var(--space-10)); }
.statgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-6); }
.statcell { display: flex; flex-direction: column; gap: var(--space-2); }
.statcell b {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-weight: var(--weight-bold);
  font-size: var(--text-3xl);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-3xl);
  line-height: 1;
}
.statcell span { font-size: var(--text-sm); color: var(--chalk-3); }
@media (max-width: 700px) { .statgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-7); } }

/* ============================================================== leagues */

.lgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--space-3); }
.lcard {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  text-align: center;
  padding: var(--space-7) var(--space-5);
  background: var(--stand);
  border: var(--border) solid var(--hairline);
  border-radius: var(--radius);
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.lcard:hover { background: var(--terrace); border-color: var(--rule); }
.lcard b { font-size: var(--text-sm); font-weight: var(--weight-medium); line-height: var(--leading-snug); }
.lcard span { font-size: var(--text-xs); color: var(--chalk-3); }

/* ============================================================== closing */

.closing { border-top: var(--border) solid var(--hairline); background: var(--stand); }
.closing-in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-7);
  flex-wrap: wrap;
  padding-block: clamp(var(--space-9), 6vw, var(--space-11));
}
.closing-in p {
  margin: 0 0 var(--space-1);
  font-family: var(--hand);
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--floodlight-hi);
}

/* ========================================================= fixture page */

.back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 36px;
  margin-bottom: var(--space-5);
  font-size: var(--text-sm);
  color: var(--chalk-2);
}
.back:hover { color: var(--chalk); }
.back svg { width: 14px; height: 14px; flex: none; }

/*
 * The detail masthead is the front door's, shorter.
 *
 * A fixture page that opened with a different shape from the page that linked
 * to it read as a different site. Same photograph treatment, same stacked tie,
 * same kick-off chip — just less height, because the page below it is the point.
 */
.fx-top .hero-inner { min-height: clamp(280px, 34vw, 380px); padding-block: var(--space-6) var(--space-8); }
/* The fixture hero has no match centre, so its copy column can be wider than
   the front page's 340px: a long name beside a goal tally needs the room, and
   "Netherlands 1" was breaking in half without it. */
@media (min-width: 1041px) {
  .fx-top .hero-inner { grid-template-columns: minmax(0, 1fr) minmax(340px, 520px); }
  .fx-top .hero-copy { max-width: none; }
}
.fx-top .back { grid-column: 1 / -1; align-self: flex-start; margin-bottom: auto; }
/*
 * The two clubs' colours, each glowing from behind its own crest: the home
 * side's from above its row, the away side's from below its own. Soft and
 * low on purpose -- the first version washed the whole masthead in two flat
 * bands, which shouted. Drawn on the rows rather than the masthead, so the
 * glow follows the crest at any width, and sized to the viewport so it fills
 * a desktop banner without swamping a phone.
 */
.fx-top.has-colors .fx-line { position: relative; }
.fx-top.has-colors .fx-line::before {
  content: '';
  position: absolute;
  z-index: -1;
  pointer-events: none;
  left: 17px;
  top: 50%;
  width: clamp(440px, 80vw, 1150px);
  height: clamp(440px, 34vw, 500px);
  transform: translate(-50%, calc(-50% + var(--glow-dy)));
  background: radial-gradient(closest-side, color-mix(in srgb, var(--glow-c) 28%, transparent), transparent);
}
.fx-top.has-colors .fx-line:nth-child(1) { --glow-c: var(--home-c); --glow-dy: -50px; }
.fx-top.has-colors .fx-line:nth-child(2) { --glow-c: var(--away-c); --glow-dy: 50px; }
/* The masthead's foot fades into the page, so the glows never end in an edge. */
.fx-wash {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to top, var(--pitch) 0%, transparent 45%);
}
.fx-top.has-colors[data-shot="none"] .hero-media { background: var(--terrace); }
.fx-top .fx-line .chips { margin-left: var(--space-2); }
.fx-top .hero-blurb { margin-bottom: 0; }

/* The scoreline, where the form chips sit on a match still to come.
 *
 * It takes the right-hand edge rather than trailing the name, so the two
 * numbers line up under each other and read as a score instead of as two
 * facts. Tabular figures for the same reason. The losing side's number is
 * dimmed rather than the winner's being coloured: on a photograph, one bright
 * number beside one dim one says who won without needing a legend. */
.fx-stack.scored .fx-line { flex-wrap: nowrap; }
/* A size down beside a score, so "Netherlands" fits on one line next to its
   goal tally instead of breaking in half. The unscored line keeps the full
   hero size; it has the whole width to itself. */
.fx-stack.scored .fx-line .name { flex: 1 1 auto; font-size: clamp(1.75rem, 3.2vw, 3rem); }
.fx-line .gf {
  flex: none;
  margin-left: auto;
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-size: var(--text-hero);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  font-variation-settings: 'wdth' var(--condensed);
  color: var(--chalk-3);
}
.fx-line .gf.win { color: var(--chalk); }

/* A settled call is reported, not offered. The left rule is the whole signal:
   it colours the block without recolouring the prose inside it, which still
   has to be read as ordinary text. */
.verdict.settled { border-left: 2px solid var(--hairline); padding-left: var(--space-5); }
.verdict.settled.won  { border-left-color: var(--won); }
.verdict.settled.lost { border-left-color: var(--lost); }
.verdict.settled.part,
.verdict.settled.back { border-left-color: var(--void); }
.verdict-head .mark { flex: none; margin-left: auto; }

/* Why this call: the members' paragraph, the argument for this market at its
   odds. A left rule in the accent sets it apart from the free preview above
   without making it a second card. */
.verdict .why {
  margin-top: var(--space-5);
  padding-left: var(--space-5);
  border-left: 2px solid var(--floodlight);
}
.verdict .why-head {
  margin: 0 0 var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--floodlight-hi);
}
.verdict .why p:last-child {
  margin: 0;
  max-width: 68ch;
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--chalk);
}

/* Set apart from the prose it qualifies, because it is about the prose rather
   than about the match: a narrative written in the future tense on a game
   that has been played needs saying so, not rewriting. */
.verdict .aside {
  margin: var(--space-3) 0 0;
  font-size: var(--text-xs);
  color: var(--chalk-3);
  font-style: italic;
}

.grid-2 { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: var(--space-5); align-items: start; }
@media (max-width: 980px) { .grid-2 { grid-template-columns: minmax(0, 1fr); } }

/* ------------------------------------------------------------- verdicts */

.verdict + .verdict {
  margin-top: var(--space-7);
  padding-top: var(--space-7);
  border-top: var(--border) solid var(--hairline);
}
.verdict-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.verdict-head .sel { flex: 1 1 14ch; }
.verdict-head .odds { flex: none; margin-left: auto; }

.narrative {
  margin: 0;
  max-width: 68ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--chalk);
  text-wrap: pretty;
}
.narrative + .narrative { margin-top: var(--space-5); }

.numbers { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-5); }
.numbers span {
  padding: var(--space-2) var(--space-4);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--terrace);
  font-size: var(--text-xs);
  color: var(--chalk-2);
}
.numbers b { color: var(--chalk); font-weight: var(--weight-medium); font-variant-numeric: tabular-nums; }

.disclosure {
  margin: var(--space-4) 0 0;
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--chalk-3);
  max-width: 68ch;
}

/*
 * How a handicap settles. Collapsed by default: it is the answer to a question
 * most readers will never ask, and unmissable for the ones who do.
 */
.settles { margin-top: var(--space-6); padding-top: var(--space-5); border-top: var(--border) solid var(--hairline); }
.settles summary {
  cursor: pointer;
  min-height: 32px;
  font-size: var(--text-sm);
  color: var(--chalk-2);
}
.settles summary:hover { color: var(--chalk); }
.settle-tbl { margin-top: var(--space-4); font-size: var(--text-sm); width: 100%; border-collapse: collapse; }
.settle-tbl td { padding: var(--space-3) 0; border-bottom: var(--border) solid var(--hairline); }
.settle-tbl tr:last-child td { border-bottom: 0; }
.settle-tbl .win { color: var(--won); }
.settle-tbl .loss { color: var(--chalk-3); }
.settle-tbl .push,
.settle-tbl .part { color: var(--warn); }

/* ------------------------------------------------------ factors and bars */

.reads { display: grid; }
.read { padding: var(--space-4) 0; border-bottom: var(--border) solid var(--hairline); }
.read:first-child { padding-top: 0; }
.read:last-child { padding-bottom: 0; border-bottom: 0; }
.read b {
  display: block;
  margin-bottom: 3px;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--floodlight-hi);
}
.read p { margin: 0; font-size: var(--text-sm); line-height: var(--leading-normal); color: var(--chalk-2); }

.bars { display: grid; gap: var(--space-4); }
.bar-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-2) var(--space-4);
  align-items: center;
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--chalk-2);
}
.bar-row .lab { display: flex; justify-content: space-between; gap: var(--space-3); min-width: 0; }
.bar { grid-column: 1 / -1; height: 5px; border-radius: var(--radius-pill); background: var(--terrace); overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--floodlight); }

/* Two sides of one number, shown as one track rather than two. */
.sbar + .sbar { margin-top: var(--space-5); }
.sbar-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-2);
  font-size: var(--text-xs);
  color: var(--chalk-3);
}
.sbar-top b { color: var(--chalk); font-weight: var(--weight-medium); font-variant-numeric: tabular-nums; }
.sbar-track { display: flex; height: 5px; border-radius: var(--radius-pill); overflow: hidden; background: var(--terrace); }
.sbar-track i.h { background: var(--floodlight); }
.sbar-track i.a { background: var(--chalk-3); }

/* ------------------------------------------------------------------ form */

.form-top { display: flex; justify-content: space-between; align-items: center; gap: var(--space-4); margin-bottom: var(--space-6); flex-wrap: wrap; }
.form-side { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.form-side.right { margin-left: auto; }
.run { font-size: var(--text-xs); color: var(--chalk-3); white-space: nowrap; }
.form-split { margin: var(--space-5) 0 0; font-size: var(--text-sm); color: var(--chalk-2); line-height: var(--leading-normal); }
.form-split b { color: var(--chalk); font-weight: var(--weight-medium); }

/* ------------------------------------------------------------------- h2h */

.h2h-list { margin-top: var(--space-5); border-top: var(--border) solid var(--hairline); }
.h2h-row {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-3) 0;
  border-bottom: var(--border) solid var(--hairline);
  font-size: var(--text-sm);
}
.h2h-row:last-child { border-bottom: 0; }
.h2h-date { flex: none; width: 64px; font-size: var(--text-xs); color: var(--chalk-3); }
.h2h-teams { color: var(--chalk-2); min-width: 0; }
.h2h-teams b { color: var(--chalk); font-weight: var(--weight-bold); font-variant-numeric: tabular-nums; padding: 0 var(--space-2); }

/* ----------------------------------------------------------- the pitch */

/*
 * Two halves of a pitch, side by side.
 *
 * The tracks were `minmax(0, 1fr)`, which explicitly permits a column to
 * shrink BELOW its content. On a phone they resolved to 140px while each half
 * kept its 240px min-width, so both halves spilled out of their tracks and
 * overlapped by nearly a hundred pixels — two team sheets drawn on top of each
 * other, names over names. The same `minmax(0, …)` also defeated the
 * `overflow-x: auto` underneath it: the grid shrank to the container instead
 * of staying as wide as its content and letting the container scroll.
 *
 * The floor is now the width five players actually need, so the grid is at
 * least as wide as a pitch and scrolls when it has to.
 */
/* ============================================================ team sheet
 *
 * One pitch, two teams facing each other.
 *
 * It was two half-pitches stacked, both laid out in the same direction, which
 * is a list with a green background: the entire point of drawing a team sheet
 * is that you can see a back four against a front three. Home attacks up from
 * the bottom, away attacks down from the top, and the markings are actually
 * drawn -- that is what makes it read as a pitch rather than as a panel, and
 * it costs one inline SVG scaled to a real 68x105 so the boxes are the right
 * size relative to everything else.
 */
.sheet-heads {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}
.sheet-team {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}
.sheet-team b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet-heads .sheet-team:last-child { flex-direction: row-reverse; text-align: right; }
.formation {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  color: var(--floodlight-hi);
}

.pitch {
  position: relative;
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-2);
  aspect-ratio: 68 / 96;
  border: var(--border) solid var(--hairline);
  border-radius: var(--radius);
  /* Mown stripes across the pitch, the way they are actually cut. */
  background:
    repeating-linear-gradient(180deg, rgba(255, 255, 255, 0.022) 0 8%, transparent 8% 16%),
    linear-gradient(170deg, #12281c, #0b1a13);
  overflow: hidden;
}
.pitch-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: rgba(255, 255, 255, 0.13);
  stroke-width: 0.45;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
.pitch-lines .spot { fill: rgba(255, 255, 255, 0.18); stroke: none; }

.pitch-side {
  position: relative;
  display: grid;
  align-content: space-between;
  gap: var(--space-2);
  min-height: 0;
}
.pitch-row {
  display: flex;
  justify-content: space-evenly;
  align-items: flex-start;
  gap: var(--space-1);
}

.pp {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  width: 64px;
  min-width: 0;
}
.pp .crest {
  width: 32px;
  height: 32px;
  background: rgba(0, 0, 0, 0.45);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
}
/* The best-rated starter on each side. Ringed rather than labelled: the
   rating behind it is ours and stays ours. */
.pp.key .crest { box-shadow: 0 0 0 2px var(--floodlight-hi), 0 1px 4px rgba(0, 0, 0, 0.45); }
.pp-name {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10px;
  font-weight: var(--weight-medium);
  line-height: 1.2;
  letter-spacing: 0.01em;
  color: var(--chalk);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
}

@media (max-width: 420px) {
  .pitch { padding-inline: 2px; }
  .pp { width: 54px; }
  .pp .crest { width: 28px; height: 28px; }
  .pp-name { font-size: 9px; }
}

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

.tabs {
  display: flex;
  gap: var(--space-1);
  margin: 0 0 var(--space-5);
  border-bottom: var(--border) solid var(--hairline);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  flex: none;
  min-height: var(--tap);
  padding: var(--space-3) var(--space-5);
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--chalk-3);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.tab:hover { color: var(--chalk-2); }
.tab.on { color: var(--chalk); border-bottom-color: var(--floodlight); }

/* ================================================================ tables */

.tbl { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.tbl th {
  text-align: left;
  padding: var(--space-3) var(--space-4) var(--space-3) 0;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--chalk-3);
  border-bottom: var(--border) solid var(--rule);
  white-space: nowrap;
}
.tbl td {
  padding: var(--space-4) var(--space-4) var(--space-4) 0;
  border-bottom: var(--border) solid var(--hairline);
  vertical-align: middle;
}
.tbl tr:last-child td { border-bottom: 0; }
.tbl .num { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ============================================================== results */

/*
 * The record, said in money.
 *
 * The figure is the headline and the sample-size caveat sits under it — never
 * the other way round, and never omitted. This page being believable is the
 * entire marketing strategy, so the sign is never softened and the losses are
 * never filtered out.
 */
.record { margin-bottom: var(--space-9); }
.record-line {
  margin: 0;
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-size: var(--text-3xl);
  letter-spacing: var(--tracking-3xl);
  line-height: var(--leading-tight);
  text-wrap: balance;
}
.record-sub { margin: var(--space-4) 0 0; font-size: var(--text-lg); color: var(--chalk-2); max-width: 54ch; }
.record-note { margin: var(--space-5) 0 0; font-size: var(--text-sm); color: var(--chalk-3); max-width: 60ch; line-height: var(--leading-normal); }

/* `.ledger` and its own `.stat` lived here for a panel no view renders any
   more, and a second `.stat` further down was quietly overriding it from the
   bottom of the file. One definition now, with the record strip. */

/* ============================================================== the wall */

/*
 * A locked call is an offer, not an error.
 *
 * It sits directly under the reasoning on a fixture page, which is the only
 * place it is worth anything — a reader who has just been argued into caring
 * about a match is in a different position from one shown a price up front. So
 * it uses the accent and a raised surface rather than the muted treatment an
 * empty state gets, and it says what is behind it rather than that something
 * is missing.
 */
.locked {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  flex-wrap: wrap;
  margin-top: var(--space-6);
  padding: var(--space-6) var(--space-7);
  background: var(--terrace);
  border: var(--border) solid var(--floodlight-dim);
  border-left: 3px solid var(--floodlight);
  border-radius: var(--radius);
}
.locked-body { min-width: 0; flex: 1 1 260px; }
.locked-body b {
  display: block;
  font-family: var(--hand);
  font-weight: 700;
  font-size: var(--text-2xl);
  color: var(--chalk);
}
.locked-body p {
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--chalk-2);
}
/*
 * On a phone the two halves stack.
 *
 * Side by side they do not simply look cramped, they push the page sideways:
 * the button's min-content width becomes a floor that the verdict, the panel
 * and finally the document all have to honour. Three pixels of horizontal
 * scroll on every fixture with a call on it, traced back to one declaration.
 */
@media (max-width: 560px) {
  .locked { flex-direction: column; align-items: stretch; }
  .locked .btn { width: 100%; }
}

/* ============================================================== pricing */

.pricing {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: var(--space-5);
  align-items: start;
}
/* The paid plan is raised rather than shouted at: one accent border and a
   lighter ground. No badge, and no "most popular" on a page with one plan. */
.plan-free { background: var(--stand); }
.plan-paid { background: var(--terrace); border-color: var(--floodlight-dim); }
.plan-price {
  margin: 0 0 var(--space-6);
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.plan-price b {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-weight: var(--weight-bold);
  font-size: var(--text-4xl);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-4xl);
  line-height: 1;
}
.plan-price span { font-size: var(--text-md); color: var(--chalk-3); }
.plan-note { margin: var(--space-5) 0 0; font-size: var(--text-xs); color: var(--chalk-3); line-height: var(--leading-normal); }

.ticks { list-style: none; margin: 0 0 var(--space-7); padding: 0; }
.ticks li {
  position: relative;
  padding-left: var(--space-7);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--chalk-2);
}
.ticks li b { color: var(--chalk); font-weight: var(--weight-medium); }
.ticks li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.38em;
  width: 9px;
  height: 5px;
  border-left: 2px solid var(--floodlight-hi);
  border-bottom: 2px solid var(--floodlight-hi);
  transform: rotate(-45deg);
}

.pricing-small { margin-top: var(--space-10); font-size: var(--text-sm); }

/* ============================================================== sign in */

.signin { display: flex; flex-direction: column; gap: var(--space-5); }
.signin form { display: flex; flex-direction: column; gap: var(--space-4); }
.signin label { font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--chalk-2); }
.signin input {
  width: 100%;
  min-height: var(--tap);
  padding: var(--space-4) var(--space-5);
  background: var(--pitch);
  color: var(--chalk);
  border: var(--border) solid var(--rule-firm);
  border-radius: var(--radius);
  font-size: var(--text-md);
}
.signin input::placeholder { color: var(--chalk-3); }
.signin input:focus-visible { outline: none; box-shadow: var(--focus-ring); border-color: var(--floodlight); }

.or { display: flex; align-items: center; gap: var(--space-4); font-size: var(--text-xs); color: var(--chalk-3); }
.or::before, .or::after { content: ''; flex: 1; height: 1px; background: var(--rule); }

.signin-note { margin: 0; min-height: 1.4em; font-size: var(--text-sm); line-height: var(--leading-normal); }
.signin-note.ok { color: var(--chalk-2); }
.signin-note.bad, .form-error { color: var(--lost); }
.form-error { margin: 0 0 var(--space-5); font-size: var(--text-sm); }

/* ============================================================== account */

.acct-state { margin: 0 0 var(--space-3); font-size: var(--text-lg); }
.acct-state.on b { color: var(--chalk); font-weight: var(--weight-medium); }
.acct-state.off { color: var(--chalk-2); }
.acct-line { margin: 0 0 var(--space-5); font-size: var(--text-sm); color: var(--chalk-3); line-height: var(--leading-normal); }

/* ================================================================ prose */

.prose { max-width: var(--maxw-read); }
.prose h2 {
  margin: var(--space-9) 0 var(--space-4);
  font-family: var(--display);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-xl);
}
.prose p, .prose li {
  color: var(--chalk-2);
  font-size: var(--text-md);
  line-height: var(--leading-normal);
}
.prose ul { padding-left: var(--space-6); }
.prose li { margin-bottom: var(--space-2); }
.prose a { color: var(--chalk); text-decoration: underline; text-underline-offset: 2px; }

/* ======================================================== cookie notice */

.cookie {
  position: fixed;
  right: var(--space-5);
  bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
  z-index: var(--z-overlay);
  width: min(400px, calc(100vw - var(--space-8)));
  display: flex;
  align-items: center;
  /* It is the first thing on the site anybody sees and it is not the product,
     so it takes as little of a phone screen as it can while still being a
     real choice: one sentence, two small buttons, tight padding. It was three
     lines of text and two full-size buttons, which is a fifth of the viewport
     spent on a notice about one localStorage key. */
  gap: var(--space-3) var(--space-4);
  flex-wrap: wrap;
  padding: var(--space-4) var(--space-5);
  background: var(--terrace);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--elev-3);
}
.cookie p { flex: 1 1 100%; margin: 0; font-size: var(--text-xs); line-height: var(--leading-snug); color: var(--chalk-2); }
.cookie a { color: var(--chalk); text-decoration: underline; text-underline-offset: 2px; }

/*
 * On a phone it stops floating.
 *
 * A fixed card at the bottom of a 390px viewport is sitting on top of roughly
 * an eighth of the page, and the page decides what is underneath it. On the
 * pricing page that was the button that takes the money, and the tap went to
 * the notice instead: nothing a reader could see was wrong, and nothing they
 * did worked. Reserving space at the foot of the document does not fix it
 * either, because the thing being covered is in the middle of the page with a
 * footer below it.
 *
 * So on a narrow screen it is an ordinary bar in the flow, directly under the
 * header, where it pushes the page down instead of covering it. Same words,
 * same two buttons, and it cannot be on top of anything because it is not on
 * top of anything.
 */
@media (max-width: 700px) {
  .cookie {
    position: static;
    width: auto;
    margin: 0 var(--space-4) var(--space-4);
    border-radius: var(--radius-sm);
    box-shadow: none;
  }
}

/* ===================================================== reduced motion */

/* Everything above degrades to a colour change. Nothing here is load-bearing
   on movement — a reader who has asked the operating system to stop animating
   things loses no information. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------------------------------------------------------------- the recap
 *
 * The results page, matchday by matchday.
 *
 * The layout is one idea: what happened on the left, what we said in the
 * middle, and the mark on the right, so the eye can run down any one of the
 * three columns on its own. A reader checking whether we were any good reads
 * the right column. A reader who remembers the game reads the left. A reader
 * deciding whether to pay for this reads the middle.
 *
 * The left edge carries the colour, not the whole card. A red-tinted panel per
 * loss turns a page that is one-third losses into a page that looks broken --
 * which was the note on the board, and it is truer here, where losses are the
 * point rather than an embarrassment.
 */
.recap-day { margin-bottom: var(--space-9); }
.recap-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: var(--border) solid var(--rule-firm);
}
.recap-head h3 {
  font-family: var(--display);
  font-weight: var(--weight-black);
  font-size: var(--text-xl);
  letter-spacing: var(--tracking-xl);
  line-height: 1;
}
.recap-tally {
  flex: none;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--chalk-3);
  white-space: nowrap;
}
.recap-say {
  margin: var(--space-3) 0 var(--space-5);
  font-size: var(--text-lg);
  color: var(--chalk-2);
}

.recap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr) auto;
  /* Top-aligned, not centred: opening the reason makes the middle column four
     times the height of the other two, and centring then floats the clubs and
     the mark in the middle of a paragraph they have nothing to do with. */
  align-items: start;
  gap: var(--space-5);
  padding: var(--space-4) var(--space-5);
  border-left: 3px solid var(--rule-firm);
  border-bottom: var(--border) solid var(--hairline);
  transition: background var(--dur-fast) var(--ease-out);
}
.recap:hover { background: var(--stand); }
.recap.is-won { border-left-color: var(--won); }
.recap.is-lost { border-left-color: var(--lost); }
.recap.is-part,
.recap.is-back { border-left-color: var(--void); }

.recap-tie { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.recap-side {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}
.recap-side > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.recap-body { min-width: 0; }
.recap-call { font-size: var(--text-sm); color: var(--chalk-2); }
.recap-call b { color: var(--chalk); font-weight: var(--weight-bold); }
.recap-what { margin-top: 2px; font-size: var(--text-sm); color: var(--chalk-3); }

/* The argument we made before kick-off, kept closed. Open by choice, because
   on a loss it is the most interesting thing on the page and on a win nobody
   needs convincing twice. */
.recap-why { margin-top: var(--space-3); }
.recap-why summary {
  display: inline-block;
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--chalk-3);
  cursor: pointer;
}
.recap-why summary:hover { color: var(--chalk-2); }
.recap-why[open] summary { margin-bottom: var(--space-2); color: var(--chalk-2); }
.recap-why p {
  padding-left: var(--space-4);
  border-left: var(--border) solid var(--rule-firm);
  font-size: var(--text-sm);
  color: var(--chalk-2);
}

/* On a phone the three columns become three rows, with the mark pulled up
   beside the tie so the answer is still visible without reading the card. */
@media (max-width: 760px) {
  .recap {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      'tie  mark'
      'body body';
    gap: var(--space-3) var(--space-4);
    padding: var(--space-4) var(--space-4) var(--space-5);
  }
  .recap-tie { grid-area: tie; }
  .recap-body { grid-area: body; }
  .recap .mark { grid-area: mark; align-self: start; }
}

/* The rest of what we checked, folded away. Nothing is hidden; it is just not
   in front of the two facts that decided the call. */
.more-reads { margin-top: var(--space-5); }
.more-reads summary {
  display: inline-block;
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--chalk-3);
  cursor: pointer;
}
.more-reads summary:hover { color: var(--chalk-2); }
.more-reads[open] summary { margin-bottom: var(--space-4); color: var(--chalk-2); }

/* A game we passed on, and a game behind the wall: two lines, not four. The
   answer sits in the column the price would be in, and the reasoning is still
   one tap away on the fixture page. */
.row.is-terse { padding-block: var(--space-3); }
.row-pass {
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--chalk-3);
  white-space: nowrap;
}

/* The wall, on a board row. An offer rather than an absence, so it takes the
   accent colour -- but at the weight of a label, not a button: two hundred
   purple buttons down a board is a page that is shouting. */
.row-locked-mark {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--floodlight-hi);
  white-space: nowrap;
}
.row-locked-mark svg {
  width: 13px; height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

/* ======================================================== a page masthead
 *
 * The title is the biggest thing on the page. That sounds obvious and the
 * results page had it the other way round: "Results" at subheading size with
 * the record set beneath it in the largest display type on the site, so the
 * page's own name read as a caption and the element that reflowed worst was
 * the one taking up the most room.
 */
.page-head { margin-bottom: var(--space-7); }
.page-sub {
  margin-top: var(--space-3);
  max-width: 56ch;
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--chalk-2);
}

/*
 * The record, as figures.
 *
 * Four numbers with what each one is. A record is read by scanning, not by
 * parsing a sentence, and a grid is legible at any width where a two-line
 * display-face sentence is not. Two across on a phone, four on a laptop.
 */
/* ================================================================= pager
 *
 * Numbered, not "load more". A number is somewhere you can go back to; a
 * button that grows the page is not, and it makes the thing you were reading
 * move. The steps read Newer and Older rather than Previous and Next, because
 * on a record that is what the direction actually means.
 */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-8);
  padding-top: var(--space-5);
  border-top: var(--border) solid var(--rule-firm);
}
.pager-nums { display: flex; align-items: center; gap: var(--space-2); }
.pager-num,
.pager-step {
  min-height: var(--tap);
  padding: var(--space-2) var(--space-4);
  background: transparent;
  border: var(--border) solid var(--rule-firm);
  border-radius: var(--radius-sm);
  color: var(--chalk-2);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.pager-num { min-width: var(--tap); padding-inline: var(--space-3); }
.pager-num:hover,
.pager-step:hover:not([disabled]) { background: var(--terrace); color: var(--chalk); }
.pager-num.on {
  background: var(--chalk);
  border-color: var(--chalk);
  color: var(--pitch);
  font-weight: var(--weight-bold);
}
.pager-step[disabled] { opacity: 0.35; cursor: default; }
.pager-gap { padding: 0 var(--space-1); color: var(--chalk-3); }
.pager-num:focus-visible,
.pager-step:focus-visible { outline: none; box-shadow: var(--focus-ring); }

@media (max-width: 480px) {
  /* The numbers are the part worth keeping at this width; Newer and Older are
     one tap of scrolling away from the same place. */
  .pager-step { padding-inline: var(--space-3); font-size: var(--text-xs); }
  .pager-nums { gap: 3px; }
  .pager-num { min-width: 38px; padding-inline: var(--space-2); }
}

/* "How it went" was sitting on top of the sentence above it, at a size that
   read as a caption rather than as the heading of the longest section on the
   page. */
.with-side .side-head {
  margin-top: var(--space-8);
  font-size: var(--text-xl);
  letter-spacing: var(--tracking-xl);
}

/* Who is missing. A wrapping row rather than an inline run, because the reason
   a player is out is a sentence and five of them side by side pushed the page
   nine hundred pixels sideways on a phone. */
.outlist {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-5);
}
.outlist > b {
  flex: 0 0 100%;
  margin-bottom: var(--space-1);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--chalk-3);
}

/* The count behind each state on the board's control. It is the difference
   between a tab and a tab worth pressing. */
.seg button i {
  margin-left: var(--space-2);
  font-style: normal;
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-medium);
  opacity: 0.55;
}
.seg button[disabled] { opacity: 0.35; cursor: default; }
.seg button[disabled]:hover { background: transparent; color: inherit; }

/* The call filter, demoted to a sentence. It answers a question nobody arrives
   with, so it sits under the board rather than beside the thing that does. */
.board-toggle { margin: var(--space-4) 0 var(--space-5); }
.board-toggle button {
  padding: 0;
  background: none;
  border: 0;
  color: var(--chalk-3);
  font: inherit;
  font-size: var(--text-xs);
  text-align: left;
  cursor: pointer;
  border-bottom: var(--border) solid transparent;
}
.board-toggle button:hover { color: var(--chalk-2); border-bottom-color: var(--rule-firm); }
.board-toggle button:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ======================================================== the post-mortem
 *
 * Why it landed, or why it did not. The verdict reads as a sentence and the
 * three facts behind it sit under it as a row, so a reader can take the
 * sentence and move on, or check the working. The colour is on the left edge
 * of the card already; this block stays neutral, because a page where every
 * loss is red is a page that looks broken rather than honest.
 */
.pm {
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--terrace);
  border-radius: var(--radius-sm);
}
.pm-line {
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--chalk-2);
}
.pm-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-2);
}
.pm-facts span {
  font-size: var(--text-2xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--chalk-3);
  white-space: nowrap;
}
.pm-facts span + span { position: relative; }
.pm-facts span + span::before {
  content: '';
  position: absolute;
  left: calc(var(--space-2) * -1 - 1px);
  top: 50%;
  width: 3px; height: 3px;
  margin-top: -1px;
  border-radius: 50%;
  background: var(--rule-firm);
}

/* ============================================================== leagues
 *
 * One line per competition, in the same language as the board: crest, name,
 * then the counts out at the right edge so they line up down the page and can
 * be read as a column. The name carries the weight because the name is what
 * somebody is scanning for -- it was the other way round, with the counts in
 * white and the name in the muted colour.
 */
.lg-list { display: flex; flex-direction: column; margin-bottom: var(--space-8); }
.lg {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-2);
  border-bottom: var(--border) solid var(--hairline);
  transition: background var(--dur-fast) var(--ease-out);
}
.lg:hover { background: var(--stand); }
.lg:focus-visible { outline: none; box-shadow: var(--focus-ring); position: relative; z-index: 1; }

.lg-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  color: var(--chalk);
}
.lg-games {
  font-size: var(--text-xs);
  color: var(--chalk-3);
  white-space: nowrap;
}
/* The call count is the reason this page exists, so it gets the tabular
   column and the accent -- and a dash rather than a nought, because "0 calls"
   forty times down a page reads as a broken feed. */
.lg-calls {
  min-width: 68px;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--chalk-3);
  white-space: nowrap;
}
.lg-calls.on { color: var(--floodlight-hi); font-weight: var(--weight-bold); }

.lg-live {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  color: var(--lost);
}
.lg-live i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
  animation: ping 1.8s var(--ease-in-out) infinite;
}

/* The competitions we have nothing in still belong on the page -- it is a
   list of what is on, not a list of what we fancied -- but they recede. */
.lg-list.muted .lg-name { color: var(--chalk-2); font-weight: var(--weight-normal); }

/*
 * On a touch screen, 34px is a miss waiting to happen.
 *
 * Every guideline puts the floor somewhere between 44 and 48, and the controls
 * that were under it here are not incidental: the header's sign-in, the two
 * consent buttons, the board's own to-play/live/played switch and the toggle
 * that hides the games we have no call on. The type stays where it is -- this
 * is padding, not a redesign -- and nothing above the touch breakpoint
 * changes, because a cursor does not miss.
 *
 * It lives at the end of the last stylesheet on purpose: the rules it has to
 * beat are ordinary single-class selectors, so specificity cannot settle it
 * and order has to.
 */
@media (max-width: 700px) {
  .btn-sm,
  .seg button,
  .board-toggle button,
  select,
  input { min-height: 44px; }
}

/* =========================================================== home: side */

/* The column beside the record. It stacks its blocks with the panel gap and
   sticks under the header on a wide screen, so the slip stays in view while
   the record scrolls past it. */
.home-side { display: flex; flex-direction: column; gap: var(--space-5); }
.home-side .panel + .panel { margin-top: 0; }
@media (min-width: 1041px) { .home-side { position: sticky; top: var(--space-9); } }
.side-block { padding: var(--space-5) var(--space-6); }

/* ------------------------------------------------------------- bet slip */

.slip { border-color: var(--floodlight-dim); }
.slip-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
}
.slip-odds {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-bold);
  font-size: var(--text-3xl);
  line-height: 1;
  color: var(--floodlight-hi);
}
.slip-odds small {
  margin-left: var(--space-3);
  font-family: var(--body);
  font-variation-settings: normal;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--chalk-3);
}
.slip-legs { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--chalk-2); white-space: nowrap; }
.slip-chance { margin: var(--space-4) 0 0; font-size: var(--text-sm); line-height: var(--leading-snug); color: var(--chalk-2); }
.slip-chance b { color: var(--chalk); }
.slip-empty { margin: 0; font-size: var(--text-sm); line-height: var(--leading-snug); color: var(--chalk-2); }
.slip-list { list-style: none; margin: var(--space-5) 0 0; padding: 0; counter-reset: leg; }
.slip-list li { border-top: var(--border) solid var(--hairline); }
.slip-list a {
  display: grid;
  gap: var(--space-1);
  padding: var(--space-4) 0 var(--space-4) var(--space-7);
  position: relative;
}
.slip-list a::before {
  counter-increment: leg;
  content: counter(leg);
  position: absolute;
  left: 0;
  top: var(--space-4);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--floodlight-hi);
}
.slip-tie { font-size: var(--text-xs); color: var(--chalk-3); }
.slip-sel { font-weight: var(--weight-bold); color: var(--chalk); }
.slip-list a:hover .slip-sel { color: var(--floodlight-hi); }
.slip-meta { display: flex; justify-content: space-between; gap: var(--space-4); font-size: var(--text-xs); color: var(--chalk-3); }
.slip-meta b { font-variant-numeric: tabular-nums; color: var(--chalk-2); }
.slip-locked {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: var(--border) solid var(--hairline);
}
.slip-locked p { margin: 0 0 var(--space-4); font-size: var(--text-sm); color: var(--chalk-2); }
.slip-record { margin: var(--space-5) 0 0; font-size: var(--text-xs); color: var(--chalk-3); }
.slip-record b { color: var(--chalk-2); }

/* ---------------------------------------------------------- league chips */

.league-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.league-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 36px;
  padding: var(--space-2) var(--space-3);
  border: var(--border) solid var(--hairline);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  color: var(--chalk-2);
}
.league-chip b { font-variant-numeric: tabular-nums; color: var(--floodlight-hi); }
.league-chip:hover { border-color: var(--floodlight); color: var(--chalk); }

/* ----------------------------------------------- results: calls per match */

.played-calls {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: var(--space-3) 0 0;
  border-top: var(--border) solid var(--hairline);
  display: grid;
  gap: var(--space-2);
}
.played-calls li { display: flex; justify-content: space-between; align-items: center; gap: var(--space-4); font-size: var(--text-xs); color: var(--chalk-2); }

/* On one column the side comes first. It carries the bet slip, what is on now
   and where today's calls are -- the things a reader opens the page for -- and
   stacked after the main column it sat under forty results at the very bottom
   of a phone screen. */
@media (max-width: 1040px) {
  .with-side > .home-side { order: -1; }
}

/* ============================================================ owner's page */

.kv { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-2) var(--space-5); margin: 0; font-size: var(--text-sm); }
.kv dt { color: var(--chalk-3); }
.kv dd { margin: 0; color: var(--chalk); overflow-wrap: anywhere; }
.muted { color: var(--chalk-3); }
.small { font-size: var(--text-xs); line-height: var(--leading-snug); }
.panel .seg { display: inline-flex; margin-bottom: var(--space-4); }

/* The "view as" pill. A full-width band at the very top, in the warning
   colour, because a preview switch that can be forgotten is one that will be. */
.viewas-pill {
  display: block;
  padding: var(--space-2) var(--space-4);
  background: var(--warn);
  color: var(--pitch);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  text-align: center;
}

/* ================================================================ ticker */

/* One line that moves. Under the header on the front page only. */
.ticker {
  overflow: hidden;
  border-bottom: var(--border) solid var(--hairline);
  background: var(--stand);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 4%, #000 96%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 4%, #000 96%, transparent);
}
.ticker-track {
  display: flex;
  width: max-content;
  animation: ticker calc(var(--tick-n, 8) * 4.5s) linear infinite;
}
.ticker-track > span { display: contents; }
.ticker:hover .ticker-track { animation-play-state: paused; }
.tick {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-6);
  border-right: var(--border) solid var(--hairline);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--chalk-2);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.tick i { width: 6px; height: 6px; border-radius: 50%; background: var(--chalk-3); flex: none; }
.tick.live i { background: var(--lost); animation: ping 2.6s var(--ease-in-out) infinite; }
.tick.won i { background: var(--won); }
.tick.lost i { background: var(--lost); }
.tick.next i { background: var(--sodium); }
.tick:hover { color: var(--chalk); }
@keyframes ticker { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .ticker { overflow-x: auto; mask-image: none; -webkit-mask-image: none; }
  .ticker-track { animation: none; }
  .ticker-track > span { display: none; }
}

/* ============================================================ free call */

/* The masthead's call, in the scoreboard face. */
.freecall { margin: var(--space-5) 0 var(--space-6); }
.freecall-tag,
.plan-tagline {
  display: inline-block;
  padding: 3px var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--sodium);
  color: var(--pitch);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
}
.freecall-sel {
  margin: var(--space-3) 0 0;
  font-family: var(--display);
  font-weight: var(--weight-black);
  font-size: var(--text-3xl);
  letter-spacing: var(--tracking-3xl);
  line-height: var(--leading-tight);
  color: var(--chalk);
  text-shadow: 0 1px 12px rgba(10, 10, 12, 0.9);
}
.freecall-meta { margin: var(--space-2) 0 0; font-size: var(--text-md); color: var(--chalk-2); }
.freecall-meta b { color: var(--sodium); font-variant-numeric: tabular-nums; }
.freecall .hero-blurb { margin-top: var(--space-4); }

/* The same call, as a line on the pricing page. */
.freecall-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-8);
  padding: var(--space-4) var(--space-5);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius);
  background: var(--stand);
  font-size: var(--text-sm);
  color: var(--chalk-2);
}
.freecall-line b { color: var(--chalk); }
.freecall-line:hover { border-color: var(--sodium); }

/* ================================================================= plans */

.plans {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
  margin-bottom: var(--space-9);
  align-items: stretch;
}
@media (max-width: 860px) { .plans { grid-template-columns: minmax(0, 1fr); } }
.plan {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-7);
  border: var(--border) solid var(--hairline);
  border-radius: var(--radius-lg);
  background: var(--stand);
}
.plan-main { background: var(--terrace); border-color: var(--floodlight); box-shadow: var(--elev-2); }
.plan h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-size: var(--text-xl);
  letter-spacing: var(--tracking-xl);
}
.plan .plan-price { margin: var(--space-2) 0 0; display: flex; align-items: baseline; gap: var(--space-3); }
.plan .plan-price b {
  font-family: var(--display);
  font-weight: var(--weight-black);
  font-size: var(--text-board);
  line-height: 1;
  letter-spacing: var(--tracking-num);
  color: var(--chalk);
}
.plan .plan-price span { font-size: var(--text-sm); color: var(--chalk-3); }
.plan-per { margin: 0; font-size: var(--text-xs); color: var(--sodium); }
.plan-blurb { margin: 0 0 var(--space-4); flex: 1; font-size: var(--text-sm); line-height: var(--leading-normal); color: var(--chalk-2); }
.plan .btn { width: 100%; justify-content: center; }

.tiers {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5);
  margin-bottom: var(--space-9);
}
@media (max-width: 700px) { .tiers { grid-template-columns: minmax(0, 1fr); } }
.tier { padding: var(--space-6) var(--space-7); border: var(--border) solid var(--hairline); border-radius: var(--radius); }
.tier-paid { border-color: var(--floodlight-dim); background: var(--stand); }
.tier h3 { margin: 0 0 var(--space-4); font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--chalk-2); }
.tier .ticks b { color: var(--chalk); }

/* ============================================================= turnstile */

.turnstile-aside { margin: 0 0 var(--space-2); font-size: var(--text-xl); color: var(--sodium); }
.btn-google { gap: var(--space-3); }
.btn-google svg { width: 18px; height: 18px; flex: none; }
.sent { display: grid; gap: var(--space-3); }
.sent-head {
  margin: 0;
  font-family: var(--display);
  font-weight: var(--weight-bold);
  font-size: var(--text-2xl);
  letter-spacing: var(--tracking-2xl);
}
.sent p { margin: 0; font-size: var(--text-md); line-height: var(--leading-normal); color: var(--chalk-2); }
.sent b { color: var(--chalk); overflow-wrap: anywhere; }
.linklike {
  padding: 0;
  border: 0;
  background: none;
  color: var(--chalk-2);
  text-decoration: underline;
  text-underline-offset: 2px;
  font: inherit;
  cursor: pointer;
}
.linklike:disabled { color: var(--chalk-3); text-decoration: none; cursor: default; }

/* ================================================================ ticket */

/* The membership as a ticket: a main part and a stub, torn along a dashed
   rule. The stub carries whatever there is to do about it. */
.ticket {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  margin-bottom: var(--space-5);
  border: var(--border) solid var(--floodlight);
  border-radius: var(--radius-lg);
  background: var(--terrace);
  overflow: hidden;
}
.ticket.off { border-color: var(--rule); background: var(--stand); }
.ticket-main { display: grid; gap: var(--space-2); padding: var(--space-7); }
.ticket-kind {
  font-family: var(--display);
  font-weight: var(--weight-black);
  font-size: var(--text-3xl);
  letter-spacing: var(--tracking-3xl);
  line-height: var(--leading-tight);
}
.ticket-who { font-size: var(--text-sm); color: var(--chalk-3); overflow-wrap: anywhere; }
.ticket-until { font-size: var(--text-md); color: var(--chalk-2); }
.ticket-until b { color: var(--chalk); }
.ticket-stub {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-3);
  min-width: 180px;
  padding: var(--space-6);
  border-left: 2px dashed var(--rule);
  font-size: var(--text-xs);
  color: var(--chalk-3);
}
@media (max-width: 560px) {
  .ticket { grid-template-columns: minmax(0, 1fr); }
  .ticket-stub { border-left: 0; border-top: 2px dashed var(--rule); }
}

/* ============================================================ form guide */

.formline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-5); margin: var(--space-5) 0 var(--space-6); }
.chips.big { gap: 4px; flex-wrap: wrap; }
.chips.big .chip { width: 24px; height: 24px; font-size: 11px; border-radius: 4px; }
.formline-note { font-size: var(--text-xs); color: var(--chalk-3); }
.formline-note b { color: var(--won); }

/* ============================================================ live tracker */

/*
 * How a call stands while the match is on.
 *
 * Two words and a dot. "On track" in the won green, because that is what it
 * would be if the whistle went now; "Not yet" in amber rather than red, because
 * a call behind at the hour is pending, not lost, and a page that turned red at
 * every goal against would be shouting at people for ninety minutes.
 */
.track {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-2xs);
  font-weight: var(--weight-black);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1.2;
}
.track i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; animation: ping 2.6s var(--ease-in-out) infinite; }
.track.on  { color: var(--won);    background: color-mix(in srgb, var(--won) 14%, transparent); }
.track.off { color: var(--sodium); background: color-mix(in srgb, var(--sodium) 14%, transparent); }
.row-price .track { justify-self: end; }
.track-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin: var(--space-3) 0 0; font-size: var(--text-sm); color: var(--chalk-2); }
.side-meta .track { margin-left: auto; }

/* The slots the front page redraws in place. Invisible in the layout. */
[data-live] { display: contents; }

/* ============================================================ figure line */

/*
 * Figures in a sentence: "11 calls today: 3 landed and 1 is being played."
 * The numbers are set in the scoreboard face so they are found at a glance,
 * and the words around them say what they are -- which a grid of boxed cells
 * with a caption under each number did less clearly.
 */
.figure-line {
  margin: var(--space-6) 0 0;
  max-width: 62ch;
  font-size: var(--text-lg);
  line-height: 1.45;
  color: var(--chalk-2);
}
.figure-line a { color: inherit; text-decoration: none; }
.figure-line a:hover { color: var(--chalk); text-decoration: underline; text-underline-offset: 4px; }
.fig {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 1.5em;
  line-height: 1;
  color: var(--chalk);
}
.fig.won  { color: var(--won); }
.fig.lost, .fig.now { color: var(--lost); }
.fig.run  { color: var(--floodlight-hi); }
.record-line { margin: 0 0 var(--space-6); }
.player-facts { margin: 0 0 var(--space-7); }

/* ============================================================== slip clock */

.slip-lock { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-3) 0 0; font-size: var(--text-xs); color: var(--chalk-3); }
.slip-lock b { color: var(--sodium); font-variant-numeric: tabular-nums; }
.slip-lock b.live { color: var(--lost); }
.slip-lock.live { color: var(--chalk-2); }
.slip-lock.live i { width: 6px; height: 6px; border-radius: 50%; background: var(--lost); flex: none; animation: ping 1.8s var(--ease-in-out) infinite; }
.slip-state { display: inline-flex; align-items: center; gap: var(--space-3); }
.slip-state .mark { padding: 2px var(--space-2); }

/* The live block's meta line: league, score, and how the call stands. The
   league gives way first; the score and the mark never wrap. */
.side-league { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-meta b { white-space: nowrap; }
.side-meta .track { flex: none; }

/* The free call when it is not the headline match: the tie it belongs to,
   named above the call and linking to it. */
.freecall-tie {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-3) 0 var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--chalk-2);
}
.freecall-tie span { color: var(--chalk-3); font-size: var(--text-xs); margin-left: var(--space-2); }
.freecall-tie:hover { color: var(--chalk); }
.freecall-sel a { color: inherit; text-decoration: none; }
.freecall-sel a:hover { text-decoration: underline; text-decoration-color: var(--floodlight-hi); }

/* Who is missing, with a face. The reason sits under the name in the quiet
   colour rather than after it in brackets. */
.out-chip { display: inline-flex; align-items: center; gap: var(--space-3); padding-block: var(--space-2); }
.out-chip .out-name { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.out-chip .out-name small { font-size: var(--text-2xs); color: var(--chalk-3); }

/* The minute, beside the live badge. */
.minute { font-family: var(--display); font-variation-settings: 'wdth' var(--condensed); font-variant-numeric: tabular-nums; font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--lost); margin-left: var(--space-2); }
.side-meta .minute { margin-left: 0; font-size: var(--text-2xs); }

/* ============================================================ match report */

/*
 * What happened, in order. Home events sit left, away events right, the way
 * every timeline in football is drawn; the minute runs down the middle. The
 * icons are drawn in CSS so they match the page rather than the emoji set.
 */
.report .panel-head span { font-variant-numeric: tabular-nums; }
.rep-heads {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--chalk-3);
}
.rep-heads span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rep-heads span:last-child { text-align: right; }
.timeline { display: flex; flex-direction: column; gap: 2px; margin-bottom: var(--space-6); }
.ev {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 44px minmax(0, 1fr);
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: var(--border) solid var(--hairline);
}
.ev:last-child { border-bottom: 0; }
.ev-min {
  grid-column: 2;
  text-align: center;
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--chalk-3);
}
.ev-body {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  min-width: 0;
  font-size: var(--text-sm);
}
.ev.home .ev-body { grid-column: 1; grid-row: 1; justify-content: flex-start; }
.ev.away .ev-body { grid-column: 3; grid-row: 1; justify-content: flex-end; text-align: right; }
.ev-body b { font-weight: var(--weight-bold); color: var(--chalk); }
.ev-body small { font-size: var(--text-xs); color: var(--chalk-3); }
.ev-body em { font-style: normal; font-variant-numeric: tabular-nums; font-size: var(--text-xs); color: var(--chalk-2); }
.ev.is-goal { background: color-mix(in srgb, var(--won) 6%, transparent); }
.ev.is-sub .ev-body b { font-weight: var(--weight-medium); }

.ev-ico { display: inline-block; flex: none; vertical-align: middle; }
.ev-ico.ico-goal {
  width: 11px; height: 11px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff 0 25%, var(--chalk-3) 26% 45%, #fff 46%);
  box-shadow: 0 0 0 1px var(--pitch);
}
.ev-ico.ico-goal.ico-own { background: radial-gradient(circle at 35% 35%, var(--lost) 0 25%, var(--stand) 26% 45%, var(--lost) 46%); }
.ev-ico.ico-card { width: 9px; height: 12px; border-radius: 2px; }
.ev-ico.ico-card.c-yellow { background: var(--sodium); }
.ev-ico.ico-card.c-red { background: var(--lost); }
.ev-ico.ico-card.c-second { background: linear-gradient(135deg, var(--sodium) 50%, var(--lost) 50%); }
.ev-ico.ico-sub {
  width: 12px; height: 12px;
  background:
    linear-gradient(var(--won), var(--won)) 2px 1px / 2px 10px no-repeat,
    linear-gradient(var(--lost), var(--lost)) 8px 1px / 2px 10px no-repeat;
  position: relative;
}
.ev-ico.ico-sub::before, .ev-ico.ico-sub::after {
  content: ''; position: absolute; width: 0; height: 0;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
}
.ev-ico.ico-sub::before { left: -1px; top: -2px; border-bottom: 5px solid var(--won); }
.ev-ico.ico-sub::after { left: 5px; bottom: -2px; border-top: 5px solid var(--lost); }

.rep-numbers { margin-top: var(--space-2); }
.rep-numbers .rep-heads { margin-bottom: var(--space-4); }
.rep-highlights {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-6);
  padding: var(--space-3);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--terrace);
  color: var(--chalk);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  text-decoration: none;
}
.rep-highlights img { width: 72px; height: 44px; object-fit: cover; border-radius: 3px; flex: none; }
.rep-highlights:hover { border-color: var(--floodlight); }
.rep-att { margin: var(--space-4) 0 0; font-size: var(--text-xs); color: var(--chalk-3); }

/* Scorers under a scoreline, home then away, on the results sheet and the
   record on the front page. */
.scorers {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-4);
  margin-top: var(--space-2);
  font-size: var(--text-2xs);
  line-height: 1.4;
  color: var(--chalk-3);
  font-variant-numeric: tabular-nums;
}
.scorers span:last-child { text-align: right; }
.recap-tie .scorers { grid-template-columns: minmax(0, 1fr); }
.recap-tie .scorers span:last-child { text-align: left; }
.recap-tie .scorers span:empty { display: none; }

/* What a player did, on the pitch chip and in the squad list. */
.pp { position: relative; }
.pp-rating, .squad-row .rating {
  display: inline-block;
  padding: 1px 4px;
  border-radius: 3px;
  background: var(--chalk-3);
  color: var(--pitch);
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-size: 10px;
  font-weight: var(--weight-black);
  line-height: 1.3;
}
.pp-rating { position: absolute; top: -4px; right: 4px; }
.pp-rating.top, .squad-row .rating.top { background: var(--won); color: #fff; }
.pp-rating.good, .squad-row .rating.good { background: var(--floodlight-hi); color: #fff; }
.pp-rating.poor, .squad-row .rating.poor { background: var(--lost); color: #fff; }
.pp-marks { position: absolute; top: -4px; left: 2px; display: flex; align-items: center; gap: 2px; }
.pp-marks .ev-ico.ico-goal { width: 10px; height: 10px; }
.pp-marks .ev-ico.ico-card { width: 7px; height: 10px; }
.pp-marks .ev-ico.ico-sub { transform: scale(0.85); }
.pp-assist, .pp-sub {
  display: inline-block;
  padding: 0 3px;
  border-radius: 3px;
  font-family: var(--body);
  font-style: normal;
  font-size: 8px;
  font-weight: var(--weight-black);
  line-height: 1.5;
  letter-spacing: 0.02em;
  background: var(--stand);
  color: var(--chalk-2);
  font-variant-numeric: tabular-nums;
}
.pp-sub.off { color: var(--lost); }
.pp-sub.on { color: var(--won); }
.squad-row .no { display: inline-flex; align-items: center; justify-content: flex-end; gap: var(--space-2); }
.squad-row .no .pp-marks { position: static; }
.squad-row .no .pp-assist, .squad-row .no .pp-sub { font-size: 9px; }
.squad-row .unused { font-size: var(--text-2xs); color: var(--chalk-3); }
.squad-row.bench .name { color: var(--chalk-2); }
.squad-row .name small { color: var(--chalk-3); font-size: var(--text-2xs); }

/* =============================================================== league page */

.league-title { display: flex; align-items: center; gap: var(--space-5); }
.league-title .crest { flex: none; width: 48px; height: 48px; }
.league-title h1 { margin: 0; }
.league-head a { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: var(--space-2); }
.league-head a:hover { color: var(--floodlight-hi); }
.league-link { color: inherit; text-decoration: underline; text-decoration-color: var(--rule); text-underline-offset: 3px; }
.league-link:hover { text-decoration-color: var(--floodlight-hi); }

.tbl.standings td.team { display: flex; align-items: center; gap: var(--space-3); white-space: nowrap; }
.tbl.standings td.team span { overflow: hidden; text-overflow: ellipsis; }
.tbl.standings th.num, .tbl.standings td.num { font-variant-numeric: tabular-nums; }

.scorer-list { list-style: none; margin: 0; padding: 0; }
.scorer-list li {
  display: grid;
  grid-template-columns: 24px auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: var(--border) solid var(--hairline);
}
/* The rank, shared between level scorers (see chartRank in app.js). */
.scorer-list li::before {
  content: attr(data-rank);
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  color: var(--chalk-3);
}
.scorer-list li:last-child { border-bottom: 0; }
.scorer-name { display: flex; flex-direction: column; min-width: 0; }
.scorer-name small { font-size: var(--text-2xs); color: var(--chalk-3); }
.scorer-list b {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-xl);
  line-height: 1;
  color: var(--chalk);
}
.scorer-list li > small { grid-column: 4; justify-self: end; font-size: var(--text-2xs); color: var(--chalk-3); }

/* The shape of a page before its data: a title bar, a line and rows. */
.skeleton-title { height: 44px; width: min(420px, 70%); margin-bottom: var(--space-4); }
.skeleton-line { height: 14px; width: min(560px, 90%); margin-bottom: var(--space-8); }
.skeleton-rows { display: flex; flex-direction: column; gap: var(--space-3); }


/* ============================================================== figures */

/*
 * Display-face numbers that stack in a column or tick in place take the
 * equal-width cut (tokens.css, --display-figures), so 1.18 sits over 2.35
 * with the points aligned and a countdown does not shuffle sideways every
 * second. Last in the file on purpose: several of these set the display
 * face earlier, and this has to win.
 */
.odds, .price, .row-goals, .row-time, .fx-line .gf, .mc-count, [data-countdown],
.ev-min, .minute, .slip-odds { font-family: var(--display-figures); }
.freecall-tie b { font-family: var(--display-figures); font-size: var(--text-lg); color: var(--chalk); margin: 0 var(--space-1); }
.freecall-meta .mark { margin-right: var(--space-3); }

/* The cookie choice on the cookie page. */
.consent-panel { max-width: var(--maxw-read); margin-top: var(--space-8); }
.consent-panel p { margin: 0 0 var(--space-5); color: var(--chalk-2); }
.prose code { font-family: var(--body); font-size: 0.92em; color: var(--chalk); background: var(--terrace); padding: 1px 5px; border-radius: 3px; }
.prose .tbl { margin: var(--space-4) 0 var(--space-6); }
.prose .tbl td { vertical-align: top; font-size: var(--text-sm); line-height: var(--leading-snug); }
/* One table per group, two across where there is room. */
.group-tables { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr)); gap: var(--space-5); }
.group-tables .panel { margin: 0; }

/* ================================================================ players */

/* A name in the analysis that goes somewhere. Underlined quietly, so a
   paragraph with five names in it still reads as a paragraph. */
.plink {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--floodlight-hi) 55%, transparent);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
}
.plink:hover { color: var(--floodlight-hi); text-decoration-color: var(--floodlight-hi); }
.ev-body .plink, .squad-row .plink, .scorer-name .plink { text-decoration-color: transparent; }
.ev-body .plink:hover, .squad-row .plink:hover, .scorer-name .plink:hover { text-decoration-color: var(--floodlight-hi); }
a.pp { color: inherit; text-decoration: none; }
a.pp:hover .pp-name { color: var(--floodlight-hi); }

.player-head { display: flex; align-items: center; gap: var(--space-5); }
.player-face .crest { width: 84px; height: 84px; font-size: 22px; flex: none; }
.player-head h1 { margin: 0; }
.player-head .page-sub { display: flex; align-items: center; gap: var(--space-2); }
.scorer-list li.is-me { background: var(--floodlight-dim); margin: 0 calc(-1 * var(--space-3)); padding-inline: var(--space-3); border-radius: var(--radius-sm); }

.pl-matches { display: flex; flex-direction: column; }
.pl-match {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: var(--border) solid var(--hairline);
  color: inherit;
  text-decoration: none;
}
.pl-match:last-child { border-bottom: 0; }
.pl-match:hover .pl-tie { color: var(--chalk); }
.pl-when { display: flex; flex-direction: column; font-size: var(--text-xs); color: var(--chalk-2); }
.pl-when small { color: var(--chalk-3); font-size: var(--text-2xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-tie { display: flex; align-items: center; gap: var(--space-2); min-width: 0; font-size: var(--text-sm); color: var(--chalk-2); flex-wrap: wrap; }
.pl-tie b { font-family: var(--display-figures); font-size: var(--text-lg); color: var(--chalk); }
.pl-did { display: inline-flex; align-items: center; gap: var(--space-2); }
.pl-did small { font-size: var(--text-2xs); color: var(--chalk-3); }
.pl-did .rating {
  padding: 1px 5px; border-radius: 3px; background: var(--chalk-3); color: var(--pitch);
  font-family: var(--display-figures); font-weight: var(--weight-black); font-size: var(--text-sm);
}
.pl-did .rating.top { background: var(--won); color: #fff; }
.pl-did .rating.good { background: var(--floodlight-hi); color: #fff; }
.pl-did .rating.poor { background: var(--lost); color: #fff; }
@media (max-width: 560px) { .pl-match { grid-template-columns: minmax(0, 1fr) auto; } .pl-when { grid-column: 1 / -1; flex-direction: row; gap: var(--space-2); } }
.player-body > .stack { order: 1; } .player-body > .home-side { order: 2; }
/* The scorer a reader followed a link to: highlighted, and a brief pulse so
   the eye finds it after the page has moved. */
.scorer-list li.flash { animation: scorer-flash 1.6s var(--ease-in-out) 2; }
@keyframes scorer-flash { 50% { background: color-mix(in srgb, var(--floodlight) 38%, transparent); } }
@media (prefers-reduced-motion: reduce) { .scorer-list li.flash { animation: none; } }
.player-line { margin: var(--space-2) 0 0; font-size: var(--text-lg); color: var(--chalk-2); }
.pp.notable .pp-name { text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--floodlight-hi) 60%, transparent); text-underline-offset: 2px; }

/* ================================================================ account */

/*
 * The account: who you are here, what you follow, what you pay for, and the
 * controls every account owes its holder. The face is the one strong thing
 * on the page -- a picture or initials in a ring, violet for a member -- and
 * everything under it is plain forms and lists on the page's own ground.
 */
.avatar {
  position: relative;
  display: inline-grid;
  place-items: center;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: var(--terrace);
  color: var(--chalk);
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-weight: 600;
  line-height: 1;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar i { font-style: normal; display: none; }
.avatar.noimg i { display: block; }
.avatar-sm { width: 34px; height: 34px; font-size: 0.875rem; }
.avatar-md { width: 48px; height: 48px; font-size: 1.125rem; }
.avatar-lg { width: 84px; height: 84px; font-size: 2rem; box-shadow: 0 0 0 2px var(--pitch), 0 0 0 4px var(--rule-firm); }
.account .acct-head:has(.acct-plan.on) .avatar-lg { box-shadow: 0 0 0 2px var(--pitch), 0 0 0 4px var(--floodlight); }

/* The header button, signed in: the reader's own face. */
.account-chip {
  display: inline-flex;
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--rule);
  transition: box-shadow var(--dur-fast) var(--ease-out);
}
.account-chip:hover { box-shadow: 0 0 0 2px var(--floodlight); }
.account-chip:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.acct-head {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  margin: 0 0 var(--space-8);
}
.acct-who { min-width: 0; }
.acct-who h1 { margin: 0; overflow-wrap: anywhere; }
.acct-who p { margin: var(--space-1) 0 var(--space-3); color: var(--chalk-2); font-size: var(--text-sm); overflow-wrap: anywhere; }
.acct-plan {
  display: inline-block;
  padding: 3px var(--space-3);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--chalk-2);
  text-decoration: none;
}
.acct-plan.on { border-color: var(--floodlight); color: var(--floodlight-hi); }

.acct-pane { padding-top: var(--space-4); }
.acct-sub {
  margin: var(--space-9) 0 var(--space-3);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--chalk);
}
.acct-pane > .acct-sub:first-child { margin-top: 0; }
.acct-hint { margin: var(--space-2) 0 var(--space-4); max-width: 60ch; font-size: var(--text-sm); color: var(--chalk-3); }
.acct-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.acct-note { font-size: var(--text-sm); color: var(--won); }
.acct-note.bad { color: var(--lost); }

.acct-form { display: flex; flex-direction: column; gap: var(--space-2); max-width: 440px; }
.acct-form label, .follow-find label, .acct-choice legend { font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--chalk-2); }
.acct-form input, .follow-find input {
  width: 100%;
  min-height: var(--tap);
  padding: var(--space-4) var(--space-5);
  background: var(--pitch);
  color: var(--chalk);
  border: var(--border) solid var(--rule-firm);
  border-radius: var(--radius);
  font-size: var(--text-md);
}
.acct-form input::placeholder, .follow-find input::placeholder { color: var(--chalk-3); }
.acct-form input:focus-visible, .follow-find input:focus-visible { outline: none; box-shadow: var(--focus-ring); border-color: var(--floodlight); }

.acct-facts { margin: var(--space-9) 0 0; }
.acct-facts div {
  display: grid;
  grid-template-columns: 7rem minmax(0, 1fr);
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-top: var(--border) solid var(--hairline);
  font-size: var(--text-sm);
}
.acct-facts dt { color: var(--chalk-3); }
.acct-facts dd { margin: 0; color: var(--chalk); overflow-wrap: anywhere; }

/* Following: a search over the board, then the lists. */
.follow-find { display: flex; flex-direction: column; gap: var(--space-2); max-width: 520px; }
.follow-results, .follow-list { list-style: none; margin: 0; padding: 0; }
.follow-results:not(:empty) { margin-top: var(--space-2); border: var(--border) solid var(--hairline); border-radius: var(--radius); }
.follow-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
}
.follow-results .follow-item + .follow-item, .follow-list .follow-item + .follow-item { border-top: var(--border) solid var(--hairline); }
.follow-list .follow-item { padding-inline: 0; }
.follow-name { flex: 1 1 auto; min-width: 0; font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--chalk); overflow-wrap: anywhere; }
a.follow-name { text-decoration: none; }
a.follow-name:hover { text-decoration: underline; text-underline-offset: 3px; }
.follow-name small { display: block; font-size: var(--text-2xs); font-weight: var(--weight-normal); color: var(--chalk-3); }
.follow-none { padding: var(--space-4); font-size: var(--text-sm); color: var(--chalk-3); }
.follow-item .btn { flex: none; }

/* Odds format: three choices, each showing what it looks like. */
.acct-choice { margin: 0; padding: 0; border: 0; }
.seg { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }
.seg-opt { position: relative; cursor: pointer; }
.seg-opt input { position: absolute; opacity: 0; pointer-events: none; }
.seg-opt span {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 104px;
  padding: var(--space-3) var(--space-5);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius);
  background: var(--stand);
}
.seg-opt b { font-size: var(--text-sm); font-weight: 600; }
.seg-opt small {
  font-family: var(--display);
  font-variation-settings: 'wdth' var(--condensed);
  font-size: var(--text-lg);
  color: var(--chalk-2);
}
.seg-opt:hover span { border-color: var(--rule-firm); }
.seg-opt input:checked + span { border-color: var(--floodlight); background: var(--floodlight-dim); }
.seg-opt input:checked + span small { color: var(--floodlight-hi); }
.seg-opt input:focus-visible + span { box-shadow: var(--focus-ring); }

.danger-zone { margin-top: var(--space-10); padding-top: var(--space-2); border-top: var(--border) solid var(--hairline); }
.btn.danger { color: var(--lost); border: var(--border) solid color-mix(in srgb, var(--lost) 45%, transparent); }
.btn.danger:hover { background: color-mix(in srgb, var(--lost) 12%, transparent); color: var(--chalk); }

/* Follow buttons on a competition and a match. */
.league-title .follow-btn { margin-left: auto; align-self: center; }
.follow-btn.on { color: var(--floodlight-hi); }
.fx-follow { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }
.fx-follow .follow-btn { background: rgba(12, 11, 9, 0.5); backdrop-filter: blur(6px); }

@media (max-width: 560px) {
  .acct-head { gap: var(--space-4); }
  .avatar-lg { width: 64px; height: 64px; font-size: 1.5rem; }
  .acct-facts div { grid-template-columns: 5.5rem minmax(0, 1fr); }
  .seg-opt { flex: 1 1 0; }
  .seg-opt span { min-width: 0; padding-inline: var(--space-3); }
  .league-title { flex-wrap: wrap; }
  .league-title .follow-btn { margin-left: 0; }
}
