
/* ============================================================
   dodworldseries.com — design prototype (full rework).
   Design system: the KTP property olive-drab scheme, tokens and
   component shapes copied from support-web/app/templates/index.html
   (itself derived from KTPAntiCheat/docs/bundles-web/styles.css).
   Nothing here is reinterpreted — see design/DESIGN.md for the
   token mapping and the deliberate page-specific additions.

   Page-specific additions (all documented in DESIGN.md):
   - .crest        : the WSDoD patch, recoloured into the olive scheme
   - .statstrip    : event fact tiles under the hero
   - .dayboard     : the per-day stats board (the structural answer to
                     "KTPR is not comparable across days")
   - .rolepill     : the four league positions (neutral — not status)
   - .edbar        : the edition switcher (multi-year archive spine)
   - .bkt-maps     : maps-played footer row on bracket cards (veto.json)
   - .field/.fb-id : the feedback form (treatment from support-web)

   Hard rules carried from the property:
   - static header (not sticky, not animated)
   - zero external requests; JetBrains Mono rides the fallback stack
   - committed dark; no light variant
   - colour carries information only: rust=accent/alert, moss=ok/
     info/actions, tan=degraded/attention, warm-grey ramp for the rest
   ============================================================ */
:root {
  --bg:        #171c0a;
  --panel:     #252a14;
  --panel-2:   #323920;
  --inset:     #101407;
  --border:    #3d432b;
  --rule:      rgba(61,67,43,0.5);
  --text:      #eae7d4;
  --dim:       #b6b299;
  --faint:     #98947c;
  --red:       #d0513b;   /* rust — alert / accent */
  --red-soft:  #e07a63;   /* rust lifted for small text */
  --blue:      #819746;   /* moss — ok / info / actions (name kept from the blue era) */
  --blue-soft: #9fb45c;
  --amber:     #c08b5c;   /* tan — attention only */
  /* medal ramp — derived from the olive palette, used ONLY for standings
     (rows 1–5 of the boards, podium slots). See DESIGN.md § medals. */
  --gold:      #d2b356;   /* --amber rotated toward yellow, same value range */
  --silver:    #c9cdbb;   /* the warm-grey ramp lifted and cooled a step */
  --bronze:    #c08b5c;   /* --amber verbatim */
  --medal45:   #9fb45c;   /* 4th–5th share moss-soft */
  --radius: 14px;
  --panel-grad: linear-gradient(180deg, var(--panel) 0%, #1e230f 100%);
  --mono: "JetBrains Mono", ui-monospace, "Cascadia Code", Consolas, Menlo, monospace;
  color-scheme: dark;
}
* { margin:0; padding:0; box-sizing:border-box; }
html { scroll-behavior:smooth; }
body {
  background:
    radial-gradient(120% 80% at 50% -10%, #252a14 0%, rgba(37,42,20,0) 55%),
    var(--bg);
  background-attachment: fixed;
  color: var(--text);
  font-family: var(--mono);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}
a { color: var(--blue); text-decoration: none; }
a:hover { color: var(--blue-soft); }
code { font-family: var(--mono); color: var(--blue-soft); }
::selection { background: var(--red); color:#150b04; }
.wrap { max-width: 1180px; margin: 0 auto; padding: 0 22px; width: 100%; }
/* The stats boards carry more columns than the prose measure can hold, so they
   break out of .wrap rather than scroll sideways inside it. Capped at 1460 —
   past that the reading line for the notes above the table gets silly. The
   negative margin is symmetric, so the section stays centred. */
@media (min-width: 1240px) {
  section#stats, section#stats-25 {
    width: min(1460px, calc(100vw - 44px));
    margin-left: calc(50% - min(730px, calc(50vw - 22px)));
    margin-right: calc(50% - min(730px, calc(50vw - 22px)));
  }
  /* .sec-body is the fold wrapper the folding module inserts; the notes are
     direct children of it once a section can fold.
     Centred, not just capped: the section breaks out to 1460 so the board fits,
     so a capped block with no auto margins sits flush left and reads as
     misaligned against the full-width board below it. The About panel is capped
     with them — one measure for every block of prose in the section. */
  section#stats > .sec-body > .note-box, section#stats-25 > .sec-body > .note-box,
  section#stats > .sec-body > .status-foot, section#stats-25 > .sec-body > .status-foot,
  section#stats > .sec-body > .kt-about,
  section#stats > .note-box, section#stats-25 > .note-box,
  section#stats > .status-foot, section#stats-25 > .status-foot,
  section#stats > .kt-about,
  section#stats > .sec-head, section#stats-25 > .sec-head {
    max-width: 1180px; margin-left: auto; margin-right: auto;
  }
}
[hidden] { display: none !important; }

a:focus-visible, button:focus-visible, summary:focus-visible { outline: 2px solid var(--blue-soft); outline-offset: 2px; }

.mt8  { margin-top: 8px; }
.mt16 { margin-top: 16px; }

/* ---- top bar — STATIC by property requirement ---- */
nav {
  border-bottom: 1px solid var(--border);
  background: rgba(16,20,7,0.72);
  position: static;
}
/* The bar needs more than the 1180 content column, so on a nowrap row it spilled
   past the viewport and scrolled the whole page on any window under ~2020px. It
   gets its own width to stay on one line, and wraps rather than overflowing when
   even that isn't enough. */
nav .wrap { max-width: 1560px; }
nav .row { display:flex; align-items:center; gap: 14px; min-height: 58px; flex-wrap: wrap; row-gap: 4px; }
.brand { font-weight: 800; letter-spacing: 1px; font-size: 1.05rem; color: var(--text); white-space: nowrap; }
.brand .k { color: var(--red); }
nav .spacer { flex: 1; }
.sponsor-slot {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.4px;
  color: var(--red-soft); border: 1px solid var(--red); border-radius: 999px;
  padding: 4px 13px; white-space: nowrap; text-transform: none;
}
.sponsor-slot:hover { background: var(--red); color: #150b04; }

nav .navlink { color: var(--dim); font-size: 0.82rem; letter-spacing: 0.6px; }
nav .navlink:hover { color: var(--text); }
.who {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 0.72rem; color: var(--dim); letter-spacing: 0.4px;
  border: 1px solid var(--border); border-radius: 999px; padding: 6px 13px;
  white-space: nowrap;
}
.who b { color: var(--text); font-weight: 700; }
@media (max-width: 1200px) { nav .row { gap: 10px; } }
@media (max-width: 860px) { nav .hidesm { display: none; } }
@media (max-width: 640px) { nav .row { padding: 10px 0; gap: 8px 14px; } }

/* ---- shared bits (verbatim from the property) ---- */
.eyebrow {
  font-size: 0.72rem; letter-spacing: 2.4px; text-transform: uppercase;
  color: var(--dim); display:flex; align-items:center; gap: 10px; flex-wrap: wrap;
}
.eyebrow::before { content:""; width: 26px; height: 2px; background: var(--blue); display:inline-block; flex:none; }
.accent { color: var(--red); }
.panel { background: var(--panel-grad); border: 1px solid var(--border); border-radius: var(--radius); }
.panel + .panel { margin-top: 16px; }
.teamcard.place-gold   { border-color: var(--gold); }
.teamcard.place-silver { border-color: var(--silver); }
.teamcard.place-bronze { border-color: var(--amber); }
.teamcard.place-gold .head b   { color: var(--gold); }
.teamcard.place-silver .head b { color: var(--silver); }
.teamcard.place-bronze .head b { color: var(--amber); }

/* The stacked-panel margin must be cancelled inside every grid, or the second
   cell sits a gap lower than the first. */
.cards3 > .panel, .teamgrid > .panel, .staffgrid > .panel,
.twocol > .panel { margin-top: 0; }
.panel .head,
details.panel > summary {
  font-size:0.68rem; letter-spacing:1.8px; text-transform:uppercase; color:var(--dim);
  padding: 13px 16px; border-bottom:1px solid var(--border);
  display:flex; align-items:center; justify-content:space-between; gap: 10px;
}
.panel .head .n,
details.panel > summary .n { color: var(--faint); letter-spacing: 0.6px; text-transform: none; font-size: 0.72rem; }
.panel .body { padding: 15px 16px; }
.pill { font-size: 0.7rem; padding: 3px 12px; border-radius: 999px; border: 1px solid var(--border); color: var(--dim); letter-spacing: 0.4px; white-space: nowrap; }
.pill.ok { border-color: var(--blue); color: var(--blue-soft); }
.pill.warn { border-color: var(--amber); color: var(--amber); }
.note-box { border-left: 3px solid var(--red); background: var(--inset); padding: 14px 16px; border-radius: 0 var(--radius) var(--radius) 0; margin: 16px 0; font-size: 0.86rem; color: var(--dim); }
.note-box b { color: var(--text); }
.hint { font-size: 0.72rem; color: var(--faint); letter-spacing: 0.3px; }
.prose { font-size: 0.86rem; color: var(--dim); }
.prose b { color: var(--text); }
.prose p + p { margin-top: 8px; }
.measure { max-width: 56ch; }
.scrollbox { overflow-x: auto; }

/* ---- hero ---- */
header.hero { padding: 56px 0 0; }
.hero-grid { display: grid; grid-template-columns: 1fr auto; gap: 32px; align-items: start; }
@media (max-width: 760px) { .hero-grid { grid-template-columns: 1fr; } .crest { display:none; } }
h1 { font-size: clamp(2rem, 5vw, 3.2rem); font-weight: 800; letter-spacing: -1px; line-height: 1.04; margin: 16px 0 12px; }
.lede { color: var(--dim); max-width: 68ch; font-size: 0.92rem; }
.lede b { color: var(--text); font-weight: 600; }
/* The venue is the one proper noun on the page that belongs to someone else,
   so it carries a dotted underline rather than the full link treatment. */
.venue-link { color: inherit; border-bottom: 1px dotted var(--faint); }
.venue-link:hover, .venue-link:focus-visible { color: var(--blue-soft); border-bottom-color: var(--blue); }
.discord-slot {
  margin-left: auto; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.4px;
  color: var(--blue-soft); border: 1px solid var(--blue); border-radius: 999px;
  padding: 4px 13px; white-space: nowrap; text-transform: none;
}
.discord-slot:hover { background: var(--blue); color: #0b0f04; }
/* the crest — the one pictorial element on the page (see DESIGN.md).
   The real WSDoD patch, inlined as a data URI (zero external requests). */
.crest { width: 180px; height: auto; flex: none; margin-top: 12px; }

/* ---- event fact strip ---- */
.statstrip { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-top: 32px; }
.stile { background: var(--panel-grad); border: 1px solid var(--border); border-radius: var(--radius); padding: 13px 15px; }
.stile b { display: block; font-size: 1.3rem; font-weight: 800; color: var(--text); letter-spacing: -0.4px; }
.stile span { display: block; font-size: 0.72rem; color: var(--faint); letter-spacing: 0.4px; }

/* ---- section scaffolding ---- */
section { padding: 48px 0 0; }
.sec-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 14px; margin-bottom: 16px; }
h2 { font-size: 1.3rem; font-weight: 800; letter-spacing: -0.4px; }
.sec-head h2::before { content:""; display:block; width: 26px; height: 2px; background: var(--blue); margin-bottom: 10px; }
.sec-head .meta { font-size: 0.72rem; color: var(--faint); letter-spacing: 0.4px; }

/* ---- folding ----
   Anything the top bar can reach folds away, so a reader can shut the parts
   they didn't come for. Open is the default: a first visit reads whole, and
   the state persists per visitor rather than being baked into the page. */
.foldable { cursor: pointer; }
.foldmark { margin-left: auto; display: inline-flex; align-items: center; gap: 7px; flex: none;
  font-size: 0.62rem; letter-spacing: 1.4px; text-transform: uppercase; color: var(--faint);
  border: 1px solid var(--border); border-radius: 999px; padding: 3px 10px; background: none; font-family: inherit; }
.foldmark::after { content: "\2013"; font-size: 0.8rem; line-height: 1; }
.folded > * > .foldmark::after { content: "+"; }
.foldable:hover .foldmark { color: var(--dim); border-color: var(--dim); }
section.folded > .sec-head { margin-bottom: 0; }
section.folded > .sec-body { display: none; }
.panel.folded > .head { border-bottom: none; }
.panel.folded > .body { display: none; }
/* order keeps it right of the chips even though the switcher re-renders them */
.foldall { margin-left: auto; order: 99; background: none; border: 1px solid var(--border); border-radius: 999px;
  color: var(--faint); font: inherit; font-size: 0.66rem; letter-spacing: 1.4px; text-transform: uppercase;
  padding: 4px 12px; cursor: pointer; }
.foldall:hover { color: var(--dim); border-color: var(--dim); }

/* ---- the weekend cards ---- */
.cards3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; }
.daycard .head b { color: var(--text); letter-spacing: 1.8px; }
.daycard .body { font-size: 0.82rem; color: var(--dim); }
.daycard .body b { color: var(--text); }
.venue-row { display: grid; grid-template-columns: 2fr 3fr; gap: 16px; margin-top: 16px; align-items: start; }
@media (max-width: 860px) { .venue-row { grid-template-columns: 1fr; } }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; font-size: 0.82rem; }
.kv dt { color: var(--faint); font-size: 0.72rem; letter-spacing: 1.4px; text-transform: uppercase; padding-top: 2px; }
.kv dd { color: var(--dim); }
.kv dd b { color: var(--text); }

/* ---- teams ---- */
.teamgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
/* podium-lead: the first three cards are the podium, so they get a row to
   themselves at the width four ordinary cards occupy. A 12-track grid divides
   cleanly both ways — 4 tracks each for three leads, 3 each for the rest —
   which is why the count is 12 and not the 4 the eye sees. Only above 1080px;
   narrower falls back to the auto-fill above, where a wider card buys nothing. */
@media (min-width: 1080px) {
  /* 24 tracks, not 12: three leads at span 8 and fours at span 6 both divide
     evenly, and a short last row can be centred on a half-card offset — which
     a 12-track grid cannot express. The JS sets --tail-start. */
  .teamgrid.podium-lead { grid-template-columns: repeat(24, 1fr); }
  .teamgrid.podium-lead > .teamcard { grid-column: span 6; }
  .teamgrid.podium-lead > .teamcard:nth-child(-n+3) { grid-column: span 8; }
  .teamgrid.podium-lead > .teamcard.tail-first { grid-column: var(--tail-start) / span 6; }
  .teamgrid.podium-lead > .teamcard:nth-child(-n+3) .head b { font-size: 0.95rem; }
  .teamgrid.podium-lead > .teamcard:nth-child(-n+3) .roster li { font-size: 0.88rem; padding: 6px 0; }
  .teamgrid.podium-lead > .teamcard:nth-child(-n+3) .roster .num { font-size: 0.76rem; }
  .teamgrid.podium-lead > .teamcard:nth-child(-n+3) .reg { font-size: 0.72rem; }
}
.teamcard .head b { color: var(--text); letter-spacing: 0.4px; text-transform: none; font-size: 0.82rem; }
.teamcard .head .n { max-width: 12em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.roster { list-style: none; }
.roster li { display: flex; align-items: baseline; gap: 8px; padding: 4px 0; border-bottom: 1px solid var(--rule); font-size: 0.82rem; }
.roster li:last-child { border-bottom: none; }
.roster .num { color: var(--faint); font-size: 0.72rem; min-width: 2ch; text-align: right; }
.roster .cpt { font-size: 0.62rem; letter-spacing: 1px; color: var(--red-soft); border: 1px solid var(--red); border-radius: 4px; padding: 0 5px; }
.roster .nm { color: var(--dim); }
.roster li:first-child .nm { color: var(--text); }
/* Grid stretches the cards to equal height, but the roster lists differ in
   length — a 7-player team pushed its footer below its neighbours'. Flexing
   the body pins every footer to the bottom, so the row reads as one line. */
.teamcard { display: flex; flex-direction: column; }
.teamcard > .body { flex: 1; }
.teamcard .reg { padding: 8px 16px 12px; font-size: 0.68rem; color: var(--faint); letter-spacing: 0.6px; border-top: 1px solid var(--rule); margin-top: 4px; }

/* ---- results / match log ---- */
.logtable { width: 100%; border-collapse: collapse; font-size: 0.78rem; min-width: 520px; }
.logtable th { text-align: left; color: var(--faint); font-weight: 400; font-size: 0.68rem; letter-spacing: 1.4px; text-transform: uppercase; padding: 6px 16px 6px 0; border-bottom: 1px solid var(--border); }
.logtable td { padding: 7px 16px 7px 0; border-bottom: 1px solid var(--rule); color: var(--dim); }
.logtable tr:last-child td { border-bottom: none; }
.logtable td.map { color: var(--text); white-space: nowrap; }
.logtable td.r { text-align: right; padding-right: 24px; }
/* aborted-start rows: dimmed, and the dagger carries the explanation */
.logtable tr.row-aborted td { color: var(--faint); }
.logtable tr.row-aborted td.map { color: var(--dim); }
.mnote { margin-left: 5px; color: var(--amber); cursor: help; font-size: 0.8em; }
.mnote:focus { outline: 1px solid var(--amber); outline-offset: 2px; }
.logtable th.r { text-align: right; padding-right: 24px; }
/* demo cells — the static span is only the no-JS state; the demo-links
   script replaces it with one link per file from #demo-urls. */
.demo-pend { display: inline-block; color: var(--faint); border: 1px dashed var(--border); border-radius: 999px; padding: 0 9px; font-size: 0.7rem; white-space: nowrap; cursor: help; }

/* ---- results: placements podium — filled from the verified standings.
   Same medal treatment as the team cards: border + name carry the metal. ---- */
.podium { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }
.podium .slot { background: var(--inset); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; }
.podium .slot .place { display: block; font-size: 0.68rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--faint); }
.podium .slot b { display: block; font-size: 0.95rem; color: var(--text); margin-top: 4px; }
.podium .slot.p1 { border-color: var(--gold); }
.podium .slot.p2 { border-color: var(--silver); }
.podium .slot.p3 { border-color: var(--bronze); }
.podium .slot.p1 .place, .podium .slot.p1 b { color: var(--gold); }
.podium .slot.p2 .place, .podium .slot.p2 b { color: var(--silver); }
.podium .slot.p3 .place, .podium .slot.p3 b { color: var(--bronze); }
/* the full 1–10, the record the podium highlights */
/* Grid, not CSS columns: columns fill top-to-bottom, so an odd count leaves a
   tall empty column under the last entry. Grid flows across, so the only gap
   is after the final item — which reads as the end of a list, not a hole. */
.placings { list-style: none; display: grid; gap: 2px 40px; margin-top: 16px;
            grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
/* the tail below the podium — fewer entries over the same width, so they get
   room rather than huddling */
.placings.rest { gap: 4px 44px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.placings.rest li { font-size: 0.92rem; padding: 8px 0; }
.placings.rest .pn { font-size: 0.8rem; min-width: 2.4ch; }
.placings li { display: flex; align-items: baseline; gap: 10px; padding: 4px 0; border-bottom: 1px solid var(--rule); font-size: 0.82rem; color: var(--dim); break-inside: avoid; }
.placings .pn { color: var(--faint); font-size: 0.72rem; min-width: 2ch; text-align: right; }
.placings li.m1 .tm { color: var(--gold); font-weight: 700; }
.placings li.m2 .tm { color: var(--silver); font-weight: 700; }
.placings li.m3 .tm { color: var(--bronze); font-weight: 700; }
@media (max-width: 640px) { .placings { columns: 1; } }

/* ---- results: the Sunday playoff bracket.
   Structure carried from the lan-web bracket page (flex round columns whose
   equal-share cells produce the merge-tree geometry; elbow connectors drawn
   with pseudo-elements), re-dressed in the olive tokens. Connections follow
   bracket.json's source_a/source_b (W:QF2 = winner of QF2) — never team names. */
.bkt-tree { display: flex; align-items: stretch; padding: 4px 0 8px; }
.bkt-round { display: flex; flex-direction: column; flex: 1; min-width: 244px; }
.bkt-round + .bkt-round { margin-left: 36px; }
.bkt-round-head { flex: none; text-align: center; font-size: 0.68rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--dim); border-bottom: 1px solid var(--border); padding-bottom: 5px; margin-bottom: 8px; }
.bkt-round-head span { display: block; font-size: 0.68rem; letter-spacing: 0.4px; text-transform: none; color: var(--faint); }
.bkt-body { display: flex; flex-direction: column; flex: 1; }
.bkt-m { flex: 1; display: flex; flex-direction: column; justify-content: center; position: relative; padding: 7px 0; }
.bkt-card { background: var(--inset); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
/* the maps the match was played on (veto.json "played", keyed by mkey) —
   a footer row inside the card so the connector geometry stays untouched */
.bkt-maps { border-top: 1px solid var(--rule); padding: 3px 8px; font-size: 0.62rem; letter-spacing: 0.3px; color: var(--faint); line-height: 1.5; text-align: center; }
/* the veto that produced those maps, on demand. Keyboard-reachable (tabindex on
   the row) because hover-only would hide it from anyone not using a mouse. */
.bkt-maps.has-veto { cursor: help; position: relative; }
/* a dotted underline is the standing convention for "there's more here" —
   without it the veto is a feature nobody discovers */
.bkt-maps.has-veto > .mapline { border-bottom: 1px dotted var(--rule); }
.bkt-maps.has-veto:hover, .bkt-maps.has-veto:focus { color: var(--dim); outline: none; }
.bkt-maps.has-veto:hover > .mapline, .bkt-maps.has-veto:focus > .mapline { border-bottom-color: var(--blue); }
/* fixed and parented to <body>: the bracket lives inside a .scrollbox, whose
   overflow clips any descendant that tries to sit outside the card */
.bkt-veto {
  position: fixed; z-index: 60; min-width: 210px; padding: 8px 10px; text-align: left;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 10px 26px rgba(0,0,0,0.5); pointer-events: none;
}
.bkt-veto .vh { display: block; font-size: 0.6rem; letter-spacing: 1.4px; text-transform: uppercase; color: var(--faint); margin-bottom: 6px; }
/* Grid, not flex: every row shares one set of column widths, so the team names
   left-align in a block, the BAN/PICK labels sit centred in a column of their
   own, and the maps line up. Flex sized each row to its own content and the
   result read as ragged. */
.bkt-veto .vr { display: grid; grid-template-columns: 1fr auto 1fr; gap: 9px;
                align-items: baseline; padding: 2px 0; white-space: nowrap; }
.bkt-veto .va { color: var(--faint); font-size: 0.62rem; text-align: right;
                overflow: hidden; text-overflow: ellipsis; }
.bkt-veto .vt { font-size: 0.58rem; letter-spacing: 0.8px; text-transform: uppercase;
                min-width: 4.8em; text-align: center; }
.bkt-veto .vt.ban { color: var(--red-soft); }
.bkt-veto .vt.pick { color: var(--blue-soft); }
.bkt-veto .vt.decider { color: var(--gold); }
.bkt-veto .vm { color: var(--dim); font-size: 0.66rem; }
.bkt-veto .vs { color: var(--faint); font-size: 0.58rem; margin-left: 5px; }
.bkt-veto .vmwrap { overflow: hidden; text-overflow: ellipsis; }
@media (hover: none) { .bkt-veto { display: none; } }
.bkt-c { display: flex; align-items: center; height: 30px; font-size: 0.78rem; }
.bkt-c + .bkt-c { border-top: 1px solid var(--rule); }
.bkt-seed { width: 22px; min-width: 22px; align-self: stretch; line-height: 30px; text-align: center; font-size: 0.68rem; color: var(--faint); background: var(--panel-2); }
.bkt-name { flex: 1; padding: 0 7px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--faint); }
.bkt-score { width: 20px; min-width: 20px; text-align: center; color: var(--faint); font-variant-numeric: tabular-nums; }
.bkt-c.win .bkt-name, .bkt-c.win .bkt-score { color: var(--blue-soft); font-weight: 700; }
.c-final .bkt-c.win .bkt-name, .c-final .bkt-c.win .bkt-score { color: var(--gold); }
.bkt-champ { font-size: 0.68rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--gold); text-align: center; margin-top: 6px; }
/* upper-bracket connectors: QF/SF pairs elbow into the next round; the
   play-in cells sit in the rows of the QFs they feed and run straight in. */
.bkt-upper .c-qf .bkt-m:nth-child(odd)::after,
.bkt-upper .c-sf .bkt-m:nth-child(odd)::after {
  content: ""; position: absolute; left: 100%; width: 18px; top: 50%; height: 50%;
  border-top: 2px solid var(--border); border-right: 2px solid var(--border); }
.bkt-upper .c-qf .bkt-m:nth-child(even)::after,
.bkt-upper .c-sf .bkt-m:nth-child(even)::after {
  content: ""; position: absolute; left: 100%; width: 18px; bottom: 50%; height: 50%;
  border-bottom: 2px solid var(--border); border-right: 2px solid var(--border); }
.bkt-upper .c-sf .bkt-m::before,
.bkt-upper .c-final .bkt-m::before {
  content: ""; position: absolute; right: 100%; top: 50%; width: 18px; border-top: 2px solid var(--border); }
.bkt-upper .c-playin .bkt-m.has::after {
  content: ""; position: absolute; left: 100%; top: 50%; width: 18px; border-top: 2px solid var(--border); }
.bkt-upper .c-qf .bkt-m.fed::before {
  content: ""; position: absolute; right: 100%; top: 50%; width: 18px; border-top: 2px solid var(--border); }
/* placement matches: same cards, no connectors — deciders, not a tree */
.bkt-lower .bkt-body { gap: 8px; }
.bkt-lower .bkt-m { flex: initial; }
.bkt-lower .bkt-card { max-width: 300px; }
.bkt-tag { font-size: 0.62rem; letter-spacing: 1.4px; text-transform: uppercase; color: var(--faint); margin-bottom: 4px; }
.bkt-sub { font-size: 0.72rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--dim); font-weight: 400; margin: 24px 0 10px; }
.bkt-sub span { display: block; letter-spacing: 0.4px; text-transform: none; color: var(--faint); }

/* ---- stats: day boards ---- */
.daytabs { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }
.daytabs.three { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 640px) { .daytabs, .daytabs.three { grid-template-columns: 1fr; } }
.daytab {
  text-align: left; cursor: pointer; font-family: var(--mono);
  background: var(--panel-grad); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 13px 16px; color: var(--dim);
}
.daytab b { display: block; font-size: 0.92rem; font-weight: 800; color: var(--text); letter-spacing: 0.4px; }
.daytab span { display: block; font-size: 0.72rem; color: var(--faint); letter-spacing: 0.4px; margin-top: 2px; }
.daytab[aria-pressed="true"] { border-color: var(--blue); }
.daytab[aria-pressed="true"] b { color: var(--blue-soft); }
.baseline {
  display: flex; flex-wrap: wrap; gap: 8px 24px; align-items: baseline;
  background: var(--inset); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 16px; margin-bottom: 16px; font-size: 0.78rem; color: var(--dim);
}
.baseline .t { font-size: 0.68rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--faint); }
.baseline b { color: var(--text); }
.filters { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.chipgroup { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.chiplabel { font-size: 0.68rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--faint); min-width: 8ch; }
.chipslot { display: contents; }
/* a chip is a <button> in the single-file preview and an <a> on the built
   site, so the anchor needs the button's reset to look identical */
a.chip { text-decoration: none; display: inline-block; }
.chip[aria-current="page"] { border-color: var(--blue); color: var(--blue-soft); }
.chip {
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.4px; cursor: pointer;
  background: var(--inset); color: var(--dim); border: 1px solid var(--border);
  border-radius: 999px; padding: 5px 14px;
}
.chip:hover { color: var(--text); border-color: #565e3b; }
.chip[aria-pressed="true"] { border-color: var(--blue); color: var(--blue-soft); background: rgba(129,151,70,0.16); }
/* disabled, not hidden: on the weekend view the map filter stays visible so it
   doesn't appear to vanish — the hint alongside says why it's unavailable */
.chip[disabled] { opacity: 0.45; cursor: not-allowed; }
.chip[disabled]:hover { color: var(--dim); border-color: var(--border); }
.chiphint { font-size: 0.72rem; color: var(--faint); letter-spacing: 0.3px; }

.leader { width: 100%; border-collapse: collapse; font-size: 0.78rem; min-width: 1080px; }
.leader th, .leader td { padding-right: 9px; }
/* provenance badge: which pipeline produced the column. HUD figures can include
   warmup; HLStatsX columns are match time only. */
/* absolutely positioned so the badge labels the column without widening it —
   in flow it added ~24px to four headers and pushed the table into a scrollbar */
.leader th { position: relative; }
/* the best streak, told as a run rather than a number */
.streakbox { background: var(--inset); border: 1px solid var(--rule); border-radius: 9px; padding: 10px 12px; margin-bottom: 12px; }
.streakbox h4 { margin: 0 0 5px; }
.sline { font-size: 0.82rem; color: var(--dim); }
.sline b { color: var(--blue-soft); font-size: 0.9rem; }
.sline .swhen { display: block; font-size: 0.66rem; color: var(--faint); margin-top: 2px; }
.sguns { font-size: 0.72rem; color: var(--dim); margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--rule); }
/* the rate beside a count — quieter than the figure it qualifies */
.leader td .pct { margin-left: 5px; color: var(--faint); font-size: 0.66rem; font-variant-numeric: tabular-nums; }
.srcbadge {
  position: absolute; top: -1px; right: 0;
  padding: 0 2px; border: 1px solid var(--rule); border-radius: 3px;
  font-size: 0.48rem; letter-spacing: 0.4px; color: var(--faint); line-height: 1.5;
}
.sortbtn:hover .srcbadge { border-color: var(--border); color: var(--dim); }
/* in prose (note boxes, footers) the badge flows inline — the absolute
   placement above is for column headers, where it must not add width */
.note-box .srcbadge, .status-foot .srcbadge { position: static; margin: 0 3px; font-size: 0.56rem; vertical-align: 1px; }
.leader th { text-align: left; color: var(--faint); font-weight: 400; font-size: 0.68rem; letter-spacing: 1.4px; text-transform: uppercase; padding: 6px 14px 6px 0; border-bottom: 1px solid var(--border); white-space: nowrap; }
.leader th.r, .leader td.r { text-align: right; }
.leader td { padding: 7px 14px 7px 0; border-bottom: 1px solid var(--rule); color: var(--dim); vertical-align: middle; white-space: nowrap; }
/* 18ch, not 24: clan tags are stripped for display, so the names are shorter
   and the saved width is what keeps the board out of a horizontal scrollbar.
   The full in-game name is still on the cell's title. */
.leader td.player { color: var(--text); max-width: 18ch; overflow: hidden; text-overflow: ellipsis; }
.leader td.rank { color: var(--faint); }
/* medal colouring follows the CURRENT sort and filter — rank 1 of the active
   metric is gold wherever it sits. The rank number carries the information;
   colour only reinforces it. */
.leader tr.m1 td.rank, .leader tr.m1 td.player { color: var(--gold); font-weight: 700; }
.leader tr.m2 td.rank, .leader tr.m2 td.player { color: var(--silver); font-weight: 700; }
.leader tr.m3 td.rank, .leader tr.m3 td.player { color: var(--bronze); font-weight: 700; }
.leader tr.m45 td.rank, .leader tr.m45 td.player { color: var(--medal45); font-weight: 700; }
/* sortable headers */
.sortbtn {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
  display: inline-flex; align-items: baseline; gap: 5px; white-space: nowrap;
}
.sortbtn:hover { color: var(--text); }
.leader th[aria-sort] .sortbtn { color: var(--blue-soft); }
.sortbtn .dir { font-size: 0.58rem; line-height: 1; }
.tipcue { border-bottom: 1px dotted var(--faint); }
/* KTPR definition tooltip — shown on hover AND keyboard focus of the header */
.tooltip {
  position: fixed; z-index: 80; max-width: 360px;
  background: var(--inset); border: 1px solid var(--border); border-radius: 10px;
  padding: 12px 14px; font-size: 0.72rem; color: var(--dim); line-height: 1.55;
  letter-spacing: 0.2px; text-transform: none; white-space: normal;
  box-shadow: 0 10px 28px rgba(0,0,0,0.5);
}
.tooltip b { color: var(--text); }
.tooltip .formula {
  display: block; background: var(--panel); border: 1px solid var(--border);
  border-radius: 6px; padding: 8px 10px; margin: 8px 0; color: var(--blue-soft);
  font-size: 0.68rem; white-space: normal;
}
/* the same treatment standing on its own, for the About KTPR panel where a
   formula is the content rather than an aside. Pre-wrapped and scrollable:
   the alignment carries the reading, so it must not reflow. */
.formula {
  display: block; background: var(--inset); border: 1px solid var(--border);
  border-radius: 8px; padding: 11px 13px; margin: 6px 0 14px;
  color: var(--blue-soft); font-size: 0.72rem; line-height: 1.65;
  white-space: pre; overflow-x: auto;
}
.formula .c { color: var(--faint); }
.kt-about .body > p + p { margin-top: 10px; }
.kt-about h4 {
  font-size: 0.68rem; letter-spacing: 1.8px; text-transform: uppercase;
  color: var(--faint); font-weight: 400; margin: 16px 0 2px;
}
.kt-thanks { border-top: 1px solid var(--rule); margin-top: 16px; padding-top: 12px; }
/* the view tabs are the next thing after the About panel and read as attached
   to it without this — they are the board's controls, not part of the essay */
.kt-about { margin-bottom: 24px; }
/* the bar is the widest discretionary thing in the row — trimmed so the extra
   HS and Prone columns fit without the board needing a horizontal scrollbar */
.ktprcell { display: flex; align-items: center; gap: 7px; min-width: 92px; }
.ktprcell b { color: var(--text); font-weight: 700; min-width: 4.4ch; }
.ktprbar { flex: 1; height: 4px; background: var(--inset); border-radius: 999px; overflow: hidden; min-width: 28px; }
.ktprbar i { display: block; height: 100%; background: var(--blue); border-radius: 999px; }
.rolepill { font-size: 0.68rem; letter-spacing: 0.6px; border: 1px solid var(--border); color: var(--dim); border-radius: 4px; padding: 1px 7px; }
.rolepill.inferred { border-style: dashed; }
.detailbtn {
  background: var(--inset); color: var(--faint); border: 1px solid var(--border);
  border-radius: 999px; padding: 1px 10px; font-size: 0.68rem; cursor: pointer;
  font-family: var(--mono); letter-spacing: 0.4px;
}
.detailbtn:hover { border-color: var(--blue); color: #e6e3cf; }
.detailbtn[aria-expanded="true"] { border-color: var(--blue); color: var(--blue-soft); }
tr.detail > td { padding: 0 0 16px; white-space: normal; }
.detailgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px; padding: 14px 16px; background: var(--inset); border: 1px solid var(--border); border-radius: 10px; margin-top: 8px; }
.detailgrid h4 { font-size: 0.68rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--faint); font-weight: 400; margin-bottom: 8px; }
.hbrow { display: flex; align-items: center; gap: 8px; font-size: 0.72rem; padding: 2px 0; }
.hbrow .lbl { min-width: 9ch; color: var(--dim); }
.hbrow .bar { flex: 1; height: 4px; background: var(--panel); border-radius: 999px; overflow: hidden; }
.hbrow .bar i { display: block; height: 100%; background: var(--blue); border-radius: 999px; }
.hbrow .ct { color: var(--faint); min-width: 8ch; text-align: right; }
.kvmini { display: grid; grid-template-columns: 1fr auto; gap: 2px 14px; font-size: 0.72rem; }
.kvmini dt { color: var(--dim); }
.kvmini dd { color: var(--text); text-align: right; }
.showall { margin-top: 12px; }
.btn {
  display: inline-block;
  background: var(--blue); color: #0b0f04; border: 1px solid var(--blue);
  border-radius: 10px; padding: 8px 18px;
  font-family: var(--mono); font-size: 0.78rem; font-weight: 700; letter-spacing: 0.6px;
  cursor: pointer; text-align: center;
  transition: background .16s ease, border-color .16s ease;
}
.btn:hover { background: #93aa55; border-color: #93aa55; }
.btn.ghost { background: var(--inset); color: var(--text); border-color: var(--border); }
.btn.ghost:hover { border-color: var(--blue); color: #e6e3cf; }
.status-foot { font-size: 0.78rem; color: var(--faint); margin-top: 12px; letter-spacing: 0.3px; }
.status-foot b { color: var(--dim); }

/* ---- rules ---- */
details.panel > summary { border-bottom: none; cursor: pointer; list-style: none; user-select: none; }
details.panel > summary::-webkit-details-marker { display: none; }
details.panel > summary:hover { color: var(--text); }
details.panel > summary::after { content: "+"; color: var(--faint); font-size: 0.95rem; flex: none; }
details.panel[open] > summary { border-bottom: 1px solid var(--border); }
details.panel[open] > summary::after { content: "\2013"; }
.reglist { font-size: 0.82rem; color: var(--dim); }
.reglist h4 { font-size: 0.72rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--text); font-weight: 700; margin: 14px 0 6px; }
.reglist h4:first-child { margin-top: 0; }
.reglist .reg { display: grid; grid-template-columns: 4.5ch 1fr; gap: 10px; padding: 4px 0; border-bottom: 1px solid var(--rule); }
.reglist .reg:last-child { border-bottom: none; }
.reglist .no { color: var(--red-soft); font-size: 0.72rem; text-align: right; }
.reglist b { color: var(--text); }
.fineprint { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--rule); font-size: 0.78rem; color: var(--faint); line-height: 1.65; }
.fineprint b { color: var(--dim); }

/* ---- staff ---- */
.staffgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
.staffsub { font-size: 0.72rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--faint); font-weight: 400; margin: 16px 0 10px; }
/* awards: a card per category. The leader is the loudest thing on a decided
   card; a vote card has no leader and says so rather than showing a blank. */
.awardgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 12px; }
.awardcard { background: var(--panel-grad); border: 1px solid var(--border); border-radius: var(--radius); padding: 13px 15px 14px; display: flex; flex-direction: column; }
/* Blurbs and runner lists wrap to different depths, which floated each card's
   winner line to its own height across a row. Subgrid puts the four parts on
   shared tracks so the winners read as one rank. */
@supports (grid-template-rows: subgrid) {
  .awardcard { display: grid; grid-template-rows: subgrid; grid-row: span 4; }
  .awardcard .ab { flex: none; }
}
.awardcard .at { font-size: 0.86rem; color: var(--text); font-weight: 700; letter-spacing: 0.3px; }
.awardcard .ab { font-size: 0.72rem; color: var(--faint); margin-top: 4px; line-height: 1.5; flex: 1; }
.awardcard .lead { margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--rule); }
.awardcard .lead .cap { display: block; font-size: 0.6rem; letter-spacing: 1.2px; text-transform: uppercase; color: var(--faint); margin-bottom: 5px; }
/* name and figure share a line — the figure stranded underneath read as a
   loose number rather than as this player's result */
.awardcard .lead .row1 { display: flex; align-items: baseline; gap: 9px; }
/* the podium three carry the same medal colours the leaderboard uses, so a
   glance at a card reads the same way a glance at the board does */
.awardcard .lead .who { font-size: 0.86rem; color: var(--gold); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.awardcard .lead .val { color: var(--gold); }
.awardcard .lead .val { margin-left: auto; font-size: 0.82rem; color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.awardcard .lead .ctx { display: block; font-size: 0.63rem; color: var(--faint); margin-top: 3px; }
.awardcard.novote .lead .who { color: var(--faint); font-weight: 400; font-size: 0.76rem; }
/* runners-up, always visible — the point is to be able to announce a category */
.runners { margin-top: 9px; border-top: 1px solid var(--rule); padding-top: 7px; }
.runners li { display: grid; grid-template-columns: 1.3em 1fr auto; gap: 6px; align-items: baseline; padding: 3px 0; font-size: 0.7rem; }
.runners li + li { border-top: 1px solid var(--rule); }
.runners li::before { content: counter(rn) "."; counter-increment: rn; color: var(--faint); font-size: 0.62rem; }
/* rows carry their competition rank as data — tied players print the same
   number rather than the counter inventing an order between them */
.runners li[data-rank]::before { content: attr(data-rank) "."; }
.runners { list-style: none; counter-reset: rn 1; }
.runners .rn { color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.runners .rv { color: var(--dim); font-variant-numeric: tabular-nums; }
/* medal colours follow the placing on the row — a shared 2nd is two silvers
   and nobody is 3rd. Rank-less rows (an unranked regen) fall back to position;
   a tie has no order, and .tied opts out. */
.runners:not(.tied) li[data-rank="2"] .rn,
.runners:not(.tied) li[data-rank="2"] .rv,
.runners:not(.tied) li:nth-child(1):not([data-rank]) .rn,
.runners:not(.tied) li:nth-child(1):not([data-rank]) .rv { color: var(--silver); font-weight: 700; }
.runners:not(.tied) li[data-rank="3"] .rn,
.runners:not(.tied) li[data-rank="3"] .rv,
.runners:not(.tied) li:nth-child(2):not([data-rank]) .rn,
.runners:not(.tied) li:nth-child(2):not([data-rank]) .rv { color: var(--bronze); font-weight: 700; }
.runners .rw { grid-column: 2 / -1; color: var(--faint); font-size: 0.6rem; }
/* The best six reads as a roster: rifle heavy 3rd / rifle heavy sniper. Three
   fixed columns, because auto-fit would reflow it to 2 or 4 and break the
   pairing the layout is there to show. Capped and centred so six slots don't
   stretch across the full breakout width. Recovered from git history
   (68c3431) for the render:"positions" award -- see the awards script. */
.sixgrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px;
           max-width: 860px; margin: 0 auto; }
@media (max-width: 720px) { .sixgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 460px) { .sixgrid { grid-template-columns: 1fr; } }
/* the alias a record was actually set under, when it isn't the usual name */
.alias { color: var(--faint); font-size: 0.6rem; font-style: italic; }
.sixslot { background: var(--inset); border: 1px solid var(--border); border-radius: 9px; padding: 10px 12px; }
.sixslot .sr { display: block; font-size: 0.6rem; letter-spacing: 1.4px; text-transform: uppercase; color: var(--faint); margin-bottom: 5px; }
.sixslot .row1 { display: flex; align-items: baseline; gap: 8px; }
.sixslot .who { font-size: 0.86rem; color: var(--blue-soft); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sixslot .val { margin-left: auto; font-size: 0.78rem; color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sixslot .ctx { display: block; font-size: 0.63rem; color: var(--faint); margin-top: 3px; }
.shortlist { margin-top: 9px; }
.shortlist > summary { cursor: pointer; list-style: none; font-size: 0.62rem; letter-spacing: 1.2px; text-transform: uppercase; color: var(--faint); }
.shortlist > summary::-webkit-details-marker { display: none; }
.shortlist > summary::before { content: "+ "; }
.shortlist[open] > summary::before { content: "− "; }
.shortlist > summary:hover { color: var(--dim); }
.shortlist ol { list-style: none; counter-reset: sl; margin-top: 7px; }
.shortlist li { counter-increment: sl; display: grid; grid-template-columns: 1.4em 1fr auto; gap: 6px; align-items: baseline; padding: 3px 0; border-top: 1px solid var(--rule); font-size: 0.7rem; }
.shortlist li::before { content: counter(sl) "."; color: var(--faint); font-size: 0.62rem; }
.shortlist .sn { color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shortlist .sv { color: var(--text); font-variant-numeric: tabular-nums; }
.shortlist .sw { grid-column: 2 / -1; color: var(--faint); font-size: 0.6rem; }
/* ballots — one per vote category, each printing the rule that built its list */
.ballot select { width: 100%; background: var(--inset); color: var(--text); border: 1px solid var(--border); border-radius: 8px; padding: 9px 11px; font: inherit; font-size: 0.84rem; }
.ballot select:focus { outline: 2px solid var(--blue); outline-offset: 1px; }
.crit { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; }
.crit li { font-size: 0.68rem; color: var(--dim); background: var(--inset); border: 1px solid var(--rule); border-radius: 999px; padding: 4px 11px; }
.awardcard.jump { cursor: pointer; }
.awardcard.jump:hover { border-color: var(--blue); }
/* ---- awards: API-driven candidates (vote, tie tiers, inline rename, and the
   master-only publish checkbox + tally) ----
   Staff-only affordances (.votebox, .renamed-badge, .renamebox,
   .mastercontrols) render conditionally in JS and are shared between
   .awardcard and the render:"positions" panel below, so none of them require
   an .awardcard ancestor. The card underneath is the exact anatomy above,
   extended not rewritten. */
.awardcard { position: relative; }
/* the vote toggle nests inside the title slot rather than adding a row of its
   own -- see the "exactly four children" comment on card() in the awards
   script. The panel below isn't part of that subgrid, so its toggle is a
   plain flex child of .head instead (see .panel .head .votebox further down). */
.awardcard .at.has-vote { padding-right: 24px; }
.awardcard .votebox { position: absolute; top: 13px; right: 15px; display: flex; align-items: center; }
.votebox input { width: 15px; height: 15px; accent-color: var(--blue); cursor: pointer; }
/* every staff member votes; a card they haven't lit reads as inert rather
   than live -- same premise "selected" used to carry, now driven by my_vote */
.notvoted { opacity: 0.5; }
.notvoted:hover { opacity: 0.8; }
.renamed-badge { display: block; width: fit-content; font-size: 0.56rem; padding: 2px 8px; margin-top: 4px; }
.renamebox { margin-top: 9px; }
/* master-only: the real publish checkbox + the tally, independent of the
   voting toggle above -- a master may tick an award they didn't vote for */
.mastercontrols { display: flex; align-items: center; gap: 8px; margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--rule); font-size: 0.68rem; color: var(--dim); }
.mastercontrols label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.mastercontrols input { width: 15px; height: 15px; accent-color: var(--blue); cursor: pointer; }
.mastercontrols .votecount { margin-left: auto; color: var(--faint); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* tie_width 2-4: every winner is a real winner, so all of them go gold rather
   than the board picking one to lead */
.awardcard .who-stack { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.awardcard .who-stack .who { display: block; }
/* tie_width 5+: a stat that wide isn't picking a winner, so the card says so
   instead of dressing up a coin-flip -- names sit behind the fold, closed */
.awardcard.shared { border-style: dashed; }
.awardcard.shared .lead .who { color: var(--faint); font-weight: 400; font-size: 0.76rem; }
.awardcard.shared .lead .val { color: var(--dim); }
/* render:"positions" panel head -- title/badge/subtitle on the left, the
   vote toggle a plain flex sibling on the right (no subgrid to respect here) */
.panel .head .headleft { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.panel .head .votebox { flex: none; }
/* staff capability cards — what a signed-in admin can change */
.capcard .body ul { list-style: none; }
.capcard .body li { font-size: 0.8rem; color: var(--dim); padding: 5px 0; border-bottom: 1px solid var(--rule); display: flex; gap: 8px; align-items: baseline; }
.capcard .body li:last-child { border-bottom: none; }
.capcard .body li::before { content: "→"; color: var(--faint); font-size: 0.72rem; }
/* player photo gallery — the four filed at the event */
.photogrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 10px; }
.photogrid figure { margin: 0; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: var(--inset); }
.photogrid img { display: block; width: 100%; height: 150px; object-fit: cover; background: var(--panel-2); }
.photogrid figcaption { padding: 6px 9px 8px; font-size: 0.68rem; color: var(--dim); line-height: 1.45; }
.photogrid figcaption .by { display: block; color: var(--faint); font-size: 0.62rem; letter-spacing: 0.4px; margin-top: 2px; }
/* asking for a photo to come down. Kept as quiet as the shortlist disclosures
   it borrows its summary from — this is a request to staff, not a delete. */
.removal { margin-top: 7px; }
.removal label { display: block; font-size: 0.6rem; letter-spacing: 1.2px; text-transform: uppercase; color: var(--faint); margin: 7px 0 4px; }
.removal input { width: 100%; background: var(--inset); color: var(--text); border: 1px solid var(--border); border-radius: 7px; padding: 5px 8px; font: inherit; font-size: 0.68rem; }
.removal input:focus { border-color: var(--blue); }
.removal .btn { font-size: 0.66rem; padding: 4px 11px; margin-top: 7px; }
.removal p { margin-top: 6px; }
.upl-file { color: var(--dim); }
.upl-by { color: var(--text); }
.staffcard { background: var(--panel-grad); border: 1px solid var(--border); border-radius: var(--radius); padding: 11px 15px; }
.staffcard b { display: block; font-size: 0.82rem; color: var(--text); font-weight: 700; }
.staffcard span { display: block; font-size: 0.68rem; color: var(--faint); letter-spacing: 0.6px; text-transform: uppercase; }

/* ---- archive ---- */
/* stretch, not start: side-by-side panels with unequal prose (Archive's Demos
   vs Broadcast) otherwise end at different heights and read as misaligned */
.twocol { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: stretch; }
.twocol > .panel { display: flex; flex-direction: column; }
.twocol > .panel > .body { flex: 1; }
/* The upload forms hold a different number of fields, so their buttons landed
   at different heights. Let the last field absorb the slack instead. */
.twocol > .panel > .body > form { display: flex; flex-direction: column; height: 100%; }
.twocol > .panel > .body > form .field:last-of-type { margin-bottom: auto; }
.twocol > .panel > .body > form > .btn,
.twocol > .panel > .body > form > button { align-self: flex-start; margin-top: 18px; }
@media (max-width: 860px) { .twocol { grid-template-columns: 1fr; } }

/* ---- feedback form (field treatment verbatim from support-web, itself
   from the bundles-web login) ---- */
.field { margin-bottom: 18px; }
.field label {
  display: block; font-size: 0.68rem; letter-spacing: 1.8px; text-transform: uppercase;
  color: var(--dim); margin-bottom: 7px;
}
.field label .soft { text-transform: none; letter-spacing: 0; }
.field input, .field select, .field textarea {
  width: 100%;
  background: var(--inset); border: 1px solid var(--border); border-radius: 10px;
  color: var(--text); font-family: var(--mono); font-size: 0.92rem;
  padding: 12px 14px; outline: none;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--blue); }
.field input::placeholder, .field textarea::placeholder { color: var(--faint); }
.field .hint { margin-top: 6px; }
.field textarea { resize: vertical; min-height: 110px; }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
/* the signed-in identity line — attribution is the point of the form */
.fb-id { display: inline-flex; align-items: center; gap: 8px; font-size: 0.78rem; color: var(--dim); border: 1px solid var(--blue); border-radius: 999px; padding: 5px 14px; margin-bottom: 16px; }
.fb-id b { color: var(--blue-soft); font-weight: 700; }
.fb-id a { color: var(--faint); font-size: 0.72rem; }
/* one status line for everything that talks to the backend. Colour is the
   outcome — nothing here ever says "sent" without the server having said so. */
.formstat { font-size: 0.72rem; letter-spacing: 0.3px; color: var(--dim); margin-top: 10px; min-height: 1em; }
.formstat.work { color: var(--amber); }
.formstat.ok   { color: var(--blue-soft); }
.formstat.err  { color: var(--red-soft); }
.formstat:empty { margin-top: 0; min-height: 0; }
input[type="file"] { font-size: 0.78rem; }
.btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.btn[disabled]:hover { background: var(--blue); border-color: var(--blue); }
.btn.ghost[disabled]:hover { background: var(--inset); border-color: var(--border); }

/* ---- edition switcher — the archive's spine. One row, static like the nav;
   chips reuse the board-filter chip treatment. Rendered from #editions by JS
   (adding an edition is a data change, not a markup change). ---- */
.edbar { border-bottom: 1px solid var(--border); background: rgba(16,20,7,0.45); }
.edbar .edrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding-top: 9px; padding-bottom: 9px; }
.edlabel { font-size: 0.68rem; letter-spacing: 1.8px; text-transform: uppercase; color: var(--faint); margin-right: 4px; }
.edchip-note { font-size: 0.68rem; color: var(--faint); letter-spacing: 0.4px; }

/* ---- footer ---- */
footer { border-top: 1px solid var(--border); padding: 32px 0 72px; color: var(--dim); font-size: 0.82rem; margin-top: 48px; }
footer.split { display:flex; flex-wrap:wrap; gap: 24px; justify-content: space-between; }
footer .col { max-width: 46ch; }
footer h4 { color: var(--text); font-size: 0.72rem; letter-spacing: 1.6px; text-transform: uppercase; margin-bottom: 8px; }
footer p { margin: 4px 0; }
footer .accent { color: var(--red); white-space: nowrap; }

/* ---- stats publication gate ---- */
/* #stats only -- 2026. #stats-25 is a past event with its own baked payload
   and is deliberately NOT covered by this gate; don't extend the selector to
   "cover both editions" without deciding that on purpose. */
/* The board hides, not the whole section: .sec-head and the "being compiled"
   line stay up, so #stats reads the way #awards does when its own gate is
   off (an honest placeholder) rather than the heading and nav link both
   vanishing with no word said. */
.stats-placeholder { display: none; }
body[data-stats="off"] #stats .stats-body { display: none; }
body[data-stats="off"] #stats .stats-placeholder { display: block; }
body[data-stats="off"] [data-stats-link] { display: none; }

/* ---- MOCKUP-ONLY publication switcher — not part of the design ---- */
.mock {
  position: fixed; right: 14px; bottom: 14px; z-index: 90;
  background: var(--inset); border: 2px dashed var(--amber); border-radius: 12px;
  padding: 10px 12px; max-width: 260px;
}
.mock .tag { display: block; font-size: 0.68rem; letter-spacing: 1.4px; text-transform: uppercase; color: var(--amber); margin-bottom: 8px; }
.mock .btns { display: flex; flex-wrap: wrap; gap: 6px; }
.mock button {
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.4px;
  background: var(--panel); color: var(--dim); border: 1px solid var(--border);
  border-radius: 999px; padding: 5px 12px; cursor: pointer;
}
.mock button[aria-pressed="true"] { border-color: var(--blue); color: var(--blue-soft); background: rgba(129,151,70,0.16); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; scroll-behavior: auto; }
}

/* ---- demo links in the match log ---- */
.demo-links { display: inline-flex; flex-wrap: wrap; gap: 5px; justify-content: flex-end; }
.demo-links a {
  font-size: 0.68rem; letter-spacing: 0.3px; white-space: nowrap;
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 8px;
  color: var(--dim); text-decoration: none;
}
.demo-links a:hover { border-color: var(--blue); color: var(--blue-soft); }
.demo-none { color: var(--faint); font-size: 0.72rem; }
.logtable td.teams { color: var(--text); white-space: nowrap; }
.logtable td.teams .vs { color: var(--faint); padding: 0 4px; }
