/* 2026-10-07: the fonts are served from here, not from Google.
   Every page load drew text twice: once in a stand-in face and again when the
   web font arrived from another host, so paragraphs reflowed and Cinzel
   headings -- capitals only -- flipped from sentence case to capitals. Same
   origin, preloaded from the page head and cached for a year, the faces are
   ready before the first paint on any visit after the first. Each file is a
   variable font covering every weight the site uses. Cinzel blocks briefly
   rather than show the wrong case; IBM Plex Sans swaps. */
@font-face {
  font-family: "Cinzel";
  font-style: normal;
  font-weight: 400 900;
  font-display: block;
  src: url("/assets/fonts/cinzel-latin.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;
}
@font-face {
  font-family: "Cinzel";
  font-style: normal;
  font-weight: 400 900;
  font-display: block;
  src: url("/assets/fonts/cinzel-latin-ext.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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-latin.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;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-latin-ext.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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* One committed visual world: the logo lives on black, and a light theme
     would put a Dodongo on a bedsheet. Every color is painted explicitly. */
  :root {
    --ink: #0a0c09;
    --surface: #12160f;
    --raised: #1a2014;
    --edge: #2c3522;
    --edge-soft: rgba(44, 53, 34, 0.7);
    --moss: #4f8f2c;
    --moss-bright: #7ec850;
    --gold: #d9a441;
    --dodongo: #c0451f;
    --parchment: #ece3cf;
    --muted: #97a188;
    --display: "Cinzel", "Palatino Linotype", Georgia, serif;
    --body: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
    --mono: ui-monospace, SFMono-Regular, Consolas, monospace;
    --gutter: clamp(20px, 5vw, 64px);
    color-scheme: dark;
  }

  * { box-sizing: border-box; }

  body {
    margin: 0;
    background: var(--ink);
    color: var(--parchment);
    font-family: var(--body);
    font-size: 17.5px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
  }

  .wrap { max-width: 1160px; margin-inline: auto; padding-inline: var(--gutter); }

  /* ---------------------------------------------------------------- hero */

  .hero {
    position: relative;
    overflow: hidden;
    border-bottom: 1px solid var(--edge);
    padding-block: clamp(26px, 4vw, 46px) clamp(26px, 4vw, 44px);
  }

  /* The 8x8 room grid every Z1R dungeon map is drawn on. */
  .hero::before {
    content: "";
    position: absolute;
    inset: -2px;
    background-image:
      linear-gradient(to right, rgba(79, 143, 44, 0.15) 1px, transparent 1px),
      linear-gradient(to bottom, rgba(79, 143, 44, 0.15) 1px, transparent 1px);
    background-size: 56px 56px;
    mask-image: radial-gradient(130% 90% at 50% 20%, #000 20%, transparent 78%);
    pointer-events: none;
  }

  .hero-inner {
    position: relative;
    display: grid;
    gap: clamp(22px, 3.5vw, 40px);
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
  }

  @media (min-width: 900px) {
    .hero-inner { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
  }

  .brand { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }

  .brand img { width: clamp(150px, 22vw, 210px); height: auto; }

  .season-line {
    font-family: var(--body);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    line-height: 1.9;
    letter-spacing: 0.1em;
    color: var(--gold);
  }

  h1 {
    font-family: var(--display);
    font-weight: 700;
    font-size: clamp(2.1rem, 4.6vw, 3.2rem);
    line-height: 1.1;
    margin: 0 0 12px;
    text-wrap: balance;
  }

  h1 em { font-style: normal; color: var(--moss-bright); }

  .lede { margin: 0; max-width: 44ch; color: #cfd6c2; }

  .hero-actions { display: flex; flex-wrap: wrap; gap: 11px; margin-top: 22px; }

  .btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 11px 19px;
    border: 1px solid var(--edge);
    border-radius: 2px;
    background: var(--raised);
    color: var(--parchment);
    font-weight: 600;
    font-size: 0.93rem;
    text-decoration: none;
    transition: border-color 140ms ease, background 140ms ease;
  }

  .btn:hover { border-color: var(--moss); background: #212a19; }
  .btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

  .btn-primary {
    background: linear-gradient(180deg, #55972f, #3d7521);
    border-color: #6fb23f;
    color: #f6fbef;
  }

  .btn-primary:hover { background: linear-gradient(180deg, #62a838, #457f25); }

  /* --------------------------------------------------------- hero player */

  .player {
    position: relative;
    display: block;
    border: 1px solid var(--edge);
    background: #000;
    text-decoration: none;
    overflow: hidden;
  }

  .player img { display: block; width: 100%; height: auto; opacity: 0.82; transition: opacity 160ms ease; }

  .player:hover img { opacity: 1; }
  .player:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

  .player-tag {
    position: absolute;
    top: 10px;
    left: 10px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 11px;
    background: rgba(10, 12, 9, 0.82);
    border: 1px solid var(--edge);
    font-family: var(--body);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--moss-bright);
  }

  /* Dead center was right while a thumbnail was whatever frame YouTube
     picked. The cards are drawn now, and measuring one says where the room is:
     on a 1280x720 card the lockup runs y 130-399, the season line 400-479 and
     the racer names 520-599, leaving 130px clear at the top and 120px at the
     bottom. Center is on the artwork, so the badge moves out of it.

     Top right, not bottom right: the top band is the larger of the two, the
     date chip already has the bottom left, and a corner each balances the
     card. The size is what fits -- the card renders around 394px wide, so
     that 130px band is only about 40px on screen and the old 62px badge
     would not fit either band. Anything that grows this badge has to check
     it against the band again. */
  .player-play {
    position: absolute;
    inset: 8px 8px auto auto;
    display: grid;
    place-items: center;
  }

  .player-play span {
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border: 2px solid rgba(236, 227, 207, 0.85);
    border-radius: 50%;
    background: rgba(10, 12, 9, 0.55);
    color: var(--parchment);
    font-size: 12px;
    padding-left: 3px;
  }

  .player-foot {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 6px 16px;
    padding: 11px 13px;
    border-top: 1px solid var(--edge);
    background: var(--surface);
    color: var(--parchment);
    font-size: 0.9rem;
  }

  .player-foot .meta { color: var(--muted); font-family: var(--mono); font-size: 0.8rem; }

  /* ------------------------------------------------------------ air rail */

  .rail {
    border-bottom: 1px solid var(--edge);
    background: linear-gradient(180deg, #171d10, #10140d);
  }

  .rail-inner { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; padding-block: 15px; }

  .air {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 7px 13px 7px 11px;
    border: 1px solid rgba(192, 69, 31, 0.6);
    background: rgba(192, 69, 31, 0.14);
    font-family: var(--body);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: #ffb9a3;
  }

  .dot {
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--dodongo);
    box-shadow: 0 0 0 3px rgba(192, 69, 31, 0.24);
    animation: pulse 1.9s ease-in-out infinite;
  }

  @keyframes pulse {
    0%, 100% { box-shadow: 0 0 0 3px rgba(192, 69, 31, 0.22); }
    50% { box-shadow: 0 0 0 7px rgba(192, 69, 31, 0.05); }
  }

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

  .rail p { margin: 0; }
  .rail .now { font-weight: 600; }
  .rail .then { color: var(--muted); font-size: 0.92rem; }
  .rail .then b { color: var(--parchment); font-weight: 600; }

  /* --------------------------------------------------------- section kit */

  section { padding-block: clamp(34px, 5vw, 58px); }

  .section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 6px 20px;
    margin-bottom: 20px;
    padding-bottom: 11px;
    border-bottom: 1px solid var(--edge);
  }

  h2 {
    font-family: var(--display);
    font-weight: 700;
    font-size: clamp(1.45rem, 2.6vw, 2rem);
    letter-spacing: 0.02em;
    margin: 0;
  }

  .section-head p { margin: 0; color: var(--muted); font-size: 1rem; }
  .section-head a { color: var(--gold); font-size: 0.92rem; text-decoration: none; }
  .section-head a:hover { text-decoration: underline; }

  h3 { font-family: var(--display); letter-spacing: 0.02em; }

  /* ----------------------------------------------------------- schedule */

  .schedule { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(min(255px, 100%), 1fr)); }

  .slot {
    display: grid;
    gap: 7px;
    /* Even on all four sides. It was 15/17, which is close enough to square to
       look like a mistake rather than a choice, and the footer sitting against
       the bottom made the difference read as extra space down there. */
    padding: 15px;
    border: 1px solid var(--edge);
    border-left: 3px solid var(--edge);
    background: var(--surface);
  }

  .slot.league { border-left-color: var(--moss); }
  .slot.ttp { border-left-color: var(--gold); }

  .slot .day {
    font-family: var(--body);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--muted);
  }

  /* Smaller as of 1 Oct: it is when and which round, above the thing the card
     is actually about. At body size it read as the card's headline and the
     pairing underneath read as the detail, which is backwards. */
  .slot .time { font-weight: 600; font-variant-numeric: tabular-nums; font-size: 0.86rem; }

  .slot .what { color: #cfd6c2; font-size: 0.98rem; }

  .slot .teams { display: flex; align-items: center; gap: 8px; font-size: 0.93rem; }

  .slot .teams img { width: 22px; height: 22px; object-fit: contain; }

  .restream {
    justify-self: start;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 8px;
    border: 1px solid rgba(192, 69, 31, 0.5);
    background: rgba(192, 69, 31, 0.12);
    color: #ffb9a3;
    font-family: var(--body);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
  }

  .restream.open { border-color: var(--edge); background: transparent; color: var(--muted); }

  /* ---------------------------------------------------------- standings */

  .divisions { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }

  .division { border: 1px solid var(--edge); background: var(--surface); }

  .division-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--edge);
    background: var(--raised);
  }

  .division-head h3 { margin: 0; font-size: 1.02rem; }

  .division-head span { color: var(--muted); font-family: var(--mono); font-size: 0.75rem; }

  table { width: 100%; border-collapse: collapse; font-size: 1rem; }

  th {
    text-align: left;
    font-family: var(--body);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    font-weight: 400;
    padding: 10px 16px;
  }

  th.num, td.num { text-align: right; }

  td {
    padding: 8px 16px;
    border-top: 1px solid var(--edge-soft);
    font-variant-numeric: tabular-nums;
  }

  td.team { display: flex; align-items: center; gap: 9px; }

  td.team img { width: 24px; height: 24px; object-fit: contain; flex: none; }

  td.rank { color: var(--muted); width: 2.2rem; }

  tbody tr.qualify td { background: rgba(79, 143, 44, 0.08); }

  tbody tr.qualify td.rank { color: var(--moss-bright); }

  #standings tbody tr.relegated { background: rgba(193, 67, 58, 0.10); }
  #standings tbody tr.relegated td.rank, .relegation-label { color: #e4968f; }
  .season-outcome p { margin: 4px 0; }
  .season-outcome strong { font-weight: 600; }

  .division-foot {
    padding: 9px 16px 12px;
    color: var(--muted);
    font-size: 0.8rem;
    border-top: 1px solid var(--edge-soft);
  }

  /* ------------------------------------------------------------ results */

  .weeks { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }

  .week-pill {
    padding: 6px 13px;
    border: 1px solid var(--edge);
    background: var(--surface);
    color: var(--muted);
    font-size: 0.86rem;
    text-decoration: none;
  }

  .week-pill[aria-current="true"] { border-color: var(--moss); color: var(--parchment); background: var(--raised); }

  .results { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }

  .results.championship-results { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
  .championship-intro { grid-column: 1 / -1; }
  .championship-intro h3 { margin: 0 0 8px; color: var(--gold); }
  .championship-intro p { margin: 6px 0; color: var(--muted); font-size: .94rem; }
  .championship-series { min-width: 0; border: 1px solid var(--edge); background: var(--surface); }
  .championship-series > h3 { margin: 0; padding: 12px 16px; background: var(--raised); font-size: 1.05rem; border-bottom: 1px solid var(--edge); }
  .championship-teams { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 10px; padding: 18px 16px; }
  .championship-teams > div { display: flex; align-items: center; gap: 10px; min-width: 0; }
  .championship-teams > div:last-child { flex-direction: row-reverse; text-align: right; }
  .championship-teams img { width: 44px; height: 44px; object-fit: contain; flex: none; }
  .championship-teams small { display: block; color: var(--muted); font-size: .73rem; }
  .championship-teams strong { font-size: .98rem; line-height: 1.3; display: block; }
  .championship-vs { color: var(--muted); font-size: .8rem; }
  /* 2026-10-27: the series as it is played -- score between the seeds, each
     raced game as the scoreboard's own race grid. */
  .championship-score { font-size: 1.35rem; font-weight: 700; color: var(--gold); font-variant-numeric: tabular-nums; }
  .championship-status { margin: 0; padding: 0 16px 12px; text-align: center; color: var(--gold); font-size: .9rem; }
  .championship-winner { color: var(--gold); font-size: .8rem; }
  .championship-game.played .race-grid { margin-top: 8px; }
  .championship-games { list-style: none; margin: 0; padding: 0; }
  .championship-game { border-top: 1px solid var(--edge-soft); padding: 12px 16px; }
  .championship-game > div:not(.race-grid) { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .championship-game strong { font-size: .92rem; }
  .championship-game p { margin: 5px 0 2px; font-size: .87rem; color: var(--muted); }
  .championship-game small, .championship-conditional { color: var(--muted); font-size: .75rem; }
  .championship-conditional { font-style: italic; }
  @media (max-width: 800px) { .results.championship-results { grid-template-columns: minmax(0, 1fr); } }
  @media (max-width: 380px) {
    .championship-teams { padding-inline: 10px; gap: 6px; }
    .championship-teams > div { gap: 6px; }
    .championship-teams img { width: 32px; height: 32px; }
    .championship-teams strong { font-size: .85rem; }
  }

  .match { border: 1px solid var(--edge); background: var(--surface); padding: 14px 16px; }

  .match-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--edge-soft);
    font-weight: 600;
  }

  .match-head img { width: 26px; height: 26px; object-fit: contain; }

  .match-head .score { margin-left: auto; font-family: var(--mono); color: var(--gold); }

  .match-head .vs { color: var(--muted); font-weight: 400; font-size: 0.85rem; }

  .race-line {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: baseline;
    gap: 8px;
    padding-top: 9px;
    font-size: 0.9rem;
  }

  .race-line .right { text-align: right; }

  .race-line .won { color: var(--moss-bright); font-weight: 600; }

  .race-line .lost { color: var(--muted); }

  .race-line .clock { font-family: var(--mono); font-size: 0.82rem; font-variant-numeric: tabular-nums; }

  .race-line .dash { color: var(--edge); }

  /* ----------------------------------------------------------- channels */

  .channels { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }

  .channel {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 15px 17px;
    border: 1px solid var(--edge);
    border-left: 3px solid var(--moss);
    background: var(--surface);
    text-decoration: none;
  }

  .channel:hover { background: var(--raised); }
  .channel:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
  .channel.is-live { border-left-color: var(--dodongo); }

  .channel .name { font-weight: 600; }
  .channel .role { color: var(--muted); font-size: 0.92rem; }

  .channel .state {
    font-family: var(--body);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--moss-bright);
  }

  .channel.is-live .state { color: #ff9b7d; }

  /* ------------------------------------------------------------ archive */

  .archive { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(min(235px, 100%), 1fr)); }

  .vod {
    display: flex;
    flex-direction: column;
    gap: 7px;
    padding: 14px 16px;
    border: 1px solid var(--edge);
    background: var(--surface);
    text-decoration: none;
  }

  .vod:hover { background: var(--raised); }
  .vod:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
  .vod .when { font-family: var(--mono); font-size: 0.77rem; color: var(--muted); }
  .vod .title { font-weight: 500; line-height: 1.4; }
  .vod .who { color: var(--muted); font-size: 0.84rem; }

  /* ---------------------------------------------------------------- ttp */

  .flagsets { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(min(245px, 100%), 1fr)); }

  .flagset {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 17px;
    border: 1px solid var(--edge);
    background: var(--surface);
  }

  .flagset h3 { margin: 0; font-size: 1.1rem; color: var(--moss-bright); }
  .flagset p { margin: 0; color: #cfd6c2; font-size: 0.98rem; }

  .flagset code, .tc-flagstring {
    display: block;
    padding: 8px 10px;
    border: 1px dashed var(--edge);
    background: #0d110a;
    color: var(--gold);
    font-family: var(--mono);
    font-size: 0.71rem;
    line-height: 1.5;
    word-break: break-all;
  }

  .tc-announcement { margin-bottom: 24px; padding-bottom: 22px; border-bottom: 1px solid var(--edge); }
  .tc-announcement h3 { margin-top: 0; }
  .tc-archive > h3 { margin-bottom: 12px; }
  .tc-archive .pr-edition > summary::before { content: '▸'; }
  .tc-archive .pr-edition[open] > summary::before { content: '▾'; }

  .times {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(auto-fit, minmax(min(205px, 100%), 1fr));
    margin-top: 14px;
    padding: 15px 17px;
    border: 1px solid var(--edge);
    border-left: 3px solid var(--gold);
    background: var(--surface);
  }

  .times div { display: flex; flex-direction: column; gap: 2px; }

  .times .label {
    font-family: var(--body);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--muted);
  }

  .times .slots { font-variant-numeric: tabular-nums; font-weight: 500; }

  /* ------------------------------------------------------- torneo corto */

  .corto { display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr); }

  @media (min-width: 880px) {
    .corto { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
  }

  .corto-lead {
    padding: 18px 20px;
    border: 1px solid var(--edge);
    border-left: 3px solid var(--dodongo);
    background: var(--surface);
  }

  .corto-lead h3 { margin: 0 0 4px; font-size: 1.15rem; }
  .corto-lead .qualifier { color: var(--muted); font-size: 0.9rem; margin: 0 0 14px; }
  .corto-lead p { margin: 0 0 14px; color: #cfd6c2; font-size: 1rem; }

  .corto-slots { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }

  .corto-slots span {
    padding: 5px 10px;
    border: 1px solid var(--edge);
    background: #0d110a;
    font-family: var(--mono);
    font-size: 0.82rem;
    font-variant-numeric: tabular-nums;
  }

  .champs { padding: 18px 20px; border: 1px solid var(--edge); background: var(--surface); }
  .champs h3 { margin: 0 0 12px; font-size: 1.05rem; }
  .champ-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }

  .champ-list li {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--edge-soft);
    font-size: 0.93rem;
  }

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

  .champ-list .ed {
    font-family: var(--body);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--gold);
    width: 3.6rem;
    flex: none;
  }

  .champ-list .who { font-weight: 600; }
  .champ-list .note { margin-left: auto; color: var(--muted); font-size: 0.82rem; }

  /* -------------------------------------------------------------- links */

  .links { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(min(215px, 100%), 1fr)); }

  .link-card {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 13px 15px;
    border: 1px solid var(--edge);
    background: var(--surface);
    text-decoration: none;
  }

  .link-card:hover { background: var(--raised); border-color: var(--moss); }
  .link-card:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
  .link-card .what { font-weight: 600; font-size: 0.95rem; }
  .link-card .why { color: var(--muted); font-size: 0.83rem; }

  /* ---------------------------------------------------------------- nav */

  .topnav {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    padding-block: 12px;
    border-bottom: 1px solid var(--edge);
    font-size: 0.88rem;
  }

  .topnav a { color: var(--muted); text-decoration: none; }
  .topnav a:hover { color: var(--parchment); }
  .topnav a:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

  /* --------------------------------------------------------------- join */

  .join { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr)); }

  .join-card { padding: 19px; border: 1px solid var(--edge); background: linear-gradient(180deg, #171d10, #11150e); }
  .join-card h3 { margin: 0 0 6px; font-size: 1.08rem; }
  .join-card p { margin: 0 0 14px; color: var(--muted); font-size: 0.91rem; }

  footer { border-top: 1px solid var(--edge); padding-block: 24px 32px; color: var(--muted); font-size: 0.85rem; }

  .footer-inner { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px 24px; }

  footer a { color: var(--muted); text-decoration: none; }
  footer a:hover { color: var(--parchment); text-decoration: underline; }

  .triforce {
    display: inline-block;
    width: 0; height: 0;
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-bottom: 10px solid var(--gold);
    margin-right: 8px;
    vertical-align: -1px;
  }

  /* --------------------------------------------------- what we run cards */

  .competitions { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(min(235px, 100%), 1fr)); }

  .competition {
    display: flex;
    flex-direction: column;
    gap: 7px;
    padding: 18px;
    border: 1px solid var(--edge);
    background: var(--surface);
    text-decoration: none;
  }

  .competition:hover { background: var(--raised); border-color: var(--moss); }
  .competition:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

  .competition img { width: 100%; max-width: 210px; height: auto; margin-bottom: 4px; align-self: center; }

  .comp-name { font-family: var(--display); font-size: 1.08rem; letter-spacing: 0.02em; }
  .comp-tag { font-family: var(--body); font-size: 11px; letter-spacing: 0.1em; color: var(--gold); }
  .comp-blurb { color: #cfd6c2; font-size: 0.97rem; }

  .foot-note { margin: 14px 0 0; color: var(--muted); font-size: 0.85rem; }

  .slot .at, .fixture-list .at { color: var(--muted); }

  .fixture-list li .away, .fixture-list li .home { display: inline-flex; align-items: center; gap: 7px; }
  .fixture-list li img { width: 22px; height: 22px; object-fit: contain; }

  .brand { width: clamp(220px, 32vw, 380px); height: auto; display: block; margin-bottom: 18px; }

  .player img { aspect-ratio: 16 / 9; object-fit: cover; }

/* ---------------------------------------------- review pass, 17 Sept ---- */

/* Brand marks on the buttons. Sized to the text, never larger. */
.icon { width: 1.15em; height: 1.15em; flex: none; }

/* "What we run": the four logos are different shapes and aspect ratios, so
   each sits in a fixed box and is scaled to fit rather than to fill. */
.competitions { grid-template-columns: repeat(auto-fit, minmax(min(255px, 100%), 1fr)); }

.competition { gap: 9px; padding: 20px; }

.comp-art {
  display: grid;
  place-items: center;
  height: 128px;
  margin-bottom: 6px;
  padding: 8px 10px;
  border: 1px solid var(--edge-soft);
  background: #0d110a;
}

.comp-art img { width: 100%; max-width: 250px; height: 100%; object-fit: contain; }

.comp-name { font-family: var(--display); font-size: 1.16rem; letter-spacing: 0.02em; }

.comp-tag {
  font-family: var(--body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--gold);
}

/* Results: real tab buttons, and co-op matches carry a summed total row. */
.week-pill {
  padding: 8px 15px;
  border: 1px solid var(--edge);
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: 0.93rem;
  cursor: pointer;
}

.week-pill:hover { color: var(--parchment); border-color: var(--moss); }
.week-pill[aria-current="true"] { border-color: var(--moss); color: var(--parchment); background: var(--raised); }
.week-pill:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.weeks-label { display: none; }

@media (max-width: 700px) {
  .weeks { align-items: center; gap: 6px; }
  .weeks-label { display: inline; color: var(--muted); font-size: 0.9rem; }
  .week-prefix, .week-coop { display: none; }
  .week-pill { min-width: 36px; min-height: 40px; padding: 6px 10px; white-space: nowrap; }
}

.coop-note {
  grid-column: 1 / -1;
  margin: 0 0 2px;
  color: var(--gold);
  font-size: 0.92rem;
}

.match-head { display: flex; align-items: center; gap: 10px; }
.match-head .side { display: inline-flex; align-items: center; gap: 9px; flex: 1 1 0; min-width: 0; }
.match-head .side.right { justify-content: flex-end; text-align: right; }
.match-head .score { font-family: var(--mono); color: var(--gold); flex: none; }

.race-line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding-top: 10px;
  font-size: 0.95rem;
}

.race-line .racer { display: inline-flex; align-items: baseline; gap: 7px; min-width: 0; }
.race-line .racer.right { justify-content: flex-end; text-align: right; }
.race-line .clock { font-family: var(--mono); font-size: 0.86rem; font-variant-numeric: tabular-nums; }

.race-line.total {
  margin-top: 8px;
  padding-top: 10px;
  border-top: 1px solid var(--edge-soft);
  font-weight: 600;
}

.race-line.total .clock { font-size: 0.95rem; }

/* Latest races: one row per race, scanned top to bottom. */
.archive { display: flex; flex-direction: column; gap: 0; border: 1px solid var(--edge); background: var(--surface); }

.vod {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 14px;
  padding: 13px 18px;
  border: 0;
  border-bottom: 1px solid var(--edge-soft);
  background: transparent;
}

.vod:last-child { border-bottom: 0; }
.vod .when { font-family: var(--mono); font-size: 0.84rem; color: var(--muted); }
.vod .title { font-weight: 500; }
.vod .go { color: var(--gold); font-size: 0.88rem; }

@media (max-width: 560px) {
  .vod { grid-template-columns: minmax(0, 1fr) auto; }
  .vod .when { grid-column: 1 / -1; }
}

/* Matchups list: away at home, one line each. */
.fixture-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--edge);
  background: var(--surface);
}

.fixture-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--edge-soft);
}

.fixture-list li:last-child { border-bottom: 0; }
.fixture-list .away, .fixture-list .home { display: inline-flex; align-items: center; gap: 9px; font-weight: 600; }
.fixture-list .home { color: #d8e0cb; }

/* Channel rows carry the Twitch mark beside the name. */
.channel .name { display: inline-flex; align-items: center; gap: 8px; }

.brand { width: clamp(260px, 34vw, 420px); }

td.pts { font-weight: 600; color: var(--parchment); }

/* ------------------------------------ results layout, second review ---- */

/* The panel is a grid, and a grid beats [hidden] unless it is said again. */
.results[hidden] { display: none; }

/* Each race is two halves: name outside, clock against the center line, so a
   long name never runs into a time. */
.race-line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 20px;
}

.race-line .racer { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.race-line .racer.right { flex-direction: row-reverse; }

.race-line .who { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.race-line .clock { margin-left: auto; white-space: nowrap; }
.race-line .racer.right .clock { margin-left: 0; margin-right: auto; }

/* Match heading: team, score, team — the score never wraps under a logo. */
.match-head { flex-wrap: nowrap; align-items: center; }
.match-head .side { min-width: 0; }
.match-head .side img { flex: none; }
.match-head .score { white-space: nowrap; padding: 0 4px; }

@media (max-width: 520px) {
  .match-head .side { font-size: 0.95rem; }
}

/* ------------------------------------- results: room to read, 3rd pass -- */

/* Two match cards per row at most: three columns squeezed racer names into
   ellipses, which is worse than scrolling a little further. */
.results { grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr)); }

/* A co-op game lists two racers a side, so each side stacks and the clock sits
   under its own name rather than fighting the opposite team for width. */
.race-line { align-items: start; row-gap: 4px; }
.race-line .racer { flex-wrap: wrap; row-gap: 2px; }
.race-line .who { white-space: normal; overflow: visible; text-overflow: clip; }
.race-line .racer .who + .clock + .who { flex-basis: 100%; }

.race-line.total .who { white-space: nowrap; }


/* ------------------------------------------------ links and art, 4th ---- */

/* Restored: without this every card heading takes the browser's link blue. */
a { color: inherit; text-decoration: none; }
a:hover { color: inherit; }
.section-head a { color: var(--gold); }
.section-head a:hover { text-decoration: underline; }
.vod .title { color: var(--parchment); }
.vod:hover .title { color: var(--moss-bright); }

/* The logos carry their own titles, so the cards no longer repeat them. */
.comp-art { height: 168px; padding: 10px 12px; }
.comp-art img { max-width: 100%; }

/* Team logos are 200px sources now: crisp on a 5K display at these sizes. */
td.team img { width: 30px; height: 30px; }
.match-head img { width: 30px; height: 30px; }
.slot .teams img, .fixture-list li img { width: 26px; height: 26px; }

.sub-head {
  margin: 4px 0 2px;
  font-family: var(--display);
  font-size: 1.12rem;
  letter-spacing: 0.02em;
}

.sub-note { margin: 0 0 14px; color: var(--muted); font-size: 0.93rem; }
.schedule + .sub-head { margin-top: 30px; }


/* -------------------------------------------- co-op race lines, 5th ----- */

.race-line .racer { display: flex; flex-direction: column; gap: 3px; flex-wrap: nowrap; }
.race-line .racer .line { display: flex; align-items: baseline; gap: 12px; }
.race-line .racer.right .line { flex-direction: row-reverse; }
.race-line .racer .who { flex: 1 1 auto; }
.race-line .racer .clock { margin: 0; flex: none; }


/* ------------------------------------ aligned tables and rows, 6th ----- */

/* Divisions stack: Hyrule above Lorule, each full width, so the racers
   column has room. */
.divisions { grid-template-columns: minmax(0, 1fr); gap: 22px; }

td.racers { color: var(--muted); font-size: 0.93rem; }
td.racers .sep { color: var(--edge); }

.points-short { display: none; }

/* Mobile rows share one grid: the logo spans the team and roster lines,
   and the roster uses the space below Record and Pts as well as the name. */
@media (max-width: 700px) {
  #standings table, #standings thead, #standings tbody { display: block; }
  #standings tr {
    display: grid;
    grid-template-columns: 1.2rem 40px minmax(0, 1fr) 3.1rem 1.6rem;
    grid-template-areas: "rank logo team record points" "rank logo roster roster roster";
    column-gap: 8px;
    row-gap: 3px;
    padding: 9px 8px;
    align-items: center;
  }
  #standings thead tr { grid-template-areas: "rank team team record points"; }
  #standings tbody tr { border-top: 1px solid var(--edge-soft); min-height: 58px; }
  #standings tbody tr.qualify { background: rgba(79, 143, 44, 0.08); }
  #standings th, #standings td { padding: 0; border: 0; background: transparent; min-width: 0; }
  #standings .rank { grid-area: rank; width: auto; }
  #standings th.team { grid-area: team; }
  #standings td.team, #standings .standings-team { display: contents; }
  #standings .standings-team img { grid-area: logo; width: 40px; height: 40px; }
  #standings .team-name { grid-area: team; white-space: nowrap; font-size: clamp(.75rem, 3.5vw, .94rem); }
  #standings .record { grid-area: record; }
  #standings .pts { grid-area: points; }
  #standings th.racers, #standings td.racers { display: none; }
  #standings .standings-roster { display: block; grid-area: roster; margin: 0; white-space: nowrap; font-size: clamp(.6rem, 2.7vw, .72rem); }
  #standings .points-full { display: none; }
  #standings .points-short { display: inline; }
}

@media (max-width: 380px) {
  #standings tr { grid-template-columns: 1rem 32px minmax(0, 1fr) 2.75rem 1.5rem; column-gap: 6px; padding-inline: 6px; }
  #standings table { font-size: .9rem; }
  #standings th { font-size: 10px; letter-spacing: .04em; }
  #standings .standings-team img { width: 32px; height: 32px; }
  #standings .standings-roster { letter-spacing: -.02em; }
}

#standings th.num, #standings td.num { white-space: nowrap; }
.division td.team { display: table-cell; }
.standings-team { display: flex; align-items: center; gap: 12px; }
.standings-roster { display: none; font-size: .72rem; line-height: 1.4; font-weight: 400; color: var(--muted); }
.standings-roster > span { white-space: nowrap; }
.standings-roster > span:not(:last-child)::after { content: ' ·'; margin-right: 3px; }

/* Team logos read at a glance rather than as a smudge. */
td.team img { width: 44px; height: 44px; }
.match-head img { width: 40px; height: 40px; }
.slot .teams img, .fixture-list li img { width: 34px; height: 34px; }
td.team { gap: 12px; }

/* A match is one grid: name | time | time | name, so every row lines up. */
.race-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto minmax(0, 1fr);
  align-items: baseline;
  column-gap: 14px;
  row-gap: 6px;
  margin-top: 12px;
}

.race-grid .cell { font-size: 0.95rem; min-width: 0; }
.race-grid .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.race-grid .name.right { text-align: right; }
.race-grid .time { font-family: var(--mono); font-size: 0.88rem; font-variant-numeric: tabular-nums; }
.race-grid .time.right { text-align: right; }

.race-grid .total {
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px solid var(--edge-soft);
  font-weight: 600;
}

/* Matchups line up on three columns instead of drifting with name length. */
.fixture-list li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 2.5rem minmax(0, 1fr);
  align-items: center;
  gap: 12px;
}

.fixture-list .away, .fixture-list .home { min-width: 0; }
.fixture-list .home { justify-content: flex-end; text-align: right; flex-direction: row-reverse; }
.fixture-list .at { text-align: center; color: var(--muted); font-size: 0.9rem; }

@media (max-width: 560px) {
  .fixture-list li { grid-template-columns: minmax(0, 1fr) 2rem minmax(0, 1fr); gap: 8px; }
  .fixture-list li span span { font-size: 0.9rem; }
}

/* Champions: edition, name, note — aligned, not wrapped mid-row. */
.champ-list li {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 10px;
}

.champ-list .ed { width: auto; }
.champ-list .note { margin-left: 0; }


/* Channel cards are a name and a mark, nothing else. */
.channel { padding: 18px 20px; }
.channel .name { font-size: 1.02rem; }


/* -------------------------------------- winners and co-op games, 7th --- */

/* Fixed time columns so the two games in a co-op card line up with each
   other, not just within themselves. */
.race-grid { grid-template-columns: minmax(0, 1fr) 5.4rem 5.4rem minmax(0, 1fr); }

/* One card can hold two games on a co-op week: give the second some air. */
.race-grid + .race-grid {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px dashed var(--edge);
}

/* The winning side reads green; the other side steps back. */
.race-grid .won { color: var(--moss-bright); font-weight: 600; }
.race-grid .lost { color: var(--muted); }
.race-grid .won.time { color: var(--moss-bright); }


/* ------------------------------------------- runners and crests, 8th --- */

/* Who is actually racing, under the teams. */
.slot .runners {
  display: block;
  color: var(--muted);
  font-size: 0.92rem;
}

.slot .runners .vs { color: var(--edge); padding: 0 2px; }
.slot .runners .and { padding: 0 8px; color: var(--edge); }

/* The home crest sits before the home name, the same way the away one does. */
.fixture-list .home { flex-direction: row; justify-content: flex-start; text-align: left; }
.match-head .side.right { flex-direction: row; justify-content: flex-end; }


/* ------------------------------------- names wrap, buttons wear their own
   colours, 7th pass ------------------------------------------------------ */

/* A long name used to be cut off with an ellipsis. Let it wrap onto a second
   line instead: the grid columns hold their alignment either way. */
.race-grid { align-items: start; }

.race-grid .name {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.3;
}

/* The two off-site calls to action carry the color people already associate
   with where they land. */
.btn-youtube {
  background: linear-gradient(180deg, #e8322a, #bf1610);
  border-color: #ff4d40;
  color: #fff4f2;
}

.btn-youtube:hover { background: linear-gradient(180deg, #f43c33, #cf1a13); border-color: #ff6656; }

.btn-discord {
  background: linear-gradient(180deg, #5d6ef5, #4453d6);
  border-color: #808cf8;
  color: #f2f4ff;
}

.btn-discord:hover { background: linear-gradient(180deg, #6b7bf7, #4f5ee0); border-color: #96a0fa; }



/* ------------------------------------------------- room to breathe, 8th --

   Nine sections stacked on one page read as a wall unless each one is given
   its own air and a line to sit behind. The rhythm below is the whole change:
   more space between sections than inside them, so the eye lands on a
   heading, reads one block, and stops. */

main > section { padding-block: clamp(48px, 6vw, 92px); }
main > section + section { border-top: 1px solid var(--edge-soft); }

.section-head { margin-bottom: 30px; padding-bottom: 14px; }
.section-head h2 { line-height: 1.15; }

/* Cards sit further apart, and carry more padding inside. */
.competitions, .join, .channels, .flagsets, .results { gap: 22px; }
.divisions { gap: 34px; }
.slots { gap: 14px; }
.champ-list { gap: 12px; }

.join-card { padding: 24px; }
.match { padding: 18px 20px; }

/* The closing note under a section is a footnote, not another row. */
.foot-note { margin-top: 22px; }

@media (max-width: 700px) {
  main > section { padding-block: 40px; }
  .section-head { margin-bottom: 22px; }
}


/* --------------------------------------------------------- phones, 9th --

   The page is read on a phone as often as a desktop, so the two dense grids
   -- a match's four columns of names and clocks, and the matchup ladder --
   get their own narrow-screen shapes rather than being squeezed. */

@media (max-width: 560px) {
  .race-grid { grid-template-columns: minmax(0, 1fr) 4.6rem 4.6rem minmax(0, 1fr); column-gap: 8px; }
  .race-grid .cell { font-size: 0.88rem; }
  .race-grid .time { font-size: 0.8rem; }
  .match { padding: 14px; }

  .match-head { gap: 8px; }
  .match-head img { width: 30px; height: 30px; }

  .slot .teams img, .fixture-list li img { width: 28px; height: 28px; }

  .hero-actions { gap: 10px; }
  .hero-actions .btn { flex: 1 1 auto; justify-content: center; }
}


/* ---------------------------------------------- the tenth pass, phones --

   The four logos are different shapes, so the picture is capped on both axes
   and the box never grows to meet it: a logo that spilled its frame was
   landing on the gold line underneath. */

/* A grid area sized by its own content cannot answer "100%" of what, so the
   percentage was silently dropped and the logo grew past its frame. A flex
   box with a fixed height can, and the clip is there so a future logo of some
   other shape still cannot land on the line below. */
.comp-art {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.comp-art img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
}

/* One match per line under an upcoming fixture. */
.slot .runners + .runners { margin-top: 2px; }

/* The brand mark is the one centered thing on a phone: it is a picture, not a
   line of text, and it reads as the masthead. */
@media (max-width: 720px) {
  .brand { margin-inline: auto; width: clamp(200px, 62vw, 300px); }
  .hero h1 { text-align: center; }
  .comp-art { height: 128px; }
  .competition { padding: 16px; }
}

/* The three calls to action lead with their platform, so the mark carries
   its share of the button. */
.hero-actions .icon { width: 1.45em; height: 1.45em; }


/* ------------------------------------------------- date and clock, 11th --

   The date sits on the clock's own line and carries the same weight: they
   are one piece of information, not a label above a number. */

.slot .time .day {
  font-size: inherit;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--gold);
}

/* Standing weekly rows keep the label on its own line, but it is no longer a
   whisper above the times. */
.slot .day {
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  color: var(--parchment);
}


/* ------------------------------------------- one name, one line, 12th ----

   A racer's handle broken across two lines is harder to read than the same
   handle a point smaller. Three things keep it on one line: a result card
   that would rather be wide than share the row, clocks no wider than the
   time they hold, and a size step for the long handles. */

.results { grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr)); }

.race-grid { grid-template-columns: minmax(0, 1fr) 4.9rem 4.9rem minmax(0, 1fr); column-gap: 11px; }

.race-grid .name { white-space: nowrap; overflow-wrap: normal; }
.race-grid .name.small { font-size: 0.87rem; }
.race-grid .name.tiny { font-size: 0.8rem; }

/* A phone has no room to hold a fourteen-character handle on one line at a
   readable size, so there it wraps rather than running into the clock. */
@media (max-width: 560px) {
  .race-grid { grid-template-columns: minmax(0, 1fr) 4.3rem 4.3rem minmax(0, 1fr); column-gap: 7px; }
  .race-grid .name { white-space: normal; overflow-wrap: anywhere; }
  .race-grid .name.small { font-size: 0.8rem; }
  .race-grid .name.tiny { font-size: 0.73rem; }
}


/* Live races go out on Twitch; every race ends up on YouTube, so the archive
   sits in the same list under its own color. */
.channel.youtube { border-left-color: var(--dodongo); }


/* A raster mark on a button sits at the same size as the inline ones. */
img.icon { width: 1.3em; height: 1.3em; object-fit: contain; }


/* Short labels, but a card still never lets one spill past its border. */
.channel .name { min-width: 0; max-width: 100%; }
.channel .name .icon { flex: none; }


/* ------------------------------------------- racetime rooms, 13th pass --

   The rail carried one line: the next League match. racetime knows what is
   actually happening right now, so the rooms sit under it as links out. */

.rail-inner { flex-wrap: wrap; }

.rooms {
  border-top: 1px solid var(--edge-soft);
  /* padding-block only: the shorthand would zero the page gutter this
     element inherits from .wrap. */
  padding-block: 14px 16px;
}

.rooms-label {
  display: block;
  margin-bottom: 9px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}

.room-list { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); }

.room {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  gap: 4px 10px;
  padding: 10px 13px;
  border: 1px solid var(--edge);
  border-left: 3px solid var(--edge);
  background: var(--surface);
  text-decoration: none;
}

.room:hover { background: var(--raised); border-color: var(--moss); }
.room:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.room.running { border-left-color: var(--dodongo); }

.room .state {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.room.running .state { color: var(--dodongo); }
.room .what { font-weight: 600; font-size: 0.95rem; overflow-wrap: anywhere; }
.room .meta { grid-column: 2; color: var(--muted); font-size: 0.85rem; }
/* 2026-10-21: a race nobody is restreaming says who the Race Viewer opens on. */
.room .watch { grid-column: 2; color: var(--gold); font-size: 0.85rem; font-weight: 600; }
/* 2026-10-22: who is watching the race in the viewer, for anyone signed in. */
.room .watching { grid-column: 2; color: var(--muted); font-size: 0.8rem; overflow-wrap: anywhere; }

/* ----------------------------------- a match's two sides, side by side --

   Each racer sits under the team they race for, which is the question the
   card is actually answering. No "vs" to read in the dark. */

.fixture {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: start;
  gap: 4px 12px;
}

.fixture .side { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

.fixture .team {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.95rem;
  font-weight: 600;
}

.fixture .team img { width: 26px; height: 26px; object-fit: contain; flex: none; }
.fixture .runner { color: var(--muted); font-size: 0.9rem; overflow-wrap: anywhere; }
.fixture .at { align-self: center; color: var(--muted); font-size: 0.85rem; }

/* The old faint separators were unreadable on this ground. */
.slot .at, .fixture-list .at, .match-head .at { color: var(--muted); }

@media (max-width: 480px) {
  .fixture { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 4px 8px; }
  .fixture .team { font-size: 0.9rem; }
  .fixture .team img { width: 22px; height: 22px; }
}

/* ------------------------------------------------ the season ranking ---- */

.board { margin-top: 26px; }

.sub-head-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 16px;
}

.sub-head-row .sub-head { margin-bottom: 10px; }
.sub-head-row a { color: var(--gold); font-size: 0.9rem; text-decoration: none; }
.sub-head-row a:hover { text-decoration: underline; }

.board td.racer a { color: inherit; text-decoration: none; }
.board td.racer a:hover { color: var(--moss-bright); text-decoration: underline; }


/* A League card holds two columns of names in about 300px, so the same size
   steps the result cards use apply here. */
.schedule { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }

.fixture .runner { white-space: nowrap; }
.fixture .runner.small { font-size: 0.84rem; }
.fixture .runner.tiny { font-size: 0.78rem; }

@media (max-width: 480px) {
  .fixture .runner { white-space: normal; overflow-wrap: anywhere; }
}


/* --------------------------------------------- lineups line up, 14th ----

   "Dodongo Ate My Baby" takes two lines and "Bow Mode" takes one, so a
   lineup that simply followed its own team name started lower on one side
   than the other. The team names share a row and the lineups share the next,
   so both sides start together however the names wrap. */

.fixture {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-items: start;
  column-gap: 12px;
  row-gap: 5px;
}

.fixture .team.away { grid-column: 1; grid-row: 1; }
.fixture .at { grid-column: 2; grid-row: 1; align-self: center; }
.fixture .team.home { grid-column: 3; grid-row: 1; }
.fixture .lineup.away { grid-column: 1; grid-row: 2; }
.fixture .lineup.home { grid-column: 3; grid-row: 2; }

.fixture .lineup { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

/* A table is the one thing allowed to be wider than the phone, inside its
   own scroller rather than pushing the page sideways. */
.division, .board { overflow-x: auto; }


/* ------------------------------------------- the masthead, 15th pass ----

   Stacked, the mark and the headline read as two separate announcements of
   the same thing. Side by side they read as one masthead -- but only where
   there is room for the headline to hold its line length beside a 200px
   mark, which is why the row starts at 900px and a phone keeps the stack. */

@media (min-width: 960px) {
  .hero-inner { grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); }

  .masthead {
    display: flex;
    align-items: center;
    gap: clamp(20px, 2.4vw, 32px);
  }

  .masthead .brand {
    flex: none;
    width: clamp(150px, 16vw, 215px);
    margin-bottom: 0;
  }

  .masthead .titles { min-width: 0; }

  /* Narrower than the full column, so the headline still breaks in two. */
  .masthead h1 { font-size: clamp(2.05rem, 3.1vw, 2.8rem); }
  .masthead .lede { max-width: 40ch; margin-top: 10px; }
}


/* --------------------------------------------- the menu follows, 16th ---

   The page is long enough that the menu was only useful at the very top.
   It sticks now, and once the hero mark has scrolled away the small mark
   takes its place in the bar -- a way back to the top that is always in the
   same spot. The slot is held open either way, so nothing shifts as it
   appears. */

.topnav {
  position: sticky;
  top: env(safe-area-inset-top, 0px);
  z-index: 40;
  align-items: center;
  background: rgba(10, 12, 9, 0.93);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
}

.topnav .home {
  display: flex;
  align-items: center;
  flex: none;
  opacity: 0;
  pointer-events: none;
  transition: opacity 160ms ease;
}

.topnav .home img { width: 26px; height: 26px; object-fit: contain; display: block; }
.topnav.pinned .home { opacity: 1; pointer-events: auto; }

/* Anchored sections clear the bar instead of hiding under it. */
:target, section[id], header[id] { scroll-margin-top: 62px; }

@media (prefers-reduced-motion: reduce) {
  .topnav .home { transition: none; }
}


/* ------------------------------------ the masthead spans it, 17th pass --

   Confined to the column beside the replay, the lockup read as one item in a
   two-column hero. Across the whole width it reads as the top of the page:
   the mark, then the line, on one row -- with the lede, the calls to action
   and the replay sharing the row underneath. */

@media (min-width: 960px) {
  .hero-inner {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    align-items: start;
    row-gap: clamp(20px, 2.6vw, 34px);
  }

  .masthead {
    grid-column: 1 / -1;
    gap: clamp(22px, 2.6vw, 36px);
  }

  .masthead .brand { width: clamp(170px, 18vw, 260px); }

  /* Room enough now to hold the line it was written for. */
  .masthead h1 { margin: 0; font-size: clamp(2.2rem, 3.7vw, 3.15rem); }

  .hero-copy { display: flex; flex-direction: column; gap: 22px; align-self: center; }
  .hero-copy .lede { max-width: 46ch; }
  .hero-actions { margin-top: 0; }
}


/* A racer's name carries their racetime profile where racetime knows them,
   and reads as plain text where it does not -- so the underline waits for a
   hover rather than speckling every list with links. */
.racer-link { color: inherit; text-decoration: none; }
.racer-link:hover { color: var(--moss-bright); text-decoration: underline; }
.racer-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }


/* ------------------------------------------- this month's bracket, 18th --

   Eight names in four pairs, seeded. The seeds sit in their own narrow
   columns so the names line up down the card however long they are. */

.bracket { margin: 20px 0 22px; }

.bracket h4 {
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}

.bracket-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }

.bracket-list li {
  display: grid;
  grid-template-columns: 1.6rem minmax(0, 1fr) 1.2rem minmax(0, 1fr) 1.6rem;
  align-items: baseline;
  gap: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--edge-soft);
}

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

.bracket-list .seed {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--gold);
  text-align: center;
}

.bracket-list .who { font-size: 0.95rem; overflow-wrap: anywhere; }
.bracket-list .who.right { text-align: right; }
.bracket-list .v { color: var(--muted); font-size: 0.82rem; text-align: center; }


/* ------------------------------------------- the bar's mark, 19th pass --

   The mark used to fade in once the hero logo had scrolled away. It is
   simpler, and steadier, for it to be there the whole way down.

   It also sits outside the links rather than among them, so when the links
   wrap on a narrow screen the second row starts under the first instead of
   under the mark. */

.topnav {
  flex-wrap: nowrap;
  align-items: center;
  gap: 12px;
}

.topnav .home {
  opacity: 1;
  pointer-events: auto;
  align-self: center;
  flex: none;
}

.topnav-links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  min-width: 0;
}

/* ------------------------------------ raced, not yet official, 20th pass --

   racetime has the result minutes after the race; the sheet has it when a
   captain gets to it. This is that gap, clearly marked as the gap: the
   league's own sheet is what counts, and everything here is already public on
   racetime. */

.unofficial { margin-bottom: 26px; }
.unofficial .sub-head-row span { color: var(--muted); font-size: 0.9rem; }

/* The bracket carries the time the racers agreed, on its own line under the
   pair, so the seeds and names keep their columns. */
.bracket-list li { grid-template-rows: auto auto; }

.bracket-list .agreed {
  grid-column: 1 / -1;
  font-size: 0.82rem;
  color: var(--muted);
  text-align: center;
}

/* A Torneo Corto match in Coming up: no crests, so the seed does the work the
   team logo does on a League card. */
.slot.corto { border-left-color: var(--dodongo); }

.slot.corto .seed {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--gold);
  margin-right: 6px;
}

.slot.corto .fixture { grid-template-rows: auto; }
.slot.corto .team { font-size: 0.98rem; }

/* ------------------------------------------- the hero's replays, 21st ----

   One Latest races, in the hero. The label and the controls sit under the
   picture rather than on it, so nothing covers the frame. */

.replays { display: grid; gap: 12px; }

.stage { position: relative; }

/* ---------------------------------------------------- 35th pass, 26 Sept

   The caption used to sit over the foot of the frame on the reasoning that a
   thumbnail is darkest there. That held while the thumbnails were whatever
   frame YouTube picked. They are drawn cards now, and a card is a centered
   stack -- lockup, season, `A vs B` -- whose lowest line lands around three
   quarters of the way down, which is exactly where a four-line caption and
   its scrim were sitting. So the caption is gone and the date is a chip in a
   corner the card leaves empty by construction: the stack is centered inside a
   32px margin, so nothing is ever drawn there.

   The lines themselves are not lost. They are the image's alt text, which is
   where they were always the most use. */
.player-when {
  position: absolute;
  left: 10px;
  /* 8, not 10: at the size the hero renders the chip is about 95 thumbnail
     pixels tall, and from 10px up it started at y 596 -- three pixels inside
     the racer names, which end at 599. Measured, not guessed. */
  top: 8px;
  padding: 5px 10px;
  background: rgba(10, 12, 9, 0.82);
  border: 1px solid var(--edge);
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--parchment);
}

.replay-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
}

.replay-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}

.replay-nav { display: flex; align-items: center; gap: 8px; }

.step {
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 2px;
  background: var(--surface);
  color: var(--parchment);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.step:hover { border-color: var(--moss); background: var(--raised); }
.step:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.dots { display: flex; gap: 6px; }

.dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

.dot span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.dot[aria-current="true"] { background: var(--moss-bright); border-color: var(--moss-bright); }
.dot:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.replay-bar .all { margin-left: auto; color: var(--gold); font-size: 0.9rem; text-decoration: none; }
.replay-bar .all:hover { text-decoration: underline; }

@media (max-width: 560px) {
  .replay-bar .all { margin-left: 0; }
  .player-when { left: 8px; top: 8px; font-size: 0.72rem; padding: 4px 8px; }
  .player-play { inset: 6px 6px auto auto; }
  .player-play span { width: 24px; height: 24px; font-size: 10px; }
}

/* A Torneo Corto match in the schedule is laid out like its row in the
   bracket -- seeds in their own narrow columns, names filling the rest --
   rather than borrowing the League card's grid, which is built around crests
   and two-racer lineups and collapses without them. */
.bout {
  display: grid;
  grid-template-columns: 1.6rem minmax(0, 1fr) 1.2rem minmax(0, 1fr) 1.6rem;
  align-items: baseline;
  gap: 10px;
}

.bout .seed {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--gold);
  text-align: center;
}

.bout .who { font-size: 0.95rem; overflow-wrap: anywhere; }
.bout .who.right { text-align: right; }
.bout .v { color: var(--muted); font-size: 0.82rem; text-align: center; }

/* The card is one column of full-width rows. Without this the slot's grid
   lays two children out side by side and the match gets squeezed into half a
   card. */
.slot.corto { grid-template-columns: minmax(0, 1fr); }

/* Each racer's picture from racetime, so a Torneo Corto card carries faces
   the way a League card carries crests. */
.bout .who { display: flex; align-items: center; gap: 9px; }
.bout .who.right { flex-direction: row-reverse; }

.bout .face {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  background: var(--raised);
}

/* The dodongo stands in for a racer with no portrait. It is artwork rather than
   somebody's photograph, so it sits a little back: whole rather than cropped to
   the circle, and quiet enough that a card of two real faces and one dodongo
   does not read as the dodongo being the loud one. */
.bout .face.stand-in {
  object-fit: contain;
  background: rgba(255, 255, 255, 0.04);
  opacity: 0.9;
}

/* ------------------------------------------------ hidden means hidden ----

   Any element that sets its own `display` beats the browser's `[hidden]`
   rule, which is how five carousel slides all rendered at once and how the
   results panels once did the same. Said here, once, for every element that
   will ever be toggled. */
[hidden] { display: none !important; }

/* An open restream slot is the one thing on a League card a reader can act
   on, so it reads as a link rather than as a badge shaped like a button that
   does nothing, and it sits clear of the race detail above it. */
.restream.open {
  justify-self: start;
  margin-top: 6px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--gold);
  text-decoration: none;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.86rem;
  font-weight: 600;
}

.restream.open:hover { text-decoration: underline; }
.restream.open:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

.sub-note a { color: var(--gold); }

/* ------------------------------------------ the restream line, 22nd ------

   What is known about a race's restream, and an ask where it is short. The
   ask is a button because it is the one thing on the card to act on; the rest
   is detail and reads as detail. */

/* Tightened 2026-10-01. This footer was taller than the pairing above it on a
   card whose whole job is the pairing -- twenty pixels of rule and gap before a
   line that is usually three words. It is a caption, so it is sized like one. */
.crew {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
  margin-top: 3px;
  padding-top: 5px;
  border-top: 1px solid var(--edge-soft);
}

.crew .known {
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.3;
}

.crew .known.open { color: #ffb9a3; }
.crew .known .sep::before { content: '·'; padding: 0 7px; color: var(--edge); }

.signup {
  margin-left: auto;
  padding: 1px 9px;
  border: 1px solid #6fb23f;
  border-radius: 2px;
  background: linear-gradient(180deg, #55972f, #3d7521);
  color: #f6fbef;
  font-size: 0.74rem;
  line-height: 1.35;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
}

/* Small enough to read as a caption, still big enough to hit with a thumb.
   A finger wants about 24px and the tightened button is under that, so touch
   gets the padding back -- there is room for it on a phone, where the card is
   full width and the row has nothing else on it. */
@media (pointer: coarse) {
  .signup { padding: 5px 13px; }
}

.signup:hover { background: linear-gradient(180deg, #62a838, #457f25); }
.signup:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.sub-note.appeal { margin: -6px 0 22px; }

@media (max-width: 480px) {
  .signup { margin-left: 0; }
}

/* A racer with a picture and a racer without do not share a baseline -- a
   flex row's baseline is its first item's, and an image's is its bottom edge
   -- so the two names sat at different heights. Center them instead. */
.bout, .bracket-list li { align-items: center; }

/* ------------------------------------------- Torneo Corto bracket, 23rd --

   Two things were wrong with the bracket in its own section.

   The agreed time carried `class="slot"`, which is the schedule's race-card
   class: it inherited that card's padding, border and surface, so a one-line
   time rendered as a bordered block under every match and pulled the eye off
   the matchup itself. It has its own name now, and reads as a caption.

   And the matches showed names where the same matches in Schedule show faces.
   One bracket, one treatment. */

.bracket-list .who { display: flex; align-items: center; gap: 9px; }
.bracket-list .who.right { flex-direction: row-reverse; }

.bracket-list .face {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  background: var(--raised);
}

.bracket-list .agreed {
  grid-column: 1 / -1;
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.02em;
  color: var(--muted);
  text-align: center;
}

/* ------------------------------------- a match that fits a phone, 24th --

   Five columns -- seed, name, vs., name, seed -- leave each name about 60px
   on a phone, so "FreedomFighter" came apart as "FreedomFig / hter". The row
   stacks instead: one racer per line, each with the full width.

   The trigger is the block's own width, not the window's. These matches sit
   in a column that is half the page on a desktop and all of it on a phone, so
   a viewport breakpoint would either stack too early on one or too late on
   the other. */

.corto-lead, .slot.corto { container-type: inline-size; }

@container (max-width: 430px) {
  .bout, .bracket-list li {
    grid-template-columns: 1.75rem minmax(0, 1fr);
    row-gap: 4px;
  }

  /* The seeds keep their column; the racers take turns in the second one.
     Placed explicitly because the second seed follows its racer in the
     markup, where it belongs on a wide screen. */
  .bout > .seed:first-child, .bracket-list li > .seed:first-child { grid-area: 1 / 1; }
  .bout > .who, .bracket-list li > .who { grid-area: 1 / 2; }
  .bout > .v, .bracket-list li > .v { grid-area: 2 / 2; text-align: left; }
  .bout > .who.right, .bracket-list li > .who.right { grid-area: 3 / 2; }
  .bout > .seed:last-child, .bracket-list li > .seed:nth-child(5) { grid-area: 3 / 1; }
  .bracket-list li > .agreed { grid-area: 4 / 1 / 5 / -1; text-align: left; }

  /* Both racers now read left to right, so the right-hand one stops being a
     mirror of the left. */
  .bout > .who.right, .bracket-list li > .who.right {
    flex-direction: row;
    text-align: left;
  }
}

/* ------------------------------------------ live, and a crew line, 25th --

   Two changes to the foot of a race card.

   The channel and the crew were one run-on line -- "Restream · Z1Rracing ·
   Comms · A, B · Tracker · C" -- which reads as a list of facts about nothing
   in particular. They answer different questions, so they get a line each: the
   channel (and the ask, while the slot is short) on the first, the people who
   are working the broadcast on the second.

   And when Twitch says that channel is on air, the card leads with the way in. */

.crew {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  /* Tightened 2026-10-01 with the rest of this footer. This rule is the one in
     effect -- it is the second `.crew` block in the file and wins on order --
     so tightening only the first one above changed nothing visible. */
  gap: 2px 10px;
}

.crew .known.who {
  grid-column: 1 / -1;
}

.signup { margin-left: 0; justify-self: end; }

.watch-live {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 10px;
  padding: 9px 13px;
  border: 1px solid #a970ff;
  border-radius: 2px;
  background: linear-gradient(180deg, #9146ff, #7626f5);
  color: #fff;
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
}

.watch-live:hover { background: linear-gradient(180deg, #a06bff, #8a3ff8); }
.watch-live .icon { width: 18px; height: 18px; flex: none; }

/* The one thing on the page that moves by itself, and only while a race is
   actually on air. */
.watch-live .pulse {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);
  animation: live-pulse 1.8s ease-out infinite;
}

@keyframes live-pulse {
  70% { box-shadow: 0 0 0 7px rgba(255, 255, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
}

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

/* Keep the restream status and its Sign Up action on one line on phones. */

/* ------------------------------------------------- on air now, 26th pass --

   "I now have no clue what is on the air right now." The schedule answers
   what is coming; nothing answered what is happening. This is the first thing
   under the hero whenever a channel is live, and it is simply absent the rest
   of the time -- no empty shell saying nobody is streaming. */

.live-strip { margin-bottom: 26px; }

.live-head {
  margin: 0 0 10px;
  font-family: var(--display);
  font-size: 1.05rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #d6b8ff;
}

.on-air-list { display: grid; gap: 8px; }

.on-air {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 12px 15px;
  border: 1px solid #a970ff;
  border-left: 3px solid #fff;
  background: linear-gradient(180deg, rgba(145, 70, 255, 0.92), rgba(118, 38, 245, 0.92));
  color: #fff;
  text-decoration: none;
}

.on-air:hover { background: linear-gradient(180deg, rgba(160, 107, 255, 0.95), rgba(138, 63, 248, 0.95)); }

.on-air .where {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-weight: 600;
  white-space: nowrap;
}

.on-air .where .icon { width: 18px; height: 18px; }

.on-air .what {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #f0e6ff;
  font-size: 0.92rem;
}

.on-air .go { font-size: 0.85rem; font-weight: 600; white-space: nowrap; }

.on-air .pulse {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);
  animation: live-pulse 1.8s ease-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .on-air .pulse { animation: none; }
}

/* On a phone the title earns its own line rather than being clipped to
   nothing between the channel and the arrow. */
@media (max-width: 620px) {
  .on-air { grid-template-columns: auto minmax(0, 1fr) auto; }
  .on-air .what { grid-column: 1 / -1; white-space: normal; }
}

/* The room the race is actually being run in, under the card's watch link. */
.race-room {
  display: inline-block;
  margin-top: 8px;
  color: var(--gold);
  font-size: 0.85rem;
  text-decoration: none;
}

.race-room:hover { text-decoration: underline; }

/* Two channels means two buttons; they stack rather than crowd. */
.watch-live + .watch-live { margin-top: 6px; }

/* Cards in a row are stretched to the tallest, and an auto-row grid hands that
   slack to its rows -- so the same fixture sat 167px down one card and 52px
   down the next, and nothing lined up across the schedule. The rows keep their
   own heights; the slack goes to the bottom of the card, where it shows as
   space rather than as drift. */
.slot { align-content: start; }

/* The booth title now arrives as lines -- the week, the teams, the racers --
   so it is set as lines. Run together on one row they read as one long
   sentence and the end of it falls off the card. */
.on-air .what {
  display: grid;
  gap: 1px;
  white-space: normal;
  overflow: visible;
}

.on-air .what .line {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The event is context; the teams and racers are the race. */
.on-air .what .line.lead {
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #e3d2ff;
}

.on-air .what .line:not(.lead) { font-size: 0.95rem; color: #fff; }

.on-air { align-items: center; }

@media (max-width: 620px) {
  .on-air .what .line { white-space: normal; }
}

/* Saturday's races moved to the weekday slots. The mark says so for the couple
   of weeks it takes people to notice; it comes off with the flag in
   content.mjs. */
.fresh {
  margin-left: 7px;
  padding: 1px 6px;
  border: 1px solid var(--gold);
  border-radius: 2px;
  color: var(--gold);
  font-family: var(--body);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  vertical-align: middle;
}

/* Saturday gained a fourth race as well as new times, so it carries two
   marks: what changed, and that it changed. The extra race is the good news,
   so it gets the moss. */
.fresh.super { border-color: var(--moss-bright); color: var(--moss-bright); }



/* ------------------------------------- scoreboard and rounds, 27th pass --

   The season used to be told in two sections: Results, which stopped at the
   last finished week, and Matchups, which showed only the next one. The week
   being played was in neither. One strip now runs the whole season, the way a
   scoreboard opens on today, and the bracket gets the same treatment by
   round. The pills are the ones the results weeks already used. */

.rounds { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 14px; }

.round-pill {
  padding: 6px 13px;
  border: 1px solid var(--edge);
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: 0.88rem;
  cursor: pointer;
}

.round-pill:hover { color: var(--parchment); border-color: var(--dodongo); }
.round-pill[aria-current="true"] { border-color: var(--dodongo); color: var(--parchment); background: var(--raised); }
.round-pill:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* A week nobody has raced yet lists its fixtures, and says when each game is
   due -- the question somebody opens a future week to answer. */
.fixture-when {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 4px;
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.02em;
  color: var(--muted);
}

/* ------------------------------------------- scoreboard layout, 28th ----

   The upcoming fixtures sat in one column of a two-column grid, so half the
   panel was empty while the list ran down the side. The list spans the panel
   and lays its own fixtures out in two, the same width the result cards use.
   The flags line spans it too: it belongs to the week, not to a card. */

.results .flags {
  grid-column: 1 / -1;
  margin: 0 0 4px;
}

}

/* A fixture card is the same object as a result card with the races not yet
   run: crests, the two teams, and when each game is due. "at" sits where the
   score will be, so the two read as one column of cards rather than as a list
   and a grid. */
.match.upcoming .score.at {
  font-family: var(--body);
  font-size: 0.85rem;
  color: var(--muted);
  text-transform: lowercase;
}

.race-line.upcoming {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding-top: 10px;
  color: var(--muted);
  font-size: 0.9rem;
}

.race-line.upcoming .clock { color: #cfd6c2; }

/* A scheduled game on an upcoming card: when it is, who is racing it, and
   the restream line if a channel or crew is known. */
/* Games of one card are separated whatever kind each is: a game still to
   come sits under one already raced as often as the other way round. */
.match > .game + .game { margin-top: 12px; border-top: 1px solid var(--edge-soft); }

/* Three columns, not a flex row: with space-between, "vs." lands wherever
   the two names happen to end, so it sat in a different place on every line.
   A column of its own puts every "vs." under the last. */
.race-line.pairing {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: baseline;
  gap: 10px;
  padding-top: 6px;
  font-size: 0.92rem;
}

.race-line.pairing .racer.right { text-align: right; }
.race-line.pairing .v { color: var(--muted); font-size: 0.8rem; text-align: center; }
.match.upcoming .crew { margin-top: 8px; }

/* ------------------------------------- a game on a result card, 29th ----

   A card used to be a stack of race grids with nothing saying which game was
   which or when it happened. Each game now opens with its number and time,
   the way a game still to come does, and closes with the places it can be
   watched: the race room, and a recording for each pairing that was
   restreamed -- a co-op game is restreamed twice. */

.race-line.upcoming.played { color: var(--muted); }
.race-line.upcoming.played .clock { color: var(--muted); }

.game-links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  padding-top: 8px;
}

.game-links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--gold);
  font-size: 0.82rem;
  text-decoration: none;
}

.game-links a:hover { text-decoration: underline; }
.game-links .icon { width: 1em; height: 1em; }
.icon-racetime {
  display: inline-block;
  background-color: currentColor;
  -webkit-mask: url('/assets/racetime.svg') center / contain no-repeat;
  mask: url('/assets/racetime.svg') center / contain no-repeat;
}


/* ------------------------------------------ times meet in the middle, 21st --

   Each clock column used to align to its own outer edge, which pushed the two
   times of a head-to-head apart -- the eye had to cross the whole card to
   compare them. Turning both inward sets them either side of the center gap,
   so the comparison the row exists to make is one glance wide. */

.race-grid .time { text-align: right; }
.race-grid .time.right { text-align: left; }


/* --------------------------------------- cards on the panel's rows, 22nd --

   Two cards side by side are read across, not down: Game 1 against Game 1,
   this week's totals against that week's. They drifted because each card
   sized its own rows -- a team name that wrapped to two lines, a game with
   no recording to link, an async pairing where the neighbour had a finished
   race -- and by the foot of a card the two were an inch apart.

   Subgrid hands the rows back to the panel. A card no longer has heights of
   its own: it spans as many of the panel's rows as it has parts, and every
   card on that band agrees on how tall each one is. */

@supports (grid-template-rows: subgrid) {
  .results .match {
    display: grid;
    grid-row: span var(--rows, 7);
    grid-template-rows: subgrid;
    /* The panel's gap belongs between cards, not between a card's own rows
       -- which are now the panel's rows too, and would inherit it. */
    row-gap: 0;
  }

  .results .match > .game {
    display: grid;
    grid-row: span 3;
    grid-template-rows: subgrid;
    row-gap: 0;
  }
}

/* The score sits on the same line as the teams it belongs to.
   Topping the head out aligned the crests across a band, but a crest is
   taller than the score beside it, so the score rose off the names. The row
   is shared now anyway, and centring is what keeps a one-line card sitting
   level with the two-line card beside it. */
.match-head { align-items: center; }


/* -------------------------------------------- formats as signposts, 23rd --

   Four large marks and four paragraphs, a full screen of them, explaining to
   people who race here every week what the formats they race are. They are
   really four signposts to the sections below, so they are built like the
   channel buttons under Where to watch: the mark, the name, one row.

   The line that says what a format is keeps its place on hover, where it is
   there for the visitor who has not met these before and costs the regulars
   no room. The sections themselves explain properly. */

/* Four, or two, or one -- never three with the fourth alone underneath,
   which is what auto-fitting four things does at the wrong width. */
.competitions { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }

@media (max-width: 900px) { .competitions { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 460px) { .competitions { grid-template-columns: minmax(0, 1fr); } }

.competition {
  position: relative;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  border: 1px solid var(--edge);
  border-left: 3px solid var(--moss);
  background: var(--surface);
}

.competition:hover { background: var(--raised); }
.competition:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* The mark keeps its own proportions inside a fixed box, so four logos of
   four different shapes still line their names up with one another.

   Both margins are cleared, and both are from the days when the mark sat
   above the name and wanted air under it: six pixels on the box, four on the
   picture inside it. A row that centers its children centers the margin box
   too, so between them they left every logo five pixels high of its name. */
.comp-art {
  flex: none;
  width: 56px;
  height: 44px;
  margin: 0;
  padding: 0;
  background: none;
  border: 0;
}

.comp-art img { width: 100%; height: 100%; max-width: none; margin: 0; object-fit: contain; }

.comp-name {
  font-family: var(--display);
  font-size: 0.97rem;
  line-height: 1.22;
  color: var(--parchment);
  min-width: 0;
  text-wrap: balance;
}

/* Sits under the button rather than inside it: revealed on hover, the row
   keeps its height and nothing below it moves. */
.comp-tag {
  position: absolute;
  z-index: 3;
  top: calc(100% + 6px);
  left: -1px;
  right: -1px;
  padding: 9px 12px;
  border: 1px solid var(--edge);
  border-left: 3px solid var(--gold);
  background: var(--raised);
  font-family: var(--body);
  font-size: 0.82rem;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.35;
  color: #cfd6c2;
  opacity: 0;
  pointer-events: none;
  transition: opacity 130ms ease;
}

.competition:hover .comp-tag,
.competition:focus-visible .comp-tag { opacity: 1; }

/* No hover on a touch screen, so there the line simply sits under the name:
   the button is taller, and still a quarter of what the cards were. */
@media (hover: none) {
  .comp-tag {
    position: static;
    padding: 0;
    border: 0;
    background: none;
    opacity: 1;
    font-size: 0.78rem;
    color: var(--muted);
  }

  .competition { align-items: center; }
  .comp-said { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
}

@media (prefers-reduced-motion: reduce) { .comp-tag { transition: none; } }


/* ------------------------------------------ headings on a phone, 24th ----

   The heading size is a clamp, and on a phone it sits on the clamp's floor,
   where "Triforce Triple Play — Season 5" is a few pixels too long and drops
   its season onto a second line. The floor comes down a little rather than
   that one heading being made a different size from the rest of them. */

@media (max-width: 460px) {
  h2 { font-size: 1.28rem; }
}


/* ------------------------------------------ the jump bar, 25th pass ------

   The buttons had a heading over them that named the set -- Racing Formats,
   then Competitions -- and every name was either too long, wrong about a
   one-off tournament, or in competition with the Schedule section next to
   it. The buttons carry their own marks and their own names, and racing is
   what the whole site is: the heading was saying nothing the row did not.

   So it is a bar rather than a section. It keeps its id, because the links
   into it are worth more than the label over it, and a heading stays in the
   markup for anyone arriving by screen reader, where a row of four links
   with nothing above them is genuinely worse. */

main > section.jumpbar {
  padding-block: clamp(20px, 2.4vw, 30px);
  border-bottom: 1px solid var(--edge-soft);
}

/* Read aloud, never drawn. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* --------------------------------------- the times on the cards' grid, 26th

   The three times sat in one panel whose columns were on their own rhythm --
   its own padding, a tighter gap, a different column width -- so by the third
   one the label was half an inch left of the flagset title above it. The
   panel now lays out on exactly the grid the cards use, and carries its
   padding on each column instead, so every label starts where the title above
   it starts.

   The gold rule becomes an inset shadow on the way: a border would take three
   pixels out of the content box and put the columns back off the grid. */

.times {
  grid-template-columns: repeat(auto-fit, minmax(min(245px, 100%), 1fr));
  gap: 22px;
  padding-inline: 0;
  border-left: 0;
  box-shadow: inset 3px 0 0 var(--gold);
}

/* A card indents its content by its own border plus its padding; the panel
   has no border down that edge, so its columns carry the pixel instead. */
.times > div { padding-inline: 18px; }


/* --------------------------------------- a bracket match's time, 27th ----

   Most racers never write their match into the tournament sheet, so the time
   column said TBD for matches that had already been raced and for one that
   was being raced while somebody was reading the page. It says what racetime
   knows now, and links to the room it knows it from. */

.bracket-list .agreed a { color: var(--gold); text-decoration: none; }
.bracket-list .agreed a:hover { text-decoration: underline; }

/* On air reads like the live badges elsewhere, not like a date. */
.bracket-list .agreed a.racing { color: var(--dodongo); font-weight: 600; }


/* ----------------------------------- the replay bar's middle, 28th pass --

   The bar carried a "Latest races" label over a carousel that shows nothing
   else, and the label's width was what decided where the arrows and dots
   landed: a little left of the picture's center, and somewhere else again
   when it wrapped. The row is three columns now -- nothing, the nav, the
   channel -- so the nav sits on the center line whatever stands beside it.

   The channel link says what it links to the way a race footer does: the
   mark at text size, then the handle. */

.replay-bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 10px 16px;
}

.replay-nav { grid-column: 2; justify-content: center; }

.replay-bar .all {
  grid-column: 3;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 0;
}

.replay-bar .all .icon { width: 1em; height: 1em; }

/* Side by side the two would crowd a phone, so the channel sits under the
   nav there and both keep the center line. */
@media (max-width: 560px) {
  .replay-bar { grid-template-columns: minmax(0, 1fr); justify-items: center; }
  .replay-nav, .replay-bar .all { grid-column: 1; justify-self: center; }
}


/* ------------------------------------ a channel that is on air, 29th ----

   Where to watch was four buttons that looked the same whether a race was
   running on them or not, which is the one thing somebody opening that
   section at eight on a Tuesday wants to know. A live channel now carries
   Twitch's purple, a dot that moves while the race does, and the line of the
   booth's title that names the race -- not the strip's full treatment, which
   already sits at the top of the page for exactly this. */

.channel.is-live {
  border-color: #7b46c9;
  border-left-color: #a970ff;
  background: linear-gradient(180deg, rgba(145, 70, 255, 0.16), rgba(118, 38, 245, 0.1));
}

.channel.is-live:hover {
  background: linear-gradient(180deg, rgba(145, 70, 255, 0.26), rgba(118, 38, 245, 0.18));
}

.channel.is-live .state { color: #d6b8ff; }

.channel .pulse {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 50%;
  background: #a970ff;
  box-shadow: 0 0 0 0 rgba(169, 112, 255, 0.7);
  animation: channel-pulse 1.8s ease-out infinite;
}

@keyframes channel-pulse {
  70% { box-shadow: 0 0 0 7px rgba(169, 112, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(169, 112, 255, 0); }
}

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

/* One line, whatever the booth wrote: the button keeps the height of the
   three beside it. */
.channel .now {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #e3d6ff;
  font-size: 0.88rem;
}


/* ------------------------------------------- power rankings, 30th pass ----

   The first thing on the page that nobody's sheet can produce: the editorial
   staff's order of the League, written on Mondays once a week is done. Each
   team shows its rank and a one-line verdict and opens to the four parts of
   its write-up, so fourteen of them read as a list rather than a wall. The
   record beside the name is the standings' own, not the writer's. */

/* 2026-10-05: the lede runs as wide as the list it introduces.
   Capped at 72ch it stopped around the division-and-record column of the first
   team, so the paragraph read as a column of its own rather than as the top of
   the table. The section is already inside .wrap, which is the measure every
   other block of prose on this page is set to. */
.pr-lede { margin: 0 0 20px; color: #cfd6c2; }

.pr-list { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }

/* 2026-10-05: earlier editions, kept where somebody can find them.
   An edition is never revised once it is buried, so this is not a changelog --
   it is what the staff thought that Monday, with the record each team carried
   then. Shut by default, because the current week is still the page. */
.pr-archive { margin-top: 34px; border-top: 1px solid var(--edge); padding-top: 22px; }
.pr-archive > h3 { margin: 0 0 4px; font: 600 1.05rem/1.3 var(--body); }
.pr-archive > p { margin: 0 0 16px; color: var(--muted); font-size: 0.85rem; }
.pr-edition { border: 1px solid var(--edge); border-radius: 4px; margin-bottom: 8px; }
.pr-edition > summary {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 11px 14px;
  cursor: pointer;
  list-style: none;
}
.pr-edition > summary::-webkit-details-marker { display: none; }
.pr-edition > summary::before { content: '▸'; color: var(--muted); font-size: 0.8rem; }
.pr-edition[open] > summary::before { content: '▾'; }
.pr-edition[open] > summary { border-bottom: 1px solid var(--edge); }
.pr-edition-week { font-weight: 600; }
.pr-edition-date { color: var(--muted); font-size: 0.8rem; }
.pr-edition .pr-lede,
.pr-edition .pr-list { margin: 14px; }
.pr-edition .pr-lede { margin-bottom: 12px; font-size: 0.9rem; }

.pr-team {
  border: 1px solid var(--edge);
  border-left: 3px solid var(--moss);
  background: var(--surface);
}

.pr-team[open] { background: var(--raised); }

.pr-team summary {
  position: relative;
  display: grid;
  grid-template-columns: 2.6rem minmax(0, 1fr) auto;
  grid-template-areas:
    "rank name meta"
    "move head head";
  align-items: center;
  column-gap: 14px;
  row-gap: 4px;
  padding: 13px 44px 13px 14px;
  cursor: pointer;
  list-style: none;
}

.pr-team summary::-webkit-details-marker { display: none; }
.pr-team summary:hover { background: var(--raised); }
.pr-team summary:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* The one hint that there is more: a plus that turns to a minus. */
.pr-team summary::after {
  content: "+";
  position: absolute;
  top: 50%;
  right: 16px;
  transform: translateY(-50%);
  color: var(--muted);
  font-size: 1.3rem;
  line-height: 1;
}

.pr-team[open] summary::after { content: "\2212"; }

.pr-rank {
  grid-area: rank;
  font-family: var(--display);
  font-size: 1.6rem;
  line-height: 1;
  color: var(--gold);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.pr-move {
  grid-area: move;
  justify-self: center;
  font-family: var(--mono);
  font-size: 0.75rem;
}

.pr-move.up { color: var(--moss-bright); }
.pr-move.down { color: #ff9b7d; }
.pr-move.same, .pr-move.new { color: var(--muted); }

.pr-name {
  grid-area: name;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  font-family: var(--display);
  font-size: 1.08rem;
  color: var(--parchment);
}

.pr-name img { width: 32px; height: 32px; flex: none; }

.pr-meta {
  grid-area: meta;
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--muted);
  white-space: nowrap;
}

.pr-head { grid-area: head; color: #d8e0cb; font-size: 0.95rem; line-height: 1.4; }

.pr-body {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 28px;
  padding: 4px 20px 18px calc(2.6rem + 28px);
}

.pr-part h4 {
  margin: 0 0 4px;
  font-family: var(--body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold);
}

.pr-part p { margin: 0; color: #cfd6c2; font-size: 0.95rem; line-height: 1.5; }

/* On a phone the verdict takes the full width under the name, the record
   moves under it, and the four parts stack. */
@media (max-width: 620px) {
  .pr-team summary {
    grid-template-columns: 2.2rem minmax(0, 1fr);
    grid-template-areas:
      "rank name"
      "move meta"
      ". head";
    padding-right: 38px;
  }
  .pr-rank { font-size: 1.35rem; }
  .pr-meta { white-space: normal; }
  .pr-body { grid-template-columns: minmax(0, 1fr); padding: 4px 16px 16px; }
}

/* A shared link lands under the bar, not behind it. The bar is one row on a
   desktop and three on a phone, so the page measures it (see the script)
   rather than guessing; 50px is the one-row bar, for a browser that cannot. */
:target, section[id], header[id], details[id] {
  scroll-margin-top: calc(var(--nav-height, 50px) + 12px);
}


/* -------------------------------------------- the stats page, 31st pass --

   Randometrics has every Z1R race since 2013 and the site had no way in but
   the address bar. The section is the pitch and the shortcut in one: what is
   over there on the left, and a lookup on the right that goes straight to a
   racer or a head-to-head.

   The form posts to /stats itself -- the same GET the stats page's own search
   makes -- so there is no script here, and the stats site is free to move its
   pages without this one knowing. */

.stats-promo {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: 22px;
  align-items: start;
}

.stats-lead p {
  margin: 0 0 18px;
  max-width: 54ch;
  color: #cfd6c2;
}

.stats-actions { display: flex; flex-wrap: wrap; gap: 10px; }

.stats-lookup {
  display: grid;
  gap: 12px;
  padding: 20px;
  border: 1px solid var(--edge);
  border-left: 3px solid var(--gold);
  background: var(--surface);
}

.stats-lookup h3 {
  margin: 0;
  font-family: var(--display);
  font-size: 1.05rem;
  color: var(--parchment);
}

.stats-lookup .field {
  display: grid;
  gap: 5px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

/* "optional" belongs beside the label, not under it. */
.stats-lookup .field .what { display: block; }
.stats-lookup .hint { text-transform: none; letter-spacing: 0.02em; font-weight: 400; }

.stats-lookup input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--edge);
  border-radius: 2px;
  background: #0d110a;
  color: var(--parchment);
  font: inherit;
  font-size: 0.95rem;
}

/* A suggestion of what the box is for, never mistakable for a value already
   in it: gray, and dimmer than the muted text around it. */
.stats-lookup input::placeholder { color: #66705c; opacity: 1; }
.stats-lookup input:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; border-color: var(--moss); }

.stats-lookup button { justify-self: start; cursor: pointer; }
.stats-lookup .foot-note { margin: 0; }

@media (max-width: 760px) {
  .stats-promo { grid-template-columns: minmax(0, 1fr); }
  .stats-actions .btn { flex: 1 1 auto; justify-content: center; }
}


/* ------------------------------------------ the bar on a phone, 32nd pass --

   Two names carry the bar over three rows on a phone -- Triforce Triple Play
   and Torneo Corto are longer than the four other links together -- and the
   community writes them TTP and TC anyway. Below 620px the short forms show
   instead, and the full names stay in the markup, unseen but still read out,
   so the bar says the same thing to a screen reader at every width. */

.topnav-links .short { display: none; }

@media (max-width: 620px) {
  .topnav-links .full {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .topnav-links .short { display: inline; }
}


/* Card appearance comes from Randometrics; this page owns only placement. */
.racer-card { position: fixed; z-index: 60; }

/* ---------------------------------------------------------------- 34th pass
   24 Sept 2026 -- the schedule, subscribable.

   The Schedule section answers "what is on this week" for anyone looking at
   the site. This line answers it for everyone who does not look, because the
   race is already in the calendar they check anyway. It sits under the
   volunteer appeal rather than in the heading: subscribing is done once, and
   it should not compete with the fixtures for attention.
-------------------------------------------------------------------------- */
.sub-note.subscribe {
  margin-top: -4px;
}

/* The Subscribe link moved out of here and into the section head; its rules
   went with it, unscoped, in the 37th pass. Nothing renders .sub-note
   .subscribe any more. */

/* ---------------------------------------------------- 36th pass, 27 Sept

   The Autumn Tournament: a promotion on the home page and a page of its own.

   Sixty-four racers double eliminated is 126 matches. Drawn the way a
   bracket is usually drawn -- left to right, a column per round -- that is
   about four thousand pixels wide, and this stylesheet has a standing rule
   against making a reader drag a panel sideways. So the rounds are stacked
   sections instead: winners down one column, losers down the other, and on a
   phone one after the other. It loses the lines joining a match to the next
   one, which a bracket of this size could not have drawn legibly anyway. */

.autumn-promo {
  border: 1px solid var(--edge);
  background: var(--surface);
  padding: 18px 20px;
  display: grid;
  gap: 10px;
}

.autumn-lede { margin: 0; font-size: 1.02rem; }
.autumn-when { margin: 0; color: var(--muted); font-size: 0.9rem; }
.autumn-calls { margin: 4px 0 0; display: flex; flex-wrap: wrap; gap: 10px; }

.tourney-hero { padding-bottom: 8px; }
.tourney-hero h1 { margin: 0 0 8px; }
.tourney-hero .lede { margin: 0 0 16px; max-width: 62ch; font-size: 1.05rem; }

/* Facts as a description list rather than prose: a reader wanting the flags
   is scanning for them, not reading a paragraph to find them. */
.tourney-facts {
  margin: 0 0 18px;
  display: grid;
  gap: 8px 22px;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}

/* Each fact is a two-row grid inside a stretched grid cell, and an auto row
   in a stretched grid takes the spare height -- so a short value like Flags
   sat pushed down the cell while a three-line one like Seeding did not, and
   the column read as though it were misaligned. align-content keeps both rows
   at the top whatever the tallest fact in the row is doing. */
.tourney-facts > div { display: grid; gap: 2px; align-content: start; }
.tourney-facts dt { font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.tourney-facts dd { margin: 0; }

/* The tournament page's registration block used to live here, as a bare
   `.signup` with `.closes` and `.closed` inside it. The block went when
   registration closed; its styles did not, and because they sit later in the
   file than the schedule card's own `.signup` they kept winning -- handing that
   button `display: flex` and twelve pixels of bottom margin it never asked for.
   Most of the restream footer's height was this. Nothing emits `.closes` or
   `.signup.closed` any more, so the rules are gone rather than scoped. */
.tourney-links { margin: 0; color: var(--muted); font-size: 0.9rem; }

.tourney-section { margin-bottom: 30px; }
.tourney-section > h2 { margin: 0 0 6px; }
.tourney-section .sub { margin: 0 0 14px; color: var(--muted); font-size: 0.92rem; }

/* The bracket is a preview until the wheel is drawn, and a reader who thinks
   these are the pairings has been misled by us rather than by the page. */
.notice {
  margin: 0 0 16px;
  padding: 10px 14px;
  border: 1px solid var(--edge);
  border-left: 3px solid var(--gold);
  background: var(--raised);
  color: var(--parchment);
  font-size: 0.92rem;
}

/* ------------------------------------------------- the bracket, as a tree

   Rounds are columns with equal-height groups and equal-height match slots.
   Center each card in its slot, even when a scheduled time, series score or
   bye makes neighboring cards different heights. Flex space-around only
   aligns equal-height cards; grid tracks keep the connector centers fixed.

   Where a round does not halve -- the losers bracket's drop rounds, which
   take a racer falling out of the winners bracket -- matches are grouped one
   at a time and the connector runs straight across rather than joining a
   pair.

   Sixty-four racers is wider than any screen, so the bracket scrolls inside
   its own box. The page does not: the rule against making a reader drag the
   page sideways still holds, and this is the difference between a panel that
   scrolls on purpose and a page that overflows by accident. */

.scroll-note { margin: 0 0 14px; color: var(--muted); font-size: 0.86rem; }

.tree-side { margin-bottom: 26px; }
.tree-side .side-head { margin: 0 0 8px; font-size: 1.05rem; }
.tree-side .sub { margin: 10px 0 0; }

.tree-scroll {
  overflow-x: auto;
  overflow-y: hidden;
  padding: 4px 4px 12px;
  border: 1px solid var(--edge);
  background: var(--surface);
  /* A visible edge while it is scrollable, so the affordance is not a secret. */
  scrollbar-color: var(--moss) var(--raised);
}

.tree-scroll:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.tree { display: flex; gap: 36px; align-items: stretch; padding: 8px 10px; width: max-content; }

.col { display: flex; flex-direction: column; flex: 0 0 auto; width: 176px; }

.col-head {
  margin: 0 0 8px;
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  display: flex;
  justify-content: space-between;
  gap: 8px;
  white-space: nowrap;
}
.col-head .count { font-family: var(--mono); }

.col-body { flex: 1; display: grid; grid-auto-rows: 1fr; }

.grp { display: grid; grid-auto-rows: 1fr; align-items: center; position: relative; }

.tree .match {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  border: 1px solid var(--edge);
  background: var(--raised);
  padding: 4px 8px 4px 22px;
}

/* The match number sits in the gutter, the way a bracket prints it, because
   every other slot on the page refers to matches by that number. */
.tree .match .no {
  position: absolute;
  left: 4px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.62rem;
}

/* Added 2026-10-01. The number is also the matchup's handle, where there is a
   head-to-head to show: gold says a card is behind it, and the gutter is the one
   place on a bracket where a hover target is in nobody's way. The padding is
   there because 0.62rem of digits is a smaller thing than a pointer can be
   expected to find -- it grows the hit area without moving the glyph, which the
   translate keeps centered.

   No `cursor: help`. It was here for a day and it was the same mistake the 39th
   pass had already fixed on the names: a question mark is the wrong promise for
   somebody's results, and it is a cursor nothing else on this site uses. The
   gold and the tint on hover are the affordance. */
.tree .match .no[data-matchup] {
  color: var(--gold);
  padding: 3px 4px;
  margin: -3px -4px;
  border-radius: 3px;
}

.tree .match .no[data-matchup]:hover,
.tree .match .no[data-matchup]:focus-visible {
  background: rgba(214, 177, 92, 0.18);
  outline: none;
}

.tree .match .row {
  display: block;
  font-size: 0.78rem;
  line-height: 1.5;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tree .match .row + .row { border-top: 1px solid var(--edge); }

.tree .match .row.named { color: var(--parchment); font-weight: 600; }
.tree .match .row.seed { color: var(--gold); font-family: var(--mono); font-size: 0.72rem; }
.tree .match .row.winner,
.tree .match .row.loser { color: var(--muted); font-size: 0.72rem; }
.tree .match .row.loser { font-style: italic; }
.tree .match .row.empty { color: var(--muted); opacity: 0.5; }
.tree .match .row.bye-note {
  color: var(--moss-bright);
  font-size: 0.64rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.tree .match.if-needed { border-style: dashed; }

/* --- the connectors ---------------------------------------------------- */

/* Out of every match, towards the next column. */
.col:not(:last-child) .match::after {
  content: '';
  position: absolute;
  right: -18px;
  top: 50%;
  width: 18px;
  border-top: 1px solid var(--edge-bright, #3a4433);
}

/* Down the pair, joining the two stubs. Equal slots with a 10px gap and
   5px outer padding center the cards at a quarter and three quarters. */
.col:not(:last-child) .grp.pair::before {
  content: '';
  position: absolute;
  right: -18px;
  top: 25%;
  height: 50%;
  border-right: 1px solid var(--edge-bright, #3a4433);
}

/* And on from the middle of that join into the next column's match. */
.col:not(:last-child) .grp::after {
  content: '';
  position: absolute;
  right: -36px;
  top: 50%;
  width: 18px;
  border-top: 1px solid var(--edge-bright, #3a4433);
}

@media (max-width: 560px) {
  .col { width: 150px; }
  .tree { gap: 28px; }
  .col:not(:last-child) .match::after,
  .col:not(:last-child) .grp.pair::before { right: -14px; }
  .col:not(:last-child) .match::after { width: 14px; }
  .col:not(:last-child) .grp::after { right: -28px; width: 14px; }
  .tree .match .row { font-size: 0.72rem; }
  /* Three digits have to fit the gutter: the bracket runs to 126 matches. */
  .tree .match .no { font-size: 0.56rem; left: 3px; }
}

.tourney-foot { padding: 10px 0 34px; color: var(--muted); font-size: 0.9rem; }
.tourney-foot a { color: var(--gold); text-decoration: none; }
.tourney-foot a:hover { text-decoration: underline; }

@media (max-width: 560px) {
  /* Two rules stood here, sizing `.match` for the list the bracket was drawn
     as before it was drawn as a tree. Nothing renders that markup now -- but
     `.match` is also a League Scoreboard card, so on a phone they were giving
     every card three columns and its own padding, and the card's rows flowed
     across each other instead of stacking. The tree sets its own columns and
     is unaffected either way, which is why this survived being looked at.

     The match number used to be hidden here too, on the reasoning that a
     phone wants names rather than numbers. That was wrong: every slot in the
     draw reads "Winner of 48", so the number is the only way to find the
     match it points at. It stays, one size smaller and tight to the edge,
     in the tree's own block above. */
  .tourney-facts { gap: 8px 0; }
}

/* --------------------------------------------- the League's page, 29 Sept ---
   Standings, the power rankings and the scoreboard were three of the nine
   things in the masthead while the League itself was none of them. They are one
   page now, and it takes the tournament page's shape so the two read as
   siblings: the competition's own mark, a line about it, and then the content.

   Getting between the three is this row rather than a hover menu in the
   masthead. A hover menu needs a mouse, so it does nothing on a phone, and it
   would have offered three anchors into one page -- which is what this is, and
   it stays visible while you read. */

.page-hero { padding-bottom: 10px; }

.page-hero .lede { margin: 10px 0 16px; max-width: 52ch; }

.page-subnav { display: flex; flex-wrap: wrap; gap: 8px; }

.page-subnav a {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--parchment);
  text-decoration: none;
  padding: 7px 13px;
  border: 1px solid rgba(207, 214, 194, 0.28);
  border-radius: 999px;
}

.page-subnav a:hover,
.page-subnav a:focus-visible { border-color: var(--gold); color: var(--gold); }

/* The tournament and League pages wear the home page masthead, so the mark
   sits beside the name at the same size rather than above it at a larger one. */
.page-hero .masthead { margin-bottom: 14px; }

/* ---------------------------------------------------- 37th pass, 29 Sept

   The Subscribe link, wherever it is.

   These rules were written when the link lived in a .sub-note under the
   Schedule heading, and were scoped to it. Moving the link up into the
   .section-head beside the heading left the scope behind, and an <svg> that
   carries a viewBox and no width or height is not a small icon without CSS --
   it is 300x150, the replaced-element default. So the icon did not go
   missing, it went enormous and dark, and the paragraph holding it became
   150px tall. .section-head aligns on the baseline, which is why "Schedule"
   then sat up at the top of a box nothing else was filling.

   Scoped to the class rather than to a place this time, so the next move
   does not cost the icon again.
-------------------------------------------------------------------------- */
.cal-link { font-weight: 600; }

/* A calendar drawn in the page's own gold. The emoji version of this is the
   only full-color thing on the page, which is how you notice it is borrowed
   from somewhere else. */
.cal-icon {
  width: 0.95em;
  height: 0.95em;
  margin-right: 5px;
  vertical-align: -1px;
  fill: currentColor;
  flex: none;
}

/* ---------------------------------------------------- 38th pass, 29 Sept

   A racer's ranking, beside their name on the bracket.

   The draw is random, so a pairing on its own says nothing about whether it
   is a formality or the match of the round. The ranking is what answers that,
   and it has to sit close enough to read as one thing while staying quiet
   enough that the name is still the name.

   Tabular figures because a column of them should line up, and no-wrap
   because "(46)" breaking across two lines in a narrow slot reads as a
   different racer.
-------------------------------------------------------------------------- */
.rank {
  margin-left: 6px;
  color: var(--muted);
  font-size: 0.82em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* On the drawn tree the slots are tight, so it gets quieter still rather than
   wider: a name that no longer fits is worse than a ranking that is faint. */
.tree .row .rank { margin-left: 4px; font-size: 0.78em; }

/* In a Schedule card the name and its ranking are one flex item, so the row's
   9px gap separates the portrait from the person and the ranking keeps the
   closer spacing of its own margin. `min-width` lets a long name wrap inside
   the cell instead of pushing the ranking out of it. */
.bout .who .named { min-width: 0; }
/* ---------------------------------------------------- 39th pass, 30 Sept

   A name on the bracket is hoverable.

   The cards were already on this page; nothing on it was something they
   could attach to. The hook sits on the name rather than the cell, so the
   card comes from the racer and not from the empty half of a box with a
   short name in it.

   No cursor change. It was `help`, which draws a question mark -- the
   wrong promise for a card of somebody’s results, and a cursor nothing
   else on the site uses. The faint underline is affordance enough, and it
   is on the thing that answers.
-------------------------------------------------------------------------- */
.tree .racer,
.matches .racer { text-decoration: underline dotted transparent; text-underline-offset: 3px; }

.tree .racer:hover,
.tree .racer:focus-visible,
.matches .racer:hover,
.matches .racer:focus-visible { text-decoration-color: var(--edge); }

/* A bye that has dropped into the losers bracket. It is a real slot with a
   real name in it -- BYE 1 lost match 21 and came down here -- but it is not
   a racer, so it reads quieter than one and carries no ranking and no card. */
.bye-slot { color: var(--muted); font-style: italic; }

/* ---------------------------------------------------------------- 2026-10-01
   The tournament in the schedule, Torneo Corto's qualifying night, and the way
   through to a head-to-head.

   The tournament's slots borrow the Corto bout layout: two names and a "vs." is
   the same shape whoever is racing, and a second set of rules for it would drift
   from the first. What it adds is a round label in the time line, because
   "Winners round 1" is the thing that says where in 127 matches this one sits.

   Revised 1 Oct: a racer a line. This was a wrapping flex row, which on a card
   a third of the page wide meant two names, a "vs." and a ranking each all
   looking for room on one line -- and when they ran out, every piece took a
   line of its own: "1ganondwarf(58) / vs. / AceKingSpade(55) / Matchup". Four
   ragged lines to say two names. Stacked, a long name costs its own line and
   nothing else moves.

   A single column, so the mirroring goes with it: both racers now read
   portrait, name, ranking, left to right, the way a list does.

   This rule is the one in effect. It sits after the generic `.bout` grid and
   matches with the same weight, so anything about the tournament bout has to be
   said here or it is said and ignored -- which is what happened to the first
   attempt at this layout. */

.slot.tourney .bout.stacked {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  gap: 5px;
}

.slot.tourney .bout .who {
  font-weight: 600;
  font-size: 0.95rem;
}

/* Punctuation between the two of them, so it keeps the first name's line rather
   than taking one of its own. */
.slot.tourney .bout .v { margin-left: 2px; text-align: left; }

/* The link lines up over the Sign Up button, in the column the card already
   uses for the thing to click. */
.slot .matchup-row { margin: 2px 0 0; text-align: right; }

/* What the room said: a finishing time, or that there was not one. It sits
   after the name in the same tabular figures the rest of the site clocks with,
   quiet enough that the pairing is still the first thing read. A DNF is the
   muted red the schedule uses for an open restream slot rather than an alarm --
   it is an ordinary outcome of a race, not a fault. */
.result-time {
  margin-left: auto;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.result-time.dnf { color: #e0a08c; letter-spacing: 0.06em; }

/* The time goes last so the two of them line up in a column. `margin-left: auto`
   pushes it to the card's edge, and with the winner's badge between the name and
   the time, the badge takes its space out of the middle rather than out from
   under the time -- which is what left a time and a DNF at different x. */
.result-card .who .result-winner + .result-time { margin-left: 10px; }

/* A link whose whole content is an icon, so it needs a target of its own rather
   than inheriting the text's line height. */
.matchup-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.3em;
  padding: 0.1em 0.45em 0.1em 0.3em;
  margin-left: 0.15rem;
  border-radius: 999px;
  color: var(--muted);
  font-size: 0.78rem;
  text-decoration: none;
  flex: 0 0 auto;
  transition: color 120ms ease, background-color 120ms ease;
}

/* Bolt then word. No longer a round button: it is a labelled link now, so it
   sits on the line like one instead of floating in a circle of its own. */
.matchup-link .mark {
  width: 0.95em;
  height: 0.95em;
  display: block;
  flex: 0 0 auto;
}

.matchup-link:hover,
.matchup-link:focus-visible {
  color: var(--moss-bright);
  background: var(--raised);
}

/* Qualifying is three times and a reason, with no bout: nobody is drawn against
   anybody yet, which is the point of qualifying. */
.slot.ttp.qualifier {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.qualifier-note {
  color: var(--muted);
  font-size: 0.9rem;
}

/* A box that has an agreed time says so on a third line. Only six of a hundred
   and twenty-seven do, so the bracket's height is unchanged almost everywhere;
   where it is not, a start time is worth the row. */
.tree .match .row.when {
  grid-column: 1 / -1;
  color: var(--moss-bright);
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  text-align: right;
  padding-top: 0.1rem;
}

/* ---------------------------------------------------------------- 2026-10-01
   Races grouped by the day they fall on.

   A flat list repeats the date on every line and still reads as one run. A
   heading per day turns it into "what is on tonight" and then "and then", which
   is the question being asked. The front page shows three days of it and links
   to the tournament page for the rest. */

/* `.schedule` is an auto-fit grid, so each day becomes a column and its races
   stack inside it -- days across, races down, and on a narrow screen the whole
   thing collapses to one column and the days stack instead. Separate day rows
   more than the cards inside a day, so each heading belongs to what follows it.
   Column spacing stays unchanged when days can sit side by side. */
.schedule:has(> .day-group) { row-gap: 2rem; }

.day-group {
  display: grid;
  gap: 12px;
  align-content: start;
}

.day-head {
  font-family: var(--display);
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

.more-races {
  margin: 0.9rem 0 0;
  font-size: 0.95rem;
}

.more-races a {
  color: var(--moss-bright);
}

/* The whole schedule, on the tournament page. A list rather than cards: it is
   twenty rows read top to bottom, not six things to choose between. */
.sched-day + .sched-day {
  margin-top: 1.25rem;
}

.sched-head {
  font-family: var(--display);
  font-size: 1rem;
  color: var(--parchment);
  margin: 0 0 0.45rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--edge);
}

.sched-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}

.sched-list li {
  display: grid;
  grid-template-columns: 7.5rem 1fr auto;
  gap: 0.75rem;
  align-items: baseline;
  /* No height of its own. The list already separates its items by 0.35rem, and
     a further 0.35rem above and below each one tripled the space between two
     races for the sake of a tint on one of them. The sides keep their room --
     the channel mark needs somewhere to sit -- and are given back as margin,
     so every line starts where it always did. */
  padding-block: 0;
  padding-inline: 0.6rem;
  margin-inline: -0.6rem;
  border-radius: 4px;
}

/* A scheduled broadcast uses the same moss wash as the Council schedule. */
.sched-list li[data-channel="true"] {
  background: rgba(79, 143, 44, 0.08);
  box-shadow: inset 2px 0 var(--moss);
}

.sched-time {
  color: var(--moss-bright);
  font-variant-numeric: tabular-nums;
}

.sched-who .v {
  color: var(--muted);
  padding: 0 0.2rem;
}

.sched-round {
  color: var(--muted);
  font-size: 0.85rem;
  text-align: right;
}

/* The bolt rides the end of the round line rather than sitting on its own, so
   the hover is where the eye already is when it finishes reading the match. */
.sched-round .matchup-link { margin-left: 0.35rem; vertical-align: baseline; }

/* The channel rides the same line as the matchup link and is built the same
   way, so the only thing telling them apart is where they go: Twitch's purple
   on hover against the house moss. */
.matchup-link.race-channel .icon { width: 0.95em; height: 0.95em; display: block; flex: 0 0 auto; }
.crew .known.broadcast, .crew .broadcast .race-channel { color: #b98bff; }
.crew .broadcast .race-channel { font: inherit; padding: 0; vertical-align: middle; }
.matchup-link.race-channel:hover,
.matchup-link.race-channel:focus-visible { color: #b98bff; background: var(--raised); }

/* On its own, with no word beside it, the mark has to say Twitch by itself --
   so it wears the colour rather than waiting for a cursor that a phone does
   not have. */
.matchup-link.race-channel-mark { color: #9146ff; padding: 0.1em 0.25em; margin-left: 0.25rem; }
.matchup-link.race-channel-mark:hover,
.matchup-link.race-channel-mark:focus-visible { color: #c9a9ff; }

@media (max-width: 34rem) {
  /* Three columns do not fit a phone. The round is the one that can wrap under
     the pairing without the row losing its sense. */
  .sched-list li {
    grid-template-columns: 6.5rem 1fr;
  }

  .sched-round {
    grid-column: 2;
    text-align: left;
  }
}

/* Recorded outcomes and best-of scores come from the engine snapshot. */
.tree .match .row.named.winner { font-weight: 750; font-size: .78rem; color: var(--gold); }
.tree .match .row.series-score { font-size: .72rem; opacity: .85; padding-top: .2rem; }
/* Results use the Schedule's racer cards, grouped into native disclosures so a
   full tournament stays browsable without JavaScript or an endless flat list. */
.result-rounds { display: grid; gap: 12px; }
.result-round { border: 1px solid var(--edge); background: var(--surface); }
.result-round > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  cursor: pointer;
  list-style: none;
  font-weight: 600;
}
.result-round > summary::-webkit-details-marker { display: none; }
.result-round > summary::before { content: '+'; color: var(--gold); width: 1em; flex: none; }
.result-round[open] > summary::before { content: '−'; }
.result-round > summary:hover { background: var(--raised); }
.result-round > summary:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.result-count { margin-left: auto; color: var(--muted); font-size: .8rem; font-weight: 400; white-space: nowrap; }
.result-grid {
  list-style: none;
  margin: 0;
  padding: 0 14px 14px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(290px, 100%), 1fr));
  gap: 12px;
}
.slot.tourney.result-card { min-width: 0; grid-template-columns: minmax(0, 1fr); border-left-color: var(--gold); gap: 12px; }
.result-meta { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 6px; color: var(--muted); font-size: .78rem; }
.result-meta > :first-child { color: var(--parchment); font-weight: 600; }
.result-card .bout.stacked { gap: 9px; }
.result-card .who .named { flex: 1; }
.result-card .who.winner .named { color: var(--gold); }
.result-card .who.winner .racer-link { color: inherit; }
.result-winner { flex: none; color: var(--gold); font-size: .64rem; font-weight: 700; letter-spacing: .035em; text-transform: uppercase; }
.result-card .series-score { color: var(--muted); font-size: .82rem; }
.result-links { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; padding-top: 8px; border-top: 1px solid var(--edge); font-size: .78rem; }
.result-links > .matchup-link { margin-left: auto; }

.tree .grp { gap: 10px; padding-block: 5px; }

/* Community guides and Council workspace, 2 October 2026. */
.guide-hero .wrap { position: relative; }
.guide-hero .lede { max-width: 65ch; }
.guide-eyebrow { margin: 0 0 8px; color: var(--gold); font-size: .72rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; }
.guide-small { color: var(--muted); font-size: .87rem; }
.guide-main { padding-block: 30px 42px; }
.guide-directory { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
@media (max-width: 1100px) { .guide-directory { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* The booth category has one card (its detail lives on /booth-guide/), so it takes the full row. */
.guide-card-grid.guide-card-grid--one { grid-template-columns: 1fr; }
.guide-directory-item { display: flex; align-items: flex-start; gap: 14px; padding: 20px; border: 1px solid var(--edge); background: var(--surface); }
.guide-directory-item img { width: 56px; height: 56px; object-fit: contain; flex: none; }
.guide-directory-item h2 { margin: 0; font: 600 1rem/1.35 var(--body); }
.guide-directory-item p { margin: 6px 0 13px; color: var(--muted); font-size: .75rem; }
.guide-role-links { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.guide-main a { color: var(--gold); text-underline-offset: 4px; }
.guide-main a:hover { color: var(--parchment); }
.guide-main a:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
.guide-role-links a { font-size: .85rem; text-decoration: none; }
.guide-basics { margin: 22px 0 42px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; padding: 20px 0; border-block: 1px solid var(--edge); }
.guide-basics strong { font-size: .9rem; }
.guide-basics p { margin: 6px 0 0; color: var(--muted); font-size: .85rem; }
.guide-event { margin: 0 0 44px; padding: 0; border: 0; }
.guide-event-heading { display: flex; align-items: center; justify-content: space-between; gap: 18px; margin-bottom: 18px; }
.guide-event-heading h2 { margin: 0; font: 700 clamp(1.35rem, 3vw, 1.8rem)/1.2 var(--display); }
.guide-event-heading > a { flex: none; font-size: .85rem; }
.guide-card-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; align-items: start; }
.twitch-management-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.twitch-management-head p { margin: 0; flex: 1; }
.twitch-management-head[data-environment="staging"] { padding: 14px 16px; border: 1px solid var(--gold); border-left-width: 4px; background: color-mix(in srgb, var(--gold) 12%, var(--surface)); }
.twitch-management-head[data-environment="staging"] .crew-environment { font-size: .85rem; font-weight: 800; }
.twitch-management-head[data-environment="staging"] p { font-size: .95rem; font-weight: 600; color: var(--parchment); }
.twitch-management-layout { display: grid; grid-template-columns: minmax(190px, 240px) minmax(0, 1fr); gap: 18px; align-items: start; }
.twitch-management-channels { display: grid; gap: 7px; }
.twitch-management-editor { --card-pad: 18px; }
.twitch-management-editor .crew-field { margin-bottom: 12px; }
.twitch-management-editor .crew-field input { background: var(--ink); border-color: var(--edge); color: var(--parchment); padding: 9px 10px; }
.twitch-management-editor .guide-event-heading { align-items: center; flex-wrap: wrap; gap: 10px; }
.twitch-management-editor h2 { margin: 0; }
.twitch-management-editor .crew-actions { flex-wrap: wrap; align-items: center; }
.twitch-management-layout button:disabled { opacity: .55; cursor: default; }
@media(max-width: 650px) {
 .twitch-management-head { display: grid; grid-template-columns: auto 1fr; }
 .twitch-management-head p { grid-column: 1/-1; grid-row: 2; }
 .twitch-management-head>button { justify-self: end; }
 .twitch-management-layout { grid-template-columns: 1fr; }
 .twitch-management-channels { grid-template-columns: repeat(2, minmax(0, 1fr)); }
 .twitch-management-channels .crew-person { padding: 10px; }
}
.guide-card { --card-pad: clamp(18px, 3vw, 28px); min-width: 0; background: var(--surface); border: 1px solid var(--edge); border-top: 3px solid var(--moss); padding: var(--card-pad); font-size: .94rem; }
.guide-card-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.guide-card h3 { margin: 0 0 15px; font: 600 1.3rem/1.3 var(--body); scroll-margin-top: 140px; }
.guide-card .guide-eyebrow { font-size: .65rem; }
.guide-share { flex: none; font-size: .72rem; border: 1px solid var(--edge); border-radius: 3px; padding: 5px 9px; text-decoration: none; }
.guide-where { margin: 0 0 22px; padding-bottom: 15px; border-bottom: 1px solid var(--edge); font-size: .83rem; overflow-wrap: anywhere; }
.guide-where span { display: block; color: var(--muted); font-size: .68rem; text-transform: uppercase; letter-spacing: .08em; margin-bottom: 4px; }
.guide-steps { margin: 0; padding-left: 23px; }
.guide-steps li { margin: 0 0 18px; padding-left: 4px; }
.guide-steps li::marker { color: var(--moss-bright); font-weight: 700; }
.guide-main code { font: .84em/1.6 var(--mono); color: #d8ecc9; overflow-wrap: anywhere; }
.guide-command { margin: 10px 0; padding: 12px 14px; background: var(--ink); border: 1px solid var(--edge); border-left: 2px solid var(--moss-bright); }
.guide-note { border-left: 2px solid var(--gold); background: rgba(217,164,65,.055); padding: 12px 15px; margin: 20px 0; font-size: .87rem; }
.guide-commands { margin: 20px 0; }
.guide-commands dt { margin-top: 18px; }
.guide-commands dd { margin: 5px 0 0; color: #c4cdb9; font-size: .9rem; }
.guide-help { max-width: 72ch; padding: 0 0 15px; }
.guide-help h2 { font: 600 1.2rem var(--body); }
.guide-help p { color: var(--muted); font-size: .94rem; }
.guide-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.guide-main h2[id], .guide-event { scroll-margin-top: 140px; }
.guide-card:has(h3:target) { border-color: var(--gold); }
@media (max-width: 950px) { .guide-directory-item { flex-direction: column; } }
@media (max-width: 760px) {
  .guide-card-grid, .guide-basics { grid-template-columns: 1fr; }
  .guide-directory { grid-template-columns: 1fr; gap: 10px; }
  .guide-directory-item { flex-direction: row; padding: 15px; }
  .guide-role-links { flex-direction: row; flex-wrap: wrap; gap: 10px 18px; }
  .guide-basics { gap: 18px; margin-bottom: 30px; }
  .guide-event-heading { align-items: flex-start; flex-direction: column; gap: 8px; }
  .guide-card h3, .guide-main h2[id], .guide-event { scroll-margin-top: 165px; }
}
.council-toolbar { display: flex; justify-content: space-between; align-items: center; gap: 20px; margin-bottom: 15px; }
.council-toolbar form { margin: 0; }
.council-toolbar button { color: var(--parchment); background: var(--surface); cursor: pointer; }
.guide-hero .page-subnav { margin-top: 24px; }
.page-subnav [aria-current="page"] { border-color: var(--gold); color: var(--gold); }
.council-event { margin-top: 35px; }
.council-event header img { object-fit: contain; }
.council-source { margin: 0 0 18px; color: var(--muted); font-size: .82rem; }
.council-warning { color: var(--gold); }
.council-volunteer { display: block; font-weight: 600; }
.council-metrics { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 18px; padding-bottom: 22px; border-bottom: 1px solid var(--edge); margin-bottom: 18px; }
.council-metrics strong { display: block; color: var(--moss-bright); font: 600 2rem/1.2 var(--body); }
.council-metrics span { display: block; color: var(--muted); font-size: .8rem; margin-top: 7px; }
.council-links { display: flex; flex-wrap: wrap; gap: 8px 22px; margin: 18px 0; font-size: .85rem; }
.council-table-wrap { overflow-x: auto; }
/* The schedule is a grid sized to its container, so it never needs the
   horizontal scroller the wide service table does -- and that scroller was the
   reason a row could not reach past the card's padding on a desktop. */
.council-schedule-wrap { overflow: visible; }
.council-table { width: 100%; border-collapse: collapse; font-size: .83rem; }
.council-table th { text-align: left; color: var(--muted); font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; }
.council-table th, .council-table td { padding: 13px 12px; border-bottom: 1px solid var(--edge); vertical-align: top; }
.council-table small { display: block; margin-top: 4px; color: var(--muted); }
.council-login { padding-block: 80px; max-width: 820px; }
.council-login img { margin-bottom: 25px; }
.council-login .btn { margin-top: 16px; }
@media(max-width:760px) { .council-metrics { gap: 10px; } .council-metrics strong { font-size: 1.6rem; } }
/* Council War Room — October 2026. */
/* War Room inherits the same .wrap width as its masthead and navigation. */
.warroom-topbar,.warroom-buttons,.warroom-log-controls { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.warroom-topbar { justify-content:space-between; color:var(--muted); font-size:.9rem; }
.warroom-tabs { margin:20px 0 32px; }
.warroom-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; }
.warroom .guide-card { margin-bottom:16px; min-width:0; }
.warroom h3 { margin-top:0; }
.warroom-stats { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:12px; }
.warroom-stats strong { display:block; margin-top:10px; font-size:1.02rem; }
.warroom-badge { display:inline-block; font-size:.75rem; font-weight:700; letter-spacing:.02em; padding:4px 9px; border-radius:20px; border:1px solid #64715e; color:#c9d0c4; background:#222c24; }
.warroom-badge.good { background:#203d2b; color:#b7e8b9; border-color:#467851; }
.warroom-badge.bad { background:#412a29; color:#ffc0ad; border-color:#955747; }
.warroom-badge.pending { background:#3c3420; color:#f5dda0; border-color:#756641; }
.warroom-warnings { padding-left:22px; margin:0; }
.warroom-warnings li { margin:8px 0; overflow-wrap:anywhere; }
.warroom input,.warroom select { font:inherit; color:#f4f0e6; background:#17231f; border:1px solid #5d6857; border-radius:6px; padding:9px 12px; max-width:100%; }
#service-filter { width:100%; margin:8px 0 18px; }
.warroom-table th,.warroom-table td { font-size:.84rem; padding:13px 10px; }
.warroom-table td:first-child { min-width:190px; }
.warroom-table small,.warroom-lanes small { display:block; color:var(--muted); font-size:.75rem; margin-top:5px; }
.warroom-lanes { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:18px; }
.warroom-lanes strong { display:block; margin-bottom:7px; }
.warroom-detail summary { cursor:pointer; font-weight:700; }
.warroom-action { border-top:1px solid #3b4739; padding:15px 0; margin-top:10px; overflow-wrap:anywhere; }
.warroom-action p { margin:6px 0; }
.warroom-action small { color:var(--muted); }
#log-output { background:#101813; color:#dbe6ce; padding:18px; border-radius:8px; font:12px/1.7 Consolas,monospace; white-space:pre-wrap; overflow-wrap:anywhere; max-height:480px; overflow:auto; }
.warroom-metrics { display:flex; gap:24px; flex-wrap:wrap; margin:22px 0; }
.warroom-metrics strong { font-size:1.8rem; display:block; color:#e9d493; }
.warroom-metrics span { font-size:.82rem; color:var(--muted); }
.warroom-channel { padding:14px 0; border-bottom:1px solid #354433; }
.warroom-channel p { margin:8px 0; }
.warroom button:disabled { opacity:.45; cursor:not-allowed; }
#control-dialog { max-width:500px; width:calc(100% - 40px); color:#eee8d8; background:#213127; border:1px solid #73805f; border-radius:12px; padding:28px; }
#control-dialog::backdrop { background:#000b; }
.warroom-notice:not(:empty) { position:sticky; bottom:16px; padding:18px; background:#273b2d; color:#fff1c6; border:1px solid #8d976b; border-radius:8px; box-shadow:0 8px 35px #0008; }
@media(max-width:800px) { .warroom-grid { grid-template-columns:1fr; } .warroom-stats { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media(prefers-reduced-motion:reduce) { html { scroll-behavior:auto; } }
.warroom .guide-share { appearance:none; font:inherit; font-size:.8rem; color:#ddd9bc; background:#253023; border:1px solid #667153; padding:8px 12px; cursor:pointer; }
.warroom .guide-share:hover:not(:disabled) { border-color:#b9ab68; color:#fff0bd; }

.warroom-metrics small { display:block; margin-top:4px; color:var(--muted); font-size:.74rem; }

.warroom-audience { grid-template-columns:2fr 1fr; align-items:start; }
#twitch { display:block; }
#twitch > p { grid-column:1/-1; }
#twitch .warroom-channel { min-width:0; }
@media(max-width:800px) { .warroom-audience { grid-template-columns:1fr; } }
@media(max-width:520px) { #twitch { grid-template-columns:1fr; } }

#ga4 .council-table { min-width:0; table-layout:fixed; }
#ga4 td:first-child { overflow-wrap:anywhere; width:75%; }

/* Council sheet controls: names remain readable links; actions use a focused dialog. */
.council-crew-link{display:block;border:0;background:none;padding:2px 0;color:inherit;font:inherit;font-weight:700;text-align:left;cursor:pointer;text-decoration:underline;text-decoration-color:transparent;text-underline-offset:3px}
.council-crew-link:hover,.council-crew-link:focus-visible{text-decoration-color:currentColor;color:var(--gold)}
.council-crew-link:disabled{opacity:.55;cursor:default}
.crew-dialog{box-sizing:border-box;width:min(600px,calc(100% - 28px));max-height:90vh;overflow:auto;padding:26px;border:1px solid #63543b;border-radius:14px;background:#171a21;color:#eee;box-shadow:0 24px 100px #0009}
.crew-dialog::backdrop{background:#05070bbb;backdrop-filter:blur(3px)}
.crew-dialog-head{display:flex;align-items:start;justify-content:space-between;gap:16px}.crew-dialog h2{font-size:1.6rem;margin:0}.crew-dialog .guide-eyebrow{margin-top:0}.crew-match{font-weight:600}.crew-match span{font-weight:400;color:#b9bcc4}
.crew-field{display:grid;gap:7px;margin:18px 0;font-weight:600}.crew-field select{width:100%;box-sizing:border-box;background:#242932;border:1px solid #5a606d;border-radius:6px;color:#fff;padding:11px;font:inherit}.crew-actions{display:flex;flex-wrap:wrap;gap:10px;margin:20px 0}.crew-dialog button{cursor:pointer}.crew-dialog button:disabled{opacity:.5;cursor:default}.crew-remove{color:#f6b7ab}.crew-conflicts{background:#25251f;border-radius:8px;padding:14px;font-size:.9rem}.crew-conflicts ul{padding-left:20px}.crew-conflicts li+li{margin-top:8px}.crew-confirm{display:flex;align-items:start;gap:9px;margin-top:15px}.crew-confirm[hidden],#crew-reassign[hidden]{display:none}#crew-reassign{border-top:1px solid #424550;padding-top:3px}#crew-feedback:not(:empty){padding:12px;border:1px solid #736037;background:#29251c;border-radius:6px}#crew-notice:empty{display:none}

.council-crew-link.council-warning{color:var(--gold)}.crew-dialog .guide-share{appearance:none;font:inherit;font-size:.9rem;color:#e5e0cd;background:#292d32;border:1px solid #626358;padding:9px 13px;border-radius:6px}.crew-dialog .guide-share:hover:not(:disabled){border-color:var(--gold)}.crew-dialog .crew-remove{color:#f6b7ab}

/* Council audience charts and identity editing */
/* 2026-10-05: each audience panel wears its platform's colour on the top rule
   that .guide-card draws. Three identical moss bars said nothing about which
   card was which, and these are the two people recognise without reading.
   Brand values: Twitch #9146FF, YouTube #FF0000. The website panel keeps the
   house moss, being ours rather than anybody else's. */
.audience-panel[data-platform="twitch"] { border-top-color: #9146ff; }
.audience-panel[data-platform="youtube"] { border-top-color: #ff0000; }

.audience-panels{display:grid;gap:24px}.audience-heading,.audience-caption{display:flex;justify-content:space-between;align-items:baseline;gap:14px;flex-wrap:wrap}.audience-heading h3{font-size:1.35rem;margin:0 0 14px}.audience-heading>span{font-size:.72rem}.audience-caption{font-size:.78rem;color:var(--muted)}.audience-live{color:#a9e7b7}.audience-metrics{display:flex;gap:8px;flex-wrap:wrap;margin:22px 0 8px}.audience-metrics button{flex:1;min-width:120px;text-align:left;border:1px solid transparent;border-radius:8px;background:transparent;color:var(--muted);padding:12px 14px;cursor:pointer}.audience-metrics button[aria-pressed=true]{background:#2c291f;border-color:#ac9046;color:#efddb0}.audience-metrics strong{display:block;font-size:1.9rem;line-height:1.4;color:#efddb0}.audience-metrics span{font-size:.8rem}.audience-metrics small{display:block;font-size:.7rem}.audience-chart svg{display:block;width:100%;height:auto;min-height:160px;overflow:visible}.audience-chart text{fill:#aaa9a4;font-size:11px}.chart-grid{stroke:#383a3e;stroke-width:1}.chart-line{stroke:#d6b65b;stroke-width:2.5;fill:none;stroke-linejoin:round}.audience-chart circle{fill:#ebca77}.chart-hit{fill:transparent}.audience-chart g:hover circle,.audience-chart g:focus circle{r:6;fill:#fff4c8}.chart-readout{color:var(--muted);font-size:.75rem;min-height:1.3em;margin:0 0 12px}.audience-breakdown{display:grid;grid-template-columns:1fr 1fr;gap:32px}.audience-bars h4{font-size:.86rem;margin:8px 0 14px}.audience-bar{position:relative;display:flex;justify-content:space-between;gap:10px;font-size:.8rem;padding:7px 0 12px;margin:6px 0;overflow:hidden}.audience-bar span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.audience-bar i{height:3px;background:#9d874d;position:absolute;bottom:3px;left:0;border-radius:4px}.audience-bar strong{font-weight:500}.audience-details{font-size:.78rem;color:var(--muted);margin-top:18px;border-top:1px solid #393a3e;padding-top:12px}.audience-details summary{cursor:pointer}.twitch-channel-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:9px;margin-top:20px}.twitch-channel-pick{background:#20242a;border:1px solid #44464d;border-radius:8px;color:#eee;padding:13px 12px;text-align:left;cursor:pointer}.twitch-channel-pick[aria-pressed=true]{border-color:#b69a52;background:#2b2921}.twitch-channel-pick strong,.twitch-channel-pick span{display:block}.twitch-channel-pick strong{font-size:.95rem}.twitch-channel-pick span{font-size:.74rem;margin-top:8px;color:var(--muted)}.twitch-channel-pick .audience-live{color:#a9e7b7}.twitch-channel-pick b{color:#e9d493}.audience-empty,.audience-connect{padding:32px 20px;margin:18px 0;background:#20242a;border-radius:8px;text-align:center;color:var(--muted)}.audience-connect strong{font-size:1.1rem;color:#e9d493}.audience-connect p{font-size:.9rem}.crew-field input,.crew-field textarea{width:100%;box-sizing:border-box;background:#242932;border:1px solid #5a606d;border-radius:6px;color:#fff;padding:11px;font:inherit}.crew-identity{margin-top:22px;border-top:1px solid #424550;padding-top:16px}.crew-identity summary{cursor:pointer;color:#e9d493}.crew-identity p{font-size:.85rem}
@media(max-width:700px){.twitch-channel-grid{grid-template-columns:1fr 1fr}.audience-breakdown{grid-template-columns:1fr}.audience-metrics{gap:3px}.audience-metrics button{min-width:100px;padding:9px}.audience-metrics strong{font-size:1.5rem}.audience-chart svg{min-height:130px}.audience-heading>span{font-size:.67rem}}

/* Council controls: destructive power actions stay visibly distinct. */
.warroom .btn-danger { background:#aa303b; border:1px solid #f2707b; color:#fff; }
.warroom .btn-danger:hover:not(:disabled) { background:#c33b47; }
.warroom .btn:disabled { opacity:.5; cursor:not-allowed; }
.crew-dialog select#crew-person { width:100%; min-height:12rem; }

.crew-slot + .crew-slot { margin-top:.5rem; }
.council-table small.crew-slot-label { font-size:.65rem; margin:0 0 .1rem; }

/* Council rows become cards on phones; every value keeps its column label. */
@media (max-width:800px) {
  .council-table-wrap { overflow:visible; min-width:0; }
  .council-table,.council-table tbody { display:block; width:100%; min-width:0; }
  .council-table thead { position:absolute; width:1px; height:1px; padding:0; overflow:hidden; clip-path:inset(50%); }
  .council-table tr { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:14px; padding:16px 0; border-bottom:1px solid var(--edge); }
  .council-table td,.warroom-table td:first-child { display:block; grid-column:1/-1; min-width:0; padding:0; border:0; overflow-wrap:anywhere; }
  .council-table td::before { content:attr(data-label); display:block; margin-bottom:5px; color:var(--muted); font-size:.67rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em; }
  .council-table td[data-crew-cell="assigned"],.council-table td[data-crew-cell="offers"] { grid-column:auto; }
  .council-table button { max-width:100%; white-space:normal; overflow-wrap:anywhere; }
  .guide-card,.council-event { min-width:0; }
}

/* Compact War Room on phones; preserve readable text and tappable controls. */
@media (max-width:800px) {
  /* 2026-10-04: every page of the workspace, not just the two built from the
     War Room's own hero. The Council Dashboard, the Council Guide and the VOD
     Trim Tool are the same workspace behind the same sign-in, and a heading
     that lands a third larger on one of them makes them look like different
     sites on a phone. */
  .warroom-hero,.council-hero { padding-block:16px; }
  .warroom-hero .council-toolbar { gap:8px; margin-bottom:10px; }
  .warroom-hero .guide-eyebrow { font-size:.6rem; letter-spacing:.06em; margin:0; }
  .warroom-hero h1,.council-hero h1 { font-size:1.9rem; margin-bottom:6px; }
  .warroom-hero .lede,.council-hero .lede { font-size:.83rem; line-height:1.4; }
  .warroom-hero .page-subnav,.council-hero .page-subnav { margin-top:12px; gap:6px; }
  .warroom-hero .page-subnav a,.council-hero .page-subnav a,.warroom-tabs a { font-size:.65rem; letter-spacing:.02em; padding:7px 9px; min-height:34px; }
  .warroom { padding-top:14px; line-height:1.4; }
  .warroom-topbar { gap:8px; font-size:.75rem; }
  .warroom-tabs { gap:6px; margin:12px 0 20px; }
  .warroom .guide-event { margin-bottom:24px; }
  .warroom .guide-event-heading { gap:4px; margin-bottom:10px; }
  .warroom .guide-event-heading h2 { font-size:1.25rem; }
  .warroom .guide-eyebrow { margin-bottom:3px; font-size:.62rem; }
  .warroom .guide-small { font-size:.75rem; }
  .warroom .guide-card { padding:12px; margin-bottom:10px; font-size:.84rem; }
  .warroom .guide-card h3 { font-size:1rem; margin-bottom:8px; }
  .warroom .guide-card p { margin-block:7px; }
  .warroom-grid { gap:0; }
  #targets .guide-card { display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:10px; align-items:center; }
  #targets h3 { margin:0; }
  #targets [id^="target-"]:not([id$="-details"]) { margin:0; justify-self:end; }
  #targets [id$="-details"] { grid-column:1/-1; }
  #targets .warroom-buttons { grid-column:1/-1; }
  .warroom-buttons { gap:8px; }
  .warroom .btn { min-height:42px; padding:8px 16px; font-size:.85rem; justify-content:center; }
  #targets .btn { flex:1; }
  .warroom .guide-share { min-height:38px; padding:7px 10px; }
  .warroom-stats { gap:8px; }
  .warroom-stats .guide-card { margin:0 0 8px; }
  .warroom-stats strong { margin-top:4px; font-size:.85rem; }
  .warroom-lanes { grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; }
  .warroom-lanes>div { min-width:0; padding:8px 0; border-bottom:1px solid var(--edge); overflow-wrap:anywhere; }
  .warroom-lanes strong { font-size:.8rem; margin-bottom:4px; }
  .warroom-lanes small { font-size:.67rem; margin-top:4px; }
  .warroom-badge { padding:3px 7px; font-size:.67rem; }
  .warroom-warnings { padding-left:16px; }
  .warroom-warnings li { margin:5px 0; font-size:.8rem; }
  #service-filter { margin:6px 0 8px; }
  .warroom-table tr { grid-template-columns:minmax(0,1fr) auto; gap:6px 10px; padding:11px 0; }
  .warroom-table td { font-size:.77rem; }
  .warroom-table td[data-label="Service"] { grid-column:1; grid-row:1; }
  .warroom-table td[data-label="State"] { grid-column:2; grid-row:1; justify-self:end; }
  .warroom-table td[data-label="Last run / since"] { grid-column:1; grid-row:2; align-self:center; color:var(--muted); font-size:.7rem; }
  .warroom-table td[data-label="Actions"] { grid-column:2; grid-row:2; justify-self:end; align-self:center; }
  .warroom-table td[data-label="Details"] { grid-column:1/-1; grid-row:3; color:var(--muted); font-size:.7rem; }
  .warroom-table td::before { display:none; }
  .warroom-table small { font-size:.66rem; margin-top:3px; }
  .warroom-log-controls { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:8px; }
  .warroom-log-controls label { grid-column:1/-1; font-size:.75rem; }
  .warroom-log-controls select { min-width:0; width:100%; padding:9px 6px; font-size:.78rem; }
  #load-logs { font-size:.72rem; }
  #log-output { padding:10px; max-height:55vh; font-size:11px; line-height:1.5; margin-bottom:0; }
  .warroom .audience-panels { gap:10px; }
  .warroom .audience-heading { gap:3px; }
  .warroom .audience-heading h3 { margin-bottom:3px; }
  .warroom .audience-metrics { margin-top:10px; }
  .warroom .audience-metrics button { min-width:90px; padding:7px; }
  .warroom .audience-metrics strong { font-size:1.3rem; }
  .warroom .twitch-channel-grid { margin-top:10px; gap:6px; }
  .warroom .twitch-channel-pick { padding:9px; }
  .warroom .audience-breakdown { gap:12px; }
  .warroom .audience-empty,.warroom .audience-connect { padding:15px 10px; margin:10px 0; }
}

.race-filters{display:flex;gap:12px;flex-wrap:wrap;margin:0 0 12px}.race-filters label{display:flex;align-items:center;gap:8px;font-size:.85rem}.race-filters select{max-width:100%;background:var(--panel,#151724);color:inherit;border:1px solid #444;border-radius:6px;padding:8px}
.race-activity-card{border:1px solid var(--edge,#383747);border-radius:8px;margin:8px 0;background:rgba(255,255,255,.025);overflow:hidden}
.race-activity-card summary{display:grid;grid-template-columns:10px minmax(0,1fr) auto;align-items:start;gap:8px 10px;padding:10px 12px;cursor:pointer;list-style:none}
.race-activity-card summary::-webkit-details-marker{display:none}
.race-activity-card summary::before{content:'▸';grid-column:1;grid-row:1;margin-top:15px;color:var(--gold,#e6bb5b)}
.race-activity-card[open] summary::before{content:'▾'}
.race-activity-card summary:focus-visible{outline:2px solid var(--gold,#e6bb5b);outline-offset:-2px}
.race-summary-main{grid-column:2;min-width:0}.race-summary-main strong{display:block;font-size:.96rem;line-height:1.3;margin:2px 0;overflow-wrap:anywhere}
.race-identity,.race-when{display:block;color:var(--muted,#b4b2c3);font-size:.74rem;line-height:1.4;overflow-wrap:anywhere}
.race-overall{grid-column:3;display:grid;justify-items:end;gap:6px}.race-overall .warroom-badge{font-size:.69rem;white-space:normal;text-align:right}.race-expand{font-size:.7rem;color:var(--muted,#b4b2c3)}
.race-status-strip{grid-column:2/-1;display:flex;flex-wrap:wrap;gap:4px 16px}
.race-checkpoint-status{display:inline-flex;align-items:center;gap:6px;padding:2px 0;line-height:1.25;white-space:nowrap}
.race-checkpoint-name{font-size:.7rem;color:var(--muted,#b4b2c3)}
.race-checkpoint-light{width:.6rem;height:.6rem;flex:0 0 .6rem;box-sizing:border-box;border-radius:50%;border:1px solid rgba(255,255,255,.25);box-shadow:inset 0 1px 1px rgba(255,255,255,.2)}
.race-checkpoint-light.good{background:#83cd83}.race-checkpoint-light.pending{background:#efc75e}.race-checkpoint-light.bad{background:#ee786b}.race-checkpoint-light.empty{background:transparent;border-color:var(--muted,#b4b2c3);box-shadow:none}
/* Columns rather than a grid: a grid fills left to right, so the checkpoints
   -- which are a sequence, thread then schedule then room -- read across in
   threes and the eye zigzags. Multi-column fills top to bottom, so a column
   is read down and the order holds, and it balances itself for the eight a
   League race has or the nine a tournament race has. */
.race-checkpoints{columns:3;column-gap:18px;list-style:none;padding:0 12px 0 32px;margin:2px 0 10px}
.race-checkpoints li{break-inside:avoid}
.race-checkpoints li{border-top:1px solid var(--edge,#383747);padding:8px 0;min-width:0}.race-checkpoints li>div:first-child{display:flex;align-items:center;gap:6px;justify-content:space-between}.race-checkpoints strong{font-size:.77rem}.race-checkpoints .warroom-badge{font-size:.65rem;padding:2px 6px}
.race-checkpoints p{font-size:.76rem;line-height:1.4;margin:4px 0;overflow-wrap:anywhere}.race-checkpoint-meta{display:flex;flex-wrap:wrap;gap:3px 10px;font-size:.7rem;overflow-wrap:anywhere}.race-checkpoint-meta time{color:var(--muted,#b4b2c3)}
.race-card-footer{display:flex;align-items:center;flex-wrap:wrap;gap:8px 16px;padding:0 12px 10px 32px;font-size:.78rem}#race-problems:not(:empty){color:#e6bb5b;margin-bottom:12px}
@media(max-width:600px){
 .race-filters{gap:8px}.race-filters label{flex:1;flex-direction:column;align-items:stretch;gap:4px}.race-filters select{min-width:0;width:100%;font-size:.8rem}
 .race-activity-card summary{gap:7px;padding:10px;grid-template-columns:8px minmax(0,1fr)}.race-summary-main strong{font-size:.9rem}.race-overall{grid-column:2;display:flex;justify-content:space-between;align-items:center;gap:8px}.race-overall .warroom-badge{text-align:left}.race-expand{margin-left:auto;flex-shrink:0}
 .race-status-strip{grid-column:1/-1;gap:3px 12px}.race-checkpoint-name{font-size:.68rem}
 .race-checkpoints{columns:1;padding:0 10px}.race-checkpoints li{padding:7px 0}.race-checkpoint-meta{font-size:.72rem}.race-card-footer{padding:0 10px 10px}
}

/* Council: one combined rolling agenda, with resource links retained per event. */
/* Council Crew shares the site's palette and form scale; profile state stays private. */
.crew-directory-layout { display:grid; grid-template-columns:minmax(220px, .8fr) minmax(0, 1.5fr); align-items:stretch; gap:24px; margin-top:16px; }
.crew-directory-layout>* { min-width:0; }
.crew-list { position:relative; min-height:360px; }
.crew-people { position:absolute; inset:0; display:flex; flex-direction:column; gap:8px; overflow:auto; padding:2px; }
.crew-person { flex-shrink:0; text-align:left; display:grid; gap:4px; padding:14px; width:100%; border:1px solid var(--edge); border-radius:6px; background:var(--surface); color:var(--parchment); font:inherit; cursor:pointer; overflow-wrap:anywhere; }
.crew-person span { color:var(--muted); font-size:.76rem; }
.crew-person:hover,.crew-person[aria-pressed="true"] { border-color:var(--moss-bright); background:var(--raised); }
.crew-directory .crew-profile { border-left:1px solid var(--edge); padding:0 0 0 24px; }
.crew-profile h2 { margin:0 0 6px; font-size:1.5rem; overflow-wrap:anywhere; }
.crew-profile .crew-field { gap:4px; margin:0; color:var(--parchment); font-size:.85rem; line-height:1.4; }
.crew-profile .crew-field>p { margin:0; font-weight:400; overflow-wrap:anywhere; }
.crew-profile .guide-small { font-size:.78rem; font-weight:400; line-height:1.4; }
.crew-profile-meta { display:flex; align-items:baseline; flex-wrap:wrap; gap:4px 12px; margin-bottom:14px; }
.crew-profile-meta p { margin:0; }
.crew-profile-fields { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; }
.crew-field-wide { grid-column:1/-1; }
.crew-alias-editor { margin-top:12px; }
.crew-alias-editor summary { cursor:pointer; color:var(--gold); font-size:.85rem; font-weight:600; }
.crew-alias-editor p { margin:8px 0; overflow-wrap:anywhere; }
.crew-profile .crew-actions { gap:8px; margin:12px 0 0; }
.crew-access-controls { display:flex; align-items:flex-end; gap:12px; }
.crew-access-controls>.crew-field { flex:1; min-width:0; }
.crew-access-controls>.crew-active { min-height:40px; }
.crew-profile :is(#crew-profile-status,#crew-access-status):empty { display:none; }
.crew-directory input,.crew-directory textarea { width:100%; min-width:0; padding:10px; border:1px solid var(--edge); border-radius:6px; background:var(--surface); color:var(--parchment); font:inherit; }
.crew-directory textarea { resize:vertical; }
.crew-directory :is(input,textarea,select,button):focus-visible { outline:2px solid var(--gold); outline-offset:3px; }
.crew-directory button:disabled { opacity:.55; cursor:wait; }
.crew-directory [hidden] { display:none!important; }
.crew-environment { color:var(--gold); border:1px solid var(--gold); border-radius:4px; padding:4px 8px; font:700 .72rem var(--body); letter-spacing:.08em; }
.crew-access { color:var(--moss-bright); font-size:.8rem; }
.crew-add { padding:16px 0; border-block:1px solid var(--edge); }
.crew-add summary { cursor:pointer; color:var(--gold); font-weight:600; }
.crew-add select,.crew-access-form select { width:100%; padding:10px; background:var(--surface); color:var(--parchment); border:1px solid var(--edge); border-radius:6px; font:inherit; }
.crew-access-form { margin-top:16px; padding-top:16px; border-top:1px solid var(--edge); }
.crew-profile .crew-access-form h3 { margin:0 0 6px; font-size:1.05rem; }
.crew-access-form>p { margin:0 0 12px; }
.crew-access-save { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:10px; margin-top:12px; padding:12px; border:1px solid transparent; border-radius:6px; }
.crew-access-save p { margin:0; flex:1; }
.crew-access-save .btn { min-height:44px; margin-left:auto; }
.crew-access-save .btn:disabled { cursor:default; }
.has-access-changes .crew-access-save { border-color:var(--gold); background:var(--raised); }
.has-access-changes #crew-access-status { color:var(--gold); font-weight:600; }
.crew-active { display:flex; align-items:center; gap:10px; font-size:.85rem; }
.crew-active input { width:auto; }
.crew-directory .crew-dialog { background:var(--surface); color:var(--parchment); border-color:var(--edge); }
#crew-profile-status:not(:empty) { padding:12px; border:1px solid var(--edge); background:var(--surface); border-radius:6px; }
#crew-identity { overflow-wrap:anywhere; }
@media(min-width:701px) and (max-width:1000px) {
 .crew-profile-fields { grid-template-columns:1fr; }
 .crew-access-controls { align-items:stretch; flex-direction:column; }
}
@media(max-width:700px) {
 .crew-directory-layout { grid-template-columns:1fr; gap:24px; }
 .crew-list { min-height:0; height:240px; }
 .crew-directory .crew-profile { border-left:0; padding:24px 0 0; border-top:1px solid var(--edge); }
 .crew-profile-fields { grid-template-columns:1fr; }
 .crew-access-controls { align-items:stretch; flex-direction:column; gap:8px; }
}
.dashboard-filters { display:flex; flex-wrap:wrap; gap:12px; margin:20px 0; }
.dashboard-filters label { display:grid; gap:6px; flex:1 1 160px; min-width:0; color:var(--muted); font-size:.8rem; }
.dashboard-filters select { width:100%; min-width:0; padding:10px; color:var(--parchment); background:var(--surface); border:1px solid var(--edge); border-radius:6px; font:inherit; }
.council-agenda { list-style:none; padding:0; margin:14px 0 0; }
.council-agenda li { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:8px 16px; align-items:start; padding:11px 0; border-top:1px solid var(--edge); font-size:.83rem; }
/* The time used to lead its own column, so the eye met a clock before it met
   a race. Same stack as the War Room now -- what it is, who is racing, then
   when and where -- and the status sits beside it rather than in a third
   column that forced the names into a narrow strip. */
.council-agenda .agenda-main { display:grid; gap:2px; }
.council-agenda .agenda-main strong { font-size:.96rem; line-height:1.3; }
.council-agenda li>* { min-width:0; overflow-wrap:anywhere; }
/* 2026-10-05: the status column is sized to its content, which is usually the
   crew line -- so Assign and Modify sat at the left edge of a cell as wide as
   the names underneath them, pages away from the edge the eye is already at by
   the time it reaches that column. */
.council-agenda [data-agenda-status] { justify-self:end; text-align:right; }
.council-agenda a { display:grid; gap:3px; text-decoration:none; }
.council-agenda [data-agenda-details] { display:block; margin-top:4px; line-height:1.5; color:var(--parchment); }
.council-agenda time,.council-agenda small { color:var(--muted); font-size:.74rem; }
.council-metrics span[data-window-label] { display:inline; margin:0; }
.council-event[hidden],.council-agenda [hidden],.council-table tr[hidden],.council-table-wrap[hidden],[data-window-empty][hidden],#dashboard-empty[hidden] { display:none!important; }
@media(max-width:600px) {
 .dashboard-filters label { flex-basis:calc(50% - 12px); }
 .council-agenda li { grid-template-columns:minmax(0,1fr) 105px; gap:6px 10px; }
 .council-agenda time { grid-column:1/-1; }
 #dashboard-summary { padding:18px; }
 #dashboard-summary .council-metrics span { font-size:.7rem; }
}
/* ---------------------------------------------------------------- 2026-10-04
   Why a division is in the order it is in.

   Standings orders teams level on points by the League tiebreakers now, rather
   than by the order the Standings tab typed them -- which moves rows, and a row
   that moves without saying why reads as a mistake. Each tie carries a mark and
   a line under its table naming the rule that settled it and the figures it was
   settled on. Two ties in one division take one mark and two, the usual way. */

.tie-mark {
  margin-left: 3px;
  color: var(--moss-bright);
  font-family: var(--mono);
  font-size: 0.8em;
  vertical-align: super;
  line-height: 1;
}

/* The note sits where `.division-foot` sits and is built to match it, because
   it is the same kind of thing: a quiet line at the foot of the table. Only the
   first one carries the rule above it -- a second would draw a line through
   nothing -- and inside the note the mark is text rather than a superscript,
   so the sentence it opens sits on the baseline with it. */
.tie-note {
  margin: 0;
  padding: 9px 16px 12px;
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.5;
}

.division table + .tie-note { border-top: 1px solid var(--edge-soft); }
.tie-note + .tie-note { padding-top: 0; }

.tie-note .tie-mark {
  margin: 0 2px 0 0;
  vertical-align: baseline;
  font-size: 0.85rem;
}

/* ---------------------------------------------------------------- 2026-10-04
   Sign out joins the sub-nav.

   It used to sit in a bar of its own above the page title, which cost a row to
   hold one button. The sub-nav is already a row of places to go, and leaving is
   one of them -- pushed to the far end, so it is never next to the link you
   meant to press. */

.page-subnav .council-signout { margin-left: auto; display: flex; }

/* It is `.btn`, the same button the rest of the site uses, rather than a
   control invented for this one row -- sized down to sit in a row of links
   without shouting, but the same border, fill and hover as everywhere else. */
.page-subnav .council-signout .btn {
  padding: 6px 14px;
  font-size: 0.8rem;
  border-radius: 2px;
}

/* ---------------------------------------------------------------- 2026-10-04
   The races somebody is working on right now.

   The list mixes three things: what is coming up later today, what is being set
   up this minute, and what has been run. Only the middle one needs anybody, and
   it was the hardest to pick out -- every card looked the same and you read the
   times to work out which was which.

   A race is lit from thirty-five minutes out, when the first automated action
   falls due, until its result is recorded. The gold is the one the rest of the
   workspace already uses for "look here"; the bar is on the leading edge so a
   column of cards shows at a glance how many are in play. */

.race-activity-card.race-in-play {
  border-color: var(--gold, #e6bb5b);
  background: rgba(230, 187, 91, 0.06);
  box-shadow: inset 3px 0 0 var(--gold, #e6bb5b);
}

/* The summary's own disclosure arrow is already gold; the identity line is
   lifted out of muted so the heading reads as current rather than filed. */
.race-activity-card.race-in-play .race-identity { color: var(--parchment, #ece6d2); }

/* ---------------------------------------------------------------- 2026-10-04
   The agenda's status is the way in to the row that changes it.

   It read "Crew assigned" / "Crew needed", which describes a state and invites
   nobody to press it. It says "Modify" / "Assign" now and is an anchor to the
   race's own row in the schedule table below, so the word and the thing it does
   are the same object. The row gets scroll margin so the jump does not leave it
   tucked under the sticky heading. */

.agenda-action { color: var(--gold, #e6bb5b); text-decoration: none; font-weight: 600; }
.agenda-action:hover, .agenda-action:focus-visible { color: var(--parchment, #ece6d2); }

.council-table tr[id] { scroll-margin-top: 90px; }

/* A race with crew or a channel on it is one somebody has already taken in
   hand, and the League standings have a way of saying that: an eight-percent
   wash of the house moss under the rows above the cut. Same wash here, for the
   same reason -- it marks the row without colouring it, and it is already the
   colour this site uses for "this one counts". */
.council-schedule tr[data-crewed="true"],
.council-schedule tr[data-channel="true"] { background: rgba(79, 143, 44, 0.08); }

/* Marked after the jump, so the eye lands on the right row.
   2026-10-05: on the row, not on its cells. A schedule row is a grid with a
   14px column gap and a 1px row gap, so a background on the cells painted
   everything except the gaps -- a set of stripes with the row's own structure
   showing through, rather than a highlight.
   And not in gold: a twelve-percent wash of it over this surface came out the
   colour of old mustard. A plain lift of the surface itself reads as "this
   one" without tinting anything. */
.council-table tr[id]:target { background: rgba(255, 255, 255, 0.055); }

/* ---------------------------------------------------------------- 2026-10-04
   What racetime says is happening, on the card.

   The checkpoints say whether the automation did its job; they say nothing
   about the race. Mid-night the question is usually simpler than that -- has it
   started, how long has it been going, is anybody still out there. Before the
   start it reads as entrants and how many have readied; after it, the clock and
   the field. The clock is ticked in the browser, because the snapshot refreshes
   every twenty seconds and a time that jumps in twenty-second steps reads as a
   broken clock rather than a slow one. */

.race-live {
  display: block;
  color: var(--parchment, #ece6d2);
  font-size: 0.74rem;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.race-elapsed {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--gold, #e6bb5b);
  margin-right: 7px;
}

/* The agenda carries the same live line as the War Room card, in the same
   place relative to the time -- one module renders both, so they cannot drift
   into describing the same room two different ways. */
.council-agenda .race-live { font-size: 0.74rem; }
.council-agenda li.race-in-play { box-shadow: inset 3px 0 0 var(--gold, #e6bb5b); padding-left: 11px; }
.council-agenda li.race-in-play .race-identity { color: var(--parchment, #ece6d2); }

/* ---------------------------------------------------------------- 2026-10-04
   Each event's races as rows, not as a spreadsheet.

   Five columns -- when, matchup, crew, volunteers, channel -- put a third of
   the width into three stacked "needed" buttons and left the matchup, the one
   thing you are looking for, squeezed between them. The War Room reads better
   because it leads with what the race is and lets the rest sit underneath.

   Same shape here: matchup first with the channel opposite it, the time under
   it, and the crew as a row of chips rather than a column. The markup is
   untouched -- every data-crew-cell, data-choice and crew-slot hook the crew
   client reads is still there -- because this is a question about layout and
   not about what the row is.

   Scoped to .council-schedule: the War Room's service table is also a
   .council-table and still wants to be a table. */

.council-schedule, .council-schedule tbody { display: block; width: 100%; }
.council-schedule thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

.council-schedule tr {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "matchup channel" "when channel" "crew actions" "offers actions";
  gap: 6px 14px;
  /* Out to the card's own edges, with the padding put back inside, so the mark
     on a race somebody has taken runs the whole width of the row instead of
     stopping short with a bare strip of card either side. The content does not
     move: it is the same padding, just owned by the row rather than the card. */
  margin-inline: calc(-1 * var(--card-pad, 0px));
  padding-block: 11px;
  padding-inline: var(--card-pad, 0px);
  border-bottom: 1px solid var(--edge);
}

.council-schedule td { display: block; padding: 0; border: 0; min-width: 0; overflow-wrap: anywhere; }
.council-schedule td::before { content: none; }

.council-schedule td:nth-child(2) { grid-area: matchup; font-size: 0.95rem; line-height: 1.3; }
.council-schedule td:nth-child(2) small { display: inline; margin: 0 0 0 7px; font-size: 0.72rem; }
.council-schedule td:nth-child(1) { grid-area: when; color: var(--muted); font-size: 0.74rem; }


/* 2026-10-04: the crew in labelled lines.

   Three chips in a row said "needed" three times and left the names mixed in
   among the gaps; wrapped onto a phone they made a ragged column that lined up
   with nothing. Now each line opens with its own word and the words share a
   column, so Needed, Assigned and Channel start at the same place however many
   chips the line above it took. */
.council-schedule td[data-crew-cell="assigned"] { grid-area: crew; display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
.council-schedule .crew-line { display: grid; grid-template-columns: 5.8rem minmax(0, 1fr); align-items: baseline; column-gap: 7px; }
.council-schedule .crew-line-values { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 7px; min-width: 0; }

/* 2026-10-05: each chip is its own control and they were reading as one phrase.
   "Comms 1 Comms 2 Tracker", bold, five pixels apart, is a sentence -- but
   every word in it opens a different slot. A faint rule around each, and room
   to breathe inside it, says where one target ends and the next begins. */
.council-schedule .crew-line .council-crew-link,
.council-schedule td[data-crew-cell="offers"] .council-crew-link,
.council-schedule td[data-crew-cell="channel"] .council-crew-link {
  border: 1px solid var(--edge);
  border-radius: 999px;
  /* One pixel of padding and one of border is exactly the two pixels of
     padding these had before the ring, so a row is the height it always was.
     The ring was worth having; the extra line it added to every race was not. */
  padding: 1px 10px;
  font-weight: 600;
}
/* The ring is the signal now. The underline was how a flat word showed it was
   a control, and running both at once just thickened the chip.

   Selector for selector with the rule that draws the ring above, because the
   channel and volunteer chips are scoped by their cell -- an attribute more
   than the crew line carries -- and a hover written any shorter loses to it on
   specificity. Those two chips kept their resting border under the cursor
   while comms and tracker turned gold, which is the one thing a row of
   identical controls must not do. */
.council-schedule .crew-line .council-crew-link:hover,
.council-schedule .crew-line .council-crew-link:focus-visible,
.council-schedule td[data-crew-cell="offers"] .council-crew-link:hover,
.council-schedule td[data-crew-cell="offers"] .council-crew-link:focus-visible,
.council-schedule td[data-crew-cell="channel"] .council-crew-link:hover,
.council-schedule td[data-crew-cell="channel"] .council-crew-link:focus-visible { border-color: var(--gold); text-decoration: none; }
.council-schedule .council-crew-link:disabled { border-style: dashed; }
.council-schedule .crew-line-label,
.council-schedule td[data-crew-cell="channel"] .crew-line-label {
  flex: 0 0 auto;
  min-width: 4.6rem;
  color: var(--muted);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.council-schedule td[data-crew-cell="offers"] { grid-area: offers; }
.council-schedule td[data-crew-cell="offers"]:empty { display: none; }
.council-schedule td[data-crew-cell="channel"] { grid-area: channel; justify-self: end; align-self: start; display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: baseline; gap: 5px; }
.council-schedule td[data-crew-cell="channel"] .crew-line-label { min-width: 0; }
.council-schedule td[data-crew-cell="actions"] { grid-area: actions; justify-self: end; align-self: end; }
.council-schedule td[data-crew-cell="actions"] .council-crew-link { text-align: right; }

/* Keep the channel in the upper right on narrow cards, with the matchup
   on its own line so neither is squeezed. Removal stays at the lower right. */
@media (max-width: 800px) {
  .council-schedule tr {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "channel channel" "matchup matchup" "when when" "crew actions" "offers actions";
    padding-block: 14px;
  }
}

/* 2026-10-07: the Council tools under a "…" at the right of the workspace row.
   The summary wears the same pill as the links beside it; the menu drops below
   it, right-aligned so it never runs off a phone's edge, and lists the tools as
   the same pills stacked. A native <details>: no script needed to open it. */
/* Let the menu extend below the hero without extending the background grid
   beyond the viewport. */
.council-hero, .warroom-hero { overflow: visible; }
.council-hero::before, .warroom-hero::before { inset: 0; }
.council-tools { position: relative; display: flex; }
.council-tools > summary {
  list-style: none;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  font-family: var(--body);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1;
  color: var(--parchment);
  padding: 7px 13px;
  border: 1px solid rgba(207, 214, 194, 0.28);
  border-radius: 999px;
}
.council-tools > summary::-webkit-details-marker { display: none; }
.council-tools > summary:hover,
.council-tools > summary:focus-visible,
.council-tools[open] > summary,
.council-tools > summary[aria-current="page"] { border-color: var(--gold); color: var(--gold); }
.council-tools-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  display: grid;
  gap: 6px;
  min-width: max-content;
  padding: 8px;
  background: var(--raised);
  border: 1px solid var(--edge);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}
.council-tools-menu a { justify-content: flex-start; }
@media (max-width: 600px) {
  .council-subnav { position: relative; }
  .council-tools { position: static; }
}

/* Council: four visible channel columns; unassigned cards stay hidden until assigned. */
.channel-calendar { margin-top: 1.5rem; border-top: 1px solid #34404d; padding-top: 1rem; }
.channel-calendar h3 { margin: 0 0 .4rem; }
.channel-calendar-grid { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: .65rem; }
.channel-calendar-grid > section { min-width: 0; padding: .7rem; border: 1px solid #34404d; border-radius: .5rem; background: #111922; }
.channel-calendar-grid > section[data-calendar-channel="unassigned"] { grid-column: 1 / -1; }
.channel-calendar-grid h4 { margin: 0 0 .7rem; font-size: .85rem; color: #dfe8ee; }
.channel-calendar-grid ol { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.channel-calendar-grid [data-calendar-channel="unassigned"] ol { grid-template-columns: repeat(auto-fit,minmax(210px,1fr)); }
.channel-calendar-grid li { padding: .65rem; border-left: 3px solid #6ebcaf; background: #1a2631; border-radius: .3rem; overflow-wrap: anywhere; }
.channel-calendar-grid a { display: grid; gap: .25rem; color: inherit; text-decoration: none; }
.channel-calendar-grid a:hover strong { text-decoration: underline; }
.channel-calendar-grid time { color: #99d6cb; font-size: .76rem; font-weight: 700; }
.channel-calendar-grid a > span { color: #a4b4c3; font-size: .7rem; }
.channel-calendar-grid strong { font-size: .82rem; }
.channel-calendar-grid small { display: block; margin-top: .4rem; color: #bac6cf; font-size: .72rem; }
/* One event palette across the agenda and channel schedule. */
#dashboard-summary [data-event="ttp"] { --event-color: var(--moss-bright); }
#dashboard-summary [data-event="league"] { --event-color: #cf4141; }
#dashboard-summary [data-event="tc"] { --event-color: #f0ce45; }
#dashboard-summary [data-event="autumn"] { --event-color: #be612b; }
.council-agenda li,
.channel-calendar-grid li { border-left: 6px solid var(--event-color, var(--moss-bright)); }
.council-agenda li { padding: 14px 12px; margin-top: 8px; border-radius: 4px; background: #1a2119; }
.council-agenda li.race-in-play { box-shadow: none; padding-left: 12px; background: #222b1d; }
.council-agenda li[data-event="league"],
.channel-calendar-grid li[data-event="league"] { outline: 1px solid #576052; outline-offset: -1px; }
.council-agenda .agenda-main { gap: 5px; }
.council-agenda .race-when { order: -1; color: var(--parchment); }
.council-agenda .race-identity { order: 1; }
.council-agenda .race-live { order: 2; }
/* 2026-10-22: TTP needs nothing from Council, so in Next 24 Hours it is one
   quiet line and the races that want crew carry the weight of the list. */
.council-agenda li.agenda-compact { display: block; padding: 5px 12px; margin-top: 4px; border-left-width: 3px; background: transparent; }
.council-agenda li.agenda-compact .agenda-main { display: block; color: var(--muted); font-size: .8rem; }
.council-agenda li.agenda-compact time,
.council-agenda li.agenda-compact strong { display: inline; font-size: .8rem; font-weight: 500; color: var(--muted); }
.council-agenda li.agenda-compact .race-live { margin-left: 8px; }
/* 2026-10-22: the TTP section is the rooms that are open, one line each. */
.council-ttp-rooms { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.council-ttp-room { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; padding: 9px 12px; border-left: 3px solid var(--moss-bright); background: #1a2119; border-radius: 4px; font-size: .85rem; }
.council-ttp-room.is-racing { border-left-color: var(--gold); }
.council-ttp-room span { color: var(--muted); }
.council-ttp-room a:first-of-type { margin-left: auto; }
.council-event-links { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 8px; font-size: .8rem; }
.council-agenda .agenda-main strong,
.council-agenda time,
.channel-calendar-grid time { font-size: 1.05rem; font-weight: 700; line-height: 1.4; color: var(--parchment); }
.channel-calendar-grid strong { font-size: .94rem; line-height: 1.4; }
.channel-calendar-grid a > span { font-size: .78rem; }
@media (max-width: 800px) { .channel-calendar-grid { grid-template-columns: repeat(2,minmax(0,1fr)); } }
@media (max-width: 480px) { .channel-calendar-grid { grid-template-columns: minmax(0,1fr); } }

/* 2026-10-12: the editorial staff on the Autumn Tournament, one edition per
   bracket stage. The same voice as the power rankings, so the same lede and
   archive; the parts are plain paragraphs under a gold label, because a stage
   is a story about races rather than a card per team. */
.report-headline { margin: 4px 0 12px; font: 600 1.15rem/1.35 var(--body); color: var(--parchment); }
.report-part { margin: 0 0 18px; }
.report-part h4 {
  margin: 0 0 6px;
  color: var(--gold);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.report-part p { margin: 0 0 10px; color: #cfd6c2; }
.report .pr-archive .report-headline { margin-top: 14px; padding: 0 14px; }
.report .pr-edition .pr-lede,
.report .pr-edition .report-part { padding: 0 14px; }

/* 2026-10-28: the editorial's pictures -- a strip of numbers under the lede,
   result and next-match cards inside a section, a row of faces. They borrow
   the results section's faces and ranks so a racer looks the same anywhere. */
.report-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; margin: 18px 0 6px; }
.report-stat { border: 1px solid var(--edge); background: var(--surface); padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.report-stat strong { font-size: 1.6rem; line-height: 1; color: var(--gold); font-variant-numeric: tabular-nums; }
.report-stat span { color: var(--muted); font-size: .8rem; line-height: 1.3; }
.report-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px; margin: 12px 0 16px; }
.report-card { margin: 0; border: 1px solid var(--edge); background: var(--surface); padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.report-card figcaption { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: .75rem; }
.report-tag { color: var(--gold); text-transform: uppercase; letter-spacing: .04em; font-weight: 700; }
.report-when { color: var(--muted); text-align: right; }
.report-racer { display: flex; align-items: center; gap: 10px; min-width: 0; color: var(--muted); }
.report-racer .face { width: 36px; height: 36px; flex: none; }
.report-racer .named { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.report-racer.won { color: inherit; font-weight: 700; }
.report-clock { font-variant-numeric: tabular-nums; flex: none; }
.report-card.next .report-racer { color: inherit; }
.report-vs { color: var(--muted); font-size: .75rem; padding-left: 46px; }
.report-faces { display: flex; flex-wrap: wrap; gap: 10px 18px; margin: 12px 0 4px; }
.report-faces .report-racer { color: inherit; }

/* 2026-10-31: Championship Week's played games. The game's header row was a
   flex rule on every child div, so it caught the result grid too and laid
   all twelve cells in one line (Bogie: "looks jank" on a phone, and it was
   on a desktop too). The grid is now left a grid; on a phone its times take
   only their own width and the names stay on one line, smaller as the screen
   narrows, as racer names do everywhere. */
@media (max-width: 480px) {
  /* The seeds' names had a third of the row each and ran into the score
     ("0–2TekTITANS"); stacked under their logos they get the whole column. */
  .championship-teams { gap: 8px; }
  .championship-teams > div, .championship-teams > div:last-child { flex-direction: column; align-items: center; text-align: center; gap: 6px; }
  .championship-teams strong { overflow-wrap: normal; }
  .championship-game { padding: 12px 10px; }
  .championship-game .race-grid { grid-template-columns: minmax(0, 1fr) auto auto minmax(0, 1fr); column-gap: 5px; }
  .championship-game .race-grid .name { white-space: nowrap; overflow-wrap: normal; font-size: 0.84rem; }
  .championship-game .race-grid .name.small, .championship-game .race-grid .name.tiny { font-size: 0.76rem; }
  .championship-game .race-grid .time { font-size: 0.74rem; }
}
@media (max-width: 340px) {
  .championship-game { padding: 10px 8px; }
  .championship-game .race-grid { column-gap: 4px; }
  .championship-game .race-grid .name, .championship-game .race-grid .name.small, .championship-game .race-grid .name.tiny { font-size: 0.68rem; }
  .championship-game .race-grid .time { font-size: 0.66rem; }
}
