/* The pick'em. Loaded after BRIEF_CSS, so it inherits the section's tokens,
   .card, .note, .tag, .table-wrap and the type scale, and only defines what
   this section actually adds: a picker, a countdown, and an outcome chip.

   Three rules from tiebreaker/README.md govern most of what follows.

   TEAL IS CHROME ONLY. A selected pick fills with the team's own color, never
   the brand teal, and on The Board nothing is filled at all — a team chip
   sitting beside the ATS% ramp would put brand teal next to the ramp's greens,
   which measure 1.00:1 against each other and are told apart by hue alone.

   GOOD-TO-BAD IS A GRADIENT — except here. A single pick is won, lost or
   pushed: three categories, not a continuum, so they get three flat colors.
   The gradient rule still governs ATS%, which is continuous, on The Board.

   Dark is declared twice and kept adjacent, per brand.css. Change them
   together or they drift. */

:root {
  /* Not invented: --ok is BRIEF_CSS's .badge.ok, --bad is the value
     attendance/site/styles.css already carries under that name. A push is
     neither good nor bad, so it borrows --dim rather than inventing a third
     hue nobody would learn. */
  --ok:  #136536;
  --bad: #c0392b;
  --push: var(--dim);
  /* The fill for a team with no color on file. teams.json holds the sixteen
     members and nothing else, so in a non-conference week half the board is
     an opponent we have no color for — and the first version of this fell
     back to var(--accent), which put brand teal inside the data region on
     fifteen of thirty labels. Graphite is a brand neutral and unmistakably
     not the accent. */
  --tc-none: #252932;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --ok: #4ade80; --bad: #f87171;
                                    --push: var(--dim); --tc-none: #454c5a; }
}
:root[data-theme="dark"] { --ok: #4ade80; --bad: #f87171;
                           --push: var(--dim); --tc-none: #454c5a; }

/* Visually hidden, still focusable and still read aloud. Not display:none and
   not visibility:hidden — both remove the element from the tab order, which
   for the radios below would mean a picker no keyboard can reach. */
.sr-only {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* --- the lock ---------------------------------------------------------- */

/* The lock and the count share one line. Everything above the slate is space
   the slate does not get, and these are two short facts. */
#lockcard { padding: 10px 14px; }
.pk-lockline { margin: 0; display: flex; gap: 8px; flex-wrap: wrap;
            align-items: baseline; font-size: var(--t-label); }
.pk-lockline time { font-weight: 600; }
.pk-cd { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
      font-variant-numeric: tabular-nums; color: var(--dim); font-size: var(--t-row); }
.pk-slatecount { margin: 2px 0 0; color: var(--dim); font-size: var(--t-row); }

/* --- live regions ------------------------------------------------------- */

/* One line, not a card. It sits between the reader and the thing they came
   for, and everything it has to say is one sentence. */
.pk-signedout { margin: 0; font-size: var(--t-label); color: var(--dim);
                border: 1px solid var(--line); border-radius: 8px;
                padding: 8px 12px; background: var(--panel); }

/* The link inside it had no rule at all, so it rendered in the browser's
   default blue — the one color on the page that belongs to no theme, sitting
   in the one panel a signed-out visitor is meant to act on. It is the same
   treatment as .pk-onward: the section's accent, and weight to separate the
   thing you can do from the sentence explaining it. The underline stays, and
   is offset so it clears the descenders in "Sign in". */
.pk-signedout a { color: var(--accent); font-weight: 600;
                  text-underline-offset: 2px; }
.pk-signedout a:hover { text-decoration-thickness: 2px; }

/* The signed-in counterpart is a hint, not an invitation, so it is a line of
   text rather than a panel. A second bordered box above the slate would give
   a returning player the same visual weight as a call to action they have
   already answered. */
.pk-hint { margin: 0 0 2px; font-size: var(--t-row); color: var(--dim); }
.pk-hint[hidden] { display: none; }

/* Collapsed when empty so two idle live regions do not cost 40px above the
   slate. They still exist in the DOM the whole time — a live region created
   at the moment it has something to say is not announced. */
.pk-savestate, .pk-alertstate { margin: 0; font-size: var(--t-label); }
.pk-savestate:not(:empty) { min-height: 1.4em; }
.pk-savestate { color: var(--dim); }
.pk-alertstate:not(:empty) {
  color: var(--bad); font-weight: 600; border-left: 3px solid var(--bad);
  padding: 8px 12px; border-radius: 0 8px 8px 0;
  background: color-mix(in srgb, var(--bad) 9%, transparent);
}

/* --- the picker --------------------------------------------------------- */

/* A slate is fifteen or sixteen games and wants to be readable as one object:
   scrolling to see whether you have finished is the thing that makes a picker
   feel like a form. So every game is one row, tuned to fit a full week above
   the fold on a 1080p screen. The legend is visually hidden (it is still the
   group's accessible name) and the time moved into the row as its own column,
   which is what bought the line back. */

/* A status line is not reading prose. brand.css caps every .note at the
   measure, which is right for a paragraph someone reads — HOW IT WORKS, the
   rules — and wrong for a one-sentence message sitting alone in a wide card:
   there the cap breaks the sentence mid-phrase and reads as a layout
   accident, not typography. The status notes (the slate's, the card's, the
   boards', survivor's) run to their card instead. */
#slateload, #cardnote, #svnote, #boardnote, #svboardnote,
.pk-pvlinks, .pk-slate > .note { max-width: none; }

/* The gap and the row padding are the survivor card's numbers, measured:
   both games' rows live inside the same card anatomy now, and 3px-padded
   rows at a 4px gap beside survivor's 8px read as a different product.
   The rows stay one line — stacking is survivor's answer to a narrower
   card, and a whole week on one screen is still this slate's job. */
.pk-slate { display: grid; grid-template-columns: 1fr; gap: 8px; }

/* Two columns once there is room. This is what actually fits a full week on a
   screen: shrinking the type far enough to stack sixteen games in one column
   makes them unreadable, and a slate you have to scroll to count is a slate
   you cannot tell you have finished.

   Columns, not a two-column grid, and the comment that used to sit here
   claimed the grid already read down one column and then the other. It did
   not. A grid fills ROW BY ROW, so the week ran 11:24 across, then 1:24
   across, then 3:24 across — the eye tracks down a column and the times
   jumped about, because consecutive kickoffs were side by side rather than
   stacked. Column flow gives what the comment always said it did: the first
   half of the week down the left, the second half down the right, in order.
   Same DOM order either way, so the keyboard walks it the same. */
@media (min-width: 900px) {
  .pk-slate { display: block; columns: 2; column-gap: 12px; }
  /* No row gap in a column layout, so the rows carry their own — the same
     8px the grid gap gives them below 900. */
  .pk-slate-game { break-inside: avoid; margin-bottom: 8px; }
  /* The break between playable and not spans both columns, so the two groups
     never interleave across the gutter — and it starts a fresh pair of
     columns beneath it, which is what keeps the two groups from sharing one. */
  .pk-deadhead { column-span: all; }
  /* The empty-state note (loading failed mid-render, no games) is the only
     thing ever inside #slate besides game rows; half a column is no width
     for a sentence. */
  .pk-slate > .note { column-span: all; }
}

.pk-deadhead {
  margin: 10px 0 2px; font-size: var(--t-meta); letter-spacing: .06em;
  text-transform: uppercase; color: var(--dim); font-weight: 600;
}

.pk-slate-game {
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel);
  /* 8px 10px, not the old 3px 8px: the survivor card's row padding, see the
     .pk-slate note above. */
  margin: 0; padding: 8px 10px; min-width: 0;
  display: grid; gap: 0 8px; align-items: center;
}
.pk-slate-game legend { padding: 0; }
.pk-when { color: var(--dim); font-size: var(--t-meta); white-space: nowrap;
        font-variant-numeric: tabular-nums; }

.pk-sides { display: grid; grid-template-columns: 1fr 1.3em 1fr; gap: 5px;
         align-items: stretch; min-width: 0; }
.pk-at { align-self: center; justify-self: center; color: var(--dim);
      font-size: var(--t-fine); }

/* The input is hidden; the label is the control. */
/* The same control The Lab already has, at slate density. Its .pick is
   inline-flex, 1px --line, 8px radius, a 6px gap and the mark first; keeping
   that here means a reader who has used one recognizes the other, which is
   the "same quantity presented the same way" rule in tiebreaker/README.md. */
.pk-side {
  display: flex; align-items: center; gap: 5px; min-width: 0;
  border: 1px solid var(--line); border-radius: 8px; padding: 4px 6px;
  cursor: pointer; background: var(--panel); color: var(--ink);
}
.pk-side img.mark { margin: 0; flex: none; }
.pk-side .pk-tname { flex: 1; min-width: 0; overflow: hidden;
               text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-label); }
/* nowrap because this slot is a spread — two or three characters — except on
   a non-conference side, where it says "not Big 12" and wrapped to two lines
   in the narrower survivor card. A quantity that reflows is a quantity that
   moves the row it sits in. */
.pk-side .pk-num { font-variant-numeric: tabular-nums; font-size: var(--t-label);
             font-weight: 600; white-space: nowrap; }
.pk-side img { flex: none; }

.pk-slate-game input:checked + .pk-side {
  /* --tc is the team's own color, set inline from teams.json; --tfg is the
     readable text color computed against it. Neither ever falls back to the
     accent — see --tc-none above. */
  background: var(--tc, var(--tc-none));
  border-color: var(--tc, var(--tc-none));
  color: var(--tfg, #fff); font-weight: 700;
}
.pk-slate-game input:checked + .pk-side .pk-num { font-weight: 700; }
/* Color is never the only signal — WCAG 1.4.1. The tick and the weight carry
   it for anyone who cannot see the fill. */
.pk-slate-game input:checked + .pk-side::after { content: "\2713"; font-weight: 700; }

.pk-side:hover { border-color: var(--accent); }

/* The ring must be forwarded from the hidden input to the label, or a keyboard
   user sees nothing at all. Same ring as brand.css:focus-visible. */
.pk-slate-game input:focus-visible + .pk-side {
  outline: 3px solid var(--accent); outline-offset: 2px;
}

/* --- a game nobody can pick --------------------------------------------- */
/* disabled on the fieldset, not opacity. Native disable is the only version
   that survives forced-colors, where the browser paints its own GrayText; and
   opacity would drag --dim under the 4.5:1 floor rather than leaving it at the
   contrast it was chosen for. */

.pk-slate-game[disabled] { border-style: dashed; background: var(--bg); }
.pk-slate-game[disabled] .pk-side { cursor: default; color: var(--dim);
                              border-style: dashed; }
.pk-slate-game[disabled] .pk-side:hover { border-color: var(--line); }
/* The chip rides in the row rather than under it — another line saved, and it
   reads as a property of the game rather than a footnote to it. A third
   column, because dropping it into column 2 wraps it onto a second row and
   gives the line straight back. */
/* A third column for whichever chip the row carries — the closed reason, or
   the graded outcome. Reserved on every row so the two sides stay aligned
   down the slate instead of jumping about as results land.

   The outer two columns are as narrow as their content allows, because every
   pixel they take comes off a team name. A 16-game week is all-conference, so
   the longest name it can contain is "Oklahoma State"; the 24-character names
   only turn up in non-conference weeks, which have far fewer pickable games.
   Sized so the first case never truncates. */
/* Explicit pixels, not em. `7em` resolves against the ROW's inherited 16px,
   not the 12.5px the time is actually set in, so it reserved 112px for
   content that needs 62 — and the 50px difference came straight off the team
   names, which is what made "Texas Tech" ellipsise. */
/* Every pixel these two columns take comes off a team name, and the marks
   now want 20 of them a side. Sized to the content: "Sat 12:30p" needs 56,
   and the chip needs 40. */
.pk-slate-game { grid-template-columns: 56px minmax(0, 1fr) 40px; }
/* Closed rows say why in words, which no fixed chip column fits. They give
   the space back from the sides, where it costs nothing: the row cannot be
   picked, and the full name is still in the legend and the title. */
.pk-slate-game[disabled] { grid-template-columns: 64px minmax(0, 1fr) auto; }
.pk-nopick { margin: 0; font-size: var(--t-fine); padding: 1px 7px; white-space: nowrap;
             justify-self: end; }

/* --- graded --------------------------------------------------------------
   Flat, not a ramp: see the note at the top about categories. */

.pk-res { font-size: var(--t-fine); font-weight: 700; letter-spacing: .04em;
       border-radius: 99px; padding: 1px 7px; white-space: nowrap;
       justify-self: end; }
.pk-res.win  { color: var(--ok);   background: color-mix(in srgb, var(--ok) 15%, transparent); }
.pk-res.loss { color: var(--bad);  background: color-mix(in srgb, var(--bad) 15%, transparent); }
.pk-res.push { color: var(--push); background: color-mix(in srgb, var(--push) 15%, transparent); }
.pk-res.void { color: var(--dim);  background: color-mix(in srgb, var(--dim) 12%, transparent); }

/* --- your team ------------------------------------------------------------
   The same control as the slate — hidden radio, styled label — because it is
   the same act: one choice out of a set you recognize by its mark. */

.pk-teamgrid {
  border: 0; padding: 0; margin: 0 0 12px;
  /* A fieldset's default min-inline-size is min-content, which shrink-wrapped
     the whole grid to one column's worth however wide the card was. */
  min-inline-size: 0; inline-size: 100%;
  display: grid; gap: 6px;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
}
.pk-teamgrid legend { grid-column: 1 / -1; padding: 0 0 6px;
                      font-weight: 600; font-size: var(--t-label); }
/* The three answers that are not a team sit below the line and span it, so
   the sixteen above stay a single scannable block of marks. */
.pk-teamsep { grid-column: 1 / -1; height: 0; margin: 5px 0 2px;
              border-top: 1px dashed var(--line); }
.pk-teamopt {
  display: flex; align-items: center; gap: 7px; min-width: 0;
  border: 1px solid var(--line); border-radius: 8px; padding: 6px 9px;
  background: var(--panel); cursor: pointer; font-size: var(--t-row);
  transition: border-color .12s ease, background-color .12s ease;
}
.pk-teamopt .pk-tname { flex: 1; min-width: 0; overflow: hidden;
                        text-overflow: ellipsis; white-space: nowrap; }
.pk-teamopt img { flex: none; }
/* Holds a missing mark's width so the names stay in one column down the grid
   rather than stepping in and out by twenty pixels. */
.pk-teamgap { flex: none; width: 20px; }
.pk-teamopt-any { grid-column: 1 / -1; color: var(--dim); }

.pk-teamopt:hover { border-color: var(--accent); }
.pk-teamgrid input:checked + .pk-teamopt {
  background: var(--tc, var(--accent));
  border-color: var(--tc, var(--accent));
  color: var(--tfg, #fff); font-weight: 700;
}
/* Color is never the only signal — WCAG 1.4.1. */
.pk-teamgrid input:checked + .pk-teamopt::after {
  content: "\2713"; margin-left: auto; font-weight: 700;
}
/* Forwarded from the hidden input, or a keyboard user sees nothing at all. */
.pk-teamgrid input:focus-visible + .pk-teamopt {
  outline: 3px solid var(--accent); outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) { .pk-teamopt { transition: none; } }

/* --- the board ---------------------------------------------------------- */

.pk-boardhead { display: flex; justify-content: space-between; gap: 12px;
             align-items: baseline; flex-wrap: wrap; }
/* The week picker. A bare <select> is the one control on these pages the
   browser draws for itself, and next to the pills and chips everything else
   is made of it read as something the page had forgotten to style. Same pill
   geometry as .yearpill, with the browser's arrow replaced by one that takes
   its color from the text, so it follows both themes without a second asset
   or a data URI to keep in sync. */
.pk-wksel { font-size: var(--t-row); color: var(--dim); position: relative;
            display: inline-flex; align-items: center; gap: 7px; }
/* display on the element beats the UA's [hidden] rule, and this label is
   hidden whenever there is only one week to offer. */
.pk-wksel[hidden] { display: none; }
.pk-wksel select {
  font: inherit; font-size: var(--t-row); font-weight: 600; color: var(--ink);
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 999px; padding: 4px 27px 4px 12px; cursor: pointer;
  appearance: none; -webkit-appearance: none;
}
.pk-wksel select:hover { border-color: var(--accent); }
.pk-wksel select:focus-visible { outline: 3px solid var(--accent);
                                 outline-offset: 2px; }
/* On the label, not the select: a <select> cannot carry a pseudo-element in
   every engine. clip-path rather than a background image, so the arrow is
   currentColor and needs no light and dark copy. */
.pk-wksel::after {
  content: ""; position: absolute; right: 12px; width: 9px; height: 6px;
  background: currentColor; pointer-events: none;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}

#board { width: 100%; border-collapse: collapse; }
#board th, #board td { padding: 7px 10px; text-align: left;
                       border-bottom: 1px solid var(--line); }
#board td.n, #board th.n { text-align: right;
                           font-variant-numeric: tabular-nums; }
#board tfoot td { border-top: 2px solid var(--line); border-bottom: none;
                  color: var(--dim); font-style: italic; }

/* The sort control is a button inside the th, not the th itself. The
   attendance table makes its headers clickable with no tabindex and no key
   handler, which is mouse-only — a WCAG 2.1.1 failure this section should not
   inherit just because it inherited the markup. aria-sort stays on the th,
   where the spec puts it. */
#board th button {
  font: inherit; color: inherit; background: none; border: 0; padding: 0;
  cursor: pointer; display: inline-flex; gap: 4px; align-items: center;
}
#board th[aria-sort] button { color: var(--accent); }
#board th button:hover { color: var(--accent); }
#board th button:focus-visible { outline: 3px solid var(--accent);
                                 outline-offset: 2px; }
/* Your own row. --you is your team's color, set inline from your profile;
   the accent is the fallback for the two answers that are not a team. Kept to
   a wash: this sits directly beside the ATS% ramp, and anything stronger would
   read as a statement about the numbers rather than about whose row it is. */
#board tr.you td { background: color-mix(in srgb, var(--you, var(--accent)) 10%, transparent); }
#board tr.you td:first-child { box-shadow: inset 3px 0 0 var(--you, var(--accent)); }
#board tr.you img.mark { vertical-align: -2px; margin-right: 6px; }

#teamform { display: flex; flex-direction: column; gap: 8px;
            align-items: flex-start; }
#teamform label { font-weight: 600; font-size: var(--t-label); }
#teampick { font: inherit; padding: 7px 10px; border: 1px solid var(--line);
            border-radius: 8px; background: var(--bg); color: var(--ink);
            min-width: min(320px, 100%); }
#teampick:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* --- forms -------------------------------------------------------------- */
/* The first real form on the domain. */

#nameform { display: flex; flex-direction: column; gap: 8px;
            align-items: flex-start; }
#nameform label { font-weight: 600; font-size: var(--t-label); }
#nameform input {
  font: inherit; padding: 8px 10px; border: 1px solid var(--line);
  border-radius: 8px; background: var(--bg); color: var(--ink);
  min-width: min(320px, 100%);
}
#nameform input:focus-visible { outline: 3px solid var(--accent);
                                outline-offset: 2px; }
#nameform input[aria-invalid="true"] { border-color: var(--bad); }
.pk-fielderr { margin: 0; color: var(--bad); font-size: var(--t-label); font-weight: 600; }
.pk-signins { display: flex; gap: 10px; flex-wrap: wrap; }

/* --- the account chip in the masthead ----------------------------------- */
/* Chrome, so teal is allowed here. */

.b12-acct { font-size: var(--t-row); color: var(--b12-bone); opacity: .85;
            margin-right: 10px; white-space: nowrap; }
.b12-acct a { color: inherit; text-underline-offset: 2px; }

/* Narrow: the density that fits a desktop is unusable at 375px, so the row
   becomes two lines and the sides stack. Fitting a whole slate on one screen
   is a desktop goal; on a phone the thumb is doing the scrolling anyway. */
@media (max-width: 620px) {
  .pk-slate-game,
  .pk-slate-game[disabled],
  .pk-locked .pk-slate-game:not([disabled]) {
                          grid-template-columns: 1fr; gap: 4px 0;
                          padding: 8px 10px; }
  .pk-res, .pk-nopick { justify-self: start; }
  .pk-sides { grid-template-columns: 1fr; gap: 4px; }
  .pk-at { display: none; }
  .pk-side { padding: 7px 10px; }
  .b12-acct { display: none; }
  .pk-slate { gap: 8px; }
}

/* Nothing here animates, so there is nothing for reduced-motion to suppress —
   deliberately. A countdown that pulses as the deadline nears would be a
   WCAG 2.3.1 problem and an anxiety machine. */

/* --- the card ------------------------------------------------------------
   Your slate, after the fact. Same row rhythm as the picker so the two read
   as the same object seen twice, but nothing here is a control: the picking
   is over, or it is happening on the other page. */

/* One column, unlike the slate. The card lists only the games you could
   pick, so it is always the shorter of the two, and a full-width row is what
   lets the six fields — time, matchup, score, line, crowd, result — coexist
   without ellipsising every team name.

   The tracks live HERE, on the list, and each row borrows them with subgrid.
   Every row having its own grid was the bug: six independent grids sized
   themselves to six different sets of content, so no two rows agreed where a
   column started and the gauges all came out different lengths. One set of
   tracks means the parts line up down the card — the alignment of a table,
   without becoming one: no rules, no header row, and each game still its own
   rounded panel. */
.pk-card {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 3px;
  grid-template-columns: max-content max-content 3.6em 3.2em minmax(0, 1fr) 4.6em;
}
/* Only when there is actually a gauge to draw — before the lock the server
   sends no split, and a 1fr column holding nothing swallows the row. */
.pk-card:has(.pk-splitbar) {
  grid-template-columns:
    max-content max-content 3.6em 3.2em minmax(120px, 1fr) 4.6em;
}
/* And when there is not, THE ROW STOPS BEING FULL WIDTH.
   That is the fix, and two earlier attempts at it were not. minmax(0, 1fr)
   on the gauge column held 494px of a 1042px row — half the card was an empty
   track. Handing that slack to the matchup instead did not remove it, it just
   moved the hole from the right of the row to the middle of it: a flexible
   column with nothing to fill it is a gap wherever you put it.
   So none of the columns flex. Every track is content-sized, the list is
   exactly as wide as its widest row needs, and the rows are dense. The
   matchup goes back to centring inside a track set by the longest pair, which
   is what it was for. */
.pk-card:not(:has(.pk-splitbar)) {
  grid-template-columns: max-content max-content 3.6em 3.2em 0 4.6em;
  width: max-content;
  max-width: 100%;
}

/* And the CARD around the list shrinks with it. Tightening the rows moved the
   empty space rather than removing it: a 537px list sat in a 1330px panel and
   the void was simply outside the rows instead of inside them.
   fit-content, floored so the header does not crush and capped at the chrome
   width, and centerd. A locked week whose rows carry a gauge is wider, and
   the same rule sizes to that without a second breakpoint. */
@media (min-width: 900px) {
  /* Only when there is no gauge. fit-content shrinks to the smallest the
     content will accept, and a gauge column of minmax(120px, 1fr) accepts
     120px — so fitting the card unconditionally squeezed the bar down to its
     floor on exactly the weeks it exists to be read on. With a gauge the card
     stays full width and the 1fr gets what it was asking for. */
  .pk-fitcard:not(:has(.pk-splitbar)) {
    width: fit-content;
    min-width: min(100%, 34rem);
    max-width: 100%;
    margin-inline: auto;
  }
}

.pk-cardrow {
  /* Borrows the list's tracks rather than defining its own, which is what
     makes every column line up down the card. The fallback below is the old
     per-row grid: without subgrid the rows align less well and break not at
     all. */
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: max-content max-content 3.6em 3.2em minmax(0, 1fr) 4.6em;
  grid-template-columns: subgrid;
  gap: 0 14px; align-items: center;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel);
  padding: 4px 10px; min-width: 0;
}
/* The track is the widest matchup on the card; every shorter one centers
   inside it, so the column reads as one block rather than a ragged left edge
   of names that happen to differ in length. */
.pk-cardmatch { min-width: 0; overflow: hidden; text-overflow: ellipsis;
                white-space: nowrap; font-size: var(--t-label);
                justify-self: center; }
/* The side you took carries the team's color as a chip. On the picker the
   whole control fills; here it is one word inside a sentence, so it takes the
   smaller treatment. Still never the accent. */
.pk-took { background: var(--tc, var(--tc-none)); color: var(--tfg, #fff);
           font-weight: 700; border-radius: 4px; padding: 1px 5px; }
/* A fill alone was not enough to read at a glance, and it could not be: on a
   card of fifteen rows every row has some color in it — the marks, the
   result chips — so one more colored thing is not a signal. The tick is,
   and it is the same tick the picker uses on the side you chose, so the two
   pages say "this one" the same way. Color is never the only signal
   anyway — WCAG 1.4.1 — and this is the row that most needed the other one. */
.pk-took::after { content: "\00a0\2713"; font-weight: 700; }
/* And the side you did not take steps back, so the contrast is between two
   things rather than between one thing and the background. */
.pk-nottook { color: var(--dim); }

.pk-score { font-variant-numeric: tabular-nums; font-size: var(--t-row);
             color: var(--dim); white-space: nowrap; }

.pk-cardrec { margin: 0 0 12px; font-size: var(--t-copy); }
.pk-cardrec b { font-size: var(--t-subhead); }
.pk-open { color: var(--warn); font-weight: 600; }

/* A game whose result is not in yet. A dot, not an empty cell, so the row
   reads as waiting rather than as missing. */
.pk-res.pending { color: var(--dim); background: none; }
.pk-res.nopick { color: var(--dim);
                 background: color-mix(in srgb, var(--dim) 10%, transparent); }

/* --- what the room did ---------------------------------------------------
   A single percentage beside a row never said what it was a percentage OF.
   This runs from one team's color to the other with each side's number at
   its own end, so the reading is positional: which way the room leaned, and
   how hard. Only ever rendered after the lock; the server withholds the field
   before it.

   The gradient carries the identity, the marker carries the number. A
   gradient on its own looks better and says less — you cannot read a split
   off a blur. */

/* Inline, not a row of its own. Spanning the full width left the matchup
   stranded at one edge, the line stranded at the other and a bar running the
   whole way between them saying nothing about the distance it covered. At a
   fixed width it is a gauge sitting where a gauge belongs, and it absorbs the
   slack the matchup column used to hand to the gutter. */
.pk-split { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* The waiting state, in the gauge's own slot. Muted and small on purpose:
   it is an explanation for an absence, not a number anybody is playing for,
   and it must not compete with the spread and the result either side of it.
   Centred because it replaces a bar that filled the column, and a left-aligned
   fragment there reads as a broken bar rather than as a caption. */
.pk-splitwait {
  justify-content: center; font-size: var(--t-micro);
  color: var(--dim); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.pk-splitbar {
  position: relative; flex: 1; min-width: 40px; height: 7px;
  border-radius: 4px; overflow: hidden;
}
/* Sits ON the color, so it needs to read against sixteen different ones:
   a white bar with a dark outline is legible over every team in the
   conference and over the graphite an unknown opponent gets. */
.pk-splitmark {
  position: absolute; top: -2px; bottom: -2px; width: 3px;
  transform: translateX(-1.5px);
  background: var(--bg); box-shadow: 0 0 0 1px var(--ink);
  border-radius: 1px;
}
.pk-splitpct {
  font-size: var(--t-fine); color: var(--dim); font-variant-numeric: tabular-nums;
  white-space: nowrap; min-width: 2.2em;
}
.pk-splitpct.pk-home { text-align: right; }
/* Your side, in weight rather than hue — the crowd is not a verdict, and
   coloring it would make it look like one. */
.pk-splitpct.pk-mine { color: var(--ink); font-weight: 700; }

.pk-cardseason { margin: 0 0 10px; font-size: var(--t-row); color: var(--dim);
                 font-variant-numeric: tabular-nums; }

/* Five states. A card read mid-afternoon is mostly games that have not
   finished, and the two that are not outcomes get no color: nothing has
   happened yet, and a chip that looks like a result would be a lie. */
/* A picked game the scores have not caught up with holds the cell open so the
   rows stay aligned, and says nothing, because there is nothing yet to say. */
.pk-res-none { padding: 0; background: none; }
.pk-res.locked  { color: var(--dim);
                  background: color-mix(in srgb, var(--dim) 12%, transparent); }
.pk-res.live    { color: var(--warn); font-weight: 700;
                  background: color-mix(in srgb, var(--warn) 16%, transparent); }
.pk-res.pending { color: var(--dim); background: none; }
.pk-res.nopick  { color: var(--dim);
                  background: color-mix(in srgb, var(--dim) 10%, transparent); }

@media (max-width: 620px) {
  .pk-cardrow { grid-template-columns: 1fr auto; gap: 3px 8px; }
  .pk-split { grid-column: 1 / -1; }
  .pk-cardrow .pk-when { grid-column: 1; }
}

/* --- a locked slate ------------------------------------------------------
   Once the week is locked the picker is a record, not a control. Disabled
   inputs stop the picking, but the borders still lit on hover and the cursor
   still turned — an interface going on asking for something it will not
   accept. Everything that suggested interactivity is off here, and the rows
   fall back to reading as what they are: what you picked, fixed. */

.pk-locked .pk-side { cursor: default; }
.pk-locked .pk-side:hover { border-color: transparent; }
/* A locked row is still a card, and stays --panel like every other one on the
   page. Dropping it to --bg was meant to make it recede; what it actually did
   was make the six playable games the only things on the page painted in the
   page's own color, so they read as holes in the panel rather than as rows
   that had closed. The stripped borders and the .6 opacity below already do
   the receding, and they do it without leaving the row a different object. */

/* The chip column was sized for "WIN" \2014 40px, the widest a graded row
   needed. Once the week is locked every playable row carries a word instead,
   and at 40px "LOCKED" ran straight out over the spread number to its left. */
.pk-locked .pk-slate-game:not([disabled]) {
  grid-template-columns: 56px minmax(0, 1fr) 62px;
}

/* The side you did not take stops being a box. A bordered panel on a plain
   background is the shape of an available choice, and after the lock there
   are none — leaving them looking pressable was the page going on offering
   something it would refuse. Border and fill go; the words stay. */
.pk-locked input:not(:checked) + .pk-side {
  border-color: transparent; background: none; color: var(--dim);
}
/* What you did take keeps its color, because that is the record. */
.pk-locked input:checked + .pk-side { box-shadow: none; }
/* --- signed out ----------------------------------------------------------
   .pk-locked is reused to switch the picking off, and then most of it has to
   be switched back on, because the two states differ in what they are FOR.
   A locked week is a record: the side you took is the only thing worth
   reading, so everything else recedes. Signed out there is no record at all
   and the lines are the entire reason the page is worth loading — dimming
   them to --dim washed out the one thing a new reader came to see, and left
   fifteen games looking broken rather than available.
   Borders, fills and text color all stay. Only the interactivity goes. */
.pk-readonly .pk-slate-game:not(:has(input:checked)) { opacity: 1; }
.pk-readonly input:not(:checked) + .pk-side {
  border-color: var(--line);
  background: var(--panel);
  color: var(--ink);
}
/* No tick, because nothing is picked, and no hover, because nothing can be. */
.pk-readonly .pk-side { cursor: default; }

/* A game you never picked has no record to show, so the whole row recedes. */
.pk-locked .pk-slate-game:not(:has(input:checked)) { opacity: .6; }

/* --- the look-ahead ------------------------------------------------------
   Before the first slate publishes, the upcoming week renders through the
   ordinary renderer with everything shut (see renderPickemPreview). The
   rows stay at full strength — like signed-out, there is no record to
   recede behind, and the week is the whole reason to look. */
.pk-preview .pk-slate-game:not(:has(input:checked)) { opacity: 1; }
/* Every row that carries its schedule link — live weeks borrow them from
   the look-ahead files (mergePeeks) — grows a fourth column for it, so the
   link coexists with whatever the chip column holds (a result, LOCKED, a
   no-line tag) instead of competing for its 40px. The middle 1fr pins both
   trailing columns to the right edge. */
.pk-slate-game:has(.pk-peek),
.pk-slate-game:has(.pk-peek):not([disabled]),
.pk-locked .pk-slate-game:has(.pk-peek):not([disabled]) {
  grid-template-columns: 56px minmax(0, 1fr) auto auto;
}
.pk-peek { font-size: var(--t-meta); white-space: nowrap; justify-self: end;
           color: var(--accent2); text-decoration: underline;
           text-underline-offset: 2px; text-decoration-thickness: 1px; }

/* --- the game's own state ------------------------------------------------
   The kickoff time is only interesting until kickoff. After that this column
   says what the game is doing, and the chip at the other end goes on saying
   what your pick did. One column for the game, one for you.

   FINAL and WAITING are quiet: they are bookkeeping. IN PLAY is the one state
   worth an eye, and takes --warn, which this section already uses for the
   thing that wants attention without being an error. */
.pk-when.pk-st-final,
.pk-when.pk-st-wait,
.pk-when.pk-st-live {
  font-size: var(--t-micro); font-weight: 700; letter-spacing: .05em;
  border-radius: 99px; padding: 2px 7px; text-align: center;
}
.pk-when.pk-st-final { color: var(--dim);
  background: color-mix(in srgb, var(--dim) 12%, transparent); }
.pk-when.pk-st-wait  { color: var(--dim); border: 1px dashed var(--line);
  background: none; padding: 1px 6px; }
.pk-when.pk-st-live  { color: var(--warn);
  background: color-mix(in srgb, var(--warn) 16%, transparent); }

/* --- first run -----------------------------------------------------------
   Signing in used to drop a brand-new account back on the slate, where the
   only sign anything had happened was a chip reading "Choose a name" in the
   corner. These are the two steps that were implied and never asked for. */
.pk-steps { margin: 6px 0 0; padding-left: 20px; font-size: var(--t-label); }
.pk-steps li { margin-bottom: 6px; }
.pk-steps li:last-child { margin-bottom: 0; }
.pk-onward { margin: 14px 0 0; font-size: var(--t-label); }
.pk-onward a { color: var(--accent); font-weight: 600; }

/* Holds a mark's width for a player whose answer has no logo — a team with no
   freely-licensed mark, or "the conference" and "college football", which are
   real answers rather than missing ones. Without it the names step in and out
   by fifteen pixels down the column. */
.pk-markgap { display: inline-block; width: 15px; }

/* --- week by week --------------------------------------------------------
   Hand-drawn SVG rather than a chart library. One figure does not justify a
   dependency on a section whose whole client is a single classic script, and
   the site has no bundler to tree-shake one. */
.pk-hist { width: 100%; height: auto; display: block; margin-top: 4px;
           overflow: visible; }
.pk-hgrid { stroke: var(--line); stroke-width: 1; }
.pk-haxis { fill: var(--dim); font-size: var(--t-fine);
            font-variant-numeric: tabular-nums; }
/* The three lines carry a dash pattern as well as a color, so they are told
   apart without it — WCAG 1.4.1, and it also survives the reader's own team
   color landing near one of them. */
/* Four lines over a band, so each needs a dash of its own — color alone
   would not separate them and the reader's team can land on any hue. The
   median is the odd one out: it is context rather than a competitor, so it
   is a thin light solid that reads as part of the band it sits in. */
.pk-hmed  { stroke: var(--line); stroke-width: 2; }
.pk-hchalk { stroke: var(--warn); stroke-width: 1.5;
             stroke-dasharray: 7 3 2 3; }
/* --ink, not --fg. There is no --fg on this domain: the token is --ink, and
   `var(--fg)` resolved to nothing on all eleven of its uses in this file.
   Ten of them fed `color`, which INHERITS, so an invalid value quietly became
   the parent's color and every one of them looked correct. This one fed
   `stroke`, whose initial value is `none` — so the room simply had no line,
   while sitting in the legend claiming to. An undefined custom property fails
   invisibly on inheriting properties and completely on the rest. */
.pk-hroom { stroke: var(--ink); stroke-width: 1.6; stroke-dasharray: 2 3;
            opacity: .65; }
.pk-hlead { stroke: var(--ok); stroke-width: 1.8; stroke-dasharray: 9 4; }
.pk-hdot  { stroke: var(--panel); stroke-width: 1.5; }
/* The rule down the hovered week, and the ring on your point in it. Both are
   what stop the readout reading as a box floating in the corner. */
.pk-hcross { stroke: var(--dim); stroke-width: 1; stroke-dasharray: 3 3;
             opacity: .7; pointer-events: none; }
.pk-hring  { fill: none; stroke: var(--ink); stroke-width: 1.5; opacity: .8;
             pointer-events: none; }

.pk-hkey { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 0 0 6px;
           font-size: var(--t-meta); color: var(--dim); }
.pk-hchip { display: inline-flex; align-items: center; gap: 6px; }
/* A 20-unit line in a 20-unit box, so the dasharray on the shared class draws
   at the same scale it does on the chart. */
.pk-hswatch { width: 20px; height: 6px; flex: none; overflow: visible; }
/* The band is a block rather than a line, and takes its own fill because the
   band is the reader's team color and the accent is not. */
.pk-hblock { width: 16px; height: 9px; border-radius: 2px; flex: none;
             background: var(--k, var(--line)); }
/* The "you" line has no class of its own on the chart — its color is inline
   because it comes from the reader's team — so the swatch is given the same
   weight here. */
.pk-hyou { stroke-width: 2.5; stroke-linecap: round; }

#hist { position: relative; }
.pk-htip { position: absolute; z-index: 2; pointer-events: none;
           background: var(--panel); border: 1px solid var(--line);
           border-radius: 6px; padding: 5px 8px;
           font-size: var(--t-fine); color: var(--ink); line-height: 1.35;
           font-variant-numeric: tabular-nums; white-space: nowrap; }
.pk-htip[hidden] { display: none; }
.pk-htipwk { font-size: var(--t-micro); letter-spacing: .05em; color: var(--dim);
             text-transform: uppercase; margin-bottom: 2px; }
/* Name, number, and whatever else the row has — three columns rather than a
   sentence per line, which is what made the box wider than the plot. */
.pk-htipgrid { display: grid; grid-template-columns: auto auto auto;
               gap: 0 8px; align-items: baseline; }
.pk-htipk { font-weight: 600; }
.pk-htipk.you   { color: var(--ink); }
.pk-htipk.lead  { color: var(--ok); }
.pk-htipk.room  { color: var(--ink); }
.pk-htipk.chalk { color: var(--warn); }
.pk-htipk.med   { color: var(--dim); font-weight: 400; }
.pk-htipv { text-align: right; }
.pk-htipx { color: var(--dim); font-size: var(--t-micro); }

/* --- the room, as a card ------------------------------------------------- */
.pk-roomstats { display: grid; gap: 10px; margin-bottom: 10px;
                grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
.pk-stat { background: var(--bg); border-radius: 8px; padding: 8px 11px; }
.pk-statv { font-size: var(--t-lead); font-weight: 700;
            font-variant-numeric: tabular-nums; }
.pk-statv.up   { color: var(--ok); }
.pk-statv.down { color: var(--bad); }
.pk-statl { font-size: var(--t-fine); color: var(--dim); letter-spacing: .03em;
            text-transform: uppercase; margin-top: 1px; }

/* --- the board, beside its chart ------------------------------------------
   Two panels rather than a flow of cards, so this is a grid and not the
   column flow the slate and the game pages use: these two belong side by
   side in that order, and the table must not wrap under the chart on a wide
   screen. align-items:start because the table is the taller of the two and
   there is no reason to stretch a chart to match a list of names. */
.pk-duo { display: grid; gap: 14px; align-items: start; }
@media (min-width: 980px) {
  .pk-duo { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  /* A duo with one card is not a duo: signed out and on the look-ahead the
     roster card is hidden, and holding its column open left the pick card
     narrow beside a blank — the exact width mismatch against the pick'em's
     full-row card. One visible card takes the row. */
  .pk-duo:has(> .card[hidden]) { grid-template-columns: minmax(0, 1fr); }
}
/* The room reads as a summary of the two below it, so it spans and its
   figures spread rather than stacking into a column. */
#roomcard { margin-bottom: 14px; }

/* --- survivor ------------------------------------------------------------
   The picker is the slate's control verbatim — same classes, same states —
   so the only styles here are the three facts the slate does not have: a
   team you have already spent, a run, and a row whose player is out. */

/* Spent: still legible (you will want to remember who you used), but
   unmistakably not on offer. Dashed like an unpickable game, struck like an
   eliminated team on the race pages — both signals this site already uses
   for "closed". The input is disabled, so hover and focus never light it. */
.pk-svspent { border-style: dashed; color: var(--dim); cursor: default; }
.pk-svspent .pk-tname { text-decoration: line-through;
                        text-decoration-color: var(--dim); }
.pk-svspent:hover { border-color: var(--line); }
.pk-svspent .pk-num { font-weight: 400; font-size: var(--t-fine); color: var(--dim); }

/* Survivor's line is information, not the game — the pick is straight up,
   and at chip weight the number read as the thing to optimize. Small, dim,
   and named as whose opinion it is ("Vegas says"); stays that way even on
   the selected side, where the generic rule would bold it back up. The
   pick'em's numbers keep their weight, because there the number IS the
   game. */
.pk-side .pk-vegas { font-weight: 400; font-size: var(--t-fine);
                     color: var(--dim); }
/* The look-ahead's qualifier on a line: a word, because the ~ it replaced
   read as a third sign in front of +7. Dim and small against the number's
   full weight, so the eye still lands on the number. */
.pk-num .pk-est { font-weight: 400; font-size: var(--t-fine);
                  color: var(--dim); letter-spacing: .02em; }
.pk-slate-game input:checked + .pk-side .pk-vegas { font-weight: 400; }

/* --- the matchup stacks inside the survivor card -------------------------
   The slate's 1fr / 1.3em / 1fr sides assume a card the width of the page.
   The survivor picker is 2.1fr of a duo and still runs two columns of games
   inside that, so a card lands near 390px: 56 for the time, 40 for the chip,
   and what is left splits into two sides of about a hundred pixels each.
   "Texas Tech" came out "T." on a 1400px screen, which is the exact failure
   the two-column slate exists to avoid.

   Stacked, each side gets the whole card width and a name is a name again.
   The card grows by one row, not by a column, so the week still fits.
   Away above home, which is the order the joiner already reads in. */
#svslate .pk-sides { grid-template-columns: 1fr; gap: 3px; }
/* Aligned under the logos rather than centered, so the eye going down the
   card meets one left edge instead of three. display is restated because the
   narrow-screen rule drops the joiner: that was the right call when stacking
   only happened on a phone and the space was worth more than the word, and
   it is the wrong one now that the survivor card stacks everywhere. Without
   it a neutral-site game and a road game are the same two names in the same
   order — and the joiner is the only thing that ever says which. */
#svslate .pk-at { display: block; justify-self: start; padding-left: 7px; }

/* --- eliminated ----------------------------------------------------------
   The picker is already disabled for a dead run — svRepaint has folded it
   into `disabled` since per-game locking landed — but disabled reads as
   "not yet" and locked reads as "not any more", and the two look identical.
   A run that is over is a different fact from a week that has closed, and it
   is worth saying in a way you cannot miss on the way to the games. */
.pk-svdead { position: relative; }
/* Grayscale rather than a lower opacity on the games themselves: the checked
   pick paints in its team's own color, which stays bright through opacity and
   goes on looking like a live selection. */
.pk-svdead .pk-slate { filter: grayscale(1); opacity: .5; }
.pk-svdead::after {
  content: "Eliminated"; position: absolute; inset: 0;
  display: grid; place-items: center; pointer-events: none;
  transform: rotate(-14deg);
  font-size: clamp(2.2rem, 7vw, 4.5rem); font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase;
  color: color-mix(in srgb, var(--bad) 20%, transparent);
}
/* Forced-colors throws away color-mix and filters both, which would leave a
   solid word over a full-strength slate — worse than no watermark. */
@media (forced-colors: active) {
  .pk-svdead .pk-slate { filter: none; opacity: 1; }
  .pk-svdead::after { content: none; }
}

/* The run's own ending, stated in the card that shows the run. */
.pk-svend { margin: 0 0 8px; font-weight: 600; color: var(--bad); }
/* A week you picked in after the run was already over. The server refuses
   these now; rows that predate that check still have to render as what they
   are, which is not part of the run. */
.pk-svmoot { opacity: .5; }
.pk-svnopick { color: var(--dim); font-style: italic; }

/* Your run: one line per week, the same rhythm as the card's rows. */
.pk-svrun { list-style: none; margin: 0; padding: 0; }
.pk-svrunrow { display: flex; align-items: center; gap: 10px;
               padding: 5px 0; border-bottom: 1px solid var(--line);
               font-size: var(--t-label); }
.pk-svrunrow:last-child { border-bottom: none; }
.pk-svrunrow .pk-when { min-width: 3.2em; }
.pk-svrunrow img.mark { margin: 0; }

/* The dead stay on the board — watching is the consolation game — but they
   recede the way finished rows do everywhere else on the site. */
#svboard tr.pk-svout td { color: var(--dim); }
#svboard { width: 100%; border-collapse: collapse; }
#svboard th, #svboard td { padding: 7px 10px; text-align: left;
                           border-bottom: 1px solid var(--line); }
#svboard td.n, #svboard th.n { text-align: right;
                               font-variant-numeric: tabular-nums; }
#svboard tr.you td { background: color-mix(in srgb, var(--you, var(--accent)) 10%, transparent); }
#svboard tr.you td:first-child { box-shadow: inset 3px 0 0 var(--you, var(--accent)); }
#svboard img.mark { vertical-align: -2px; margin-right: 6px; }
#svboard .pk-res { margin-left: 6px; }

#svwithdraw { margin-top: 10px; }
#svlock { padding: 10px 14px; }

/* The graveyard. A list, not a table: each line is a sentence, and the count
   is the only number, so columns would be scaffolding around nothing. */
.pk-svgrave { list-style: none; margin: 0; padding: 0;
              display: grid; gap: 6px; }
.pk-svgrave li { display: flex; align-items: center; gap: 7px;
                 background: var(--bg); border-radius: 8px;
                 padding: 7px 11px; font-size: var(--t-label); }
.pk-svgrave img { flex: none; }
.pk-svgrave b { color: var(--ink); }

/* The Run cell. Two facts on one line — when it ended and what ended it —
   with the second set back so the column still scans as a status. */
/* How a run stands, in one leaderboard cell: "Alive", or "Out wk 4" and what
   ended it. Renamed off .pk-svrun — that is the pick page's list, and this
   rule was silently flattening it into one line. */
.pk-svstate { display: inline-flex; align-items: center; gap: 6px;
              white-space: nowrap; }
.pk-svalive { color: var(--ok); font-weight: 600; }
.pk-svout   { color: var(--dim); }
.pk-svwhy   { color: var(--ink); }

/* What joining late cost. A card rather than a note, because it changes what
   the slate below it will let you do. */
.pk-handicap { border-left: 3px solid var(--accent); }
.pk-handicap p { margin: 0; }
.pk-handicap p + p { margin-top: 6px; }
.pk-handicap b { color: var(--ink); }

/* The tables scroll inside their own box, not by dragging the page sideways.
   .table-wrap and .table-scroll were in the markup from the start and styled
   nowhere, which is invisible while a dozen short display names fit a phone
   and stops being invisible the moment a real field turns up: the widest
   allowed name, a team mark, and the this-week column together run past
   375px, and an unstyled wrapper hands that overflow to the document.
   attendance/site/styles.css solves it the same way. */
/* A card is a grid item, and a grid item's min-width is auto — so it refuses
   to shrink below its contents and a wide table pushes the whole card past
   the viewport, taking the document with it. overflow-x on the wrapper does
   nothing until this is set, because by then the ancestor has already grown.
   Scoped to this stylesheet, so it applies to the pools pages and nothing
   else on the domain. */
.card { min-width: 0; }
.table-wrap { border-radius: 8px; }
.table-scroll { overflow-x: auto; overscroll-behavior-x: contain; }
.table-scroll > table { min-width: 100%; }

/* A survivor game whose own kickoff has passed, on a week that is still open
   elsewhere. Dimmed rather than hidden: knowing the early game is gone is
   part of reading what is left, and removing the row would make the card
   change shape as the afternoon went on. */
.pk-slate-game.pk-started { opacity: .55; }
.pk-slate-game.pk-started .pk-when::after {
  content: " · started"; color: var(--dim); font-size: var(--t-micro);
}

/* Sixteen marks in a row: spent first and in the order they were spent, then
   what is left. Names are dropped in favour of the marks the whole site
   already identifies teams by — sixteen names is a paragraph, sixteen marks
   is a glance, and the title attribute carries the name for anyone who wants
   it. */
.pk-roster { list-style: none; margin: 6px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.pk-mk { display: flex; align-items: center; line-height: 0; }
.pk-mk .mark { margin: 0; }
/* Spent. Faded rather than removed — which teams are gone is half the answer,
   and a row that shrank each week would stop being a roster. */
.pk-mkspent { opacity: .28; filter: grayscale(1); }
.pk-mkabbr { font-size: var(--t-micro); color: var(--dim); }
/* The leaderboard's spent column. Sixteen of these can land in one table cell
   by November, so they stay small — but not so small the logo stops being
   recognisable, which is the entire reason this column is marks and not a
   list of names. */
.pk-rostersm .mark { width: 20px; height: 20px; }
.pk-rostersm { gap: 4px; max-width: 15rem; }

/* One row per opponent: who, then their marks, then how their run ended. */
.pk-field { list-style: none; margin: 6px 0 0; padding: 0; }
.pk-fieldrow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 6px 0; border-bottom: 1px solid var(--line); }
.pk-fieldrow:last-child { border-bottom: 0; }
.pk-fieldname { min-width: 9rem; font-size: var(--t-row); }
.pk-fieldout { opacity: .6; }
.pk-fieldout .pk-fieldname { text-decoration: line-through; }

/* Zero-height children still cost a grid row.
   main is display:grid with an 18px gap, so the two live regions and the icon
   sprite — all of them empty and 0px tall — were adding 54px of nothing
   between the cards. It read as a mysterious gap under the lock banner.
   NOT display:none. These are aria-live regions, and a region that is
   display:none when its text arrives may never be announced; the sprite is
   referenced by <use> and has to stay rendered. position:absolute takes them
   out of the grid's flow while leaving them in the document, which is the
   distinction that matters here. */
.pk-savestate:empty, .pk-alertstate:empty { position: absolute; margin: 0; }
main > svg.sprite { position: absolute; }

/* The picker earns the room. Its rows carry a time, two marks, two team names
   and a number, and at an even split the names were wrapping "not Big 12"
   onto three lines while the roster beside it sat half empty. Roughly two to
   one, and the roster is a column of sixteen rather than a grid. */
@media (min-width: 980px) {
  .pk-duo-pick { grid-template-columns: minmax(0, 2.1fr) minmax(0, 1fr); }
}
/* Stacked and legible rather than a strip of thumbnails: this is the list you
   read down while deciding, so each team gets a row, its mark at a size you
   can identify without leaning in, and its name spelled out. */
.pk-rostercol { display: block; }
.pk-rostercol .pk-mk { display: flex; align-items: center; gap: 9px;
  padding: 5px 2px; border-bottom: 1px solid var(--line); line-height: 1.2; }
.pk-rostercol .pk-mk:last-child { border-bottom: 0; }
.pk-rostercol .mark { width: 26px; height: 26px; }
.pk-rostercol .pk-mkname { font-size: var(--t-row); }
.pk-rostercol .pk-mkwhen { margin-left: auto; font-size: var(--t-micro);
  color: var(--dim); white-space: nowrap; }
