/* Big12ology shared chrome — served at big12ology.com/brand.css
 * Used by the hub, /tiebreaker/, and /attendance/. Topbar, header, pill nav
 * and footer; each project keeps its own body styles.
 *
 * Theme: an explicit choice in the toggle beats the OS preference, so every
 * dark declaration appears twice — once under prefers-color-scheme for
 * readers on "system", once under [data-theme="dark"] for readers who chose.
 * The pairs are kept adjacent; change them together or they drift. */

/* ==== brand tokens ======================================================= */
:root {
  --b12-ink:        #16181A;
  --b12-graphite:   #252932;
  --b12-bone:       #F2F1EC;
  --b12-teal:       #0B6E77;   /* chrome accent, light                     */
  --b12-teal-text:  #09565D;   /* teal as body copy, AAA on the cream      */
  --b12-teal-tile-dark: #0E8A94;
  --b12-teal-lit:   #3FC7CE;   /* chrome accent, dark                      */

  --b12-accent: var(--b12-teal);
  --b12-fg:     var(--b12-ink);
  /* The measure the whole domain lays out against. It was 1120 — a prose
     measure — with the Lab overriding it to 1320 because it is two columns
     of tables rather than paragraphs. The wide one won: every page here is
     ultimately a board, a slate or a table, and the extra 200px is the
     difference between a subnav that fits and one that clips its last tab.
     What prose needs is a cap on the PARAGRAPH, not on the page, which is
     what --measure below does. */
  --chrome-w: 1320px;
  /* Body copy stops here however wide the page gets. 68 characters is the
     readable line the old 1120 was really protecting. */
  --measure: 68ch;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --b12-accent: var(--b12-teal-lit); --b12-fg: var(--b12-bone);
  }
}
:root[data-theme="dark"] {
  --b12-accent: var(--b12-teal-lit); --b12-fg: var(--b12-bone);
}

/* TEAL IS CHROME ONLY. It never appears inside or beside a percentile-
   colored cell: brand teal and the ramp's greens sit at the same lightness
   and measure 1.00:1 against each other, separated by hue alone — a gap that
   narrows further under deuteranopia. Inside the data region carry emphasis
   with weight, a rule, or the mono/sans split. Never with hue. Full
   derivation in tokens.css. */

/* ==== the type scale ======================================================
   ONE scale, for every section. This file is the only stylesheet every page
   on the domain loads — the hub, the tracker, the schedule, the attendance
   tracker and the pools all link it — so it is the only place a rule about
   type can actually be true everywhere.

   It exists because there was no scale at all: 22 distinct sizes across 176
   declarations, including six half-pixel values and the same chaos-index
   number set at 36px on one page and 38px on another. Sizes were picked to
   look right beside whatever was next to them, which is how a game page ends
   up with its own subject (19px) smaller and lighter than a spread inside a
   card below it (20px).

   The steps, and what each one is FOR. Pick by role, never by how big it
   needs to look:

     --t-display   64   a single glyph that IS the page (the 404)
     --t-hero      36   one number that is the whole point of its card
     --t-title     26   the masthead: what site am I on
     --t-headline  24   what this page is about
     --t-lead      20   a primary figure inside a card
     --t-subhead   17   a name or lead line inside a card
     --t-body      16   body copy
     --t-copy      15   secondary copy, dense body
     --t-label     14   card labels, the uppercase h2s
     --t-row       13   table and list rows
     --t-meta      12   captions and sub-labels
     --t-fine      11   chips and tags
     --t-micro     10   the smallest marks

   A size that is not on this list is a bug, not a decision. If something
   genuinely needs a step that is not here, add it here and give it a role —
   do not write the number at the call site. */
:root {
  --t-display:  64px;   /* a single glyph that IS the page: the 404 */
  --t-hero:     36px;
  --t-title:    26px;
  --t-headline: 24px;
  --t-lead:     20px;
  --t-subhead:  17px;
  --t-body:     16px;
  --t-copy:     15px;
  --t-label:    14px;
  --t-row:      13px;
  --t-meta:     12px;
  --t-fine:     11px;
  --t-micro:    10px;
}

/* ==== a card stays inside its column =====================================
   Cards sit in grid tracks — the Lab and the race board run two columns of
   them side by side — and a grid item's automatic minimum size is its
   min-content width, not zero. So one thing inside a card that refused to
   shrink (a control group set flex:0 0 auto, a line of text set nowrap)
   made the whole CARD wider than the track it was handed. Nothing clipped
   it: it drew straight across the gutter and the column beside it painted
   over the top, which is why the symptom read as a card with no padding on
   one side, sitting under its neighbor.

   min-width:0 is the whole fix and it is structural. The card no longer
   contributes a minimum to the track, so the track keeps the width the
   layout meant it to have, and the card fits in it. max-width says the same
   thing from the other side, for a card sized by something that is not a
   track at all.

   It moves the problem inward, which is the point: content that will not
   fit now overflows its own card, visibly, instead of paving over the one
   next to it. Anything that genuinely cannot shrink still has to be told
   how to give — wrap, truncate, or scroll — where that content is defined.
   Two were, when this landed: .wgroup on the Lab's control row, which now
   breaks inside itself rather than never, and .clrec on the race rows,
   which now wraps. */
.card, .chart-card { min-width: 0; max-width: 100%; }

/* ==== collapsible cards ==================================================
   Every card on the domain opens expanded and closes if the reader says so;
   cards.js does the wiring, this does the hiding. Defined here because this
   is the one stylesheet every page loads, and the rule has to be true in all
   five places cards are generated. */
/* Heading-agnostic for the same reason the rules below are: cards.js takes
   `:scope > h2, :scope > h3` on both kinds of card, so a .chart-card headed
   by an h2 — which is how the attendance tracker heads all of its — matched
   NEITHER selector and kept the browser's own button chrome. A bordered grey
   chip where a chart title belongs. */
.card > :is(h2, h3) .cardtoggle,
.chart-card > :is(h2, h3) .cardtoggle {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  font: inherit; color: inherit; letter-spacing: inherit;
  text-transform: inherit; text-align: left;
}
.card > :is(h2, h3) .cardtoggle:focus-visible,
.chart-card > :is(h2, h3) .cardtoggle:focus-visible {
  outline: 2px solid var(--b12-accent); outline-offset: 3px;
  border-radius: 3px;
}
.cardlabel { min-width: 0; }

/* Prose stops at a readable measure even where the page does not. The notes
   under the boards are full-width children of a full-width card, so at 1320
   they ran about 190 characters to the line — a paragraph you lose your
   place in on the way back. Only the TEXT is capped; the table above it goes
   on using the whole page, which is the point of the width. They were
   already 160 characters at 1120, so this is an old problem the new width
   made visible rather than one it caused. */
.note { max-width: var(--measure); }
.cardchev {
  width: 15px; height: 15px; flex: none; margin-left: auto;
  opacity: .55; transition: transform .15s ease;
}
/* Heading-agnostic, all three of these. cards.js takes `:scope > h2, :scope
   > h3` on BOTH .card and .chart-card, so which tag heads a card is the
   page's choice — and these rules had it fixed the other way, h2 for .card
   and h3 for .chart-card. Attendance heads its chart cards with h2, so its
   chevron never turned, and worse, `.chart-card.is-collapsed > *:not(h3)`
   matched that very h2 and hid the heading a collapsed card is supposed to
   leave behind. The pre-paint stylesheet cards.js writes already spells it
   `*:not(h2):not(h3)`; this now agrees with it. */
.cardtoggle[aria-expanded="false"] .cardchev {
  transform: rotate(-90deg);
}
/* Everything but the heading. Not a wrapper — the card's children stay where
   the scripts that fill them expect to find them. */
.card.is-collapsed > *:not(h2):not(h3),
.chart-card.is-collapsed > *:not(h2):not(h3) { display: none !important; }
/* A collapsed card is a line, so it should not also carry the padding of a
   full one — nor the HEIGHT of one. A grid item stretches to its row by
   default, so closing one of a pair left a card that had hidden its contents
   correctly and then inflated to match the open card beside it: a tall empty
   box with a title in the corner. It read as a chart that had vanished
   rather than one that had been put away, and on the attendance tracker —
   where the panels are built after load and the saved state is applied on
   the second pass — it read as a chart that flashed on and then disappeared.
   align-self covers grid and flex both; it is inert everywhere else. */
.card.is-collapsed, .chart-card.is-collapsed {
  padding-bottom: 8px; align-self: start;
}
.card.is-collapsed > :is(h2, h3),
.chart-card.is-collapsed > :is(h2, h3) { margin-bottom: 0; }
@media (prefers-reduced-motion: reduce) { .cardchev { transition: none; } }

/* ==== the fork ==========================================================
   Two results, two teams, four numbers. Defined here rather than in the
   tiebreaker section because the hub shows the same component for the
   week's biggest game, and one stylesheet is the only way the two can be
   the same thing rather than two things that look alike. */
/* THE FORK: two results side by side, each holding both teams. The column
   carries the winning side's colour as a top rule, so which branch you are
   reading is answered before you read a word of it — and the two columns are
   the same shape, because the whole point is that they are comparable. */
.forkgrid { display:grid; grid-template-columns:1fr 1fr; gap:12px;
  margin:12px 0 4px }
.forkcol { border:1px solid var(--line); border-radius:9px; padding:10px 12px;
  border-top:3px solid var(--fc, var(--accent)); min-width:0 }
.forkhead { font-size:var(--t-meta); text-transform:uppercase;
  letter-spacing:.05em; color:var(--dim); margin-bottom:7px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
.forkcell { display:grid; grid-template-columns:minmax(0,1fr) auto auto;
  align-items:baseline; gap:8px; margin:5px 0; font-size:var(--t-row) }
.forkteam { display:flex; align-items:center; gap:6px; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.forkp { font-size:var(--t-subhead); font-variant-numeric:tabular-nums }
/* The move, not the level. Colour is never the only signal — the arrow says
   the same thing, which is the rule the pools board already follows. */
.forkd { font-size:var(--t-meta); font-variant-numeric:tabular-nums;
  white-space:nowrap; color:var(--dim) }
.forkd.up { color:#136536 }
.forkd.down { color:var(--warn) }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .forkd.up { color:#4ade80 }
}
:root[data-theme="dark"] .forkd.up { color:#4ade80 }
/* List density. Same component, tighter: eight of these stack under one
   heading on the race page, where the game page shows exactly one. */
.forkgrid.compact { gap:8px; margin:6px 0 2px }
.forkgrid.compact .forkcol { padding:7px 9px; border-radius:7px;
  border-top-width:2px }
.forkgrid.compact .forkhead { font-size:var(--t-fine); margin-bottom:4px }
.forkgrid.compact .forkcell { font-size:var(--t-meta); margin:3px 0 }
.forkgrid.compact .forkp { font-size:var(--t-row) }
/* THE REST OF THE LEAGUE, inside the branch that moves it. A rule rather
   than a heading: "playing" and "watching" are two kinds of fact, not two
   amounts of one, and a second label in a box this size competes with the
   branch heading that gives every number in it its meaning.

   Dimmer, but only by weight — the numbers keep their size and their arrow,
   because the question these rows answer is the same question the two above
   them answer, and a reader who has to squint at half of it will read the
   fork as being about the two teams with a footnote attached. */
.forkrest { border-top:1px solid var(--line); margin-top:8px; padding-top:6px }
/* THE SECOND READING, on a preview page only. Same grid, same columns, same
   two headings — because it is the same two results, and any other shape
   would say it was a different question rather than a second answer to this
   one. Set back from the first with a label, and the colour rule on top of
   each column dropped to a hairline: this pair follows from the pair above
   it rather than standing beside it. */
.teachlab { font-size:var(--t-meta); text-transform:uppercase;
  letter-spacing:.05em; color:var(--dim); margin:16px 0 0 }
.forkgrid.teach { margin-top:4px }
.forkgrid.teach .forkcol { border-top-width:1px; border-top-color:var(--line) }
.forkrest .forkteam { color:var(--dim) }
.forkgrid.compact .forkrest { margin-top:6px; padding-top:5px }
@media (max-width:560px) { .forkgrid { grid-template-columns:1fr } }

/* ==== display face ======================================================= */
/* Archivo, the face the mark is set in. SIL Open Font License 1.1
   (Copyright 2020 The Archivo Project Authors) — self-hosting is expressly
   permitted; the license ships alongside at fonts/OFL.txt. Subset to the
   glyphs the sites actually render, both axes intact. */
@font-face {
  font-family: 'Archivo';
  src: url('fonts/Archivo-var.woff2') format('woff2-variations'),
       url('fonts/Archivo-var.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
}
:root { --b12-font-display: 'Archivo', system-ui, -apple-system, sans-serif; }

/* ==== topbar ============================================================= */
.b12-topbar {
  display: flex; align-items: center; gap: 18px; padding: 7px 20px;
  background: #14161a;
  font:var(--t-row)/1.4 -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.b12-topbar .b12-brand { display: flex; align-items: center; flex: 0 0 auto; }
/* The lockup is the wordmark. No text alongside it — that would set the name
   twice, once in outlines and once in the body face. */
.b12-topbar .b12-brand img { display: block; height: 26px; width: auto; }
.b12-topbar a { color: #9aa0aa; text-decoration: none; }
.b12-topbar a:hover, .b12-topbar a.on { color: #fff; }
.b12-topbar .b12-right { margin-left: auto; display: flex; align-items: center;
  gap: 10px; }

/* The masthead did not fit a phone. At 375px the four section links plus the
   theme toggle measured 473px against a 375px viewport, so the toggle sat off
   the right edge and the whole page scrolled sideways to reach it — every
   page on the domain, not one section. A fifth link made it 536px.
 *
 * Wrapping rather than scrolling the links: a horizontally scrollable nav
 * hides its last item behind a gesture nobody is told about, and the last item
 * here is the control that changes the theme. Two short rows cost 26px and
 * hide nothing. The gap shrinks first, so most phones still fit one row.
 */
@media (max-width: 700px) {
  .b12-topbar { flex-wrap: wrap; gap: 6px 14px; padding: 6px 14px; }
  /* The lockup stays on the first row beside the theme toggle and the links
     wrap beneath. Giving the brand a row of its own was the obvious version
     and cost 61px of vertical chrome on every page — three rows where two
     will do, on the screen with the least room to spare. */
  .b12-topbar .b12-right { order: 2; }
  .b12-topbar a:not(.b12-brand) { order: 3; }
  /* Force the break after the toggle.
     order alone did not do it. Flex decides where a line ends from the items'
     own sizes, BEFORE margin-left:auto gets to eat the slack — so whatever was
     left on row one pulled the first link up beside the lockup, and the nav
     read "Big12ology [toggle] Tiebreaker" with the other three orphaned
     below. A zero-height item with a full-width basis, last in source among
     order:2, ends the row deliberately instead of leaving it to chance. */
  .b12-topbar::after { content: ""; order: 2; flex-basis: 100%; height: 0; }
}

/* ==== theme-paired artwork =============================================== */
/* The lockup ships as two files — ink on light, bone on dark — and the page
   picks one. It cannot be a <picture media="(prefers-color-scheme: dark)">:
   that reads the OS and never hears the toggle, so a reader on a dark OS who
   chose Light got the bone wordmark on a white page and could barely see it.
   Ship both, hide one, and follow the same paired rules as everything else.
   The light file is the one that carries the alt text. */
.b12-logo--light, .b12-logo--dark { display: block; }
.b12-logo--dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .b12-logo--light { display: none; }
  :root:not([data-theme="light"]) .b12-logo--dark { display: block; }
}
:root[data-theme="dark"] .b12-logo--light { display: none; }
:root[data-theme="dark"] .b12-logo--dark { display: block; }

/* ==== theme toggle ======================================================= */
.b12-theme {
  display: inline-flex; align-items: center; gap: 1px; padding: 2px;
  background: rgba(255,255,255,.07); border-radius: 999px;
}
.b12-theme button {
  font: inherit; font-size: var(--t-meta); line-height: 1; cursor: pointer;
  background: none; border: 0; color: #9aa0aa; border-radius: 999px;
  padding: 5px 9px; display: inline-flex; align-items: center;
}
.b12-theme button:hover { color: #fff; }
.b12-theme button[aria-pressed="true"] {
  background: var(--b12-teal-lit); color: #06232b; font-weight: 700;
}
.b12-theme svg { width: 14px; height: 14px; display: block; }

/* ==== footer ============================================================= */
/* The page measure, not the prose measure. 880px is the width a paragraph
   wants to be read at, and the footer is not paragraphs — it is two rows of
   dot-separated metadata that are scanned, not read. Held at the reading
   width, each row wrapped onto a second line and a three-row footer took
   five, which is more chrome than the domain has anywhere else. At the
   content width both rows land on one line each. */
.b12-footer {
  max-width: var(--chrome-w); margin: 0 auto; padding: 14px 20px 44px;
  color: #666d7b; font-size: var(--t-row); line-height: 1.65; text-align: center;
}
.b12-footer a { color: var(--b12-teal-text); }
.b12-footer p { margin: 0 0 8px; }
.b12-footer .srcnote { font-size: var(--t-meta); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .b12-footer { color: #9aa0aa; }
  :root:not([data-theme="light"]) .b12-footer a { color: var(--b12-teal-lit); }
}
:root[data-theme="dark"] .b12-footer { color: #9aa0aa; }
:root[data-theme="dark"] .b12-footer a { color: var(--b12-teal-lit); }

/* ==== tracker chrome: the one definition ================================= */
.b12-head { border-bottom: 4px solid var(--b12-teal); padding: 24px 20px 16px;
  background: #ffffff; }
.b12-head .hwrap { display: flex; align-items: center; gap: 16px;
  max-width: var(--chrome-w); margin: 0 auto; }
.b12-head h1 { margin: 0; font-size: var(--t-title); letter-spacing: -.03em;
  color: #1a1c20; font-family: var(--b12-font-display);
  font-variation-settings: 'wdth' 85; font-weight: 800; }
.b12-head h1 .yr { color: #666d7b; }
.b12-head p { margin: 4px 0 0; color: #666d7b; font-size: var(--t-label); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .b12-head { background: #1d2026;
    border-bottom-color: var(--b12-teal-lit); }
  :root:not([data-theme="light"]) .b12-head h1 { color: #e8e6e1; }
  :root:not([data-theme="light"]) .b12-head h1 .yr,
  :root:not([data-theme="light"]) .b12-head p { color: #9aa0aa; }
}
:root[data-theme="dark"] .b12-head { background: #1d2026;
  border-bottom-color: var(--b12-teal-lit); }
:root[data-theme="dark"] .b12-head h1 { color: #e8e6e1; }
:root[data-theme="dark"] .b12-head h1 .yr,
:root[data-theme="dark"] .b12-head p { color: #9aa0aa; }

/* season switcher — the live year plus the archived ones, in the header */
.b12-head h1 .yrpills { display: inline-flex; gap: 6px; margin-left: 8px;
  vertical-align: middle; font-size: var(--t-label); font-weight: 600;
  font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  letter-spacing: 0; }
.b12-head h1 .yrpills a, .b12-head h1 .yrpills .yron {
  padding: 2px 9px; border-radius: 999px; line-height: 1.6;
  border: 1px solid #e2ddd2; }
.b12-head h1 .yrpills a { color: #666d7b; text-decoration: none; }
.b12-head h1 .yrpills a:hover { color: #1a1c20; border-color: #c8c2b4; }
.b12-head h1 .yrpills .yron { background: var(--b12-teal);
  border-color: var(--b12-teal); color: #fff; }
/* THE DARK ACTIVE PILL FILLS WITH --b12-teal-lit, NOT --b12-teal-tile-dark.
   The tile teal #0E8A94 sits in the dead middle of the range and carries small
   text at 4.13:1 against white and 3.96:1 against #06232b, so it fails AA in
   BOTH directions: there is no foreground that rescues it. --b12-teal-lit
   #3FC7CE takes the same #06232b to 8.01:1, and it is the pairing the theme
   toggle's pressed state already uses, so the three filled chrome controls now
   read as one recipe instead of two. --b12-teal-tile-dark stays defined: it is
   the LOGO tile fill, which is logotype and exempt from 1.4.3. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .b12-head h1 .yrpills a { color: #9aa0aa;
    border-color: #2f343c; }
  :root:not([data-theme="light"]) .b12-head h1 .yrpills a:hover {
    color: #e8e6e1; border-color: #4a515c; }
  :root:not([data-theme="light"]) .b12-head h1 .yrpills .yron {
    background: var(--b12-teal-lit); border-color: var(--b12-teal-lit);
    color: #06232b; }
}
:root[data-theme="dark"] .b12-head h1 .yrpills a { color: #9aa0aa;
  border-color: #2f343c; }
:root[data-theme="dark"] .b12-head h1 .yrpills a:hover { color: #e8e6e1;
  border-color: #4a515c; }
:root[data-theme="dark"] .b12-head h1 .yrpills .yron {
  background: var(--b12-teal-lit); border-color: var(--b12-teal-lit);
  color: #06232b; }

/* module tabs / page subnav — one look everywhere */
.subnav {
  max-width: var(--chrome-w); margin: 0 auto; padding: 12px 20px 0;
  display: flex; gap: 8px; flex-wrap: wrap;
}
.subnav a {
  font-size: var(--t-row); text-decoration: none; color: #666d7b;
  border: 1px solid rgba(128,128,128,.35); border-radius: 20px;
  padding: 4px 13px; background: transparent;
}
.subnav a:hover { color: inherit; border-color: var(--b12-teal); }
/* The other game, not another tab of this one. Set apart by a dashed edge and
   pushed to the far end of the row, so the eye reads the tabs as a group and
   this as a way out of it — the two pools games each link straight to the
   other rather than sending a player up to /pools/ and back down. */
.subnav a.cross { margin-left: auto; border-style: dashed;
  color: var(--b12-teal); }
.subnav a.cross:hover { border-style: solid; }
.subnav a.on { background: var(--b12-teal); border-color: var(--b12-teal);
  color: #fff; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .subnav a { color: #9aa0aa; }
  :root:not([data-theme="light"]) .subnav a:hover { border-color: var(--b12-teal-lit); }
  :root:not([data-theme="light"]) .subnav a.on {
    background: var(--b12-teal-lit); border-color: var(--b12-teal-lit);
    color: #06232b; }
}
:root[data-theme="dark"] .subnav a { color: #9aa0aa; }
:root[data-theme="dark"] .subnav a:hover { border-color: var(--b12-teal-lit); }
:root[data-theme="dark"] .subnav a.on { background: var(--b12-teal-lit);
  border-color: var(--b12-teal-lit); color: #06232b; }

/* ==== accessibility ====================================================== */
/* Bypass blocks (WCAG 2.4.1): every page repeats the topbar, the header and
   the pill nav before its content. Off-screen until focused. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--b12-teal); color: #fff; padding: 10px 16px;
  border-radius: 0 0 8px 0; font-size: var(--t-label); font-weight: 600;
  text-decoration: none;
}
.skip-link:focus { left: 0; }

/* Focus Visible (WCAG 2.4.7): the browser default ring washes out against
   the pill borders on some platforms, so state it explicitly. */
:focus-visible {
  outline: 3px solid var(--b12-teal); outline-offset: 2px; border-radius: 4px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) :focus-visible { outline-color: var(--b12-teal-lit); }
}
:root[data-theme="dark"] :focus-visible { outline-color: var(--b12-teal-lit); }

@media (forced-colors: active) {
  .b12-logo, .b12-topbar .b12-brand img { forced-color-adjust: auto; }
}
