/* Roster Predictor
 *
 * Design point of view: a broadcast scoreboard, not a SaaS dashboard. The page is a dark
 * slate; information sits on it in condensed, tabular type the way a lower-third does.
 * The site's own color is a single indigo-violet used only for site-level actions, because
 * every hue on the wheel already belongs to some NFL team; the neutral arena is what lets
 * 32 team palettes drop in without a fight. Team pages override --accent and friends.
 *
 * No build step. No framework. Custom properties do the theming.
 */

/* ---------- reset ---------- */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; }
body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
img, svg { display: block; max-width: 100%; }
/* Class rules that set display (.btn is inline-flex, .dock is flex) otherwise beat the UA
   stylesheet's [hidden] rule, so hiding an element by attribute silently does nothing. */
[hidden] { display: none !important; }
button, input, select, textarea { font: inherit; color: inherit; }
:where(a) { color: inherit; }

/* ---------- tokens ---------- */

:root {
  /* surfaces. --surface and --raised are overridden per team on team pages. */
  --base: #0d1117;
  --surface: #0d1117;
  --raised: #151b24;
  --sunken: #090d13;
  --line: #232c3a;
  --line-soft: #1b2431;

  /* ink */
  --ink: #e8eef6;
  --ink-2: #a3b1c4;
  --ink-3: #6e7d92;

  /* the site's own color, used where no team owns the page */
  --brand: #7c6cff;
  --brand-2: #9b8dff;
  --brand-ink: #ffffff;

  /* team tokens. Defaults are the site brand so any page renders before JS runs. */
  --accent: #7c6cff;
  --accent-ink: #ffffff;
  --accent-text: #a99fff;
  --accent-edge: #8f80ff;
  --accent-soft: rgba(124, 108, 255, 0.16);
  --accent-line: rgba(124, 108, 255, 0.42);
  --band: #1b2230;
  --band-ink: #ffffff;
  --band-edge: #2a3444;
  --secondary: #8b98ab;
  --secondary-ink: #0d1117;

  /* semantics. Deliberately NOT team colored: keep and cut must mean the same thing
     on all 32 boards, and must never collide with whichever team is on screen. */
  --keep: #3ddc84;
  --keep-dim: rgba(61, 220, 132, 0.14);
  --cut: #ff5a4d;
  --cut-dim: rgba(255, 90, 77, 0.13);
  --warn: #ffb020;

  /* type */
  --display: "Barlow Condensed", "Oswald", ui-sans-serif, system-ui, sans-serif;
  /* The wordmark only. Bebas Neue is caps-only by design, which is the point: RosterPredictor
     sets as one unbroken run of capitals and the colour break carries the two words. */
  --wordmark: "Bebas Neue", "Barlow Condensed", Impact, ui-sans-serif, sans-serif;
  --text: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* scale */
  --r-sm: 6px;
  --r: 10px;
  --r-lg: 16px;
  --pad: clamp(16px, 4vw, 32px);
  --wrap: 1180px;

  --shadow: 0 1px 0 rgba(255,255,255,.03) inset, 0 8px 24px -12px rgba(0,0,0,.7);
}

/* ---------- base ---------- */

body {
  background: var(--surface);
  color: var(--ink);
  font-family: var(--text);
  font-size: 15px;
  line-height: 1.55;
  min-height: 100vh;
  font-variant-numeric: tabular-nums;
}

h1, h2, h3, .display {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: 0.005em;
}

h1 { font-size: clamp(34px, 6vw, 58px); }
h2 { font-size: clamp(24px, 3.4vw, 34px); }
h3 { font-size: 20px; }

a { color: var(--accent-text); text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }

.wrap { width: min(100% - (var(--pad) * 2), var(--wrap)); margin-inline: auto; }
.stack > * + * { margin-top: var(--gap, 16px); }
.muted { color: var(--ink-2); }
.dim { color: var(--ink-3); }
.tiny { font-size: 12.5px; }
.nowrap { white-space: nowrap; }
.center { text-align: center; }

/* Screen-reader only, but focusable variant for skip links. */
.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sr:focus {
  position: static; width: auto; height: auto; clip: auto;
  padding: 8px 12px; background: var(--brand); color: #fff; border-radius: var(--r-sm);
}

:where(a, button, input, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent-edge);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- chrome ---------- */

.site-head {
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--surface) 88%, #000);
  position: sticky; top: 0; z-index: 40;
  backdrop-filter: blur(8px);
}
.site-head .bar {
  display: flex; align-items: center; gap: 16px;
  padding-block: 12px; min-height: 58px;
}
.logo {
  /* Matches the option 7 sample exactly: Bebas Neue at 21px, .02em tracking, the mark
     spaced in em so it scales with the type rather than drifting at other sizes. */
  display: inline-flex; align-items: center;
  font-family: var(--wordmark); font-weight: 400; font-size: 21px;
  letter-spacing: 0.02em; text-decoration: none; color: var(--ink);
  white-space: nowrap; line-height: 1;
  /* Bebas Neue only HAS capitals, so the mark looks like caps even though the markup says
     "RosterPredictor". Do not rely on that: if the webfont is slow, blocked or fails, the
     fallback renders it mixed case and the mark changes shape. Force it. */
  text-transform: uppercase;
}
/* The wordmark is ONE flex item. Left as two, a flex gap lands between the words and
   reopens the space the closed-up mark is supposed to remove. */
.logo .wm { display: inline-block; }
.logo .lo { color: var(--brand); font-weight: inherit; }
.logo .mark {
  /* Height is the wordmark's CAP HEIGHT, measured at 0.676em for Bebas Neue, so the badge
     and the letters read as one object rather than the badge sitting proud of the type.
     Width is auto with padding, because two digits in a cap-height SQUARE are too small to
     read. The digits use the wordmark face for the same reason: it is condensed, so it
     fills a short chip far better than the display face did. */
  height: .68em; min-width: .68em; padding: 0 .13em;
  border-radius: .16em; flex: none;
  margin-right: .17em;
  background: linear-gradient(150deg, var(--brand), #4b3ee0);
  display: inline-grid; place-items: center;
  font-family: var(--wordmark); font-size: .62em; font-weight: 400;
  color: #fff; letter-spacing: .01em; line-height: 1;
  /* The flex line box is taller than the caps, so centering on it sits the chip low.
     Nudge it onto the cap band. */
  transform: translateY(-0.03em);
}

/* Everything in the wordmark is sized in em, so one font-size handles small screens. */
@media (max-width: 420px) {
  .logo { font-size: 19px; }
  .site-nav a { padding: 6px 8px; font-size: 13px; }
}
.site-nav { margin-left: auto; display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
.site-nav a {
  color: var(--ink-2); text-decoration: none; font-size: 13.5px; font-weight: 500;
  padding: 7px 11px; border-radius: var(--r-sm);
}
.site-nav a:hover { color: var(--ink); background: var(--raised); }
.site-nav a[aria-current="page"] { color: var(--ink); background: var(--raised); }

.site-foot {
  border-top: 1px solid var(--line);
  margin-top: 64px; padding-block: 28px 44px;
  color: var(--ink-3); font-size: 13px;
}
.site-foot a { color: var(--ink-2); }
.site-foot .cols { display: flex; flex-wrap: wrap; gap: 8px 22px; align-items: baseline; }

/* ---------- countdown / status strip ---------- */

.strip {
  border-bottom: 1px solid var(--line);
  background: var(--raised);
  font-size: 13.5px;
}
.strip .bar { display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center; padding-block: 10px; }
.strip .dot {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--keep); box-shadow: 0 0 0 3px var(--keep-dim);
}
.strip[data-phase="locked"] .dot { background: var(--warn); box-shadow: 0 0 0 3px rgba(255,176,32,.15); }
.strip[data-phase="graded"] .dot { background: var(--brand); box-shadow: 0 0 0 3px rgba(124,108,255,.18); }
.strip .clock { font-family: var(--mono); font-size: 13px; color: var(--ink); }
.strip .clock b { font-weight: 700; }

/* ---------- buttons ---------- */

.btn {
  --btn-bg: var(--raised);
  --btn-ink: var(--ink);
  --btn-line: var(--line);
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--btn-bg); color: var(--btn-ink);
  border: 1px solid var(--btn-line); border-radius: var(--r);
  padding: 9px 16px; font-weight: 600; font-size: 14px;
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: transform .08s ease, filter .12s ease, background .12s ease;
}
.btn:hover { filter: brightness(1.12); }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; filter: none; }
.btn-primary { --btn-bg: var(--accent); --btn-ink: var(--accent-ink); --btn-line: transparent; }
.btn-brand { --btn-bg: var(--brand); --btn-ink: var(--brand-ink); --btn-line: transparent; }
.btn-ghost { --btn-bg: transparent; --btn-line: var(--line); }
.btn-lg { padding: 13px 24px; font-size: 16px; border-radius: var(--r); }
.btn-sm { padding: 5px 11px; font-size: 13px; border-radius: var(--r-sm); }

/* ---------- cards, panels ---------- */

.panel {
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 20px;
  box-shadow: var(--shadow);
}
.panel-tight { padding: 14px 16px; }

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 99px;
  background: var(--line-soft); color: var(--ink-2);
}
.chip-rookie { background: var(--secondary); color: var(--secondary-ink); }
.chip-inj { background: rgba(255,176,32,.16); color: var(--warn); }
.chip-ir { background: rgba(255,90,77,.15); color: var(--cut); }
.chip-accent { background: var(--accent-soft); color: var(--accent-text); }

/* ---------- the 32 team grid ---------- */

.team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
}
@media (min-width: 720px) { .team-grid { grid-template-columns: repeat(auto-fill, minmax(176px, 1fr)); } }

.team-tile {
  --tile-band: var(--band);
  position: relative; display: block; text-decoration: none; color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--raised);
  overflow: hidden;
  transition: transform .12s ease, border-color .12s ease;
}
.team-tile::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 4px;
  background: var(--tile-band);
}
.team-tile:hover, .team-tile:focus-visible {
  transform: translateY(-2px);
  border-color: var(--tile-accent, var(--line));
}
.team-tile .tile-in {
  display: flex; align-items: center; gap: 11px;
  padding: 15px 13px 13px;
  background: linear-gradient(180deg, var(--tile-wash, transparent), transparent 70%);
}
.team-tile img { width: 34px; height: 34px; object-fit: contain; flex: none; }
.team-tile .abbr {
  font-family: var(--display); font-weight: 700; font-size: 19px; letter-spacing: .04em;
  line-height: 1;
}
.team-tile .nick { font-size: 12.5px; color: var(--ink-2); line-height: 1.25; }
.team-tile .meta {
  border-top: 1px solid var(--line-soft);
  padding: 7px 13px; font-size: 11.5px; color: var(--ink-3);
  display: flex; justify-content: space-between; gap: 8px;
}
.team-tile .meta .done { color: var(--keep); font-weight: 600; }

.div-group { margin-top: 26px; }
.div-group > h3 {
  font-size: 13px; font-family: var(--text); font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
  margin-bottom: 10px;
}

/* ---------- team page header band ---------- */

.team-band {
  background: var(--band); color: var(--band-ink);
  border-bottom: 3px solid var(--accent);
}
.team-band .bar { display: flex; align-items: center; gap: 16px; padding-block: 20px; flex-wrap: wrap; }
.team-band img { width: 54px; height: 54px; object-fit: contain; flex: none; }
.team-band h1 { font-size: clamp(26px, 4.6vw, 42px); }
.team-band .sub { opacity: .82; font-size: 13.5px; }

/* ---------- roster board ---------- */

.board-layout { display: grid; gap: 20px; align-items: start; }
@media (min-width: 940px) { .board-layout { grid-template-columns: minmax(0,1fr) 300px; } }

.unit { margin-top: 22px; }
.unit-head {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 8px 2px; border-bottom: 1px solid var(--line);
  position: sticky; top: 58px; z-index: 10;
  background: var(--surface);
}
.unit-head h3 {
  font-size: 15px; font-family: var(--text); font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
}
.unit-head .count { font-family: var(--mono); font-size: 13px; color: var(--ink-2); }
.unit-head .count.over { color: var(--warn); }
.unit-head .count.under { color: var(--cut); }

.plist { list-style: none; padding: 0; margin: 0; }

.prow {
  display: grid;
  grid-template-columns: 34px minmax(0,1fr) auto;
  align-items: center; gap: 11px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line-soft);
  border-left: 3px solid transparent;
  background: transparent;
}
.prow:hover { background: var(--line-soft); }
.prow[data-state="keep"] { border-left-color: var(--keep); background: var(--keep-dim); }
/* Not-kept is the resting state of ninety rows, so it stays neutral. Marking every one of
   them in red would make an untouched board look like a catastrophe. Red is reserved for
   an actual graded miss. */
.prow[data-state="cut"] { opacity: .9; }
.prow[data-locked="true"] { opacity: 1; }

.prow .face {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: var(--line-soft) center/cover no-repeat;
  border: 1px solid var(--line);
}
.prow .who { min-width: 0; }
.prow .nm { font-weight: 600; font-size: 14.5px; }
.prow .nm .num { color: var(--ink-3); font-family: var(--mono); font-size: 12.5px; margin-right: 6px; }
.prow .bio { font-size: 12px; color: var(--ink-3); display: flex; gap: 7px; flex-wrap: wrap; }
.prow .bio .pos { color: var(--accent-text); font-weight: 700; }

/* Keep and cut are encoded by position, border, icon AND label, never by color alone. */
.toggle {
  display: inline-flex; border: 1px solid var(--line); border-radius: 99px;
  overflow: hidden; background: var(--sunken); flex: none;
}
.toggle button {
  background: transparent; border: 0; cursor: pointer;
  padding: 5px 12px; font-size: 12.5px; font-weight: 700; color: var(--ink-3);
  display: inline-flex; align-items: center; gap: 5px;
}
.toggle button[aria-pressed="true"] { color: #06120b; background: var(--keep); }
.toggle button.cut[aria-pressed="true"] { color: #1a0503; background: var(--cut); }
.toggle button:hover { color: var(--ink); }
.toggle button[aria-pressed="true"]:hover { color: inherit; }

/* ---------- sticky counter rail ---------- */

.rail { position: sticky; top: 74px; }
.counter { text-align: center; }
.counter .big {
  font-family: var(--display); font-weight: 700; font-size: 56px; line-height: 1;
  letter-spacing: -0.01em;
}
.counter .big.ok { color: var(--keep); }
.counter .big.over { color: var(--warn); }
.counter .of { color: var(--ink-3); font-size: 15px; font-family: var(--display); }
.counter .hint { font-size: 13px; color: var(--ink-2); margin-top: 6px; min-height: 2.6em; }

.meter { list-style: none; padding: 0; margin: 14px 0 0; font-size: 12.5px; }
.meter li {
  display: grid; grid-template-columns: 34px 1fr auto; gap: 8px; align-items: center;
  padding: 3px 0;
}
.meter .lab { color: var(--ink-2); font-weight: 700; font-size: 11.5px; letter-spacing: .04em; }
.meter .track { height: 6px; border-radius: 99px; background: var(--line-soft); overflow: hidden; }
.meter .fill { height: 100%; background: var(--accent); }
.meter .n { font-family: var(--mono); font-size: 12px; color: var(--ink-2); }
.meter li[data-flag="under"] .n { color: var(--cut); }
.meter li[data-flag="over"] .n { color: var(--warn); }

/* ---------- mobile submit dock ---------- */

.dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  background: color-mix(in srgb, var(--raised) 94%, #000);
  border-top: 1px solid var(--line);
  padding: 10px var(--pad);
  padding-bottom: max(10px, env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: 12px;
}
.dock .n { font-family: var(--display); font-weight: 700; font-size: 26px; line-height: 1; }
.dock .n.ok { color: var(--keep); }
.dock .n.over { color: var(--warn); }
.dock .lab { font-size: 12px; color: var(--ink-2); }
.dock .btn { margin-left: auto; }
@media (min-width: 940px) { .dock { display: none; } }
@media (max-width: 939px) { body.has-dock { padding-bottom: 76px; } }

/* ---------- toolbar ---------- */

.toolbar {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  padding: 12px 0;
}
.toolbar input[type="search"] {
  background: var(--sunken); border: 1px solid var(--line); border-radius: var(--r);
  padding: 8px 12px; min-width: 180px; flex: 1 1 200px;
}
.toolbar input[type="search"]::placeholder { color: var(--ink-3); }
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.seg button {
  background: transparent; border: 0; padding: 7px 12px; font-size: 13px; font-weight: 600;
  color: var(--ink-2); cursor: pointer;
}
.seg button[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); }

/* ---------- tables and leaderboards ---------- */

.tbl-wrap { overflow-x: auto; }
table.lb { width: 100%; border-collapse: collapse; font-size: 14px; }
table.lb th, table.lb td { padding: 9px 10px; text-align: left; border-bottom: 1px solid var(--line-soft); }
table.lb th {
  font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-3); font-weight: 700; white-space: nowrap;
}
table.lb td.num, table.lb th.num { text-align: right; font-family: var(--mono); }
table.lb tr.me { background: var(--accent-soft); }
table.lb tr.me td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
.rank { font-family: var(--display); font-weight: 700; font-size: 17px; color: var(--ink-2); }
.rank.top { color: var(--accent-text); }

/* ---------- notices ---------- */

.note {
  border: 1px solid var(--line); border-left: 3px solid var(--ink-3);
  background: var(--raised); border-radius: var(--r);
  padding: 12px 14px; font-size: 13.5px; color: var(--ink-2);
}
.note-warn { border-left-color: var(--warn); }
.note-bad { border-left-color: var(--cut); }
.note-ok { border-left-color: var(--keep); }
.note b, .note strong { color: var(--ink); }

/* ---------- result marks ---------- */

.mark { font-weight: 800; font-size: 12px; letter-spacing: .04em; }
.mark-made { color: var(--keep); }
.mark-cut  { color: var(--ink-3); }
.mark-miss { color: var(--cut); }

/* Four outcomes, not two. Treating "correctly kept" and "correctly cut" the same paints
   the whole page green, since about seventy percent of any board is correct by default and
   most of that is cuts. Only the players you actually put on your 53 get the strong mark. */
.prow[data-result="made"]      { border-left-color: var(--keep); background: var(--keep-dim); }
.prow[data-result="right-cut"] { opacity: .62; }
.prow[data-result="bad-keep"]  { border-left-color: var(--cut); background: var(--cut-dim); }
.prow[data-result="missed"]    { border-left-color: var(--warn); background: rgba(255,176,32,.1); }

/* ---------- skeleton ---------- */

.skel { background: var(--line-soft); border-radius: var(--r-sm); color: transparent; }
@keyframes pulse { 50% { opacity: .5; } }
.skel { animation: pulse 1.6s ease-in-out infinite; }

/* ---------- conference and division grouping on the picker ---------- */

.conf + .conf { margin-top: 40px; }
.conf-head {
  display: flex; align-items: baseline; gap: 11px; flex-wrap: wrap;
  padding-bottom: 9px; margin-top: 26px;
  border-bottom: 1px solid var(--line);
}
.conf-tag {
  font-family: var(--display); font-weight: 700; font-size: 26px; letter-spacing: .04em;
  line-height: 1;
}
.conf[data-conf="AFC"] .conf-tag { color: #e8564a; }
.conf[data-conf="NFC"] .conf-tag { color: #5b8ff5; }
.conf-name {
  font-family: var(--text); font-size: 12.5px; font-weight: 500; color: var(--ink-3);
}
.div-group > h4 {
  font-size: 12px; font-family: var(--text); font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3);
  margin-bottom: 10px;
}
@media (min-width: 900px) {
  /* Four divisions abreast on a wide screen reads like a standings page. */
  .conf > .div-group { display: contents; }
  .conf {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0 18px; align-items: start;
  }
  .conf-head { grid-column: 1 / -1; }
  .conf .div-group { display: block; margin-top: 18px; }
  .conf .team-grid { grid-template-columns: 1fr; }
}

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

.hero { padding-block: clamp(30px, 5.5vw, 60px) 8px; display: grid; gap: 34px; align-items: center; }
@media (min-width: 900px) { .hero { grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); gap: 54px; } }
.hero .lede { max-width: 54ch; margin-top: 14px; font-size: 17px; }
.hero-cta { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 22px; }

/* The whole premise in one picture: ninety squares, thirty seven of them go away. */
.crunch { margin: 0; }
.crunch-grid {
  display: grid;
  grid-template-columns: repeat(15, 1fr);
  gap: 5px;
}
.crunch-grid i {
  display: block; aspect-ratio: 1; border-radius: 3px;
  background: var(--line); border: 1px solid transparent;
}
.crunch-grid i.keep {
  background: var(--brand);
  box-shadow: 0 0 0 1px rgba(124, 108, 255, .35);
  animation: settle .5s ease-out backwards; animation-delay: var(--d);
}
.crunch-grid i.cut {
  background: transparent; border-color: var(--line);
  position: relative; opacity: .8;
  animation: fade .5s ease-out backwards; animation-delay: var(--d);
}
.crunch-grid i.cut::after {
  content: ""; position: absolute; inset: 1px;
  background: linear-gradient(to top right, transparent 44%, var(--ink-3) 44%, var(--ink-3) 56%, transparent 56%);
}
@keyframes settle { from { opacity: 0; transform: scale(.4); } }
@keyframes fade { from { opacity: 0; } }
.crunch figcaption {
  margin-top: 14px; display: flex; gap: 10px; flex-wrap: wrap; align-items: baseline;
  font-size: 13px; color: var(--ink-3);
}
.crunch figcaption b { color: var(--ink-2); font-family: var(--display); font-size: 17px; }
.crunch figcaption b.keeps { color: var(--brand-2); }
.crunch figcaption .cuts { margin-left: auto; }
.crunch figcaption .arrow { color: var(--ink-3); }
@media (max-width: 899px) { .crunch-grid { grid-template-columns: repeat(18, 1fr); } }

/* Compact leaderboard shown alongside a scored board. The rail is narrow, so this trades
   padding for name width rather than truncating every name to eight characters. */
table.lb.mini { font-size: 13px; }
table.lb.mini th, table.lb.mini td { padding: 5px 4px; }
table.lb.mini td:first-child { width: 22px; padding-left: 2px; }
table.lb.mini .rank { font-size: 14px; }
table.lb.mini td.who {
  width: 100%; max-width: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
table.lb.mini td.num { padding-right: 2px; }
table.lb.mini tr.me td:first-child { box-shadow: inset 2px 0 0 var(--accent); }

/* A player the club moved to a new position during camp. ESPN and most other sites will
   still show his old one, so the badge explains the difference rather than looking wrong. */
.chip-moved {
  background: var(--accent-soft);
  color: var(--accent-text);
  border: 1px solid var(--accent-line);
}

/* Active/PUP or NFI: eligible for the 53, but not practicing. Amber, like the injury chip,
   because it is the same kind of information: a risk attached to picking him. */
.chip-desig {
  background: rgba(255, 176, 32, .16);
  color: var(--warn);
  border: 1px solid rgba(255, 176, 32, .3);
}

/* ---------- the crowd: consensus, contested players, board comparison ---------- */

/* What share of submitted boards keeps this player. Three tones, because the number only
   matters as a category: a lock, a goner, or genuinely contested. */
.pct {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 11.5px;
  padding: 1px 6px;
  border-radius: 99px;
}
.pct[data-tone="lock"]      { background: var(--keep-dim); color: var(--keep); }
.pct[data-tone="gone"]      { background: rgba(255,90,77,.12); color: var(--cut); }
.pct[data-tone="contested"] { background: rgba(255,176,32,.15); color: var(--warn); }

.contested { list-style: none; padding: 0; margin: 0; font-size: 12.5px; }
.contested li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 46px 32px;
  gap: 6px; align-items: center; padding: 2px 0;
}
.contested .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.contested .bar { height: 5px; border-radius: 99px; background: var(--line-soft); overflow: hidden; }
.contested .bar i { display: block; height: 100%; background: var(--warn); }
.contested .n { text-align: right; font-family: var(--mono); font-size: 11.5px; color: var(--ink-2); }

/* ---------- comparing one board against another ---------- */
/*
 * Two aligned columns at the right edge, You and Them, one square each. The columns are what
 * make this readable: you scan straight down and a gap in a run of filled squares is the
 * disagreement. Scattered per-row markers made you hunt line by line.
 */
#board.comparing .prow { grid-template-columns: 34px minmax(0,1fr) auto 30px 30px; }
#board.comparing .unit-head { padding-right: 10px; }

.prow .cmp, .unit-head .cmp-lbl { display: none; }
#board.comparing .prow .cmp {
  display: block; justify-self: center;
  width: 16px; height: 16px; border-radius: 4px;
  border: 1.5px solid var(--line); background: transparent;
}
#board.comparing .prow .cmp[data-k="1"] { background: var(--keep); border-color: var(--keep); }
#board.comparing .prow .cmp[data-k="0"] { border-color: var(--ink-3); opacity: .45; }

/* The disagreement is what the eye should catch: ring the odd square out. */
#board.comparing .prow[data-diff] .cmp[data-k="1"] {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--keep);
}
#board.comparing .prow[data-diff="mine"]   { background: rgba(155,141,255,.07); }
#board.comparing .prow[data-diff="theirs"] { background: rgba(255,176,32,.07); }

#board.comparing .unit-head .cmp-lbl {
  display: block; width: 30px; text-align: center; flex: none;
  font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-3);
}
#board.comparing .unit-head .cmp-lbl-them { color: var(--accent-text); }

.cmp-key { display: inline-flex; align-items: center; gap: 5px; margin-left: 10px; color: var(--ink-3); }
.cmp-key i { width: 11px; height: 11px; border-radius: 3px; display: inline-block; border: 1.5px solid var(--line); }
.cmp-key i.k1 { background: var(--keep); border-color: var(--keep); }
.cmp-key i.k0 { border-color: var(--ink-3); opacity: .45; }

/* On a phone the two columns matter more than the roster bio line. */
@media (max-width: 560px) {
  #board.comparing .prow { grid-template-columns: 34px minmax(0,1fr) auto 26px 26px; }
  #board.comparing .prow .cmp { width: 14px; height: 14px; }
  #board.comparing .unit-head .cmp-lbl { width: 26px; font-size: 9px; }
}

/* ---------- board switcher ---------- */

#board-tabs { margin-bottom: 12px; }
.tabs { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.tab {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--raised); color: var(--ink-2);
  border: 1px solid var(--line); border-radius: 99px;
  padding: 6px 13px; font-size: 13px; font-weight: 600; cursor: pointer;
  white-space: nowrap;
}
.tab:hover { color: var(--ink); }
.tab[aria-selected="true"] {
  background: var(--accent-soft); color: var(--ink);
  border-color: var(--accent-edge);
}
.tab .star { color: var(--accent-text); font-size: 12px; line-height: 1; }
.tab[aria-selected="true"] .star { color: var(--accent-text); }
.tab .cnt {
  font-family: var(--mono); font-size: 11.5px; color: var(--ink-3);
  background: var(--sunken); border-radius: 99px; padding: 1px 6px;
}
.tab.add { border-style: dashed; color: var(--ink-3); }
.tab.add:hover { color: var(--ink-2); border-color: var(--ink-3); }
.tabs-actions {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-top: 8px; font-size: 12.5px;
}

/* ---------- team page view tabs ---------- */

.view-tabs {
  display: flex; gap: 2px; align-items: flex-end;
  border-bottom: 1px solid var(--line);
  margin-top: 2px;
}
.view-tabs button {
  background: none; border: 0; cursor: pointer;
  padding: 13px 16px 11px; font-size: 14.5px; font-weight: 600;
  color: var(--ink-3); border-bottom: 2px solid transparent;
  display: inline-flex; align-items: center; gap: 8px;
}
.view-tabs button:hover { color: var(--ink-2); }
.view-tabs button[aria-selected="true"] {
  color: var(--ink); border-bottom-color: var(--accent);
}
.view-tabs .pill {
  font-family: var(--mono); font-size: 11.5px; font-weight: 700;
  background: var(--accent-soft); color: var(--accent-text);
  padding: 1px 7px; border-radius: 99px;
}
.view-tabs button[aria-selected="false"] .pill { background: var(--line-soft); color: var(--ink-3); }
.view-tabs .pill:empty { display: none; }

/* ---------- all boards view ---------- */

.boards-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
/* The single-column case needs an explicit minmax(0,1fr). Without it the implicit column is
   `auto`, which sizes to max-content, so the boards table pushed the whole page wider than the
   viewport instead of scrolling inside its own .tbl-wrap. Measured: 427px page at a 390px
   viewport. */
.boards-grid {
  display: grid; gap: 22px; align-items: start; margin-top: 18px;
  grid-template-columns: minmax(0, 1fr);
}
.boards-grid > * { min-width: 0; }
@media (min-width: 940px) { .boards-grid { grid-template-columns: minmax(0, 1fr) 340px; } }

table.boards { width: 100%; border-collapse: collapse; font-size: 14px; }
table.boards th, table.boards td {
  padding: 10px; text-align: left; border-bottom: 1px solid var(--line-soft);
}
table.boards th {
  font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-3); font-weight: 700; white-space: nowrap;
}
table.boards td.num, table.boards th.num { text-align: right; font-family: var(--mono); }
table.boards tr.me { background: var(--accent-soft); }
table.boards tr.me td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
table.boards tr[data-board] { cursor: pointer; }
table.boards tr[data-board]:hover { background: var(--line-soft); }
table.boards .who { font-weight: 600; }
table.boards .tag {
  font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  color: var(--ink-3); background: var(--line-soft); padding: 2px 7px; border-radius: 99px;
  margin-left: 7px; white-space: nowrap; display: inline-block;
}
/* On a phone the name column is the one that should give, not the numbers. */
@media (max-width: 560px) {
  table.boards th, table.boards td { padding: 9px 6px; }
  table.boards .who { display: block; }
  table.boards .tag { margin-left: 0; margin-right: 5px; margin-top: 3px; }
}
table.boards .agree b { color: var(--ink); }

.contest-list { list-style: none; padding: 0; margin: 0; }
.contest-list li {
  display: grid; grid-template-columns: minmax(0,1fr) 34px 1fr 42px;
  gap: 9px; align-items: center; padding: 5px 0; font-size: 13px;
}
.contest-list .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.contest-list .pos { color: var(--ink-3); font-size: 11.5px; font-weight: 700; }
.contest-list .track { height: 6px; border-radius: 99px; background: var(--line-soft); overflow: hidden; }
.contest-list .track i { display: block; height: 100%; background: var(--warn); }
.contest-list .n { text-align: right; font-family: var(--mono); font-size: 12px; color: var(--ink-2); }
.contest-list li[data-tone="lock"] .track i { background: var(--keep); }
.contest-list li[data-tone="gone"] .track i { background: var(--cut); }

.locked-note { max-width: 62ch; }

table.boards tr[data-board]:focus-visible {
  outline: 2px solid var(--accent-edge); outline-offset: -2px;
}

/* The compare trigger is a real button so the table keeps its row semantics, but it should
   read as the name it replaces, not as a form control. */
button.linkish {
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; font-weight: 600;
  cursor: pointer; text-align: left;
}
button.linkish:hover { color: var(--accent-text); text-decoration: underline; text-underline-offset: 3px; }
