/* Nine categorical hues, generated in OKLCH and validated for colourblind
   separation and contrast against both surfaces. Nine is the ceiling: ten or
   more evenly-spaced hues fail the separation gates in one mode or the other.
   Teams past nine reuse a hue with a different line style, so every team is a
   unique colour+style pair. Baselines stay neutral ink, which no team uses. */

.viz-root {
  color-scheme: light;

  --surface-1: #fcfcfb;
  --page-plane: #f9f9f7;
  --text-primary: #0b0b0b;
  --text-secondary: #52514e;
  --text-muted: #898781;
  --gridline: #e1e0d9;
  --baseline: #c3c2b7;
  --border: rgba(11, 11, 11, 0.10);
  --wash: rgba(11, 11, 11, 0.04);

  --series-1: #a83161;
  --series-2: #e36b40;
  --series-3: #835d09;
  --series-4: #88a013;
  --series-5: #0c774e;
  --series-6: #16a7ae;
  --series-7: #0b6b9e;
  --series-8: #8285f3;
  --series-9: #8b3f9c;
  --focus: #0b6b9e;

  --good: #006300;
  --warning: #fab219;
  --critical: #d03b3b;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .viz-root {
    color-scheme: dark;

    --surface-1: #1a1a19;
    --page-plane: #0d0d0d;
    --text-primary: #ffffff;
    --text-secondary: #c3c2b7;
    --text-muted: #898781;
    --gridline: #2c2c2a;
    --baseline: #383835;
    --border: rgba(255, 255, 255, 0.10);
    --wash: rgba(255, 255, 255, 0.06);

    --series-1: #a33460;
    --series-2: #dd6d45;
    --series-3: #815c09;
    --series-4: #879f18;
    --series-5: #0b764d;
    --series-6: #16a6ac;
    --series-7: #0a6a9c;
    --series-8: #8285eb;
    --series-9: #874197;
    --focus: #0a6a9c;

    --good: #0ca30c;
    --warning: #fab219;
    --critical: #d03b3b;
  }
}

:root[data-theme="dark"] .viz-root {
  color-scheme: dark;

  --surface-1: #1a1a19;
  --page-plane: #0d0d0d;
  --text-primary: #ffffff;
  --text-secondary: #c3c2b7;
  --text-muted: #898781;
  --gridline: #2c2c2a;
  --baseline: #383835;
  --border: rgba(255, 255, 255, 0.10);
  --wash: rgba(255, 255, 255, 0.06);

  --series-1: #a33460;
  --series-2: #dd6d45;
  --series-3: #815c09;
  --series-4: #879f18;
  --series-5: #0b764d;
  --series-6: #16a6ac;
  --series-7: #0a6a9c;
  --series-8: #8285eb;
  --series-9: #874197;
  --focus: #0a6a9c;

  --good: #0ca30c;
  --warning: #fab219;
  --critical: #d03b3b;
}

* { box-sizing: border-box; }

/* A defensive backstop, not decoration. The HTML `hidden` attribute works via
   the browser's own `[hidden] { display: none; }` rule — but that's a normal-
   priority *user-agent* rule, and CSS cascade origin beats specificity: ANY
   normal-priority author rule that sets `display` on the same element wins
   regardless of selector weight or source order. `.notice-install` below sets
   `display: flex` to lay itself out, which silently defeated `hidden` for
   that one element — toggling the attribute in JS kept "working" (the
   attribute really was being set) while having zero visual effect. This
   makes `hidden` win outright, for every element, permanently, so no other
   component can reintroduce the same bug by giving a hideable element its
   own `display` value. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--page-plane);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--text-primary);
  overflow-x: hidden;
}

/* The theme tokens live on .viz-root, so the page plane is painted from here too. */
.viz-root {
  background: var(--page-plane);
  min-height: 100vh;
  padding: 20px 16px calc(32px + env(safe-area-inset-bottom));
  max-width: 900px;
  margin: 0 auto;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- header ---------- */

.page-head { margin: 0 0 16px; }

h1 {
  margin: 0;
  font-size: 1.5rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.sub {
  margin: 4px 0 0;
  color: var(--text-secondary);
  font-size: 0.875rem;
}

.sub span + span::before {
  content: "·";
  margin: 0 6px;
  color: var(--text-muted);
}

.updated {
  margin: 6px 0 0;
  color: var(--text-secondary);
  font-size: 0.8125rem;
}

.updated-rel {
  font-weight: 600;
  color: var(--text-primary);
}

/* Each trailing fact is separated by its own dot, so the line reflows cleanly
   on a narrow screen instead of leaving a dangling separator. */
.updated-abs::before {
  content: "·";
  margin: 0 6px;
  color: var(--text-muted);
}

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

.notice {
  margin: 0 0 16px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--text-muted);
  border-radius: 6px;
  background: var(--surface-1);
  color: var(--text-secondary);
  font-size: 0.875rem;
  line-height: 1.45;
}

.notice strong { color: var(--text-primary); }

.notice-error { border-left-color: var(--critical); }

/* Informational, not alarming — a thinner amber accent, not the error red. */
.notice-offline { border-left-color: var(--warning); }

/* A call to action, not a warning — the accent is the focus blue used
   elsewhere for interactive things, distinct from the error/warning tones. */
.notice-install {
  border-left-color: var(--focus);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px 16px;
}

.install-copy {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.install-copy strong { color: var(--text-primary); }

/* Plain inline flow, not flex — flex's `gap` would insert space between the
   icon and the punctuation that follows it, reading as "tap [icon] , then". */
.share-icon {
  vertical-align: -3px;
  margin: 0 2px;
}

.install-actions {
  display: flex;
  align-items: center;
  /* Enough room that the dismiss tap target doesn't sit flush against the
     Install button — the two are easy to confuse at a small gap on a real
     touchscreen, even though each is individually large enough now. */
  gap: 10px;
  flex: none;
}

.install-btn {
  appearance: none;
  border: none;
  border-radius: 8px;
  background: var(--focus);
  color: #fff;
  font: inherit;
  font-weight: 600;
  font-size: 0.8125rem;
  padding: 8px 14px;
  min-height: 36px;
  cursor: pointer;
}

.install-btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.install-dismiss {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-muted);
  /* 44px is the accepted minimum comfortable touch target (Apple/Google
     guidance) — the previous 32px was a real, plausible reason a tap could
     land next to the glyph and miss the button's hit area entirely. */
  width: 44px;
  height: 44px;
  border-radius: 8px;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  flex: none;
}

.install-dismiss:hover { background: var(--wash); }

.install-dismiss:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* ---------- cards ---------- */

.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  margin: 0 0 16px;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}

h2 {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
}

.card-note {
  margin: 4px 0 0;
  color: var(--text-muted);
  font-size: 0.8125rem;
  line-height: 1.45;
}

/* ---------- segmented controls ---------- */

/* Two groups rather than one six-way switch: three measures x two bases. Six
   buttons in a single row does not fit a phone. */
.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.segmented {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.seg {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 0.8125rem;
  padding: 8px 14px;
  min-height: 36px;
  cursor: pointer;
}

.seg + .seg { border-left: 1px solid var(--border); }

.seg.is-active {
  background: var(--wash);
  color: var(--text-primary);
  font-weight: 600;
}

.seg:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

.clear-focus {
  border: 1px solid var(--border);
  border-radius: 8px;
}

/* ---------- chart ---------- */

.chart-box {
  position: relative;
  height: 58vh;
  min-height: 300px;
  max-height: 460px;
  margin-top: 12px;
}

/* ---------- legend ---------- */

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
}

.chip {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 0.75rem;
  padding: 5px 10px;
  min-height: 30px;
  cursor: pointer;
  max-width: 100%;
}

.chip span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chip.is-off {
  opacity: 0.45;
  text-decoration: line-through;
}

.chip:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* A short stroke keys each series, matching the line it stands for. */
.chip-key {
  flex: none;
  width: 18px;
  height: 0;
  border-top-width: 3px;
  border-top-style: solid;
  border-radius: 2px;
}

.chip-key.solid  { border-top-style: solid; }
.chip-key.dashed { border-top-style: dashed; }
.chip-key.dotted { border-top-style: dotted; }

/* In the table the sample sits on the text baseline of the team name row. */
.team-cell > .chip-key { margin-top: 1px; }

/* ---------- table ---------- */

.table-wrap {
  margin-top: 12px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
  /* Fixed layout so a long team name ellipsises instead of widening the table. */
  table-layout: fixed;
}

caption { text-align: left; }

th, td {
  padding: 9px 6px;
  text-align: left;
  border-bottom: 1px solid var(--gridline);
}

th {
  color: var(--text-muted);
  font-weight: 600;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

/* The numeric columns are pinned; the team column takes whatever is left. */
.col-rank  { width: 26px; }
.col-total { width: 50px; }
.col-last  { width: 44px; }
.col-vs    { width: 68px; }
.col-team  { width: auto; }

td:first-child, th:first-child { padding-left: 0; }
td:last-child, th:last-child { padding-right: 0; }

td.num { font-size: 0.8125rem; }

.num { white-space: nowrap; }

.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

tbody tr { cursor: pointer; }

tbody tr:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

tbody tr.is-focused { background: var(--wash); }

tbody tr:last-child td { border-bottom: 0; }

.team-cell {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* Both levels need min-width:0 for the ellipsis to engage inside a flex row. */
.team-cell > div { min-width: 0; }

.team-name {
  /* Must be block: text-overflow does not apply to inline boxes. */
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}

.manager {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 400;
}

.pos { color: var(--good); }
.neg { color: var(--critical); }

/* ---------- definitions ---------- */

.defs {
  margin: 12px 0 0;
  font-size: 0.875rem;
  line-height: 1.5;
}

.defs dt {
  font-weight: 600;
  margin-top: 10px;
}

.defs dt:first-child { margin-top: 0; }

.defs dd {
  margin: 2px 0 0;
  color: var(--text-secondary);
}

/* ---------- footer ---------- */

.page-foot {
  color: var(--text-muted);
  font-size: 0.75rem;
  text-align: center;
}

.page-foot p { margin: 0; }

@media (min-width: 600px) {
  .viz-root { padding: 28px 24px 40px; }
  h1 { font-size: 1.75rem; }
  .chart-box { height: 420px; max-height: none; }
}

/* A phone held sideways is wide enough to trip the desktop rule above, but
   it's shallow — very little vertical room. Tie the chart height to the
   viewport instead of the desktop's fixed 420px, and trim vertical padding,
   so the chart doesn't alone exceed the whole screen height. Both conditions
   matter: orientation:landscape alone also matches an ordinary wide desktop
   window, which is exactly what the rule above is already tuned for. This
   comes after it in the stylesheet so it wins the properties both set. */
@media (orientation: landscape) and (max-height: 500px) {
  .viz-root { padding-top: 12px; padding-bottom: 20px; }
  .page-head { margin-bottom: 10px; }
  .card { padding: 12px; margin: 0 0 12px; }
  .chart-box { height: 68vh; max-height: 340px; min-height: 200px; margin-top: 8px; }
}
