/* Slate palette. PRD §69: football analytics department, not bookmaker.
   Bootstrap supplies layout and reset only — its default component look is
   explicitly not the target, so everything visible is defined here. */

:root {
  --bg: #12151b;
  --panel: #171b23;
  --rule: #232833;
  --rule-soft: #1c2029;
  --ink: #dfe3ea;
  --ink-bright: #f2f5f9;
  --muted: #6a7383;
  --dim: #59616f;
  --accent: #4dd4ac;
  --accent-ink: #0d1014;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  margin: 0;
}

.wrap { max-width: 1180px; margin: 0 auto; padding: 26px 22px 60px; }

.topbar {
  display: flex; align-items: baseline; gap: 22px; flex-wrap: wrap;
  padding: 14px 22px; border-bottom: 1px solid var(--rule); background: var(--panel);
}
/* nowrap, because "Head to head" broke across three lines on a phone and read
   as three separate links. */
.topbar a { color: var(--muted); text-decoration: none; font-size: 13px; white-space: nowrap; }
.topbar a:hover { color: var(--accent); }
.brand { color: var(--ink-bright); font-weight: 600; margin-right: auto; }
/* The accent, not --dim: this names what the site *is*, and at 12px in the
   dimmest grey on the page it read as a footnote to the league name. */
.brand-sub {
  color: var(--accent); font-weight: 600; font-size: 13px;
  letter-spacing: .02em; margin-left: 2px;
}

.num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--mono); }
.muted { color: var(--muted); }
.dim { color: var(--dim); }
.accent { color: var(--accent); }

table.sheet { width: 100%; border-collapse: collapse; font-size: 13px; }
table.sheet th {
  font-size: 10px; letter-spacing: .09em; text-transform: uppercase;
  font-weight: 600; color: var(--muted);
  border-bottom: 1px solid var(--rule); background: var(--panel); padding: 9px 10px;
}
table.sheet td { padding: 9px 10px; border-bottom: 1px solid var(--rule-soft); }

.foot { max-width: 1180px; margin: 0 auto; padding: 0 22px 40px;
        color: var(--dim); font-size: 11px; line-height: 1.6; }

.caveat { color: var(--muted); font-size: 11px; line-height: 1.55; margin: 10px 0 0; }
.caveat code { color: var(--accent); }

.h { font-size: 21px; font-weight: 600; color: var(--ink-bright); margin: 0 0 3px; }
.h2 { font-size: 16px; font-weight: 600; color: var(--ink-bright); margin: 32px 0 3px; }
.sub { font-size: 11px; margin: 0 0 16px; }
a.club { color: var(--ink); text-decoration: none; }
a.club:hover { color: var(--accent); }

/* Wide tables scroll inside their own box rather than pushing the page sideways. */
.scroller { overflow-x: auto; }

table.matrix { font-size: 11px; }
table.matrix td.cell {
  text-align: center; width: 38px; height: 24px;
  font-family: var(--mono); font-weight: 600; background: #161a21;
}
table.matrix td.club { white-space: nowrap; }
table.matrix .splitline { border-right: 2px solid #566072; }

.picker { display: flex; gap: 10px; align-items: center; margin: 18px 0 26px; flex-wrap: wrap; }
.picker select, .picker button {
  background: var(--panel); color: var(--ink); border: 1px solid var(--rule);
  padding: 7px 11px; border-radius: 4px; font-size: 13px;
}
.picker button { color: var(--accent); cursor: pointer; }
.picker button:hover { border-color: var(--accent); }

.triptych { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
            background: var(--rule); border: 1px solid var(--rule); border-radius: 6px;
            overflow: hidden; margin: 8px 0 18px; }
.triptych > div { background: var(--panel); padding: 20px 16px; text-align: center; }
.tri-name { display: block; font-size: 11px; letter-spacing: .08em;
            text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
.tri-p { display: block; font-size: 28px; font-family: var(--mono);
         font-weight: 600; color: var(--accent); }

.two-col { display: grid; grid-template-columns: 1fr 1.4fr; gap: 30px; align-items: start; }
@media (max-width: 820px) { .two-col { grid-template-columns: 1fr; } }

.chart { height: 340px; margin-top: 10px; }

/* Why a prediction is what it is — PRD §43. The sentence is always visible and
   the table is disclosed, so the supporter is served without the analyst's
   depth being hidden. */
.explain-lead { margin: 6px 0 2px; color: var(--ink); }
.explain summary {
  cursor: pointer; list-style: none; color: var(--muted); font-size: 13px;
  padding: 4px 0;
}
.explain summary::-webkit-details-marker { display: none; }
.explain summary .fa-chevron-right { transition: transform .15s ease; margin-right: 4px; }
.explain[open] summary .fa-chevron-right { transform: rotate(90deg); }
.explain-table { margin-top: 8px; max-width: 640px; }
.explain-ref td { color: var(--muted); }
.explain-total td { color: var(--ink-bright); border-top: 1px solid var(--rule); }
.explain-row > td { padding-top: 0; border-bottom: 1px solid var(--rule-soft); }

/* PP, as the SPFL's own fixture list marks a postponement. Styled as a status
   rather than as a time: it sits in the kickoff column because that is where
   the source puts it, but it must not read as a clock. The date beside it is
   left alone — when a fixture *was* scheduled is real information. */
.pp {
  display: inline-block; padding: 0 5px;
  border: 1px solid var(--rule); border-radius: 3px;
  color: var(--muted); font-size: 11px; letter-spacing: .5px;
  font-family: var(--mono); cursor: help;
}

/* 95% intervals on the season's log loss, drawn against one shared scale.
   One ruler for every row, because a whisker only shows overlap if the thing
   beside it is measured the same way. */
.whisker { position: relative; display: block; height: 14px; }
.whisker-bar {
  position: absolute; top: 6px; height: 2px;
  background: var(--muted); border-radius: 1px;
}
.whisker-mark {
  position: absolute; top: 2px; width: 2px; height: 10px;
  background: var(--accent); margin-left: -1px;
}
.season-scores td { vertical-align: middle; }


/* A nav item is not free. Adding a fourth one — Methodology — pushed the topbar
   past a 390px viewport: the last link was clipped and the whole page scrolled
   sideways. Invisible to every assertion about page text, and found by opening
   the page at phone width, which is why that is a step rather than a courtesy.
   The brand takes its own line below 560px so the links have the full width. */
@media (max-width: 560px) {
  .topbar { gap: 16px; padding: 12px 14px; }
  .brand { margin-right: 0; flex-basis: 100%; }
}

/* --- fixture cards -------------------------------------------------------
   The fan-facing layer. Read in five seconds, with the statistics one click
   underneath rather than removed. */
.fixtures { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; margin-bottom: 26px; }
.fixture {
  background: var(--panel); border: 1px solid var(--rule); border-radius: 8px;
  padding: 14px 16px;
}
.fixture-pp { opacity: .72; }
.fixture-when { color: var(--dim); font-size: 12px; letter-spacing: .02em; }
.pp {
  color: var(--panel); background: var(--muted); border-radius: 3px;
  padding: 0 4px; font-size: 11px; font-weight: 600;
}
.fixture-teams { margin: 6px 0 12px; font-size: 15px; font-weight: 600; color: var(--ink-bright); }
.fixture-teams .v { color: var(--dim); font-weight: 400; margin: 0 6px; }
.fixture-probs { display: flex; gap: 10px; }
.fixture-probs .prob { flex: 1; text-align: center; background: var(--bg); border-radius: 6px; padding: 8px 4px; }
.fixture-probs .pc { display: block; font-size: 20px; font-weight: 600; color: var(--accent); font-variant-numeric: tabular-nums; }
/* The club name under a percentage is a label, not a heading — it must not
   compete with the number it belongs to. */
.fixture-probs .lbl { display: block; font-size: 11px; color: var(--muted); margin-top: 2px; }

/* --- title race ----------------------------------------------------------
   CSS rather than Plotly: 1.0MB of charting library for three horizontal bars
   is the wrong trade on the page a supporter lands on. */
.title-race { margin-bottom: 26px; }
.race-row { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.race-name { flex: 0 0 130px; font-size: 13px; color: var(--ink-bright); }
.race-track { flex: 1; background: var(--bg); border-radius: 4px; height: 20px; overflow: hidden; }
/* min-width, and it is load-bearing. A club on 0.05% would otherwise render a
   bar of zero width, which reads as "impossible" — and impossible is not what a
   small number means. It only ever meant "not seen in 10,000 iterations". */
.race-bar { display: block; height: 100%; min-width: 3px; background: var(--accent); border-radius: 4px; }
.race-pc { flex: 0 0 56px; font-size: 13px; color: var(--muted); }

/* Standfirst on /models: readable prose measure, quieter than the tables. */
.about-experiment { max-width: 62ch; margin: 0 0 30px; }
.about-experiment p { color: var(--muted); font-size: 13px; line-height: 1.65; margin: 0 0 9px; }
.about-experiment p:last-child { margin-bottom: 0; }

/* --- table versus model --------------------------------------------------
   A three-column row that collapses to stacked lines under 560px. No new
   colours: the club stripe is the shared palette, everything else is the
   existing ink scale, because this section is a bridge between the title race
   above it and the table below it rather than a third thing. */
.disagree { margin-bottom: 26px; }
.disagree-row {
  display: grid;
  grid-template-columns: 150px 165px 1fr;
  align-items: baseline;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--rule-soft);
}
.disagree-row:last-of-type { border-bottom: 0; }
.disagree-club { padding-left: 9px; font-size: 13px; }
.disagree-move { font-size: 13px; color: var(--muted); }
.disagree-now { color: var(--ink-bright); }
.disagree-arrow { margin: 0 5px; font-size: 10px; color: var(--dim); }
.disagree-proj { color: var(--accent); }
.disagree-why { font-size: 12px; color: var(--muted); line-height: 1.5; }

@media (max-width: 560px) {
  .disagree-row { grid-template-columns: 1fr; gap: 3px; padding: 10px 0; }
  .disagree-club { padding-left: 8px; }
  .disagree-move, .disagree-why { padding-left: 11px; }
}

/* What has changed since the last comparable forecast. Deliberately the same
   grid as .disagree above: the two sit next to each other on the league page
   and a second rhythm would read as a second kind of thing. */
.changes { margin-bottom: 26px; }
.changes-row {
  display: grid;
  grid-template-columns: 150px 165px 1fr;
  align-items: baseline;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--rule-soft);
}
.changes-row:last-of-type { border-bottom: 0; }
.changes-club { padding-left: 9px; font-size: 13px; }
.changes-move { font-size: 13px; color: var(--muted); }
.changes-before { color: var(--dim); }
.changes-arrow { margin: 0 5px; font-size: 10px; color: var(--dim); }
.changes-after { color: var(--ink-bright); }
.changes-why { font-size: 12px; color: var(--muted); line-height: 1.5; }

/* Single column well before 390px, where a fourth nav item once overflowed. */
@media (max-width: 560px) {
  .changes-row { grid-template-columns: 1fr; gap: 3px; padding: 10px 0; }
  .changes-club { padding-left: 8px; }
  .changes-move, .changes-why { padding-left: 11px; }
}

/* The credit line sits under the disclaimer, quieter than it but not hidden. */
.foot p { margin: 0 0 6px; }
.foot-credit { color: var(--muted); }
.foot-credit a { color: var(--muted); text-decoration: underline; text-underline-offset: 2px; }
.foot-credit a:hover { color: var(--accent); }
