/* ==========================================================================
   Inner pages — shared page header, plus Schedule, News and Partnership.
   Everything here builds on tokens/base/components; nothing is redeclared.
   ========================================================================== */

/* ---------------------------------------------------------- page header */
.pagehead {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  min-height: clamp(300px, 42vh, 460px);
  padding-block: clamp(6rem, 14vh, 9rem) clamp(2rem, 4vw, 3.5rem);
  overflow: hidden;
}
.pagehead__bg { position: absolute; inset: 0; z-index: -2; }
.pagehead__bg picture { display: block; width: 100%; height: 100%; }
.pagehead__bg img { width: 100%; height: 100%; object-fit: cover; object-position: center 34%; }
/* The default 34% crop assumes a face sitting mid-frame. These source photos
   all have the face high in the frame (action shots, racket/arm filling the
   lower two-thirds), so the wide short pagehead box was cropping the face out
   entirely. Tuned per photo against the actual crop, not guessed. */
.pagehead__bg--stats img { object-position: center 0%; }
.pagehead__bg--schedule img { object-position: center 2%; }
.pagehead__bg--contact img { object-position: center 0%; }
.pagehead__bg--sponsors img { object-position: center 5%; }
/* "Signing balls for the ball kids". The band is ~3.8:1, so whatever the
   source shape a horizontal slice is all that survives. Held a little above
   centre, which is where a standing subject's head falls in most frames —
   a starting point to nudge once the picture is up, not a measured crop. */
.pagehead__bg--news img { object-position: center 38%; }
/* The left-side fade only needs to carry the headline column (it ends
   around 51% of the box), so it now clears well before that photo's
   subject typically sits - a photo positioned anywhere right of center
   no longer reads as washed out just for being on the same page as text. */
.pagehead__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(94deg,
      var(--ivory) 0%,
      color-mix(in srgb, var(--ivory) 55%, transparent) 30%,
      color-mix(in srgb, var(--ivory) 15%, transparent) 55%,
      transparent 80%),
    linear-gradient(to bottom, var(--ivory) 0%, transparent 26%),
    linear-gradient(to top, var(--ivory) 0%, transparent 24%);
}
.pagehead h1 {
  font-variation-settings: "opsz" 144, "SOFT" 20, "WONK" 1;
  font-size: var(--step-4);
  letter-spacing: -0.03em;
  line-height: 0.94;
  max-width: 16ch;
}
.pagehead .lede { margin-top: var(--sp-4); }
body.has-photo-hero .site-header:not(.is-stuck) { background: transparent; backdrop-filter: none; }

@media (max-width: 900px) {
  .pagehead { min-height: 0; display: block; padding: 0 0 var(--sp-6); }
  .pagehead__bg { position: relative; inset: auto; height: min(34svh, 280px); }
  .pagehead__bg::after {
    content: ""; position: absolute; inset: auto 0 0; height: 26%;
    background: linear-gradient(to top, var(--ivory), transparent);
  }
  .pagehead__scrim { display: none; }
  .pagehead .wrap { padding-top: var(--sp-6); }
  /* Mobile's short, narrow box crops far more aggressively than desktop's
     wide one, so a photo positioned for the desktop crop can miss the
     subject entirely here - contact.portrait needs its own mobile position. */
  .pagehead__bg--contact img { object-position: 16% 0%; }
  body.has-photo-hero .site-header:not(.is-stuck) {
    background: color-mix(in srgb, var(--ivory) 88%, transparent);
    backdrop-filter: blur(10px);
  }
}

/* ============================================================= CALENDAR
   A printed fixture-poster, not a component from the site's design system:
   months flow in newspaper columns (CSS multi-column, not a grid) so a
   one-event month costs one line, not a whole row's worth of dead space,
   and every fixture is a single row — week, date, flag, name — the way a
   real season poster reads, not a card.
   ========================================================================= */
.calendar { margin-top: var(--sp-5); }
.calendar__grid {
  column-width: 270px;
  column-gap: var(--sp-8);
}
.cal-month {
  break-inside: avoid-column;
  margin-bottom: var(--sp-7);
}
.cal-month__name {
  font-family: var(--display);
  font-variation-settings: "opsz" 40, "SOFT" 0, "WONK" 0;
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  border-bottom: 2px solid var(--ink);
  padding-bottom: 0.35rem;
  margin-bottom: 0.15rem;
}
.cal-month__list { display: flex; flex-direction: column; }

.cal-entry {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 0.5rem;
  padding: 0.4rem 0.2rem;
  border-bottom: 1px solid color-mix(in srgb, var(--divider) 55%, transparent);
  text-decoration: none;
  color: inherit;
  box-shadow: inset 3px 0 0 transparent;
  transition: background var(--dur-fast) var(--ease);
}
.cal-entry:last-child { border-bottom: 0; }
.cal-entry:hover { background: var(--ivory-deep); }
.cal-entry__wk {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.02em;
  color: var(--neutral);
  text-transform: uppercase;
  min-width: 2.4rem;
}
.cal-entry__date {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  min-width: 2.6rem;
}
/* Fixed box whichever branch renders, so a missing flag doesn't shift the
   tournament name out of line with the rows above and below it. */
.cal-entry__flag {
  flex: 0 0 auto;
  width: 1.35rem;
  height: 1.0125rem;      /* 4:3, matching the source files */
  object-fit: cover;
  border: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  border-radius: 1px;
  background: var(--ivory-deep);
}
.cal-entry__flag--code {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 0.5rem;
  letter-spacing: 0.02em;
  color: var(--neutral);
  border-style: dashed;
}
.cal-entry__name { font-size: 0.875rem; font-weight: 600; line-height: 1.3; }
.cal-entry__tier {
  font-family: var(--mono);
  font-size: 0.625rem;
  color: var(--neutral);
}
.cal-entry__badge {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 0.5625rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  padding: 0.05em 0.4em;
  border: 1px solid currentColor;
  flex-shrink: 0;
}

.cal-entry--won { box-shadow: inset 3px 0 0 var(--gold); }
.cal-entry--won .cal-entry__badge { color: var(--gold-ink); border-color: var(--gold); background: var(--gold-tint); }
.cal-entry--runner { box-shadow: inset 3px 0 0 var(--silver); }
.cal-entry--runner .cal-entry__badge { color: var(--silver-ink); border-color: var(--silver); background: var(--silver-tint); }
.cal-entry--played { box-shadow: inset 3px 0 0 color-mix(in srgb, var(--ink) 25%, transparent); }
.cal-entry--live { box-shadow: inset 3px 0 0 var(--brass); background: color-mix(in srgb, var(--brass) 6%, transparent); }
.cal-entry--live .cal-entry__wk { color: var(--brass); font-weight: 700; }

.calendar__key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--neutral);
}
.calendar__key span { display: inline-flex; align-items: center; gap: 0.45rem; }
.calendar__key i {
  width: 14px; height: 10px; display: inline-block; border: 1px solid var(--divider);
}
.key-won { background: var(--gold-tint); border-color: var(--gold) !important; }
.key-runner { background: var(--silver-tint); border-color: var(--silver) !important; }
.key-done { background: color-mix(in srgb, var(--ink) 8%, var(--ivory)); }
.key-up { background: color-mix(in srgb, var(--court) 6%, var(--ivory)); border-color: var(--court) !important; }

/* ---------------------------------------------------------- results table */
.rtable { width: 100%; margin-top: var(--sp-5); }
.rtable table { font-variant-numeric: tabular-nums; }
.rtable th, .rtable td {
  padding: 0.9rem 0.75rem;
  text-align: left;
  border-bottom: 1px solid var(--divider);
  vertical-align: top;
}
.rtable th:first-child, .rtable td:first-child { padding-left: 0; }
.rtable th:last-child, .rtable td:last-child { padding-right: 0; text-align: right; }
.rtable thead th {
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--neutral);
  border-bottom-color: var(--ink);
}
.rtable td.date { font-family: var(--mono); font-size: 0.8125rem; color: var(--neutral); white-space: nowrap; }
.rtable td.event { font-weight: 500; }
.rtable td.event small {
  display: block;
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--neutral);
  margin-top: 0.2rem;
  font-weight: 400;
}
.rtable td.meta { font-family: var(--mono); font-size: 0.75rem; color: var(--neutral); }
.rtable tbody tr:hover td { background: var(--ivory-deep); }

.round {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.6rem;
  padding: 0.2rem 0.5rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 600;
  border: 1px solid var(--divider);
}
.round--w { background: var(--brass); border-color: var(--brass); color: var(--ivory); }
.round--f { border-color: var(--brass); color: var(--brass); }
.round--upcoming { border-style: dashed; color: var(--court); border-color: var(--court); }

@media (max-width: 760px) {
  .rtable thead { display: none; }
  .rtable tbody tr { display: grid; gap: 0.3rem; padding-block: var(--sp-4); border-bottom: 1px solid var(--divider); }
  .rtable td { border: 0; padding: 0 !important; text-align: left !important; }
  .rtable td.round-cell { margin-top: var(--sp-2); }

  /* Dropping the header row works on the schedule, where every cell says what
     it is — a date reads as a date, a tournament name as a name. It fails on
     a table of bare counts: without the header, "30 / 5 / 9 / 13" under a year
     is four unlabelled numbers. Tables that opt in carry the column name into
     each cell, so a row reads as its own little record. */
  .rtable--labelled tbody tr { gap: 0; }
  .rtable--labelled td[data-label] {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--sp-4);
    padding: 0.4rem 0 !important;
    border-bottom: 1px solid color-mix(in srgb, var(--divider) 55%, transparent);
  }
  .rtable--labelled tr td[data-label]:last-child { border-bottom: 0; }
  .rtable--labelled td[data-label]::before {
    content: attr(data-label);
    font-family: var(--mono);
    font-size: 0.625rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--neutral);
  }
  /* The season is the row's heading, not one of its fields. */
  .rtable--labelled td.event {
    font-family: var(--display);
    font-size: var(--step-1);
    margin-bottom: 0.35rem;
  }
}

/* ---------------------------------------------------- season/career compare
   Two rows, same columns — "this season" and "full career" read side by
   side rather than as one merged figure. Unlike .rtable this stays a real
   table on mobile (scrolling sideways) instead of stacking into cards: the
   whole point is comparing two rows column-for-column, which a card layout
   would break. */
.compare { width: 100%; margin-top: var(--sp-5); overflow-x: auto; }
.compare table { width: 100%; min-width: 34rem; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.compare th, .compare td {
  padding: 0.9rem 0.75rem;
  text-align: right;
  border-bottom: 1px solid var(--divider);
  white-space: nowrap;
}
.compare th:first-child, .compare td:first-child { text-align: left; padding-left: 0; }
.compare th:last-child, .compare td:last-child { padding-right: 0; }
.compare thead th {
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--neutral);
  border-bottom-color: var(--ink);
}
.compare tbody th {
  text-align: left;
  font-weight: 600;
  font-size: 0.9375rem;
}
.compare tbody td { font-family: var(--mono); font-size: 1rem; }
.compare tbody td.is-highlight { color: var(--brass); font-weight: 600; }
.compare tbody tr:hover th, .compare tbody tr:hover td { background: var(--ivory-deep); }

/* --------------------------------------------------------------- filters */
.seg {
  display: inline-flex;
  border: 1px solid var(--divider);
  margin-bottom: var(--sp-5);
}
.seg button {
  background: none;
  border: 0;
  border-right: 1px solid var(--divider);
  padding: 0.65rem 1.1rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--neutral);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.seg button:last-child { border-right: 0; }
.seg button:hover { color: var(--ink); }
.seg button.is-on { background: var(--court); color: var(--ivory); }

@media (max-width: 700px) {
  /* A long category list (press filters) wraps rather than pushing the
     page wider — the two-button segments elsewhere stay one line either way. */
  .seg { flex-wrap: wrap; }
  .seg button { border-bottom: 1px solid var(--divider); }
}

/* ============================================================ NEWS INDEX */
.newsgrid {
  display: grid;
  gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  background: var(--divider);
  border: 1px solid var(--divider);
  margin-top: var(--sp-5);
}
.newscard {
  background: var(--ivory);
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: inherit;
}
.newscard__media { aspect-ratio: 3 / 2; overflow: hidden; background: var(--ivory-deep); }
.newscard__media picture { display: block; width: 100%; height: 100%; }
.newscard__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform var(--dur-slow) var(--ease);
}
.newscard:hover .newscard__media img { transform: scale(1.03); }
.newscard__body { padding: var(--sp-5) var(--sp-5) var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-3); flex: 1; }
.newscard__date {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--neutral);
}
.newscard__title {
  font-family: var(--display);
  font-variation-settings: var(--display-axes);
  font-size: var(--step-2);
  line-height: 1.08;
  letter-spacing: -0.015em;
}
.newscard:hover .newscard__title { color: var(--court); }
.newscard__excerpt { color: var(--neutral); font-size: 0.9375rem; }
.newscard__more { margin-top: auto; }

/* ============================================================= NEWS POST */
.post { max-width: 46rem; }
.post__meta {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--neutral);
  margin-bottom: var(--sp-4);
  display: flex;
  gap: var(--sp-4);
  flex-wrap: wrap;
  align-items: center;
}
.post__title { font-size: var(--step-4); letter-spacing: -0.03em; line-height: 0.98; }
.post__figure { margin: var(--sp-7) 0; }
.post__figure img { display: block; width: 100%; }
/* Pictures come from the publication that ran the story, at whatever aspect
   ratio they published. No crop is imposed: a fixed ratio would cut people
   out of their own photographs. */
.post__figure figcaption { margin-top: var(--sp-3); }
.post__body { margin-top: var(--sp-6); }
.post__body p { margin-bottom: var(--sp-5); font-size: 1.09rem; line-height: 1.68; }
.post__body p:first-of-type::first-letter {
  float: left;
  font-family: var(--display);
  font-variation-settings: "opsz" 144, "SOFT" 10, "WONK" 0;
  font-size: 3.6em;
  line-height: 0.82;
  padding: 0.06em 0.1em 0 0;
  color: var(--court);
}
.post__body h2 { font-size: var(--step-2); margin: var(--sp-7) 0 var(--sp-4); }
/* These posts summarise someone else's reporting. The credit links back, and
   is set apart from the body so it reads as attribution, not as copy. */
.post__source {
  margin-top: var(--sp-6);
  padding-left: var(--sp-4);
  border-left: 2px solid var(--court);
  font-size: var(--step--1);
  color: var(--neutral);
}
.post__source a { color: inherit; text-underline-offset: 0.2em; }
.post__nav {
  margin-top: var(--sp-8);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--divider);
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

/* ================================================================ STORY
   The About page reads as numbered chapters rather than as one unbroken
   column of prose. It opens straight into chapter 01 — no photo banner, no
   name-and-standfirst band — so the first thing on the page is the writing
   itself, with the portrait beside it.

   The ground stays the site's own ivory. An earlier version of this layout
   was drawn on a dark ground and read as a different site pasted into this
   one; the numerals and hairlines carry the structure instead of a colour
   change. */
.story { background: var(--ivory); color: var(--ink); }
.story .wrap { padding-block: clamp(2.5rem, 6vw, 5rem); }
/* Scoped to the prose blocks rather than written as `.story p`. A bare
   descendant selector outranks the single-class rules below it, so it was
   quietly flattening both the opening numeral and the date stamp to body
   size — chapter 01 rendered at 16px while 02 to 05 kept their display
   numerals, because only the chapter rule was specific enough to survive. */
.story__hero p:not(.story__num),
.story__ch p:not(.story__num) { color: var(--neutral); font-size: 1rem; line-height: 1.75; }

/* One size for every chapter numeral, including the opening one. The first
   draft set 01 larger as a page opener, but it never actually rendered that
   way — the prose rule was overriding it — so what was reviewed and approved
   had all five numerals reading at the same modest size. Keeping them level
   is also the quieter option, and the numeral should sit under the headline
   in the hierarchy, not over it. */
.story__num {
  font-family: var(--display);
  font-variation-settings: "opsz" 144, "SOFT" 0;
  font-weight: 700;
  font-size: clamp(2rem, 4vw, 2.6rem);
  line-height: 0.85;
  color: var(--divider);
}
.story__rule {
  width: 3rem;
  height: 2px;
  background: var(--court);
  margin: var(--sp-4) 0;
}

/* Chapter 01 sets the page: the opening line at display size, the portrait
   held to a column beside it. */
.story__hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}
.story__h {
  font-family: var(--display);
  font-variation-settings: "opsz" 96, "SOFT" 12;
  font-weight: 700;
  font-size: clamp(2rem, 5vw, 3.2rem);
  line-height: 1.06;
  color: var(--ink);
}
/* No crop on either photo. The portrait was being forced into a 3:4 box,
   which on a frame this tall (1406x2500) meant cutting the head and the feet
   off to make it fit. The column sets the width and the picture keeps its own
   proportions, however tall that makes it — a full-length shot is the whole
   figure or it is nothing. Stretching to fill a fixed box is not an option
   either; that distorts the subject rather than cropping him. */
.story__portrait { margin: 0; }
.story__portrait img {
  display: block;
  width: 100%;
  height: auto;
}

.story__ch {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 2.5rem);
  padding-block: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--divider);
  align-items: start;
}
/* A chapter that carries a picture beside its prose, the way the opening
   chapter does, instead of stacking it underneath. An upright photograph at
   the full width of the column is taller than the viewport, which turns one
   chapter into two screens of scrolling; in a side column it is a quarter of
   the width and the whole chapter reads in one frame. The narrower prose
   column also runs longer, so the two sides finish at roughly the same depth
   without anything being cropped. */
.story__split {
  display: grid;
  /* The prose column is capped at a readable measure rather than taking the
     whole row. That is what balances the two sides: held to ~34rem the text
     wraps to roughly the depth of the picture beside it, where at full column
     width it ran half the height and far past a comfortable line length. */
  grid-template-columns: minmax(0, 34rem) minmax(0, 17rem);
  justify-content: space-between;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}
.story__aside { margin: 0; }
.story__aside img { display: block; width: 100%; height: auto; }
@media (max-width: 800px) {
  /* Stacked, and held well under the column width so the upright frame does
     not take over a phone screen on its own. */
  .story__split { grid-template-columns: minmax(0, 1fr); }
  .story__aside { max-width: 18rem; }
}

.story__ch h2 {
  color: var(--ink);
  font-family: var(--display);
  font-size: var(--step-2);
  margin-bottom: 0.6rem;
}

/* Same rule for the interior photo: whole frame, no height cap. The width
   is held to 34rem so a tall upload cannot run the length of the chapter. */
.story__figure { margin: var(--sp-5) 0 0; max-width: 34rem; }
.story__figure img {
  display: block;
  width: 100%;
  height: auto;
}

.story__stamp {
  padding-block: var(--sp-6);
  color: color-mix(in srgb, var(--ink) 55%, transparent);
}

@media (max-width: 900px) {
  .story__hero { grid-template-columns: 1fr; }
  .story__ch { grid-template-columns: 1fr; }
  .story__portrait { max-width: 26rem; }
}

/* =========================================================== PARTNERSHIP */
.props {
  display: grid;
  gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  background: var(--divider);
  border: 1px solid var(--divider);
  margin-top: var(--sp-5);
}
.prop { background: var(--ivory); padding: var(--sp-6) var(--sp-5); display: grid; gap: var(--sp-3); align-content: start; }
.prop__n {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  color: var(--brass);
}
.prop h3 { font-size: var(--step-1); line-height: 1.15; }
.prop p { color: var(--neutral); font-size: 0.9375rem; }

.inventory { margin-top: var(--sp-6); border-top: 2px solid var(--court); }
.inv-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto;
  gap: var(--sp-4) var(--sp-5);
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--divider);
  align-items: baseline;
}
.inv-row h3 { font-size: var(--step-1); }
.inv-row p { color: var(--neutral); font-size: 0.9375rem; }
.inv-row .tag {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--court);
  border: 1px solid var(--court);
  padding: 0.25rem 0.6rem;
  white-space: nowrap;
}
/* Already promised to a sponsor: says so plainly rather than leaving the
   tier badge in place implying the category is still open. */
.inv-row--given h3, .inv-row--given p { color: var(--neutral); }
.inv-row .tag--given {
  color: var(--neutral);
  border-color: var(--divider);
}
@media (max-width: 760px) { .inv-row { grid-template-columns: 1fr; } }

.cta-band {
  margin-top: var(--sp-8);
  padding: var(--sp-7) 0 0;
  border-top: 1px solid var(--divider);
  display: grid;
  gap: var(--sp-5);
  justify-items: start;
}
.cta-band h2 { font-size: var(--step-3); max-width: 20ch; letter-spacing: -0.02em; }
.key-live {
  border-color: var(--brass) !important;
  background:
    repeating-linear-gradient(45deg,
      color-mix(in srgb, var(--brass) 35%, transparent) 0 3px, transparent 3px 6px);
}

/* ====================================================== TOURNAMENT PAGE */
.tcard--page { border-top: 2px solid var(--court); grid-template-columns: 1fr; }
.tcard--page .tcard__name { font-size: var(--step-4); letter-spacing: -0.03em; }

/* The run: one row per match, round on the left, score on the right. */
.draw { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--ink); }
.draw-row {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr) auto 4.5rem;
  gap: var(--sp-4) var(--sp-5);
  align-items: baseline;
  /* padded and pulled out, so the win tint has breathing room and the
     outcome label never sits hard against the container edge */
  padding: var(--sp-5) var(--sp-4);
  margin-inline: calc(-1 * var(--sp-4));
  border-bottom: 1px solid var(--divider);
}
.draw-row__round {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--neutral);
}
.draw-row__opp { font-size: 1.0625rem; font-weight: 500; }
.draw-row__seed { font-family: var(--mono); font-size: 0.75rem; color: var(--neutral); }
.draw-row__score {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1rem;
  font-weight: 500;
  white-space: nowrap;
}
.draw-row__opp + .caption { margin-top: 0.25rem; }
.honour__opp, .draw-row__score .caption { display: block; margin-top: 0.25rem; }
.draw-row__outcome {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  min-width: 4.5rem;
  text-align: right;
  color: var(--neutral);
}
.draw-row--win { background: color-mix(in srgb, var(--brass) 5%, transparent); }
.draw-row--win .draw-row__outcome { color: var(--brass); font-weight: 600; }
.draw-row--loss .draw-row__outcome { color: var(--neutral); }
.draw-row--pending .draw-row__outcome { color: var(--court); }
@media (max-width: 700px) {
  .draw-row { grid-template-columns: 1fr auto; gap: var(--sp-2) var(--sp-4); }
  .draw-row__round { grid-column: 1 / -1; }
  .draw-row__body { grid-column: 1; }
  .draw-row__score { grid-column: 2; text-align: right; }
  .draw-row__outcome { grid-column: 1 / -1; text-align: left; }
}

/* ============================================================= HONOURS */
.honours { list-style: none; margin: var(--sp-5) 0 0; padding: 0; border-top: 2px solid var(--court); }
.honour {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr) auto;
  gap: var(--sp-4) var(--sp-5);
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--divider);
  align-items: baseline;
}
.honour__year {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  color: var(--brass);
  font-weight: 600;
}
.honour__event { font-size: var(--step-1); line-height: 1.15; }
.honour__no {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  color: var(--neutral);
  vertical-align: middle;
}
.honour__with { margin-top: 0.35rem; font-size: 0.9375rem; }
.honour__with b { color: var(--court); font-weight: 600; }
.honour__score {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.9375rem;
  text-align: right;
  white-space: nowrap;
}
.honour--unconfirmed { opacity: 0.62; }
.honour--unconfirmed .honour__event { font-style: italic; font-weight: 400; }
@media (max-width: 700px) {
  .honour { grid-template-columns: 4rem minmax(0, 1fr); }
  .honour__score { grid-column: 2; text-align: left; }
}

/* Tournament names in the table open that event's page. */
.event-link {
  color: inherit;
  text-decoration: none;
  background-image: linear-gradient(var(--court), var(--court));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0 1.5px;
  transition: background-size var(--dur) var(--ease), color var(--dur-fast) var(--ease);
}
.event-link:hover { color: var(--court); background-size: 100% 1.5px; }

/* ======================================================== MEDAL COLOURING
   A title is gold, a runner-up is silver, everywhere the result appears:
   planner block, table row, round badge. The whole plate carries the colour,
   not just the letter, so a season reads at a glance.
   ======================================================================== */

/* -- season calendar: see .cal-entry--won / .cal-entry--runner above -- */

/* -- results table: the row itself carries the medal -- */
.rtable tr.is-won td { background: color-mix(in srgb, var(--gold-tint) 45%, var(--ivory)); }
.rtable tr.is-won:hover td { background: color-mix(in srgb, var(--gold-tint) 75%, var(--ivory)); }
.rtable tr.is-won td.event { box-shadow: inset 3px 0 0 var(--gold); padding-left: 0.75rem; }
.rtable tr.is-runner td { background: color-mix(in srgb, var(--silver-tint) 45%, var(--ivory)); }
.rtable tr.is-runner:hover td { background: color-mix(in srgb, var(--silver-tint) 80%, var(--ivory)); }
.rtable tr.is-runner td.event { box-shadow: inset 3px 0 0 var(--silver); padding-left: 0.75rem; }

/* -- round badge -- */
.round--w {
  background: var(--gold); border-color: var(--gold); color: var(--ivory);
  font-weight: 700; letter-spacing: 0.06em;
}
.round--f {
  background: var(--silver); border-color: var(--silver); color: var(--ivory);
  font-weight: 700; letter-spacing: 0.06em;
}

/* -- honours list -- */
.honour__year { color: var(--gold); }
.honour--runner .honour__year { color: var(--silver-ink); }

/* ============================================================== GALLERY
   An editorial mosaic rather than a uniform grid: three aspect ratios cycle
   across the cards so the page has rhythm without hand-placing anything.
   ========================================================================= */
/* Masonry columns, so every photograph keeps its own shape.

   This used to be a fixed grid that handed each tile one of three aspect
   ratios by its position in the list — tall, wide, square, tall — and then
   cropped the picture to fit with object-fit: cover. Which shape a photo got
   had nothing to do with the photo: a standing portrait landing in the 3:2
   "wide" slot was cropped to a horizontal band through its middle, which is
   how a full-length shot ended up showing only a pair of legs. Re-ordering
   the gallery could do that to any picture at any time.

   Columns let each tile take the height its own image needs, so nothing is
   cropped and no upload has to be a particular size to survive. */
.gallerygrid {
  columns: 4 240px;
  column-gap: var(--sp-2);
  margin-top: var(--sp-5);
}
.gphoto {
  position: relative;
  display: block;
  width: 100%;
  border: 0;
  margin: 0 0 var(--sp-2);
  padding: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
  /* Keeps a tile from being split across two columns mid-photograph. */
  break-inside: avoid;
}
.gphoto picture { display: block; width: 100%; height: auto; }
/* Beats `.frame img { height: 100%; object-fit: cover }` — the whole point
   here is that the frame follows the picture, not the other way round. */
.gphoto img {
  width: 100%;
  height: auto;
  object-fit: fill;
  transition: transform var(--dur-slow) var(--ease);
}
.gphoto:hover img { transform: scale(1.035); }
@media (max-width: 640px) {
  .gallerygrid { columns: 2 150px; }
}

.videogrid {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  margin-top: var(--sp-5);
}
.video-frame { position: relative; aspect-ratio: 16 / 9; background: var(--ink); }
.video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.presslist { list-style: none; margin: var(--sp-5) 0 0; padding: 0; border-top: 2px solid var(--court); }
.press-item {
  display: grid;
  grid-template-columns: 6rem minmax(0, 1fr) auto;
  gap: var(--sp-4) var(--sp-5);
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--divider);
  align-items: baseline;
  text-decoration: none;
  color: inherit;
}
.press-item__date {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  color: var(--neutral);
}
.press-item__pub {
  display: block;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--court);
  margin-bottom: 0.3rem;
}
.press-item__title { font-size: 1rem; font-weight: 500; }
.press-item:hover .press-item__title { color: var(--court); text-decoration: underline; }
.press-item__caption { display: block; margin-top: 0.35rem; font-size: 0.875rem; color: var(--neutral); }
.press-item__cat {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--neutral);
  border: 1px solid var(--divider);
  padding: 0.25rem 0.6rem;
  white-space: nowrap;
}
@media (max-width: 700px) {
  .press-item { grid-template-columns: minmax(0, 1fr); gap: var(--sp-2); }
  .press-item__cat { justify-self: start; }
}

/* -------------------------------------------------------------- lightbox
   A full-viewport overlay for the grid photos. Dark ground here is a
   deliberate exception to the light system: a photograph reads truer
   against near-black than against ivory, and this is a modal, not a page. */
body.lightbox-open { overflow: hidden; }
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 90;
  place-items: center;
  padding: clamp(1rem, 5vw, 4rem);
}
/* The [hidden] attribute must still win: an unconditional `display: grid`
   above would out-rank the UA stylesheet's [hidden]{display:none} and leave
   the overlay in the hit-testing tree — invisible, but still eating clicks. */
.lightbox:not([hidden]) { display: grid; }
.lightbox__scrim {
  position: absolute;
  inset: 0;
  border: 0;
  background: var(--ink);
  opacity: 0.97;
  cursor: pointer;
}
.lightbox__figure {
  position: relative;
  z-index: 1;
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  display: grid;
  gap: var(--sp-3);
  justify-items: center;
}
.lightbox__figure img {
  max-width: min(88vw, 1100px);
  max-height: 78vh;
  width: auto;
  height: auto;
  object-fit: contain;
}
.lightbox__figure figcaption {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: color-mix(in srgb, var(--ivory) 80%, transparent);
  text-align: center;
  max-width: 60ch;
}
.lightbox__close,
.lightbox__nav {
  position: absolute;
  z-index: 2;
  border: 1px solid color-mix(in srgb, var(--ivory) 35%, transparent);
  background: color-mix(in srgb, var(--ink) 60%, transparent);
  color: var(--ivory);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.lightbox__close:hover,
.lightbox__nav:hover { background: color-mix(in srgb, var(--ivory) 16%, var(--ink)); border-color: var(--ivory); }
.lightbox__close {
  top: var(--sp-4);
  right: var(--sp-4);
  padding: 0.6rem 1rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.lightbox__nav {
  top: 50%;
  transform: translateY(-50%);
  width: 3rem;
  height: 3rem;
  font-size: 1.5rem;
  line-height: 1;
  display: grid;
  place-items: center;
}
.lightbox__nav--prev { left: var(--sp-4); }
.lightbox__nav--next { right: var(--sp-4); }
@media (max-width: 640px) {
  .lightbox__nav { width: 2.4rem; height: 2.4rem; font-size: 1.25rem; }
  .lightbox__nav--prev { left: var(--sp-2); }
  .lightbox__nav--next { right: var(--sp-2); }
  .lightbox__close { top: var(--sp-2); right: var(--sp-2); }
}

/* ==================================================== NATIONAL HONOURS */
.nat { list-style: none; margin: var(--sp-5) 0 0; padding: 0; border-top: 2px solid var(--court); }
.nat li {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr) auto;
  gap: var(--sp-4) var(--sp-5);
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--divider);
  align-items: baseline;
}
.nat__year {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  color: var(--neutral);
  font-weight: 600;
}
.nat__event { font-size: var(--step-1); line-height: 1.15; }
.nat__detail { margin-top: 0.35rem; font-size: 0.9375rem; color: var(--neutral); max-width: 60ch; }
.nat__result {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--divider);
  white-space: nowrap;
}
.nat__result--gold { background: var(--gold); border-color: var(--gold); color: var(--ivory); }
.nat__result--silver { background: var(--silver); border-color: var(--silver); color: var(--ivory); }
@media (max-width: 700px) {
  .nat li { grid-template-columns: 4rem minmax(0, 1fr); }
  .nat__result { grid-column: 2; justify-self: start; }
}

/* =============================================================== CONTACT
   Two things this page is built around: the social links read as the
   headline act (large, not a footer afterthought), and the form itself
   stays plain — one honest field per line, no decoration competing with
   "did this actually send".
   ========================================================================= */
.social-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-6) var(--sp-7);
  margin-top: var(--sp-5);
}
.social-row a {
  font-family: var(--display);
  font-variation-settings: var(--display-axes);
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.social-row a:hover { color: var(--court); border-bottom-color: var(--court); }

.direct-email {
  margin-top: var(--sp-5);
  font-family: var(--mono);
  font-size: 0.9375rem;
}
.direct-email a { color: var(--court); }

/* The form sits on a full-bleed photograph rather than beside a cropped one.
   Own stacking context so the two backdrop layers can sit behind the content
   on negative z-index without escaping the section. */
.contact-section {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
/* Overrides `.section + .section { padding-top: 0 }`. That rule closes the gap
   between two sections sharing one ivory ground; here the section carries its
   own photograph, so it needs the full band back or the image starts flush
   against the panel. */
.section.contact-section { padding-top: var(--section-y); }
.contact-section__bg,
.contact-section__wash {
  position: absolute;
  inset: 0;
}
.contact-section__bg { z-index: -2; }
.contact-section__wash { z-index: -1; }

/* Scaled up past the edges: blur samples transparency beyond the element and
   would otherwise fade out along all four sides. */
.contact-section__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 65% center;
  filter: blur(1.5rem) saturate(1.15);
  transform: scale(1.12);
}

/* Feathers the photograph into the ivory sections above and below so the band
   has no hard seam, and lifts the left side — where the panel sits — without
   flattening the colour out of the right. Kept light enough overall that the
   section still reads as part of an ivory page rather than a dark break. */
.contact-section__wash {
  background:
    linear-gradient(180deg,
      rgba(246, 244, 239, 0.96) 0%,
      rgba(246, 244, 239, 0.34) 22%,
      rgba(246, 244, 239, 0.34) 78%,
      rgba(246, 244, 239, 0.96) 100%),
    linear-gradient(90deg,
      rgba(246, 244, 239, 0.62) 0%,
      rgba(246, 244, 239, 0.28) 48%,
      rgba(246, 244, 239, 0) 100%);
}

.contact-panel {
  max-width: 44rem;
  margin-top: var(--sp-6);
  padding: clamp(1.5rem, 3.5vw, 2.75rem);
  background: rgba(246, 244, 239, 0.96);
  border: 1px solid rgba(27, 27, 24, 0.08);
  box-shadow: 0 1px 2px rgba(27, 27, 24, 0.04), 0 1.5rem 3rem rgba(27, 27, 24, 0.07);
}

/* Blur is expensive to composite full-bleed, so it eases off on small screens
   — but not to zero: the strip of photograph left uncovered by the panel
   turns back into a recognisable figure without it, which pulls attention
   off the form. */
@media (max-width: 600px) {
  .contact-section__bg img { filter: blur(0.85rem) saturate(1.15); transform: scale(1.08); }
  .contact-section__wash {
    background: linear-gradient(180deg,
      rgba(246, 244, 239, 0.96) 0%,
      rgba(246, 244, 239, 0.55) 30%,
      rgba(246, 244, 239, 0.55) 70%,
      rgba(246, 244, 239, 0.96) 100%);
  }
}

.form-field { display: grid; gap: 0.4rem; margin-bottom: var(--sp-5); }
.form-field label {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--neutral);
}
.form-field input, .form-field textarea {
  border: 0;
  border-bottom: 1px solid var(--divider);
  background: transparent;
  padding: 0.65rem 0;
  font-size: 1rem;
  color: var(--ink);
  font-family: var(--body);
}
.form-field input:focus, .form-field textarea:focus {
  outline: none;
  border-bottom-color: var(--court);
}
.form-field textarea { resize: vertical; min-height: 8rem; }
.form-honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-status {
  margin-top: var(--sp-4);
  font-size: 0.9375rem;
}
.form-status--ok { color: var(--court); }
.form-status--error { color: #b3261e; }
.form-status:empty { display: none; }
