/* Mobile first. A dark hero band carries the answer and the clock; the body below is light or dark with the device.
   Colour has three jobs, kept apart. The brand's colour is the same on every page: the top bar, the mark, and the
   ring around whatever the keyboard is on. A sport's two colours, set on <body> as --h (its main hue) and --a (the
   accent hue of its clock), stay inside the hero and on small marks below it. Every other surface is neutral. */

/* --- The typeface: Archivo, served from this site. One file holds every weight from 100 to 900 and every width
   from 62% to 125%. The second file is only fetched by a page that uses letters from beyond western Europe. */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  src: url(/assets/fonts/archivo-latin-ext-wdth-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  src: url(/assets/fonts/archivo-latin-wdth-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root { color-scheme: light dark; --ease: cubic-bezier(0.2, 0.7, 0.2, 1); }
body {
  /* The brand: a floodlight yellow-green, a hue no sport on the site uses. --bar is the top bar, --brand the
     bright mark on it, and --focus the ring round whatever the keyboard is on (dark on light, bright on dark);
     --focus-page is the ring for the body, kept so a sheet opened from the dark header can ask for it back. */
  --brand-hue: 118;
  --bar: oklch(14.5% 0.025 var(--brand-hue));
  --brand: oklch(90% 0.2 var(--brand-hue));
  --focus-page: oklch(46% 0.13 var(--brand-hue));
  --focus: var(--focus-page);
  /* Neutral surfaces and ink: the same under every sport. */
  --bg: oklch(97.5% 0.003 260);
  --surface: oklch(100% 0 0);
  --ink: oklch(21% 0.012 260);
  --muted: oklch(46% 0.012 260);
  --line: oklch(89% 0.006 260);
  --hover: oklch(94% 0.006 260);
  /* The sport's colours. --accent is for small marks on the neutral body; the rest belong to the hero. */
  --accent: oklch(52% 0.17 var(--h));
  /* The band behind a winner's name: highlighter yellow, whatever the sport's own colour. */
  --win: oklch(90% 0.16 98);
  --hero-1: oklch(15% 0.02 var(--h));
  --hero-2: oklch(23% 0.04 var(--h));
  --hero-ink: oklch(98% 0.005 var(--h));
  --glow: oklch(84% 0.17 var(--h));
  --hot: oklch(68% 0.24 var(--a));
  /* Type: six steps and nothing smaller than the first. Use these, not one-off sizes. */
  --t-small: 0.8125rem;
  --t-meta: 0.9375rem;
  --t-body: 1.0625rem;
  --t-lead: 1.3125rem;
  --t-title: 1.75rem;
  --t-display: clamp(2.5rem, 6vw, 3.75rem);
  /* One typeface in two voices. Display (headings, times, numerals) is condensed and heavy: say "condensed" in a
     font shorthand, or font-stretch: 75%, with a weight of 700 or 800. Reading text is normal width at 400, with
     600 for emphasis. */
  --font-display: "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-text: "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Space between one thing and the next down the page: five steps. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 1rem;
  --space-4: 1.5rem;
  --space-5: 2.5rem;
  /* Corners: small for controls and rows, large for panels, and the pill. No others. */
  --r-small: 6px;
  --r-large: 12px;
  --r-pill: 999px;
  /* Anything tappable is at least this tall and wide on a touch screen. */
  --tap: 2.75rem;
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 var(--t-body)/1.5 var(--font-text);
}
@media (prefers-color-scheme: dark) {
  body {
    --focus-page: var(--brand);
    --bg: oklch(14% 0.006 260);
    --surface: oklch(19% 0.008 260);
    --ink: oklch(94% 0.005 260);
    --muted: oklch(72% 0.01 260);
    --line: oklch(29% 0.008 260);
    --hover: oklch(22% 0.01 260);
    --accent: oklch(78% 0.15 var(--h));
    --win: oklch(46% 0.11 95);
  }
}
/* The header and the hero are dark whatever the device's scheme, so the ring there is always the bright one. */
header, .hero { --focus: var(--brand); }

* { box-sizing: border-box; }
/* Without this, any rule that sets display would show an element the page has marked hidden. */
[hidden] { display: none !important; }
.wrap { max-width: 60rem; margin: 0 auto; padding: 0 1rem; }
/* A link in running text is the colour of the text; its underline is the sport's. */
a { color: inherit; text-decoration-color: var(--accent); text-decoration-thickness: 0.09em; text-underline-offset: 0.2em; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* --- The hero band */

.hero {
  position: relative;
  overflow: hidden;
  color: var(--hero-ink);
  padding: var(--space-3) 0 var(--space-4);
  background:
    radial-gradient(90% 70% at 95% 0%, oklch(62% 0.19 var(--h) / 0.38), transparent 60%),
    radial-gradient(70% 60% at 0% 100%, oklch(60% 0.24 var(--a) / 0.26), transparent 65%),
    linear-gradient(180deg, var(--hero-1), var(--hero-2));
}
.hero .wrap { position: relative; z-index: 1; }
.hero a { text-decoration-color: currentColor; }
.sport-icon { flex: none; width: 2rem; height: 2rem; }

/* --- Each sport's own background: its whole arena, to scale, in three dimensions (engine/backdrops.js).
   A camera is worked out the way a real one is. --p is the lens: the distance from the eye to the page, set to
   86% of the page's width, which gives a view about 60 degrees wide on any screen. --u is how many pixels a
   metre is drawn at before the lens enlarges or shrinks it; it only sets how much detail the drawings hold.
   The camera is a crane in three nested parts, each with one job, so each can move in one unbroken motion:
   .spin turns the arena to the direction faced and brings the point looked at to the centre; .tilt tips it
   to the angle looked down at; .scene sets it back by the camera's distance and applies the lens. */
.backdrop { --p: 86vw; --cx: 50%; --cy: 64%; --u: calc(170cqw / var(--w)); position: absolute; inset: 0; overflow: hidden; pointer-events: none; container-type: size; perspective: var(--p); perspective-origin: var(--cx) var(--cy); }
.scene, .tilt, .spin { position: absolute; left: 0; top: 0; transform-style: preserve-3d; transform-origin: 0 0; }
.scene { left: var(--cx); top: var(--cy); transform: translateZ(calc(var(--p) - var(--range1) * var(--u) * var(--zoom, 1))); }
/* A scene kept whole in view was measured to fit beside the scoreboard. It is brought closer to fill the room it
   has: a little with the scoreboard beside it, more in the band of its own on a phone. */
.backdrop.whole { --zoom: 0.55; }
.tilt { transform: rotateX(var(--tilt1)); }
.spin { width: calc(var(--w) * var(--u)); height: calc(var(--d) * var(--u)); transform: rotateZ(var(--turn1)) translate3d(calc(var(--lx1) * var(--u) * -1), calc(var(--ly1) * var(--u) * -1), calc(var(--lz1) * var(--u) * -1)); }
/* The drawings are made once and kept, not redrawn as the camera moves. */
.spin svg { position: absolute; overflow: visible; will-change: transform; }
.spin .ground { inset: 0; width: 100%; height: 100%; }
.spin .up, .spin .flat { left: calc(var(--x) * var(--u)); top: calc(var(--y) * var(--u)); width: calc(var(--uw) * var(--u)); height: calc(var(--uh) * var(--u)); }
/* A thing stands up from its foot, turned to the way it faces. One that leans (raked seating) tips back from there. */
.spin .up { transform-origin: 50% 100%; transform: translate(-50%, -100%) rotateZ(var(--face)) rotateX(calc(var(--lean, 0deg) - 90deg)); }
.spin .flat { transform: translate(-50%, -50%) translateZ(calc(var(--lift) * var(--u))); }
/* What would stand close in front of the camera where it stops is there at the start and gone by the end. */
.backdrop .near { opacity: 0; }
/* On a phone the arena has a band of its own under the scoreboard; with room it stands beside it, where the
   country outline stands on an event's page. Nothing is ever drawn behind the scoreboard's numbers. */
.hero:has(> .backdrop) { padding-bottom: calc(var(--space-4) + 34vw); }
.backdrop { --cy: calc(100% - 22vw); }
/* Tall things (light towers, the back of a stand) would reach up behind the words, so the drawing fades out
   before it gets there: above its band on a phone, and under the heading and behind the scoreboard with room. */
.backdrop { mask-image: linear-gradient(to bottom, transparent calc(100% - 34vw - 4rem), #000 calc(100% - 34vw - 0.5rem)); }
@media (min-width: 44rem) {
  .hero:has(> .backdrop) { padding-bottom: var(--space-4); min-height: 24rem; }
  .backdrop.whole { --zoom: 0.8; }
  .backdrop { --cx: 73%; --cy: 56%; mask-image: linear-gradient(to right, transparent 34%, #000 54%), linear-gradient(to bottom, transparent 3.5rem, #000 9rem); mask-composite: intersect; }
}
/* Surfaces take the sport's colour; lines and posts are white; shadows fall away from the light. Every width
   here is in metres, like the drawings: lines and posts are drawn a little heavier than life (30 cm) so they
   still show from high above, and the track is its real 12 metres wide. */
.backdrop .surround { fill: oklch(32% 0.06 var(--h) / 0.6); }
.backdrop .surface { fill: oklch(50% 0.13 var(--h) / 0.55); }
.backdrop .apron { fill: oklch(41% 0.1 var(--h) / 0.55); }
.backdrop .grass { fill: oklch(50% 0.13 150 / 0.55); }
.backdrop .stripe { fill: oklch(100% 0 0 / 0.06); }
.backdrop :is(.wicket, .sand) { fill: oklch(86% 0.06 90 / 0.55); }
.backdrop .tarmac { fill: oklch(22% 0.01 var(--h) / 0.85); }
.backdrop .line { fill: none; stroke: oklch(100% 0 0 / 0.62); stroke-width: 0.3; }
.backdrop .faint { stroke: oklch(100% 0 0 / 0.25); }
.backdrop .dash { stroke: oklch(100% 0 0 / 0.4); stroke-dasharray: 2; }
.backdrop :is(.spot, .check) { fill: oklch(100% 0 0 / 0.85); }
.backdrop .shade { fill: oklch(0% 0 0 / 0.3); }
.backdrop .shade-line { fill: none; stroke: oklch(0% 0 0 / 0.4); stroke-width: 0.5; stroke-linecap: round; }
.backdrop .post { fill: none; stroke: oklch(100% 0 0 / 0.95); stroke-width: 0.3; stroke-linecap: round; stroke-linejoin: round; }
.backdrop .stump { fill: none; stroke: oklch(100% 0 0 / 0.95); stroke-width: 0.045; }
.backdrop .rod { fill: none; stroke: oklch(100% 0 0 / 0.9); stroke-width: 0.1; stroke-linecap: round; stroke-linejoin: round; }
.backdrop .rope { fill: none; stroke: oklch(100% 0 0 / 0.95); stroke-width: 0.07; }
.backdrop .strand { fill: none; stroke: oklch(100% 0 0 / 0.5); stroke-width: 0.12; }
.backdrop .net { fill: oklch(100% 0 0 / 0.16); stroke: oklch(100% 0 0 / 0.45); stroke-width: 0.08; }
.backdrop .panel { fill: oklch(72% 0.06 var(--h) / 0.4); }
.backdrop .roof { fill: oklch(88% 0.03 var(--h) / 0.5); }
.backdrop .canvas { fill: oklch(93% 0.02 var(--h) / 0.8); }
.backdrop .red { fill: oklch(58% 0.22 27); }
.backdrop .blue { fill: oklch(52% 0.2 262); }
.backdrop .lamp { fill: oklch(100% 0 0 / 0.6); }
.backdrop .pad { fill: oklch(70% 0.2 var(--a) / 0.95); }
.backdrop .cloth { fill: oklch(8% 0 0 / 0.7); stroke: oklch(100% 0 0 / 0.8); stroke-width: 0.1; }
.backdrop .kerb { fill: none; stroke: oklch(100% 0 0 / 0.5); stroke-width: 13.6; }
.backdrop .track { fill: none; stroke: oklch(22% 0.01 var(--h) / 0.95); stroke-width: 12; }
.backdrop .pitlane { fill: none; stroke: oklch(22% 0.01 var(--h) / 0.85); stroke-width: 6; }
/* A running track is one colour through its lanes and the straight carried back from them, so the two are drawn
   solid and faded together. Its lane lines are their real 5 cm, drawn at 12 so they show. */
.backdrop .running { opacity: 0.55; }
.backdrop .lanes { fill: none; stroke: oklch(50% 0.13 var(--h)); stroke-width: 9.76; }
.backdrop .chute { fill: oklch(50% 0.13 var(--h)); }
.backdrop .thin { stroke-width: 0.12; }

/* --- Teams: a flag where the checked list has one, and a chip with the team's code and colour */
.matchup { display: flex; align-items: center; gap: 0.7rem; margin: 0 0 var(--space-3); }
.side { display: inline-flex; align-items: center; gap: 0.5rem; text-decoration: none; }
.vs { font-weight: 600; opacity: 0.8; }
.flag { display: block; box-shadow: 0 0 0 1px oklch(100% 0 0 / 0.25), 0 3px 8px oklch(0% 0 0 / 0.35); }
.matchup .flag { width: 2.4rem; height: 1.8rem; }
.chip { display: inline-block; padding: 0.15rem 0.5rem; border-radius: var(--r-small); background: var(--c); color: var(--t); font: 800 condensed var(--t-small)/1.4 var(--font-display); box-shadow: 0 0 0 1px oklch(100% 0 0 / 0.25); }

/* --- Countdown clocks. Their numerals are sized in cqw, hundredths of the clock's own width. */
.clock { display: grid; grid-template-columns: repeat(4, max-content); justify-content: start; align-items: start; gap: 0.5rem min(2.6cqw, 1rem); font-variant-numeric: tabular-nums; }
.unit { display: grid; justify-items: center; gap: 0.35rem; }

/* Digital: lit segments on a dark panel */
.clock-digital .value { display: flex; gap: min(1cqw, 0.3rem); padding: min(2cqw, 0.7rem); border-radius: var(--r-small); background: #040705; box-shadow: inset 0 0 0 1px oklch(100% 0 0 / 0.1); }
.seg { display: block; height: min(10cqw, 4rem); }
.seg .on { fill: var(--hot); filter: drop-shadow(0 0 2px var(--hot)); }
.seg .off { fill: oklch(100% 0 0 / 0.07); }
.seg polygon { transition: fill 0.3s, filter 0.3s; }

/* Mission: a launch-control clock, T minus days:hours:minutes:seconds */
.clock-mission { grid-template-columns: repeat(5, max-content); gap: 0.4rem 0; width: fit-content; max-width: 100%; padding: min(4cqw, 1.3rem) min(4cqw, 1.5rem) min(3cqw, 1rem); border-radius: var(--r-small); background: #000; border: 2px solid #2c2c2c; color: var(--hot); text-shadow: 0 0 14px oklch(68% 0.24 var(--a) / 0.6); }
.clock-mission .clock-lead, .clock-mission .value { font-family: var(--font-display); font-stretch: 75%; font-size: min(11cqw, 5rem); font-weight: 700; line-height: 1; }
.clock-mission .clock-lead { grid-column: auto; margin-right: 0.3em; opacity: 1; }
.clock-mission .unit + .unit .value::before { content: ":"; margin: 0 0.12em; animation: blink 1s ease-in-out infinite alternate; }
@keyframes blink { from { opacity: 0.85; } to { opacity: 0.25; } }
.clock-mission .label { color: #b9b9b9; text-shadow: none; }

/* Flip: split-flap cards */
.clock-flip .value { display: flex; gap: min(1cqw, 0.3rem); perspective: 300px; }
.card { display: grid; place-items: center; width: 0.85em; height: 1.3em; border-radius: var(--r-small); font-family: var(--font-display); font-stretch: 75%; font-size: min(10cqw, 5rem); font-weight: 800; line-height: 1; color: #fff; background: linear-gradient(#34383a 0 49%, #000 49% 51%, #1d2022 51%); box-shadow: 0 3px 0 var(--hot), 0 6px 12px #0006; }
.card.flip { animation: flip 0.45s ease-out; }
.clock-flip .label { margin-top: 0.2rem; }
@keyframes flip { from { transform: rotateX(-85deg); opacity: 0.3; } to { transform: none; opacity: 1; } }

/* Rings: each unit as a dial that empties */
.clock-ring .value { position: relative; width: min(21cqw, 7rem); aspect-ratio: 1; }
.clock-ring svg { position: absolute; inset: 0; transform: rotate(-90deg); }
.track, .arc { fill: none; stroke-width: 3; }
.track { stroke: oklch(100% 0 0 / 0.15); }
.arc { stroke: var(--hot); stroke-linecap: round; transition: stroke-dashoffset 0.9s cubic-bezier(0.3, 0, 0.2, 1); }
.num { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--font-display); font-stretch: 75%; font-size: min(8.5cqw, 3rem); font-weight: 800; line-height: 1; }

/* --- Body */
.body { padding-top: var(--space-4); padding-bottom: var(--space-3); }
.body > :first-child > h2:first-child { margin-top: var(--space-2); }

/* --- Motion. Pages cross-fade into each other, and the hero arrives once, in three beats: the heading, the
   scoreboard, then the picture (the sport's drawing settling behind them, or the country's outline beside them
   with its marker dropping onto the venue). Stepping to the event before or after is not arriving: those pages
   open as they will stay (.stepped, set in the page's head). Nothing below the hero moves as the page opens. Everything is
   switched off for visitors who ask for reduced motion (at the end of this file).
   One rule keeps it calm: a thing that arrives with an animation answers the pointer with a transition, never
   with a second animation. When the pointer left, the first animation would start again and the thing would
   arrive afresh. */
@view-transition { navigation: auto; }
/* Swiping between events (client.js): only the event's card moves, with the next event's card beside it a small
   gap away. The browser keeps up-and-down scrolling and pinching. Let go and the pair springs into place, a little
   past and back, or springs back; the hero clips whatever is off to the side. */
:root:has(.steps) main { touch-action: pan-y pinch-zoom; }
.hero .wrap > .details { position: relative; }
/* Between two events' pages the card has a part of its own in the view transition: it glides from where it was to
   where the next page has it, and only the rest of the page fades over. */
:root:has(.steps) .hero .wrap > .details { view-transition-name: card; }
.card-next { position: absolute; top: 0; z-index: 1; width: 100%; }
.swiped, .swiped > .card-next { transition: transform 0.45s, left 0.45s; transition-timing-function: linear(0, 0.06 2.4%, 0.22 5.3%, 0.45 9%, 0.69 13.6%, 0.86 18.4%, 0.97 23.6%, 1.03 29.4%, 1.045 34.5%, 1.04 40%, 1.02 48%, 1.005 58%, 0.998 70%, 1); }
html { scroll-behavior: smooth; }
@keyframes rise { from { opacity: 0; transform: translateY(12px); } }
@keyframes pop { from { opacity: 0; transform: scale(0.96); } }
@keyframes settle { from { opacity: 0; } }
/* The opening move: a camera starts high above the whole arena at an angle and comes part of the way down
   towards the middle. Each part of the crane makes one unbroken motion from its first value to the scene's
   own resting one: the turn is slow and finishes first, after which the camera keeps facing the target while
   it finishes coming down and closing in. Nothing is joined from pieces, so nothing can jerk at a join. */
@keyframes spin { from { transform: rotateZ(var(--turn0)) translate3d(calc(var(--lx0) * var(--u) * -1), calc(var(--ly0) * var(--u) * -1), calc(var(--lz0) * var(--u) * -1)); } }
@keyframes tilt { from { transform: rotateX(var(--tilt0)); } }
@keyframes dolly { from { transform: translateZ(calc(var(--p) - var(--range0) * var(--u) * var(--zoom, 1))); } }
.backdrop { animation: settle 1.6s var(--ease) 0.25s backwards; }
.scene { animation: dolly 3.9s cubic-bezier(0.4, 0, 0.1, 1) 0.3s backwards; }
.tilt { animation: tilt 3.9s cubic-bezier(0.45, 0, 0.25, 1) 0.3s backwards; }
.spin { animation: spin 2.7s cubic-bezier(0.4, 0, 0.3, 1) 0.3s backwards; }
@keyframes clear { from, 35% { opacity: 1; } }
.backdrop .near { animation: clear 3.9s ease-in 0.3s backwards; }
.backdrop.seen :is(.scene, .tilt, .spin, .near) { animation: none; }
.stepped :is(.backdrop, .scene, .tilt, .spin, .near, .map img, .pin) { animation: none; }
.map img { animation: arrive 0.9s var(--ease) 0.3s backwards; }
.pin { animation: drop 0.5s var(--ease) 1.1s backwards; }

/* === Stream A: inside the hero (the time answer, clock, actions, map, forecast) === */

/* --- The line above the heading: the sport's icon, then the competition and the stage as separate pieces
   (the competition a link, the stage in plain lettering), then the event's state. */
.eyebrow { display: flex; align-items: center; gap: 0.6rem; margin: 0 0 var(--space-2); font-size: var(--t-small); font-weight: 600; line-height: 1.3; color: var(--glow); }
@media (min-width: 44rem) { .eyebrow { font-size: var(--t-meta); } }
.eyebrow .sport-icon { width: 1.5rem; height: 1.5rem; }
/* The words wrap among themselves when they must; the icon and the state keep their places at either end. */
.eb { min-width: 0; }
.eb[data-event] { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.7rem; }
.eb .stage { font-weight: 400; color: var(--hero-ink); }

/* --- The heading is the scoreboard's caption. On a phone it is kept small, so the time and the clock stay in view. */
h1 { margin: 0 0 var(--space-3); font: 800 condensed var(--t-title)/1.05 var(--font-display); text-wrap: balance; }
@media (min-width: 44rem) { h1 { font-size: var(--t-display); } }
/* A two-team heading is written in pieces, so a crest is never parted from its name at the end of a line. */
h1 span { display: inline-block; max-width: 100%; }
/* A team's name in a heading leads to that team's page: a line draws itself under the name the pointer is on. */
h1 a { text-decoration: none; background: linear-gradient(var(--glow), var(--glow)) 0 100% / 0 0.08em no-repeat; transition: background-size 0.3s var(--ease); }
/* A team's crest stands before its name, as tall as the letters and square. */
h1 .logo, h1 .flag { display: inline-block; margin-right: 0.25em; }
h1 .logo { width: 0.9em; height: 0.9em; padding: 0.07em; vertical-align: -0.1em; }
h1 .flag { width: auto; height: 0.74em; vertical-align: -0.03em; }
/* The events before and after this one, at the top of an event's page: a link at each edge, each with an arrowhead
   drawn from two borders. The arrow keys follow them. */
.steps { display: flex; justify-content: space-between; gap: 0.75rem; margin: 0 0 var(--space-3); }
.steps a { display: flex; align-items: center; gap: 0.5rem; min-width: 0; max-width: 48%; min-height: 2rem; padding: 0.2rem 0.8rem; border: 1px solid oklch(100% 0 0 / 0.32); border-radius: var(--r-pill); font-size: var(--t-small); line-height: 1.2; text-decoration: none; transition: background-color 0.15s; }
.steps [rel="next"] { margin-left: auto; flex-direction: row-reverse; text-align: right; }
.steps a::before { content: ""; flex: none; width: 0.4rem; height: 0.4rem; border: solid currentColor; border-width: 0 0 2px 2px; transform: rotate(45deg); }
.steps [rel="next"]::before { transform: rotate(-135deg); }
.step-way { flex: none; font-weight: 600; }
.step-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: 0.85; }
@media (hover: hover) { .steps a:hover { background: oklch(100% 0 0 / 0.14); } }
@media (pointer: coarse) { .steps a { min-height: var(--tap); } }
.next-name { margin: 0 0 var(--space-3); font: 700 condensed var(--t-lead)/1.2 var(--font-display); }

/* --- The hero's layout. On a phone it is one column: the caption, the scoreboard, then the host country's
   outline. With room to spare the outline stands beside the scoreboard in a column of its own. Either way
   nothing ever sits on top of the outline or its marker. */
.hero .wrap { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; }
.hero .wrap > * { min-width: 0; }
.place { display: grid; justify-items: center; margin-top: var(--space-4); }
@media (min-width: 44rem) {
  .hero .wrap { grid-template-columns: minmax(20rem, 28rem) minmax(0, 1fr); column-gap: 2.5rem; }
  .hero .wrap > * { grid-column: 1 / -1; }
  .hero .wrap:has(> .place) > .details, .hero:has(> .backdrop) .wrap > .details { grid-column: 1; }
  .hero .wrap > .place { grid-column: 2; justify-items: start; margin-top: 0; }
}

/* --- The host country's outline, with a pulsing dot at the venue. On a phone it is held to a modest height;
   with room, it is as wide as its column allows, but a tall country (New Zealand) is still held in. */
/* The track's outline: one white line, shown at once with no drawing-on. It stands first, with
   the country smaller beneath it. Its height is fixed and its width follows its shape, within the column. */
.track { display: grid; justify-items: start; gap: 0.3rem; margin: 0 0 var(--space-3); max-width: 100%; }
.track svg { display: block; height: 11rem; max-width: 100%; aspect-ratio: var(--tk); overflow: visible; }
.track path { fill: none; stroke: oklch(100% 0 0 / 0.95); stroke-width: calc(var(--th) * 0.022); stroke-linejoin: round; stroke-linecap: round; filter: drop-shadow(0 0 3px oklch(0% 0 0 / 0.6)); }
.track figcaption { font-size: var(--t-small); line-height: 1.3; opacity: 0.85; }
.place:has(.track) .map { width: min(100%, 16rem, calc(10rem * var(--r))); }
/* On a phone a track's outline says where the race is; the country under it would push the page down a screen. */
@media (max-width: 43.99rem) {
  .place:has(.track) .map { display: none; }
  .track svg { height: 8rem; }
  .place { margin-top: var(--space-3); }
}
@media (min-width: 44rem) { .track svg { height: 13rem; } .place:has(.track) .map { width: min(100%, 20rem, calc(12rem * var(--r))); } }
.map { position: relative; width: min(100%, 22rem, calc(13rem * var(--r))); opacity: 0.9; }
@media (min-width: 44rem) { .map { width: min(100%, 33rem, calc(28rem * var(--r))); } }
.map img { display: block; width: 100%; height: 100%; transform-origin: 50% 50%; }
.pin { position: absolute; width: 0.7rem; height: 0.7rem; margin: -0.35rem 0 0 -0.35rem; border-radius: 50%; background: var(--hot); box-shadow: 0 0 0 2px oklch(100% 0 0 / 0.9); }
.pin::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--hot); animation: ping 2.2s ease-out 1.6s infinite; }
.pin b { position: absolute; left: 0.9rem; top: -0.3rem; font-size: var(--t-small); font-weight: 600; line-height: 1.2; white-space: nowrap; }
/* A venue near the right-hand edge has its name on the left of the dot, so it is not cut off. */
.pin.left b { left: auto; right: 0.9rem; }

/* --- The scoreboard: one panel in two parts. On top the answer (the date, the time, the venue); under it
   the clock. Without scripts there is no clock, and the answer is the whole panel. */
.answer, .countdown { max-width: 30rem; padding: 0.75rem 1rem; border: 1px solid oklch(100% 0 0 / 0.2); border-radius: var(--r-large); background: oklch(0% 0 0 / 0.4); }
/* The time is sized in cqw, hundredths of the panel's own width, so it is as large as the panel can hold. */
.answer { container-type: inline-size; }
.answer:has(+ .countdown:not([hidden])) { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.countdown { container-type: inline-size; border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; background: oklch(0% 0 0 / 0.62); }
/* With nothing beside it (no outline, no arena) and room to spare, the scoreboard lies on its side, as wide as
   the page's column: the answer on the left, the clock on the right. */
@media (min-width: 52rem) {
  .hero:not(:has(> .backdrop)) .wrap:not(:has(> .place)) > .details:has(> .countdown:not([hidden])) { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .hero:not(:has(> .backdrop)) .wrap:not(:has(> .place)) > .details:has(> .countdown:not([hidden])) > * { grid-column: 1 / -1; }
  .hero:not(:has(> .backdrop)) .wrap:not(:has(> .place)) > .details > .answer:has(+ .countdown:not([hidden])) { grid-column: 1; max-width: none; border-bottom-left-radius: var(--r-large); border-top-right-radius: 0; }
  .hero:not(:has(> .backdrop)) .wrap:not(:has(> .place)) > .details > .answer + .countdown:not([hidden]) { grid-column: 2; display: grid; align-content: center; justify-items: center; max-width: none; padding: 1rem 1.25rem; border-top: 1px solid oklch(100% 0 0 / 0.2); border-left: 0; border-top-right-radius: var(--r-large); border-bottom-left-radius: 0; }
}
.when-date { margin: 0 0 var(--space-2); font-size: var(--t-body); font-weight: 600; line-height: 1.3; }
/* The time. The first row is the big one: the reader's own time once the browser has drawn it, the venue's
   until then. The second, smaller row is the venue's time, or a note that the two are the same. */
.rows { display: grid; gap: var(--space-1); }
.trow { margin: 0; }
.trow.main { display: grid; gap: 0.1rem; }
.rows .tc-label { font-size: var(--t-meta); font-weight: 600; line-height: 1.3; color: var(--glow); }
.tc-when { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.5rem; }
.tc-time { font-family: var(--font-display); font-stretch: 75%; font-size: clamp(2.25rem, 14cqw, 3.5rem); font-weight: 800; line-height: 0.95; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tz { font: 700 condensed var(--t-lead)/1 var(--font-display); }
/* '+1 day': the reader's date is not the venue's. */
.day { align-self: center; padding: 0.1rem 0.55rem; border-radius: var(--r-pill); background: var(--hot); color: var(--hero-1); font-size: var(--t-small); font-weight: 600; line-height: 1.4; white-space: nowrap; }
.trow.sub { font-size: var(--t-meta); line-height: 1.4; font-variant-numeric: tabular-nums; opacity: 0.85; }
/* The reader's clocks change before the event: said once, quietly, under the times. */
.trow.clockchange { margin-top: var(--space-1); font-size: var(--t-small); line-height: 1.4; opacity: 0.85; }
.tba { margin: 0; font: 800 condensed var(--t-title)/1.2 var(--font-display); }
.tba:empty { display: none; }
/* The venue's line, with the forecast at its end: a small icon and the temperature. */
.where { display: flex; flex-wrap: wrap; align-items: center; gap: 0 0.7rem; margin: var(--space-2) 0 0; font-size: var(--t-meta); line-height: 1.4; }
.answer .where { padding-top: var(--space-2); border-top: 1px solid oklch(100% 0 0 / 0.14); }
.wx { display: inline-flex; align-items: center; gap: 0.3rem; font-weight: 600; font-variant-numeric: tabular-nums; cursor: help; }
.more-line { margin: var(--space-1) 0 0; font-size: var(--t-meta); }
/* Under the scoreboard, a weekend's next session (or the one on now): what it is and when, then how long until it. */
.sessionnext { display: grid; gap: 0.1rem; margin: var(--space-2) 0 0; padding-top: var(--space-2); border-top: 1px solid oklch(100% 0 0 / 0.14); font-size: var(--t-meta); line-height: 1.4; }
.sn-label { font-size: var(--t-small); opacity: 0.85; }
.sn-in { font-size: var(--t-small); }
.sn-in:empty { display: none; }
.sn-in .miniclock { margin-left: 0.2rem; }
.sn-when { font-variant-numeric: tabular-nums; }
.hero .more { color: var(--glow); font-weight: 600; }

/* --- The clock, the bottom half of the scoreboard. Four units always fit on one line, phone or desktop. */
.clock-lead { grid-column: 1 / -1; font-size: var(--t-meta); font-weight: 600; opacity: 0.85; }
.unit .label { font-family: var(--font-text); font-size: var(--t-small); font-weight: 400; line-height: 1.2; opacity: 0.85; }
/* Shown once the event has finished */
.clock-text { display: block; font: 800 condensed var(--t-title)/1.2 var(--font-display); }

/* --- Under the scoreboard: a row of small things to do (add to a calendar, embed, choose a clock face).
   The same small button opens the reader's settings in the header. */
.actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
.act { display: inline-flex; align-items: center; justify-content: center; gap: 0.3rem; min-height: 2rem; padding: 0.2rem 0.8rem; border: 1px solid oklch(100% 0 0 / 0.32); border-radius: var(--r-pill); background: transparent; color: inherit; font: 600 var(--t-small)/1.2 var(--font-text); text-decoration: none; white-space: nowrap; cursor: pointer; transition: background-color 0.15s, border-color 0.15s; }

/* --- Sheets: what those buttons open (the embed code, the clock faces, the reader's settings). */
.sheet { width: min(24rem, calc(100vw - 2rem)); padding: 1.25rem; border: 1px solid var(--line); border-radius: var(--r-large); background: var(--surface); color: var(--ink); box-shadow: 0 24px 70px oklch(0% 0 0 / 0.5); font: 400 var(--t-meta)/1.5 var(--font-text); --focus: var(--focus-page); }
.sheet.embed-code { width: min(34rem, calc(100vw - 2rem)); }
.subscribe-sheet input, .share-sheet input { width: 100%; padding: 0.4rem 0.6rem; border: 1px solid var(--line); border-radius: var(--r-small); font: 400 var(--t-small)/1.4 var(--font-text); color: var(--ink); background: var(--bg); }
.sheet.share-sheet { width: min(30rem, calc(100vw - 2rem)); }
.sheet .share-text { color: var(--ink); }
.share-card { width: 100%; height: auto; margin: 0 0 var(--space-3); border-radius: var(--r-small); vertical-align: top; }
.sheet:popover-open { animation: pop 0.2s ease-out both; }
.sheet::backdrop { background: oklch(0% 0 0 / 0.55); backdrop-filter: blur(3px); }
.sheet p { margin: 0 0 var(--space-3); color: var(--muted); }
.sheet .sheet-title { margin: 0 0 var(--space-3); font: 800 condensed var(--t-title)/1.1 var(--font-display); color: var(--ink); }
.sheet .sheet-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0 0; }
.sheet label { display: grid; gap: var(--space-1); margin: 0 0 var(--space-3); font-weight: 600; }
.sheet select, .sheet textarea { display: block; width: 100%; padding: 0.6rem 0.7rem; border: 1px solid var(--line); border-radius: var(--r-small); background: var(--bg); color: var(--ink); font: 400 var(--t-body)/1.4 var(--font-text); }
.sheet textarea { font: 400 var(--t-small)/1.4 ui-monospace, "SF Mono", Menlo, Consolas, monospace; resize: vertical; }
.clock-picker { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.clock-picker button { min-height: 2.25rem; padding: 0.3rem 1rem; border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--bg); color: var(--ink); font: 600 var(--t-meta)/1.2 var(--font-text); cursor: pointer; transition: background-color 0.15s, border-color 0.15s; }
.clock-picker button[aria-pressed="true"] { background: var(--ink); color: var(--bg); border-color: transparent; }

/* --- The page shown inside another site's frame: the same time rows and clock with no panel around them,
   small enough to fit the frame height given in the embed code. */
body.embed { background: var(--hero-1); }
.embed .hero { min-height: 100vh; padding: 0.7rem 0.9rem; }
.embed h1 { margin: 0 0 var(--space-1); font-size: var(--t-lead); }
.embed .when-date { margin: 0; font-size: var(--t-small); }
.embed .rows { gap: 0; }
.embed .tc-label { font-size: var(--t-small); }
.embed .trow.main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.6rem; }
.embed .tc-time { font-size: var(--t-title); line-height: 1.1; }
.embed .tz { font-size: var(--t-meta); }
.embed .trow.sub { font-size: var(--t-small); }
.embed .countdown { max-width: none; margin-top: var(--space-2); padding: 0; border: 0; background: none; }
.embed .clock { row-gap: 0.3rem; }
.embed .unit { gap: 0.2rem; }
/* Smaller clock faces, so the whole card fits the frame. */
.embed .seg { height: min(10cqw, 2.6rem); }
.embed .clock-mission .clock-lead, .embed .clock-mission .value { font-size: min(11cqw, 2.8rem); }
.embed .card { font-size: min(10cqw, 2.8rem); }
.embed .clock-ring .value { width: min(19cqw, 3.8rem); }
.embed .num { font-size: min(8cqw, 1.6rem); }
.embed .by { display: flex; gap: 0.8rem; margin: var(--space-2) 0 0; font-size: var(--t-small); opacity: 0.85; }
.embed .by a { color: var(--glow); }

/* --- On a touch screen anything tappable is at least a thumb tall and wide. Buttons grow; links inside a
   line of text keep their place and get a larger area to hit instead. */
@media (pointer: coarse) {
  .act, .clock-picker button, .sheet select, .sheet .button { min-height: var(--tap); min-width: var(--tap); }
  h1 a, .eb a, .next-name a, .hero .more, .matchup a.side, .embed .by a { position: relative; }
  h1 a::after, .eb a::after, .next-name a::after, .hero .more::after, .matchup a.side::after, .embed .by a::after { content: ""; position: absolute; left: 50%; top: 50%; width: max(100%, var(--tap)); height: var(--tap); transform: translate(-50%, -50%); }
}
/* The pointer: a button or a tab lightens a step under it. Nothing moves. */
@media (hover: hover) {
  h1 a:hover { background-size: 100% 0.08em; }
  .act:hover { background: oklch(100% 0 0 / 0.14); border-color: oklch(100% 0 0 / 0.6); }
  .clock-picker button:not([aria-pressed="true"]):hover { background: var(--hover); border-color: var(--muted); }
}

/* === Stream B: lists (fixtures, matches, players, teams, status marks) === */

/* --- Where an event stands: on now, finished, or called off. Sits beside a name, on the hero or in a list. */
.status-mark { display: inline-block; padding: 0.1rem 0.55rem; border-radius: var(--r-pill); border: 1px solid transparent; font: 600 var(--t-small)/1.4 var(--font-text); white-space: nowrap; }
.status-mark.live { background: var(--hot); color: var(--hero-1); }
.status-mark.done { border-color: color-mix(in oklch, currentColor 45%, transparent); }
.status-mark.off { background: #ffd35c; color: #3d2c00; }

/* --- Headings in the body: sentence case, in the display voice, three sizes down from the page's heading. */
h2 { margin: var(--space-5) 0 var(--space-3); font: 800 condensed var(--t-title)/1.1 var(--font-display); }
h3 { margin: var(--space-4) 0 var(--space-2); font: 700 condensed var(--t-lead)/1.2 var(--font-display); }
h4 { margin: var(--space-3) 0 var(--space-1); font: 700 condensed var(--t-body)/1.3 var(--font-display); color: var(--muted); }
.field-note, .m-note { margin: var(--space-2) 0 0; font-size: var(--t-small); color: var(--muted); }

/* --- Timetables: a heading for each day, marked in the sport's colour, then hairline rows in columns: the
   time, the event, the place, and a stage or standing. Names are never cut short: they wrap. */
.fixtures ol { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.fixtures .fx-date { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 0.5rem; margin: var(--space-4) 0 var(--space-2); font: 700 condensed var(--t-lead)/1.2 var(--font-display); color: var(--ink); }
.fixtures .fx-date:first-child { margin-top: 0; }
.fx-date:not(.sub)::before { content: ""; align-self: center; width: 0.3rem; height: 1em; background: var(--accent); }
/* A day inside a wider section, such as a Saturday inside "This weekend". */
.fixtures .fx-date.sub { margin: var(--space-3) 0 var(--space-1); font-size: var(--t-body); color: var(--muted); }
.fixtures .fx-date + .sub { margin-top: 0; }
.fx-full { font: 400 var(--t-meta)/1.3 var(--font-text); color: var(--muted); }
.fx-row { position: relative; border-bottom: 1px solid var(--line); }
/* The column of logos is only there on a board that has some, and the column of sports only where sports are mixed. */
.fixtures.marked { --mark: [mark] 1.75rem; }
.fx-line { display: grid; grid-template-columns: var(--mark,) [time] 4.75rem [event] minmax(0, 1fr) [end] auto; column-gap: 0.6rem; align-items: start; padding: 0.6rem 0.25rem; transition: background-color 0.15s; }
/* A row holds several links. Its time leads to the event and is stretched under the whole row, so a click
   anywhere that is not another link goes there; each team, person and venue named sits above it and leads to
   its own page. */
.fx-line a { text-decoration: none; }
.fx-time::after { content: ""; position: absolute; inset: 0; }
.fx-time:focus-visible { outline: none; }
.fx-time:focus-visible::after { outline: 3px solid var(--focus); outline-offset: -3px; }
.fx-line :is(.fx-event, .fx-where) a { position: relative; z-index: 1; }
.fx-mark { grid-column: mark; grid-row: 1 / span 2; display: grid; }
.fx-mark .logo, .fx-mark .sport-icon { width: 1.75rem; height: 1.75rem; }
.fx-mark .logo { padding: 0.15rem; }
.fx-time { grid-column: time; grid-row: 1 / span 2; display: grid; min-width: 0; }
.fx-time time { font: 700 condensed var(--t-lead)/1.5rem var(--font-display); font-variant-numeric: tabular-nums; white-space: nowrap; }
.fx-zone { font-size: var(--t-small); line-height: 1.35; color: var(--muted); }
.fx-zone:empty { display: none; }
/* On a list of one event a day, the row's own day stands over its time. */
.fx-day { font-size: var(--t-small); line-height: 1.35; color: var(--muted); white-space: nowrap; }
.fx-event { grid-column: event; grid-row: 1; min-width: 0; font-size: var(--t-body); font-weight: 600; line-height: 1.5rem; overflow-wrap: break-word; }
/* Two sides, each a crest and a full name. On a phone one stands above the other, crest first. */
.fx-event.pair { display: grid; gap: 0.25rem; }
.fx-side { display: flex; align-items: flex-start; gap: 0.4rem; min-width: 0; }
.fx-v { font-weight: 400; color: var(--muted); }
.fx-crest { flex: none; display: grid; place-items: center; width: 1.5rem; height: 1.5rem; }
.fx-crest:has(.chip) { width: auto; min-width: 1.5rem; }
.fx-crest .logo { width: 1.5rem; height: 1.5rem; padding: 0.1rem; }
.fx-crest .flag { width: 100%; height: auto; box-shadow: 0 0 0 1px var(--line); }
.fx-crest .chip { padding: 0 0.3rem; box-shadow: none; }
.fx-where { grid-column: event / -1; grid-row: 2; display: flex; flex-wrap: wrap; gap: 0 0.6rem; min-width: 0; margin-top: 0.15rem; font-size: var(--t-small); line-height: 1.35; color: var(--muted); }
.fx-sport { flex: none; font-weight: 600; color: var(--ink); }
.fx-place { min-width: 0; }
.fx-place .flag { display: inline-block; margin-right: 0.45em; vertical-align: -0.12em; box-shadow: 0 0 0 1px var(--line); }
.fx-end { grid-column: end; grid-row: 1; display: flex; align-items: center; justify-content: flex-end; gap: 0.2rem 0.5rem; min-height: 1.5rem; font-size: var(--t-small); color: var(--muted); }
/* A weekend's timetable gives each session still to come a small clock, and marks the next. */
.fx-in { display: inline-flex; align-items: center; gap: 0.4rem; white-space: nowrap; }
.fx-in-next { color: var(--ink); font-weight: 600; }
/* A small clock for a session: the big clock's black and glowing numerals, on one line. */
.miniclock { display: inline-block; padding: 0.1rem 0.45rem; border-radius: var(--r-small); background: #000; color: var(--hot); font: 700 condensed var(--t-meta)/1.3 var(--font-display); font-variant-numeric: tabular-nums; text-shadow: 0 0 8px oklch(68% 0.24 var(--a) / 0.6); white-space: nowrap; }
.miniclock:empty { display: none; }
.fx-tag { display: none; }
/* Finished: quieter, still readable. */
.fx-row.done .fx-line { color: var(--muted); }
.fx-row.done .fx-sport { color: inherit; }
.fx-row.done .fx-mark, .fx-row.done .fx-crest { opacity: 0.6; }
/* A board lays its rows out by its own width, not the screen's: beside a table it has less room than the screen says. */
.fixtures { container-type: inline-size; }
@container (max-width: 33.99rem) {
  /* The second side is written name first, for the wider layouts; here its crest leads like the first one's. The
     "v" between them is kept for screen readers only. */
  .fx-side:has(> .fx-v) { flex-direction: row-reverse; justify-content: flex-end; }
  /* A match's ground is on its own page; here the two sides are enough. A race keeps its circuit. */
  .fx-event.pair ~ .fx-where .fx-place { display: none; }
  .fx-event.pair ~ .fx-where:not(:has(.fx-sport)) { display: none; }
  .fx-v { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
}
@container (min-width: 34rem) {
  /* With room for a line, the two sides face each other across the "v": crest, name, v, name, crest. */
  .fx-event.pair { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.1rem 0.4rem; }
  .fx-goals { margin-left: 0; }
  .fx-line { grid-template-columns: var(--mark,) [time] 6rem [event] minmax(0, 1fr) [end] minmax(0, 7rem); column-gap: 1rem; }
  .fx-end { flex-wrap: wrap; text-align: right; }
  .fx-tag { display: inline; }
}
/* With more room still, the place has a column of its own. */
@container (min-width: 54rem) {
  .fixtures.marked .fx-line { --mark: [mark] 2.25rem; }
  /* The end column holds only a mark for what is on or off, so it is as wide as one, and nothing where there is none. */
  .fixtures.several .fx-line { --sport: [sport] 6rem; --end: auto; }
  .fx-line { grid-template-columns: var(--mark,) [time] 6rem [event] minmax(0, 2.8fr) var(--sport,) [place] minmax(0, 1fr) [end] var(--end, 7rem); align-items: center; padding: 0.5rem; }
  .fx-mark, .fx-time { grid-row: 1; }
  .fx-mark .logo, .fx-mark .sport-icon { width: 2.25rem; height: 2.25rem; }
  .fx-where { display: contents; }
  .fx-sport { grid-column: sport; grid-row: 1; }
  .fx-place { grid-column: place; grid-row: 1; }
}
/* What is over on a year's schedule, and each group of teams, fold away under a line of their own. */
.fx-over, .teamgroup { border-top: 1px solid var(--line); }
.fx-over { margin-top: var(--space-4); }
.fx-over > summary, .teamgroup > summary { display: flex; align-items: center; gap: 0.6rem; padding: 0.6rem 0.25rem; font: 700 condensed var(--t-lead)/1.2 var(--font-display); cursor: pointer; transition: background-color 0.15s; }
.fx-over > summary::-webkit-details-marker, .teamgroup > summary::-webkit-details-marker { display: none; }
.fx-over > summary::after, .teamgroup > summary::after { content: ""; flex: none; width: 0.5rem; height: 0.5rem; margin: 0 0.4rem 0.2rem auto; border: solid var(--muted); border-width: 0 2px 2px 0; transform: rotate(45deg); transition: transform 0.15s; }
.fx-over[open] > summary::after, .teamgroup[open] > summary::after { transform: rotate(-135deg); margin-bottom: -0.2rem; }
.fx-over[open] > summary { margin-bottom: var(--space-2); }

/* --- Order of play: under each day, a column for each court, its matches numbered in the order they are played. */
.courts { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr)); gap: 0.2rem 2rem; align-items: start; }
.matchlist { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); counter-reset: match; }
.matchlist li { display: grid; grid-template-columns: var(--number,) 5rem minmax(0, 1fr); gap: 0 0.6rem; align-items: baseline; padding: 0.45rem 0.25rem; border-bottom: 1px solid var(--line); }
ol.matchlist { --number: 1.25rem; }
ol.matchlist li::before { content: counter(match); counter-increment: match; grid-row: span 2; font: 700 condensed var(--t-body)/1.3 var(--font-display); font-variant-numeric: tabular-nums; color: var(--muted); }
/* A draw has no times yet, so it has no column for them. */
ul.matchlist li:has(> .m-time:empty) { grid-template-columns: minmax(0, 1fr); }
ul.matchlist .m-time:empty { display: none; }
.m-time { grid-row: span 2; font: 700 condensed var(--t-body)/1.3 var(--font-display); font-variant-numeric: tabular-nums; }
.m-time small { display: block; font: 400 var(--t-small)/1.2 var(--font-text); color: var(--muted); }
.m-players { font-size: var(--t-meta); font-weight: 600; }
.m-players i { font-style: normal; font-weight: 400; color: var(--muted); }
.m-meta { display: flex; gap: 0.6rem; font-size: var(--t-small); color: var(--muted); }

/* --- The field: who is taking part, best first, as numbered rows that run down two or three columns. */
.field { list-style: none; margin: 0; padding: 0; columns: 15rem; column-gap: 2rem; }
.field li { display: flex; align-items: baseline; gap: 0.6rem; padding: 0.4rem 0.25rem; border-bottom: 1px solid var(--line); break-inside: avoid; }
.pos { flex: none; width: 1.5rem; font: 700 condensed var(--t-body)/1.3 var(--font-display); font-variant-numeric: tabular-nums; color: var(--muted); text-align: right; }
.field .who { font-weight: 600; }
.field .who { display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
.num-plate { margin-left: auto; min-width: 1.75rem; padding: 0 0.35rem; border-radius: var(--r-small); background: var(--ink); color: var(--bg); font: 700 condensed var(--t-meta)/1.5 var(--font-display); font-variant-numeric: tabular-nums; text-align: center; }

/* --- Teams on a sport's home page: a box to find one by name, then a folding group for each competition. */
.team-filter { display: flex; align-items: center; gap: 0.6rem; margin: 0 0 var(--space-3); font-size: var(--t-meta); }
.team-filter input { flex: 1; min-width: 0; max-width: 20rem; padding: 0.45rem 0.7rem; border: 1px solid var(--line); border-radius: var(--r-small); background: var(--surface); color: var(--ink); font: inherit; }
.team-none { margin-bottom: var(--space-3); }
.teams > .teamgroup:last-of-type { border-bottom: 1px solid var(--line); }
.tg-mark { flex: none; display: grid; place-items: center; min-width: 2rem; height: 2rem; }
.tg-mark .logo { width: 2rem; height: 2rem; padding: 0.15rem; }
.tg-mark .chip { padding: 0 0.3rem; line-height: 1.6; }
.tg-count { flex: none; font: 400 var(--t-small)/1.3 var(--font-text); color: var(--muted); }
/* A weekend's results: each session folds open to its table; the race starts open. */
.rt-session { border-top: 1px solid var(--line); }
.rt-session > summary { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.8rem; padding: 0.6rem 0.25rem; cursor: pointer; }
.rt-name { font: 700 condensed var(--t-lead)/1.2 var(--font-display); }
.rt-lead { font-size: var(--t-small); color: var(--muted); }
.rt { width: 100%; margin-bottom: var(--space-3); }
.rt-results { container-type: inline-size; }
@container (max-width: 33.99rem) { .rt .rt-team, .rt .rt-laps { display: none; } }
/* Where to watch: the reader's country on a line of its own, then every country, folded away. */
.watch-mine { margin: 0 0 var(--space-2); font-size: var(--t-body); }
.watch-place { margin-right: 0.3rem; }
.watch-all > summary { cursor: pointer; font-weight: 600; padding: 0.4rem 0; }
.watch-list { margin: var(--space-2) 0 0; columns: 18rem; column-gap: 2rem; }
.watch-list > div { display: flex; gap: 0.6rem; padding: 0.3rem 0; border-bottom: 1px solid var(--line); break-inside: avoid; font-size: var(--t-small); }
.watch-list dt { flex: 0 0 9rem; font-weight: 600; }
.watch-list dd { margin: 0; color: var(--muted); }
/* A tournament's teams under their pools. */
.tg-pool { margin: var(--space-2) 0 0; padding: 0 0.25rem; font-size: var(--t-meta); color: var(--muted); }
.teamlist { list-style: none; margin: 0 0 var(--space-3); padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: 0 1rem; }
@media (min-width: 48rem) { .teamlist { grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr)); } }
.teamlist a { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.25rem; border-radius: var(--r-small); font-size: var(--t-meta); font-weight: 600; line-height: 1.3; text-decoration: none; transition: background-color 0.15s; }

/* The pointer: a row is shaded under it. Nothing moves. */
@media (hover: hover) {
  .fx-line:hover, .teamlist a:hover, .fx-over > summary:hover, .teamgroup > summary:hover { background: var(--hover); }
  .fx-line :is(.fx-event, .fx-where) a:hover { text-decoration-line: underline; }
}
@media (pointer: coarse) {
  .fx-line, .teamlist a, .fx-over > summary, .teamgroup > summary, .team-filter input { min-height: var(--tap); }
}

/* --- What is over: results in rows, the headings that part a list into what is to come and what is past,
   and a finished event's result at the head of its scoreboard. */
.fx-part { margin: var(--space-5) 0 var(--space-3); font: 800 condensed var(--t-title)/1.1 var(--font-display); }
h3.fx-part { margin-top: var(--space-4); font: 700 condensed var(--t-lead)/1.2 var(--font-display); }
section > .fx-part:first-child { margin-top: 0; }
.fx-part.past { color: var(--muted); }
.fx-goals { margin-left: auto; font: 800 condensed var(--t-lead)/1.5rem var(--font-display); font-variant-numeric: tabular-nums; }
/* A winner is marked the same way wherever a result is shown: heavier, in full ink, on a band of highlighter.
   The band is a thick underline pulled up behind the foot of the letters, so it follows the words line by line
   when a name wraps. In a row the winning side's score is also on a dark plate. */
:is(.fx-side.won .fx-team, .fx-won b, .m-players .won, .field .first .who, .br-side.won .br-name), :is(.fx-won b, .m-players .won, .field .first .who, .br-side.won .br-name) a { font-weight: 800; color: var(--ink); text-decoration: underline 0.5em var(--win); text-underline-offset: -0.22em; text-decoration-skip-ink: none; }
.fx-row.done .fx-goals { color: var(--ink); }
.fx-goals { min-width: 1.5rem; padding: 0 0.3rem; border-radius: var(--r-small); text-align: center; }
.fx-side.won .fx-goals { background: var(--ink); color: var(--bg); }
.field .first .pos { color: var(--ink); }
.r-verdict { display: block; margin-top: 0.3rem; font: 700 condensed var(--t-lead)/1.2 var(--font-display); }
.fx-won { display: block; font-size: var(--t-small); font-weight: 400; line-height: 1.3; color: var(--muted); }
.matchlist.played li { grid-template-columns: minmax(0, 1fr) auto; }
.matchlist.played .m-meta { grid-column: 1 / -1; }
.m-score { font: 700 condensed var(--t-meta)/1.3 var(--font-display); font-variant-numeric: tabular-nums; white-space: nowrap; }
.result { margin: 0 0 var(--space-2); line-height: 1.1; }
.r-score { font: 800 condensed var(--t-display)/1 var(--font-display); font-size: clamp(3rem, 21cqw, 5.5rem); font-variant-numeric: tabular-nums; }
.r-won { font: 800 condensed var(--t-title)/1.15 var(--font-display); }
.r-won b { font-weight: inherit; }
.r-note { display: block; margin-top: 0.2rem; font: 400 var(--t-meta)/1.4 var(--font-text); opacity: 0.85; }

/* --- What stands beside a list: a competition's table, or a tournament's seeding. Each is a panel that opens and
   shuts. On a wide screen they stand in a column beside the list and stay in view as the list scrolls. On a
   narrow screen they sit above the list. */
.sidepanel { margin: 0 0 var(--space-4); border: 1px solid var(--line); border-radius: var(--r-large); background: var(--surface); overflow: hidden; }
.sidepanel > summary { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 0.6rem; padding: 0.7rem 0.9rem; font: 700 condensed var(--t-lead)/1.2 var(--font-display); cursor: pointer; }
.sidepanel > summary::-webkit-details-marker { display: none; }
.sidepanel > summary::after { content: ""; flex: none; align-self: center; width: 0.5rem; height: 0.5rem; margin: 0 0.2rem 0.2rem auto; border: solid var(--muted); border-width: 0 2px 2px 0; transform: rotate(45deg); transition: transform 0.15s; }
.sidepanel[open] > summary::after { transform: rotate(-135deg); margin-bottom: -0.2rem; }
.sidepanel[open] > summary { border-bottom: 1px solid var(--line); }
.sidepanel-sub { font: 400 var(--t-small)/1.3 var(--font-text); color: var(--muted); }
.sidepanel .field-note { margin: 0; padding: 0.5rem 0.9rem 0.7rem; }
.standings { width: 100%; border-collapse: collapse; font-size: var(--t-small); line-height: 1.3; font-variant-numeric: tabular-nums; }
.standings th, .standings td { padding: 0.4rem 0.25rem; border-bottom: 1px solid var(--line); text-align: right; font-weight: 400; }
.standings tbody tr:last-child > * { border-bottom: 0; }
.fx-pens { margin: 0 0.15rem; font-size: var(--t-small); font-weight: 400; color: var(--muted); }
.standings .t-group th { padding-top: var(--space-3); text-align: left; font-weight: 600; color: var(--muted); }
.standings thead th { font-weight: 600; color: var(--muted); }
.standings abbr { text-decoration: none; }
.standings .t-pos { width: 1.75rem; padding-left: 0.7rem; color: var(--muted); }
.standings .t-name { text-align: left; }
.standings tbody .t-name { font-weight: 600; }
.standings :is(th, td):last-child { padding-right: 0.7rem; }
.standings tbody td:last-child { font-weight: 800; }
.t-who { display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
.t-who a { text-decoration: none; }
.t-who .fx-crest { width: 1.25rem; height: 1.25rem; }
.t-who .fx-crest .logo { width: 1.25rem; height: 1.25rem; }
/* The rows this page is about. */
.standings .here > * { background: var(--hover); }
.standings .here .t-pos { box-shadow: inset 0.25rem 0 var(--accent); color: var(--ink); }
@media (hover: hover) { .sidepanel > summary:hover { background: var(--hover); } .t-who a:hover { text-decoration: underline; } }
.sidepanel-own { font: 400 var(--t-small)/1.3 var(--font-text); }
.aside > .sidepanel:last-child { margin-bottom: var(--space-4); }
.sided-main > :first-child > h2:first-child { margin-top: var(--space-2); }
@media (min-width: 64rem) {
  /* The body keeps the hero's left edge and runs on to the right edge of the screen, which is where the column
     of panels gets its room. */
  .body:has(> .sided) { max-width: none; margin-left: max(0px, calc((100% - 60rem) / 2)); margin-right: 0; }
  .sided { display: grid; grid-template-columns: minmax(0, 1fr) 21rem; column-gap: 2rem; align-items: start; }
  .sided-main { grid-column: 1; grid-row: 1; min-width: 0; }
  .aside { grid-column: 2; grid-row: 1; }
}

/* --- A knockout draw: a column for each round, each tie level with the two that feed it. It scrolls sideways
   where the rounds do not fit. */
.bracket { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(11.5rem, 1fr); column-gap: 1rem; overflow-x: auto; padding-bottom: 0.4rem; }
.br-round { display: flex; flex-direction: column; min-width: 0; }
.br-round h3 { margin: 0 0 var(--space-2); font: 700 condensed var(--t-body)/1.2 var(--font-display); color: var(--muted); }
.br-round ol { flex: 1; display: flex; flex-direction: column; justify-content: space-around; gap: 0.5rem; list-style: none; margin: 0; padding: 0; }
.br-tie { border: 1px solid var(--line); border-radius: var(--r-small); background: var(--surface); font-size: var(--t-small); line-height: 1.3; }
.br-side { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; margin: 0; padding: 0.35rem 0.5rem; }
.br-side + .br-side { border-top: 1px solid var(--line); }
.br-name { min-width: 0; font-weight: 600; }
.br-name a { text-decoration: none; }
.br-side.tbd .br-name { font-weight: 400; color: var(--muted); }
.br-sets { flex: none; display: flex; gap: 0.4rem; font-variant-numeric: tabular-nums; color: var(--muted); }
.br-sets b { font-weight: 600; }
.br-side.won .br-sets { color: var(--ink); }
.br-sets sup { font-weight: 400; line-height: 0; }
.br-when { margin: 0; padding: 0.25rem 0.5rem; border-top: 1px solid var(--line); color: var(--muted); }
@media (hover: hover) { .br-name a:hover { text-decoration-line: underline; } }

/* --- Places: the choosing on the "near me" page, how far away each row is, and the list of every venue. */
.near-form { margin: 0 0 var(--space-3); padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--r-large); background: var(--surface); }
.near-pick { display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-2) var(--space-3); margin: 0; }
.near-pick > span { display: grid; gap: 0.2rem; min-width: 0; flex: 1 1 9rem; }
.near-pick label { font-size: var(--t-small); font-weight: 600; color: var(--muted); }
.near-pick select { width: 100%; min-width: 0; min-height: var(--tap); padding: 0 0.6rem; border: 1px solid var(--line); border-radius: var(--r-small); background: var(--bg); color: inherit; font: 400 var(--t-meta)/1.2 var(--font-text); }
.near-form .field-note { margin-top: var(--space-2); }
.near-status { margin: 0 0 var(--space-3); font-weight: 600; }
.fx-km { font: 600 var(--t-small)/1.4 var(--font-text); font-variant-numeric: tabular-nums; color: var(--muted); white-space: nowrap; }
.placelist { list-style: none; margin: 0 0 var(--space-3); padding: 0; columns: 18rem; column-gap: 2rem; }
.placelist li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.6rem; padding: 0.45rem 0.25rem; border-bottom: 1px solid var(--line); break-inside: avoid; }
.placelist > li > a { font-weight: 600; }
.placelist span { font-size: var(--t-small); color: var(--muted); }
.placelist span:last-child { margin-left: auto; }
.where a { text-decoration-thickness: 0.06em; }

/* === Stream C: page frame (header, navigation, breadcrumb, footer, logo tiles) === */

/* --- The header: one dark band in the brand's colour on every page, in levels that look different. The top bar
   holds the brand, the sports as pills and the reader's settings. Under it come the breadcrumb, with anything on
   now beside it, and then the tabs of the section the page is in. Every row is one line: it scrolls sideways
   before it wraps. */
header { background: var(--bar); color: var(--hero-ink); font: 400 var(--t-small)/1.3 var(--font-text); }
header a { text-decoration: none; }
header ul, header ol { position: relative; display: flex; margin: 0; padding: 0; list-style: none; overflow-x: auto; scrollbar-width: none; white-space: nowrap; }
/* A row that scrolls would cut off a focus ring drawn outside a link, so in the header it is drawn inside. */
header a:focus-visible { outline-offset: -3px; }
.topbar { display: flex; align-items: center; gap: 0.5rem; }
/* The brand: a clock face in the brand's colour with its hands cut out of it, then the name. */
.brand { flex: none; display: inline-flex; align-items: center; gap: 0.45rem; min-height: var(--tap); font: 800 condensed var(--t-lead)/1 var(--font-display); }
.brand-mark { flex: none; width: 1.5rem; height: 1.5rem; }
.brand-mark .face { fill: var(--brand); }
.brand-mark .hands { stroke: var(--bar); }
/* On a phone the mark stands for the name, so the sports fit on the same line. Screen readers still get the name. */
@media (max-width: 34rem) { .brand span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } }

/* The sports. A link is as tall as the bar, so it is easy to tap; its pill is drawn smaller inside it. The row
   fades out at either end, where it scrolls under the brand and the settings. */
.sports { flex: 1; min-width: 0; }
.sports ul { gap: 0.3rem; padding: 0 0.4rem; mask-image: linear-gradient(90deg, transparent, #000 0.6rem, #000 calc(100% - 0.6rem), transparent); }
.sports a { position: relative; z-index: 0; display: inline-flex; align-items: center; gap: 0.3rem; min-height: var(--tap); padding: 0 0.6rem 0 0.35rem; font-weight: 600; }
.sports a::before, .follow::before, .subscribe::before, .share::before, .prefs-open::before { content: ""; position: absolute; z-index: -1; inset: calc(50% - 0.95rem) 0; border-radius: var(--r-pill); border: 1px solid oklch(100% 0 0 / 0.18); background: oklch(100% 0 0 / 0.08); transition: background-color 0.15s, border-color 0.15s; }
.sports .sport-icon { width: 1.25rem; height: 1.25rem; }
.sports a[aria-current] { color: var(--bar); }
.sports a[aria-current]::before { background: var(--hero-ink); border-color: transparent; }
.sports a:focus-visible, .follow:focus-visible, .subscribe:focus-visible, .share:focus-visible, .prefs-open:focus-visible { outline: none; }
.sports a:focus-visible::before, .follow:focus-visible::before, .subscribe:focus-visible::before, .share:focus-visible::before, .prefs-open:focus-visible::before { outline: 3px solid var(--focus); outline-offset: 2px; }
/* Where the browser script puts the reader's time zone. It takes no room until it is filled. Its button is as
   tall as the bar, with its pill drawn smaller inside it, like a sport's. */
.prefs-mount { flex: none; margin-left: auto; }
.prefs-mount:empty { display: none; }
.prefs-open { position: relative; z-index: 0; min-height: var(--tap); border: 0; }
.prefs-open:hover { background: none; }

/* The breadcrumb, always one line. The page's own name, at the end, is cut short before anything else is. */
.context { display: flex; align-items: center; gap: 1rem; min-height: 2rem; }
/* A row holding only the "on now" line, with nothing on now, takes no room. */
.context:not(:has(> :not([hidden]))) { display: none; }
.context > * { margin: 0; }
nav[aria-label="Breadcrumb"] { flex: 0 1 auto; min-width: 0; }
nav[aria-label="Breadcrumb"] ol { align-items: center; gap: 0.4rem; }
nav[aria-label="Breadcrumb"] li { flex: none; display: flex; align-items: center; gap: 0.4rem; opacity: 0.8; }
nav[aria-label="Breadcrumb"] li:last-child { flex: 0 1 auto; display: block; min-width: 3rem; overflow: hidden; text-overflow: ellipsis; opacity: 1; }
nav[aria-label="Breadcrumb"] li + li::before { content: "›"; }
nav[aria-label="Breadcrumb"] li + li:last-child::before { margin-right: 0.4rem; }
/* What is under way right now, beside the breadcrumb: a dot, the words, then a link for each event. */
.onnow { flex: 0 100 auto; display: flex; align-items: center; gap: 0.75rem; min-width: 0; margin-left: auto; overflow-x: auto; scrollbar-width: none; white-space: nowrap; }
.context > .onnow:first-child { margin-left: 0; }
.onnow span { font-weight: 600; }
.onnow span::before { content: ""; display: inline-block; width: 0.5rem; height: 0.5rem; margin-right: 0.4rem; border-radius: 50%; background: var(--hot); }
.onnow a { text-decoration: underline; text-decoration-color: currentColor; }

/* Tabs, one level down from the sports: a sport's competitions, or a group's sports. Underlined rather than
   pills, so the two levels do not look alike; the line under the current one is in the sport's colour. One row
   that scrolls sideways and fades out where it runs on, with the Follow button at its end. */
.tabrow { display: flex; align-items: center; gap: 0.75rem; }
.compnav { flex: 1; min-width: 0; }
.compnav ul { gap: 1.25rem; padding-right: 1.5rem; mask-image: linear-gradient(90deg, #000 calc(100% - 1.5rem), transparent); }
.compnav a { display: inline-flex; align-items: center; gap: 0.4rem; min-height: 2.75rem; border-bottom: 3px solid transparent; color: color-mix(in oklch, var(--hero-ink) 80%, transparent); font-weight: 600; transition: color 0.15s, border-color 0.15s; }
.compnav a[aria-current] { border-bottom-color: var(--glow); color: inherit; }
.compnav .sport-icon { width: 1.25rem; height: 1.25rem; }
.compnav .chip { display: inline-grid; place-items: center; min-width: 1.75rem; height: 1.75rem; padding: 0 0.3rem; }
/* Follow: a toggle, written hidden and shown by the browser script that makes it work. A star fills when it is on. */
.follow, .subscribe, .share { position: relative; z-index: 0; flex: none; min-height: 2.75rem; padding: 0 0.75rem; border: 0; background: none; color: inherit; font: 600 var(--t-small)/1.2 var(--font-text); cursor: pointer; }
.follow::after { content: "\00a0\2606"; }
.follow[aria-pressed="true"] { color: var(--hero-1); }
.follow[aria-pressed="true"]::before { background: var(--glow); border-color: transparent; }
.follow[aria-pressed="true"]::after { content: "\00a0\2605"; }
@media (hover: hover) {
  .sports a:not([aria-current]):hover::before, .follow[aria-pressed="false"]:hover::before, .subscribe:hover::before, .share:hover::before, .prefs-open:hover::before { background: oklch(100% 0 0 / 0.2); border-color: oklch(100% 0 0 / 0.4); }
  .compnav a:not([aria-current]):hover { color: inherit; border-bottom-color: oklch(100% 0 0 / 0.4); }
  nav[aria-label="Breadcrumb"] a:hover, .footnav a:hover { text-decoration: underline; }
}

/* --- Logo tiles. Every logo sits in the same square, contained and centred with even padding, so a wide wordmark
   takes no more room than a round crest. The plate is white, so a dark logo shows on the dark hero; a logo of pale
   lettering asks for a dark plate in logos.json. A rule that resizes a tile gives its width and its height, never
   one of them or a percentage, so the tile stays square wherever it stands. */
.logo { display: block; flex: none; width: 1.75rem; height: 1.75rem; padding: 0.2rem; border-radius: var(--r-small); background: #fff; object-fit: contain; }
.logo.big { width: 4.5rem; height: 4.5rem; padding: 0.5rem; border-radius: var(--r-large); }
.logo.on-dark { background: #14171c; box-shadow: 0 0 0 1px oklch(100% 0 0 / 0.22); }
.chip.big { padding: 0.5rem 1rem; border-radius: var(--r-large); font-size: var(--t-title); line-height: 1.2; }
.comphead { display: flex; align-items: center; gap: var(--space-3); margin: 0 0 var(--space-3); }
.comphead p { margin: 0; max-width: 34rem; font-size: var(--t-meta); }
.eventmark { margin: 0 0 var(--space-3); }
.teamhead .flag { width: 4rem; height: 3rem; }
/* A team's last five results, oldest first: a letter each on its colour, leading to the match. */
.form { display: flex; align-items: center; gap: 0.3rem; margin: 0 0 var(--space-2); }
.form-label { margin-right: 0.3rem; font-size: var(--t-small); opacity: 0.85; }
.form a { display: grid; place-items: center; width: 1.6rem; height: 1.6rem; border-radius: var(--r-small); font: 700 var(--t-small)/1 var(--font-text); color: #fff; text-decoration: none; }
.form .form-w { background: oklch(55% 0.15 150); }
.form .form-d { background: oklch(55% 0.01 260); }
.form .form-l { background: oklch(55% 0.19 25); }
.teamhead .chip { padding: 0.3rem 0.8rem; font-size: var(--t-lead); }

/* --- Buttons in the body: ink on the page, or an outline for the quieter one of a pair. */
.button { display: inline-flex; align-items: center; min-height: 2.5rem; padding: 0.4rem 1.1rem; border: 0; border-radius: var(--r-pill); background: var(--ink); color: var(--bg); font: 600 var(--t-meta)/1.2 var(--font-text); text-decoration: none; cursor: pointer; transition: background-color 0.15s; }
.button.quiet { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
p:has(> .button) { margin: var(--space-3) 0 0; }

/* --- Main page: the next events of what the reader follows, filled in by the browser. */
.following ol, .sportlist, .footnav ul { list-style: none; margin: 0; padding: 0; }
.following ol { display: grid; gap: var(--space-2); }
.following a { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0 1rem; padding: 0.55rem 0.8rem; border-radius: var(--r-small); background: var(--surface); border: 1px solid var(--line); text-decoration: none; transition: border-color 0.15s; }
.following b { font-weight: 600; }
.following time { font-size: var(--t-meta); color: var(--muted); font-variant-numeric: tabular-nums; }
/* --- The "page not found" page: every sport. */
.sportlist { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.sportlist a { display: inline-flex; align-items: center; gap: 0.45rem; padding: 0.4rem 0.9rem 0.4rem 0.5rem; border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--line); font-size: var(--t-meta); font-weight: 600; text-decoration: none; transition: border-color 0.15s; }
.sportlist .sport-icon { width: 1.5rem; height: 1.5rem; }
/* The reader's own list: a row for each sport or team followed, with its button to stop at the end. */
.fl-list { list-style: none; margin: 0 0 var(--space-3); padding: 0; }
.fl-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.8rem; padding: 0.5rem 0.25rem; border-bottom: 1px solid var(--line); }
.fl-list a { display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 600; }
.fl-list .sport-icon { width: 1.5rem; height: 1.5rem; }
.fl-sport { font-size: var(--t-small); color: var(--muted); }
.fl-list .unfollow { margin-left: auto; }

/* --- Event page: the events either side of this one on one line, then two ordinary links. */
.pager { margin-top: var(--space-5); padding-top: var(--space-3); border-top: 1px solid var(--line); font-size: var(--t-meta); }
/* Where nothing stands above it in the body, it needs no line and no gap to part it from anything. */
.body > .pager:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.pager p { display: flex; flex-wrap: wrap; gap: 0 1.25rem; margin: 0 0 var(--space-1); }
.pager a { min-width: 0; }

/* --- The foot of the page: the site's sections, this sport's own, then the notice and the contact line. */
footer { margin-top: var(--space-5); padding: var(--space-4) 0 var(--space-5); border-top: 1px solid var(--line); font-size: var(--t-small); color: var(--muted); }
footer p { max-width: 70ch; margin: 0 0 var(--space-2); }
.footnav ul { display: flex; flex-wrap: wrap; gap: 0.1rem 1.1rem; margin-bottom: var(--space-2); }
.footnav a { text-decoration: none; }
.footnav:first-child a { color: var(--ink); font-weight: 600; }

/* The pointer: a button darkens or lightens a step, and a card's edge darkens. Nothing moves. */
@media (hover: hover) {
  .button:hover { background: color-mix(in oklch, var(--ink) 82%, var(--bg)); }
  .button.quiet:hover { background: var(--hover); }
  .following a:hover, .sportlist a:hover { border-color: var(--muted); }
}
@media (pointer: coarse) {
  .context a, footer a { display: inline-flex; align-items: center; min-height: var(--tap); }
  .compnav a, .follow, .subscribe, .sportlist a, .following a, .button { min-height: var(--tap); }
  .pager a { display: inline-flex; align-items: center; min-height: var(--tap); }
  .footnav ul { gap: 0 1.5rem; }
}

/* === Integration === */
/* A team page's "Next:" line carries each side's crest before its name, in the line of text. */
.next-name .fx-crest { display: inline-grid; margin-right: 0.3em; vertical-align: -0.2em; }

/* Releases: a chart and its numbers, drawn in the text colour, narrowing with the screen. */
.rel-figure { margin: 0 0 var(--space-3); max-width: 28rem; }
.rel-figure .chart { display: block; width: 100%; height: auto; }
.rel-figure figcaption { font-size: var(--t-small); line-height: 1.3; opacity: 0.85; }
.rel-table { max-width: 28rem; margin: 0 0 var(--space-3); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
