/* Silicon Sunday
 *
 * The design rule that drives everything else: three typefaces, three jobs.
 *
 *   JetBrains Mono   every number, id, label and piece of machine metadata
 *   Inter Tight      structure — headings, the standings, the interface
 *   Newsreader       the models' own words, and nothing else
 *
 * The serif is the joke and the thesis at once. It is the typeface of human
 * argument, and here it is only ever used for what a machine wrote. If a
 * serif appears anywhere outside a model's reasoning, that is a bug.
 *
 * One palette, light, for every reader. Colour is a signed axis, because
 * the headline number is signed. Edge is
 * actual minus shadow: teal beat the projection, ochre lost to it. Teal and
 * ochre rather than green and red — they survive colour blindness, and they
 * do not read as a scoreboard telling you who to cheer for.
 */

/* Self-hosted fonts. These are the variable woff2 files Google Fonts serves,
   vendored so the fonts come off this origin. One file covers
   every weight (they are variable fonts), split by subset exactly as Google
   splits them, with the same unicode-range so a latin page downloads only
   the latin file. The TTFs beside them in fonts/ are build-time assets for
   og.py and are not copied to the output. */

@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(/fonts/InterTight-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(/fonts/InterTight-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/JetBrainsMono-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/JetBrainsMono-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Newsreader-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Newsreader-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Newsreader";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Newsreader-italic-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Newsreader";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Newsreader-italic-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* One palette, deliberately. The sheet used to ship a dark set behind
     prefers-color-scheme, which meant a reader's OS chose the site's
     appearance and the light Open Graph cards opened into a dark page.
     Owner's call, 13 August 2026: light, for everyone, everywhere. */
  color-scheme: light;

  --paper:      #edeff2;
  --card:       #ffffff;
  --ink:        #0e1116;
  --ink-2:      #464f5b;
  --ink-3:      #8a93a0;
  --rule:       #d7dbe0;
  --rule-soft:  #e6e9ed;

  --plus:       #0b7285;   /* beat the projection */
  --minus:      #b45309;   /* lost to it */
  --plus-soft:  #d7ebef;
  --minus-soft: #f6e7d3;

  --display: "Inter Tight", "Inter", system-ui, -apple-system, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  --prose: "Newsreader", Georgia, "Times New Roman", serif;

  --gap: clamp(1.5rem, 4vw, 3rem);
  --radius: 3px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--display);
  font-size: 16px;
  line-height: 1.5;
  font-feature-settings: "tnum" 1;
}

a { color: inherit; }

.wrap {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 2.5rem) 6rem;
}

/* ---------------------------------------------------------------- masthead */

.masthead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem 1.25rem;
  padding: 2.5rem 0 1.25rem;
  border-bottom: 2px solid var(--ink);
}

.wordmark {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.4rem, 3.5vw, 1.9rem);
  letter-spacing: -0.035em;
  margin: 0;
}

.wordmark .dot { color: var(--plus); }

.masthead__meta {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Ten items do not fit a phone on one line, and a nav that overflows is not
   a cosmetic problem: half the site becomes unreachable, silently, while the
   page reports no horizontal overflow because the row is simply clipped.
   Wrapping costs a line and keeps every page reachable. */
.masthead nav {
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.masthead nav a { color: var(--ink-2); text-decoration: none; padding: 0.25rem 0; }
.masthead nav a:hover,
.masthead nav a[aria-current="page"] {
  color: var(--ink);
  box-shadow: inset 0 -2px 0 var(--plus);
}

/* ------------------------------------------------------------------ eyebrow */

.eyebrow {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 0.85rem;
}

section { margin-top: var(--gap); }

/* --------------------------------------------------------------- the thesis */

.thesis { padding: clamp(2.5rem, 7vw, 4.5rem) 0 1rem; }

.thesis p.lede {
  font-family: var(--display);
  font-size: clamp(1.05rem, 2.3vw, 1.3rem);
  font-weight: 500;
  letter-spacing: -0.015em;
  max-width: 46ch;
  margin: 0 0 2rem;
  color: var(--ink-2);
}

.thesis h2 {
  font-size: clamp(1.9rem, 6vw, 3.4rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1.02;
  margin: 0 0 2.5rem;
  max-width: 18ch;
}

/* -------------------------------------------------------------- THE ZERO LINE
 * The signature. One vertical rule runs down the whole block: that rule is
 * the projection. Each team gets a row, and its bar leaves the rule to the
 * right if reasoning added points, to the left if it cost them.
 *
 * This started as a single horizontal axis with ten dots on it. The edges
 * cluster inside a few points, so the dots bunched and their labels overlapped
 * into mush. Giving each team a row costs vertical space and buys total
 * legibility, and it makes the zero rule longer and more emphatic rather than
 * less.
 */

.zeroline {
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: 1.5rem 0 1.25rem;
  margin: 0 0 0.75rem;
}

.zeroline__head,
.zerorow {
  display: grid;
  grid-template-columns: minmax(7rem, 15rem) 1fr 4.25rem 4.25rem;
  align-items: center;
  gap: 0 1rem;
}

.zeroline__head {
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-bottom: 0.6rem;
}
.zeroline__head span:nth-child(3),
.zeroline__head span:nth-child(4) { text-align: right; }

.zeroline__scale {
  position: relative;
  display: flex;
  justify-content: space-between;
}
.zeroline__scale b {
  font-weight: 500;
  color: var(--ink);
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
}

.zerorow { padding: 0.18rem 0; }

.zerorow__team {
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.zerorow__track {
  position: relative;
  height: 21px;
  border-left: 1px solid var(--rule-soft);
  border-right: 1px solid var(--rule-soft);
}

/* The rule itself. Every row draws its own segment, so the line is unbroken
   from the first team to the last. */
.zerorow__track::before {
  content: "";
  position: absolute;
  left: 50%;
  top: -0.18rem;
  bottom: -0.18rem;
  width: 2px;
  margin-left: -1px;
  background: var(--ink);
}

.zerorow__bar {
  position: absolute;
  top: 5px;
  height: 11px;
  border-radius: 1px;
}
.zerorow--plus  .zerorow__bar { left: 50%;  background: var(--plus); }
.zerorow--minus .zerorow__bar { right: 50%; background: var(--minus); }

.zerorow__value {
  text-align: right;
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 700;
}
.zerorow--plus  .zerorow__value { color: var(--plus); }
.zerorow--minus .zerorow__value { color: var(--minus); }
.zerorow--zero  .zerorow__value { color: var(--ink-3); }

/* Bench points are always positive and always bad, so they get no colour —
   the signed column is the one worth looking at twice. */
.zerorow__extra {
  text-align: right;
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--ink-3);
}

/* The reveal: every bar grows out of the rule, which is the one gesture that
   says what the chart means. */
@media (prefers-reduced-motion: no-preference) {
  .zerorow__bar {
    animation: grow 700ms cubic-bezier(0.16, 0.9, 0.3, 1) both;
    transform-origin: var(--origin, left) center;
  }
  .zerorow--minus .zerorow__bar { --origin: right; }
  @keyframes grow { from { transform: scaleX(0); } }
}

/* On a phone the name column eats the track and the bars vanish. Give the
   name and the value their own line and let the track span the full width,
   so the rule stays centred and the bars stay readable. */
@media (max-width: 620px) {
  .zeroline__head { grid-template-columns: 1fr auto auto; }
  .zeroline__head .zeroline__scale {
    grid-column: 1 / -1;
    order: 4;
    padding-top: 0.45rem;
  }
  .zerorow {
    grid-template-columns: 1fr auto auto;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--rule-soft);
  }
  .zerorow:last-child { border-bottom: none; }
  /* Name and both numbers share the first line; the track takes the second.
     Without explicit order the track is the second child and steals a line. */
  .zerorow__team  { order: 1; }
  .zerorow__value { order: 2; }
  .zerorow__extra { order: 3; }
  .zerorow__track { order: 4; grid-column: 1 / -1; height: 13px;
                    margin-top: 0.3rem; }
  .zerorow__track::before { top: 0; bottom: 0; }
  .zerorow__bar { top: 1px; height: 11px; }
}

.note {
  font-family: var(--mono);
  font-size: 0.72rem;
  line-height: 1.6;
  color: var(--ink-3);
  max-width: 62ch;
  margin: 0.9rem 0 0;
}

/* ----------------------------------------------------------------- the card */

.card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.card__pad { padding: clamp(1rem, 3vw, 1.75rem); }

/* --------------------------------------------------------------- the table */

.sheet { width: 100%; border-collapse: collapse; }

.sheet th {
  font-family: var(--mono);
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
  text-align: right;
  padding: 1.1rem 0.6rem 0.7rem;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
.sheet th:first-child, .sheet td:first-child { padding-left: clamp(0.9rem, 3vw, 1.6rem); }
.sheet th:last-child,  .sheet td:last-child  { padding-right: clamp(0.9rem, 3vw, 1.6rem); }
.sheet th.left, .sheet td.left { text-align: left; }

.sheet td {
  padding: 0.7rem 0.6rem;
  border-bottom: 1px solid var(--rule-soft);
  text-align: right;
  font-family: var(--mono);
  font-size: 0.85rem;
}
.sheet tbody tr:last-child td { border-bottom: none; }
.sheet tbody tr:hover { background: var(--rule-soft); }

.rank { color: var(--ink-3); font-size: 0.78rem; width: 1.5rem; }

/* Rows are already dense with numbers; underlining every team name turns the
   table into a wall of rules. The hover is the affordance. */
.sheet a { text-decoration: none; color: inherit; }
.sheet a:hover .team { box-shadow: inset 0 -2px 0 var(--plus); }
.teamlink { display: block; }

.team { font-family: var(--display); font-weight: 650; letter-spacing: -0.01em;
        font-size: 0.95rem; }
.lab  { font-family: var(--mono); font-size: 0.68rem; color: var(--ink-3);
        letter-spacing: 0.04em; }

.num--plus  { color: var(--plus);  font-weight: 700; }
.num--minus { color: var(--minus); font-weight: 700; }
.num--zero  { color: var(--ink-3); }

/* The playoff cut. A heavier rule under the last qualifying team says more
   than any label would, and it is the line every reader is looking for. */
.sheet tbody tr.cutline td { border-bottom: 2px solid var(--ink); }

.subhead {
  font-size: clamp(1.25rem, 3vw, 1.6rem);
  font-weight: 750;
  letter-spacing: -0.025em;
  margin: 0 0 0.75rem;
}

/* ------------------------------------------------------------ the scoreboard
 * One card per matchup. The split bar is the point: it divides at the score
 * ratio, so a 114–50 blowout and a 91–86 nailbiter are told apart before any
 * number is read.
 *
 * Ink and grey, never teal and ochre. Those two already mean "beat the
 * projection" in the manager ratings, and a colour that means two things
 * means neither.
 */

/* Five matchups never divide evenly into an auto-fit grid, so the last row
   has a hole in it. Colouring the container and letting the gaps show through
   turns that hole into a grey block that reads as broken. Instead the board
   is card-coloured and each card draws its own hairline, so a missing cell is
   simply empty space. */
.board {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 1px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}

.matchup {
  background: var(--card);
  box-shadow: 0 0 0 1px var(--rule);
  padding: 1.1rem clamp(0.9rem, 2.5vw, 1.4rem) 0.95rem;
}

.matchup__row {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "team score" "meta score";
  align-items: baseline;
  column-gap: 0.75rem;
  color: var(--ink-3);
}

.matchup__team {
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: -0.012em;
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.matchup__score {
  grid-row: span 2;
  align-self: center;
  font-family: var(--mono);
  font-size: 1.35rem;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink-3);
}

/* The winner is the only thing at full contrast. */
.matchup__row--won .matchup__team  { color: var(--ink); font-weight: 700; }
.matchup__row--won .matchup__score { color: var(--ink); font-weight: 700; }

.matchup__meta {
  grid-area: meta;
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.05em;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.matchup__team  { grid-area: team; }
.matchup__score { grid-area: score; }

.matchup__bar {
  display: flex;
  height: 6px;
  margin: 0.7rem 0;
  border-radius: 3px;
  overflow: hidden;
  background: var(--rule-soft);
}
.matchup__share--won  { background: var(--ink); }
.matchup__share--lost { background: var(--rule); }

@media (prefers-reduced-motion: no-preference) {
  .matchup__share { animation: split 650ms cubic-bezier(0.16, 0.9, 0.3, 1) both; }
  @keyframes split { from { flex-basis: 50%; } }
}

.matchup__margin {
  margin: 0.55rem 0 0;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: var(--ink-3);
}

/* --------------------------------------------------------- the decision log */

.entry { border-top: 1px solid var(--rule); padding: 1.6rem 0; }
.entry:first-of-type { border-top: none; }

.entry__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 0.85rem;
  margin-bottom: 0.9rem;
}

.entry__team { font-weight: 700; letter-spacing: -0.015em; }

.tag {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.12rem 0.42rem;
}
.tag--rejected { color: var(--minus); border-color: var(--minus); }
.tag--fallback { color: var(--minus); border-color: var(--minus); }

/* The models' own words. The only serif on the site. */
.reasoning {
  font-family: var(--prose);
  font-size: 1.06rem;
  line-height: 1.62;
  color: var(--ink);
  margin: 0;
  padding-left: 1rem;
  border-left: 2px solid var(--plus);
  max-width: 70ch;
}

.outcome {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  margin-top: 0.9rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-2);
  max-width: 70ch;
}
.outcome::before {
  content: "";
  flex: none;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ink-3);
  transform: translateY(-1px);
}
.outcome--plus::before  { background: var(--plus); }
.outcome--minus::before { background: var(--minus); }

/* ------------------------------------------------- the head-to-head column
 * The layout every fantasy manager can already read: QB against QB, both
 * scores flanking the slot, and the winner of each slot in ink. It is the
 * only arrangement where you can see which position lost the game without
 * doing arithmetic.
 */

.thesis--tight { padding-top: clamp(1.75rem, 4vw, 2.75rem); padding-bottom: 0; }
.matchup-title { max-width: 22ch; }

.h2h__head {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  padding: clamp(1.1rem, 3vw, 1.75rem) clamp(0.9rem, 3vw, 1.6rem) 0;
}

.h2h__side { display: flex; flex-direction: column; gap: 0.12rem; }
.h2h__side--away { text-align: right; align-items: flex-end; }

.h2h__team {
  font-size: clamp(1rem, 2.4vw, 1.2rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink-2);
  text-decoration: none;
}
.h2h__team:hover { box-shadow: inset 0 -2px 0 var(--plus); }
.h2h__side--won .h2h__team { color: var(--ink); }

.h2h__lab, .h2h__proj {
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.05em;
  color: var(--ink-3);
}

.h2h__score {
  font-family: var(--mono);
  font-size: clamp(1.9rem, 5vw, 2.6rem);
  font-weight: 500;
  letter-spacing: -0.045em;
  line-height: 1.1;
  color: var(--ink-3);
  margin-top: 0.3rem;
}
.h2h__side--won .h2h__score { color: var(--ink); font-weight: 700; }

.h2h__vs {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.h2h__bar {
  display: flex;
  height: 6px;
  margin: 1rem clamp(0.9rem, 3vw, 1.6rem);
  border-radius: 3px;
  overflow: hidden;
  background: var(--rule-soft);
}

.h2h { border-top: 1px solid var(--rule); }

.h2h__row {
  display: grid;
  grid-template-columns: 1fr 3.2rem 4.5rem 3.2rem 1fr;
  align-items: center;
  gap: 0 0.5rem;
  padding: 0.6rem clamp(0.9rem, 3vw, 1.6rem);
  border-bottom: 1px solid var(--rule-soft);
}
.h2h__row:last-child { border-bottom: none; }

.h2h__player { display: flex; flex-direction: column; min-width: 0; }
.h2h__player--away { text-align: right; align-items: flex-end; }

.h2h__pname {
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink-2);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.h2h__player--top .h2h__pname { color: var(--ink); font-weight: 700; }
.h2h__pname--empty { color: var(--ink-3); font-weight: 400; font-style: italic; }

.h2h__pmeta {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.04em;
  color: var(--ink-3);
  white-space: nowrap;
}

.h2h__pts {
  font-family: var(--mono);
  font-size: 0.95rem;
  color: var(--ink-3);
}
.h2h__pts--home { text-align: right; }
.h2h__pts--away { text-align: left; }
.h2h__pts--top  { color: var(--ink); font-weight: 700; }

.h2h__slot {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  text-align: center;
  color: var(--ink-3);
  border-left: 1px solid var(--rule-soft);
  border-right: 1px solid var(--rule-soft);
  padding: 0.15rem 0;
}

/* Two columns that stay equal, for "what they said" and the two benches. */
.said {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1rem;
  align-items: start;
}
.said__col { min-width: 0; }

/* ------------------------------------------------------------------ week nav */

.weeknav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 1.25rem;
}
.weeknav a {
  font-family: var(--mono);
  font-size: 0.74rem;
  text-decoration: none;
  color: var(--ink-3);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.28rem 0.6rem;
  min-width: 2.1rem;
  text-align: center;
}
.weeknav a:hover { color: var(--ink); border-color: var(--ink-3); }
.weeknav a[aria-current="page"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.weeknav__todo {
  font-family: var(--mono);
  font-size: 0.74rem;
  color: var(--ink-3);
  border: 1px dashed var(--rule);
  border-radius: 2px;
  padding: 0.28rem 0.6rem;
  min-width: 2.1rem;
  text-align: center;
  opacity: 0.65;
}
/* A week that opens but has not been played. Dashed like the dead ones it
   replaced, so the strip still reads past-versus-future at a glance, but it
   is a real link and behaves like one. */
.weeknav a.weeknav__ahead { border-style: dashed; }
.weeknav a.weeknav__ahead:hover { border-style: solid; }

.weeknav__step { min-width: 0; letter-spacing: 0.04em; }

/* ------------------------------------------------------------- fixtures */

.fixtures {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
  gap: 0.75rem;
}
.fixture {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.9rem 1rem 0.7rem;
}
.fixture__side {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.35rem 0;
}
/* The favourite is marked by weight, not by colour. Colour in this palette
   is the signed edge axis and means something else already. */
.fixture__side--fav .team { font-weight: 600; }
.fixture__side--fav .fixture__proj b { color: var(--ink); }

.fixture__at {
  font-family: var(--mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-3);
  border-top: 1px solid var(--rule-soft);
  padding-top: 0.45rem;
  margin-top: 0.1rem;
}
.fixture__proj { text-align: right; flex: none; }
.fixture__proj b {
  display: block;
  font-family: var(--mono);
  font-size: 1.05rem;
  font-weight: 500;
  color: var(--ink-2);
}
.fixture__proj small {
  font-family: var(--mono);
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-3);
}
.fixture__line {
  margin: 0.6rem 0 0;
  padding-top: 0.55rem;
  border-top: 1px solid var(--rule-soft);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--ink-3);
}

/* The other games that week. A row of small cards, scrollable rather than
   wrapped, so it stays one line and does not compete with the matchup. */
.alsorow {
  display: flex;
  gap: 0.6rem;
  overflow-x: auto;
  padding-bottom: 0.35rem;
}
.also {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.6rem 0.85rem;
  text-decoration: none;
}
.also:hover { border-color: var(--ink-3); }
.also__teams {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink-2);
  white-space: nowrap;
}
.also__score {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink);
}

.matchup--link { display: block; text-decoration: none; color: inherit; }
.matchup--link:hover { background: var(--rule-soft); }

/* ------------------------------------------------------------- team page */

.slot {
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.08em;
  color: var(--ink-2);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.1rem 0.36rem;
}
.slot--bench, .slot--ir { color: var(--ink-3); }
.sheet tbody tr.row--bench td { color: var(--ink-3); }
.sheet tbody tr.row--bench .team { font-weight: 500; }

.chart { width: 100%; overflow: hidden; }
.chart svg { display: block; max-height: 240px; }

.wire__move {
  font-family: var(--mono);
  font-size: 0.82rem;
  margin: 0 0 0.7rem;
  color: var(--ink);
}

/* ----------------------------------------------------------- draft board
 * Ten columns of teams, fifteen rows of rounds, as it would look taped to a
 * wall. Position colour is its own small palette, kept low-saturation so it
 * cannot be mistaken for the teal/ochre that means beat-the-projection
 * everywhere else on the site.
 */

:root {
  --pos-qb:  #5b4bbf;  --pos-qb-bg:  #e9e6f8;
  --pos-rb:  #2f7d4f;  --pos-rb-bg:  #ddefe4;
  --pos-wr:  #2563a8;  --pos-wr-bg:  #dce8f6;
  --pos-te:  #a63d6e;  --pos-te-bg:  #f7e0ea;
  --pos-k:   #6b7280;  --pos-k-bg:   #e9ebee;
  --pos-def: #7a5c3e;  --pos-def-bg: #f0e8de;
}
.dboard {
  border-collapse: collapse;
  width: 100%;
  min-width: 900px;
  table-layout: fixed;
}
.dboard th, .dboard td {
  border: 1px solid var(--rule);
  padding: 0.4rem 0.5rem;
  vertical-align: top;
}
.dboard thead th {
  font-family: var(--display);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-align: left;
  color: var(--ink);
  background: var(--card);
  position: sticky;
  top: 0;
  z-index: 1;
}
.dboard thead th a { text-decoration: none; }
.dboard thead th a:hover { box-shadow: inset 0 -2px 0 var(--plus); }
.dboard__lab {
  display: block;
  font-family: var(--mono);
  font-size: 0.58rem;
  font-weight: 400;
  letter-spacing: 0.05em;
  color: var(--ink-3);
}
.dboard__rd {
  width: 2.4rem;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-3);
  text-align: center !important;
  background: var(--card);
}
/* The link owns the cell box, so padding lives on the link and not on the
   td. Trying to fake it with negative margins left the hover ring floating
   a couple of pixels inside the cell, which reads as a misdrawn border
   rather than as a target. */
.dboard td.dboard__cell { height: 3.4rem; padding: 0; }
.dboard__no {
  float: right;
  font-family: var(--mono);
  font-size: 0.56rem;
  color: var(--ink-3);
}
.dboard__name {
  display: block;
  font-size: 0.74rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--ink);
}
.dboard__pos {
  display: block;
  font-family: var(--mono);
  font-size: 0.56rem;
  letter-spacing: 0.04em;
  margin-top: 0.15rem;
}

/* Every cell is a door into the reasoning log. It has to look pressable
   without turning a wall of 150 cells into a wall of 150 buttons, so the
   cue is weight and a lift on hover, not a border or an underline. */
.dboard__pick {
  display: block;
  height: 100%;
  padding: 0.4rem 0.5rem;
  text-decoration: none;
  color: inherit;
  transition: background-color 110ms ease;
}
/* outline-offset pulls the ring onto the cell edge itself. `outline` rather
   than a border so it costs no layout and cannot shift the grid. */
.dboard__pick:hover,
.dboard__pick:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: -2px;
  background: rgba(0, 0, 0, 0.05);
}
.dboard__pick:hover .dboard__name { text-decoration: underline; }

/* The round rule in the log below, so fifteen rounds of entries do not read
   as one undifferentiated stack. */
.roundmark {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  border-top: 1px solid var(--rule);
  padding-top: 0.7rem;
  margin: 2rem 0 0.6rem;
}
.roundmark:first-of-type { margin-top: 0.6rem; }

/* Arriving from the board: mark the pick the reader asked for, and let the
   browser put it below the sticky nothing — there is no sticky header, so a
   little breathing room above is enough. */
.entry:target {
  scroll-margin-top: 2rem;
  box-shadow: inset 3px 0 0 var(--plus);
  padding-left: 0.9rem;
  margin-left: -0.9rem;
  background: var(--plus-soft);
  border-radius: 2px;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

.pos--qb  { background: var(--pos-qb-bg);  }
.pos--rb  { background: var(--pos-rb-bg);  }
.pos--wr  { background: var(--pos-wr-bg);  }
.pos--te  { background: var(--pos-te-bg);  }
.pos--k   { background: var(--pos-k-bg);   }
.pos--def { background: var(--pos-def-bg); }
.pos--qb  .dboard__pos { color: var(--pos-qb);  }
.pos--rb  .dboard__pos { color: var(--pos-rb);  }
.pos--wr  .dboard__pos { color: var(--pos-wr);  }
.pos--te  .dboard__pos { color: var(--pos-te);  }
.pos--k   .dboard__pos { color: var(--pos-k);   }
.pos--def .dboard__pos { color: var(--pos-def); }

/* --------------------------------------------------------- playoff odds
 * The bar sits behind the number rather than beside it: at ten teams a
 * separate column of bars is a second table to read, and the point of a
 * percentage bar is to be understood without reading anything.
 */

.odds { position: relative; }
.odds__bar {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 1.45rem;
  background: var(--plus-soft);
  border-radius: 2px;
  z-index: 0;
}
.odds__pct { position: relative; z-index: 1; }

/* --------------------------------------------------- movement and history */

.move {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0;
  margin-left: 0.35rem;
}
.move--up   { color: var(--plus); }
.move--down { color: var(--minus); }
.move--same { color: var(--ink-3); }

.h2h-history {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-3);
  margin: 0.9rem 0 0;
}
.h2h-history a { color: var(--ink-2); }

/* -------------------------------------------------------------- bracket */

.bracket {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1rem;
  align-items: start;
}
.bracket__label {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 0.6rem;
}
.bracket__game {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  margin-bottom: 0.75rem;
}
.bracket__title {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  color: var(--ink-3);
  margin: 0 0 0.5rem;
}
.bracket__side {
  display: grid;
  grid-template-columns: 1.4rem 1fr auto;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.28rem 0;
  color: var(--ink-3);
}
.bracket__side--won { color: var(--ink); font-weight: 700; }
.bracket__seed {
  font-family: var(--mono);
  font-size: 0.66rem;
  color: var(--ink-3);
}
.bracket__team {
  font-size: 0.88rem;
  letter-spacing: -0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bracket__pts { font-family: var(--mono); font-size: 0.8rem; }

/* ------------------------------------------------------------ pre-season */

.countdown {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.countdown div { background: var(--card); padding: 1.25rem clamp(0.9rem, 3vw, 1.5rem); }
.countdown dt {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 0.5rem;
}
.countdown dd {
  margin: 0;
  font-size: clamp(1.3rem, 3vw, 1.75rem);
  font-weight: 750;
  letter-spacing: -0.03em;
}
.countdown dd small {
  display: block;
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--ink-3);
  margin-top: 0.3rem;
}

/* ------------------------------------------------------------------- prose */

.doc { max-width: 68ch; }
.doc h3 {
  font-size: 1.15rem;
  font-weight: 750;
  letter-spacing: -0.02em;
  margin: 2.25rem 0 0.6rem;
}
.doc p, .doc li {
  font-size: 0.95rem;
  line-height: 1.68;
  color: var(--ink-2);
}
.doc code, .kbd {
  font-family: var(--mono);
  font-size: 0.85em;
  background: var(--rule-soft);
  padding: 0.1em 0.35em;
  border-radius: 2px;
  color: var(--ink);
}
.doc table { width: 100%; border-collapse: collapse; margin: 1rem 0; }
.doc th, .doc td {
  text-align: left;
  padding: 0.5rem 0.75rem 0.5rem 0;
  border-bottom: 1px solid var(--rule-soft);
  font-family: var(--mono);
  font-size: 0.82rem;
}
.doc th { color: var(--ink-3); font-weight: 500; letter-spacing: 0.06em;
          text-transform: uppercase; font-size: 0.66rem; }

/* Wide content scrolls inside its own box; the page never scrolls sideways. */
.scroller { overflow-x: auto; }

/* Tables written inline in prose never got a .scroller around them, and the
   method page carries model ids like deepseek/deepseek-v4-flash-0731 in a
   monospace face that will not wrap. On a phone that pushed the whole page
   15px sideways. Making them their own scroll container keeps the page
   still. */
@media (max-width: 640px) {
  .doc table {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }
  .doc code { overflow-wrap: anywhere; }
}

footer {
  margin-top: 4rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.72rem;
  line-height: 1.8;
  color: var(--ink-3);
}
footer a { color: var(--ink-2); }

:focus-visible {
  outline: 2px solid var(--plus);
  outline-offset: 2px;
}

@media (max-width: 640px) {
  .sheet td, .sheet th { padding-left: 0.4rem; padding-right: 0.4rem; }

  /* The head-to-head column is five tracks wide, which does not fit a phone.
     Keep the shape — home left, slot centre, away right — and drop the
     per-player metadata line, which is the only part that can go without
     losing the comparison. */
  .h2h__row {
    grid-template-columns: 1fr 2.4rem 3rem 2.4rem 1fr;
    gap: 0 0.3rem;
    padding-left: 0.6rem;
    padding-right: 0.6rem;
  }
  .h2h__pmeta { display: none; }
  .h2h__pname { font-size: 0.78rem; }
  .h2h__pts   { font-size: 0.82rem; }
  .h2h__slot  { font-size: 0.56rem; letter-spacing: 0.06em; }

  .h2h__head { grid-template-columns: 1fr auto 1fr; gap: 0.5rem; }
  .h2h__vs   { font-size: 0.6rem; }
}


/* ------------------------------------------------------- touch targets
 * Measured at 375px: the masthead links were 25px tall and the week strip
 * 29px. Both clear the WCAG AA floor of 24px and both are still fiddly with
 * a thumb, and they are the two things a reader taps most — the nav on every
 * page, and the week strip every time they move through the season.
 *
 * Keyed on `pointer: coarse` rather than width, because it is the input
 * device that decides this. A narrow desktop window does not need bigger
 * targets and a tablet in landscape does.
 */
@media (pointer: coarse) {
  .masthead nav { gap: 0.25rem 0.9rem; }
  .masthead nav a {
    min-height: 40px;
    display: flex;
    align-items: center;
  }

  .weeknav { gap: 0.4rem; }
  .weeknav a,
  .weeknav__todo {
    min-width: 40px;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 0.6rem;
  }

  /* The board is a 900px table on a 360px screen, so a pick is reached by
     scrolling sideways. Make the cell itself a comfortable target once it
     is on screen. */
  .dboard td.dboard__cell { height: 3.9rem; }
}

/* ------------------------------------------------------------- subscribe
 * A sentence with a field in it. The site spent two passes cutting anything
 * that decorated rather than informed, and a signup block is where that
 * discipline is hardest to keep: no badge, no incentive, no second sentence
 * restating the first.
 */
.sub { margin: 0; max-width: 34rem; }
.sub__label {
  display: block;
  font: 400 0.82rem/1.5 var(--display);
  color: var(--ink-2);
  margin-bottom: 0.5rem;
}
.sub__row { display: flex; gap: 0.4rem; }
.sub__input {
  flex: 1;
  min-width: 0;
  font: 400 0.88rem var(--display);
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.55rem 0.7rem;
}
.sub__input::placeholder { color: var(--ink-3); }
.sub__input:focus-visible {
  outline: 2px solid var(--plus);
  outline-offset: -2px;
  border-color: var(--plus);
}
.sub__go {
  flex: none;
  font: 500 0.72rem/1 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  padding: 0 0.95rem;
  cursor: pointer;
}
.sub__go:hover { background: var(--plus); border-color: var(--plus); }
.sub__go:focus-visible { outline: 2px solid var(--plus); outline-offset: 2px; }
.sub__said {
  font: 400 0.8rem/1.5 var(--display);
  margin: 0.55rem 0 0;
  color: var(--ink-2);
}
/* It stays in the document so a screen reader is already watching it, which
   means it is here on every page doing nothing until there is something to
   say. Empty, it takes no room. */
.sub__said:empty { margin-top: 0; }
.sub__said--ok  { color: var(--plus); }
.sub__said--bad { color: var(--minus); }

/* In the footer it is one line among several, so it shrinks and loses the
   label — the surrounding sentence already says what it is. */
footer .sub { margin-top: 0.9rem; max-width: 26rem; }
footer .sub__label { font-size: 0.78rem; }

@media (pointer: coarse) {
  .sub__input, .sub__go { min-height: 44px; }
}
