/* ─────────────────────────────────────────────────────────────────────────────
   craft.css — press response, focus, materials, accessibility.

   Loaded LAST on every page (after each page's own sheet) so it can refine
   shared surfaces without editing five stylesheets. Additive by design: it
   introduces no layout, only response, material and accessibility behaviour.

   The reduced-motion / reduced-transparency / contrast blocks at the bottom
   are the single source of truth for those signals — the per-page
   `* { transition: none !important }` rules were removed in favour of them,
   because `!important` from a page sheet would outrank anything here.
   ───────────────────────────────────────────────────────────────────────────── */

:root {
  /* Critically damped (no overshoot) — the default for UI that must feel
     precise rather than playful. Response ~0.3s per the interaction spec. */
  --ease-damped: cubic-bezier(.2, 0, 0, 1);
  /* Mirror of the above, for the return leg of a reversible transition. */
  --ease-damped-out: cubic-bezier(1, 0, .8, 1);
  /* Slight overshoot, reserved for momentum-driven / celebratory motion. */
  --ease-bounce: cubic-bezier(.2, 1.3, .4, 1);
  --press-fast: 100ms;
  --press-settle: 260ms;
}

/* ── Typography ───────────────────────────────────────────────────────────────
   Optical sizing lets the face adjust contrast and aperture to its rendered
   size; both Inter and Space Grotesk ship the tables for it. */
html { font-size: 100%; }
body { font-optical-sizing: auto; }

/* Tracking is size-specific, never fixed: tighten as type gets larger, let
   small caps-y labels breathe. The page sheets already tighten h1/h2, so this
   only fills in the display-scale numerals they missed. */
.recap-stat strong,
.duel-score,
.elo-rating b,
.metric strong { letter-spacing: -.03em; }

/* Every figure that polls or paginates gets tabular figures, so digits do not
   reflow as values change. Proportional numerals visibly jitter on the live
   scoreboards and the weekly recap strip. */
.recap-stat strong,
.award-value,
.live-team strong,
.live-players td.num,
.live-players td.rank,
.fact strong,
.heat-stat b,
.bar-value,
.tl-points,
.tl-diff { font-variant-numeric: tabular-nums; }

/* ── Press response ───────────────────────────────────────────────────────────
   Hover is a pointer-only affordance — on touch it never fires, so tapping a
   row currently gave no acknowledgement at all until navigation completed.
   Everything interactive now answers on pointer-down.

   Scale is inversely proportional to surface size: a full-width row scaled to
   .97 reads as a glitch, while a pill needs the full amount to register. */
.match-row,
.player-row,
.elo-row,
.history-row,
.award,
.discord-link,
.btn,
.pagination button,
.seg-btn,
.heatmap-summary,
.site-header nav a,
.nav-burger,
.back-link,
.chip {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

/* Reversible transitions mirror their easing: the outbound leg uses the
   damped curve, the return leg its inverse, so a cancelled press retraces
   the same path rather than snapping. */
.match-row,
.player-row,
.elo-row,
.history-row {
  transition:
    border-color var(--press-settle) var(--ease-damped-out),
    transform var(--press-settle) var(--ease-damped-out),
    box-shadow var(--press-settle) var(--ease-damped-out),
    background-color var(--press-settle) var(--ease-damped-out);
}
.match-row:hover,
.player-row:hover,
.elo-row:hover,
.history-row:hover {
  transition:
    border-color var(--press-fast) var(--ease-damped),
    transform var(--press-fast) var(--ease-damped),
    box-shadow var(--press-fast) var(--ease-damped),
    background-color var(--press-fast) var(--ease-damped);
}
/* Wide surfaces: a 0.5% inset plus the existing 4px nudge collapsing back to
   zero. The row is grabbed, not squashed. */
.match-row:active,
.player-row:active,
.elo-row:active,
.history-row:active {
  transform: scale(.995);
  transition: transform var(--press-fast) var(--ease-damped);
}

.discord-link,
.btn,
.pagination button,
.seg-btn,
.heatmap-summary {
  transition:
    transform var(--press-fast) var(--ease-damped),
    background-color var(--press-fast) var(--ease-damped),
    border-color var(--press-fast) var(--ease-damped),
    color var(--press-fast) var(--ease-damped),
    box-shadow var(--press-fast) var(--ease-damped);
}
/* Compact controls take the full 0.97 — small surfaces need the larger
   delta to read as a press at all. */
.btn:active,
.pagination button:active,
.seg-btn:active,
.heatmap-summary:active,
.nav-burger:active { transform: scale(.97); }
/* The CTA already lifts on hover; pressing puts it back down past rest, so
   the gesture reads as depressing a raised key. */
.discord-link:active { transform: translateY(1px) scale(.97); }

/* Nav links have no box to scale, so they answer in colour instead —
   instantly, with no transition on the way in. */
.site-header nav a:active { color: var(--accent); transition: none; }
.back-link:active { color: var(--accent); transition: none; }

/* Table rows are the one interactive surface that must not move: shifting a
   row under the pointer inside a dense scoreboard loses the reader's place. */
.scoreboard tbody tr { transition: background-color var(--press-fast) var(--ease-damped); }

/* ── Focus ───────────────────────────────────────────────────────────────────
   Only form inputs and .seg-btn had a visible focus state; every other
   interactive element left keyboard users with no position indicator.
   Matches the existing .seg-btn convention (2px cyan, 2px offset). */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 2px;
  border-radius: 4px;
}
.match-row:focus-visible,
.player-row:focus-visible,
.elo-row:focus-visible,
.history-row:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-color: var(--accent);
}
.discord-link:focus-visible { outline-color: var(--text); }
/* The burger is a <label> driving a hidden checkbox; the checkbox already
   forwards its focus ring, so suppress the doubled outline. */
.nav-burger:focus-visible { outline: none; }

/* ── Material & depth ────────────────────────────────────────────────────────
   Weight encodes hierarchy: structural regions sit darker and flatter,
   interactive surfaces sit lighter and lift toward the reader. Previously
   every surface shared --panel + 1px --line, so nothing signalled which
   things could be pressed. */
/* The two percentages MUST sum to 100: color-mix() applies any shortfall as
   alpha, which would make these rows translucent and stack one translucent
   surface on another — the thing §12 explicitly forbids. */
.match-row,
.player-row,
.elo-row,
.history-row {
  background-color: color-mix(in srgb, var(--panel) 98%, var(--text) 2%);
}
.match-row:hover,
.player-row:hover,
.elo-row:hover,
.history-row:hover {
  background-color: color-mix(in srgb, var(--panel) 95%, var(--text) 5%);
}

/* Chrome reads as thicker glass than the cards beneath it: a bigger surface
   earns a stronger blur, and saturation keeps colour alive through it. */
.site-header {
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  /* Scroll edge, not a hard divider — content dissolves into the chrome
     instead of colliding with a 1px line. */
  border-bottom: none;
  box-shadow: 0 1px 0 color-mix(in srgb, var(--line) 55%, transparent);
}
.site-header::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 22px;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--bg) 70%, transparent),
    transparent
  );
}
/* The mobile nav drawer drops out of the header; its own edge must not get
   the fade, or it double-fades over the panel below. */
.nav-toggle:checked ~ nav { box-shadow: 0 18px 40px rgba(0, 0, 0, .45); }

/* ── Accessibility signals ───────────────────────────────────────────────────
   Three independent preferences, handled independently. */

@media (prefers-reduced-motion: reduce) {
  /* Cross-fade rather than kill outright: transforms and the parallax-ish
     lift go away, opacity and colour still carry state changes. */
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 120ms !important;
    transition-property: opacity, color, background-color, border-color !important;
    scroll-behavior: auto !important;
  }
  .match-row:hover, .player-row:hover, .elo-row:hover, .history-row:hover,
  .match-row:active, .player-row:active, .elo-row:active, .history-row:active,
  .award:hover, .discord-link:hover, .discord-link:active,
  .btn:active, .pagination button:active, .seg-btn:active,
  .heatmap-summary:active, .nav-burger:active { transform: none !important; }
  html { scroll-behavior: auto; }
}

@media (prefers-reduced-transparency: reduce) {
  /* Translucent chrome becomes opaque; the scroll-edge fade would read as a
     smear against a solid header, so it is replaced by a defined edge. */
  .site-header {
    background: var(--bg);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-bottom: 1px solid var(--line-strong);
    box-shadow: none;
  }
  .site-header::after { display: none; }
  .heat-tooltip, .telemetry-legend, .stage-loading { background: var(--bg); }
}

@media (prefers-contrast: more) {
  /* Near-solid surfaces with defined, contrasting borders; secondary text
     stops being secondary. */
  :root {
    /* Percentages sum to 100 — see the note on .match-row above. */
    --panel: color-mix(in srgb, var(--bg) 96%, var(--text) 4%);
    --line: color-mix(in srgb, var(--text) 34%, transparent);
    --line-strong: color-mix(in srgb, var(--text) 52%, transparent);
    --text-2: color-mix(in srgb, var(--text) 82%, transparent);
  }
  .site-header {
    background: var(--bg);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-bottom: 1px solid var(--line-strong);
  }
  .site-header::after { display: none; }
  .match-row, .player-row, .elo-row, .history-row,
  .metric, .award, .recap-stat, .live-card, .section-block {
    border-color: var(--line-strong);
  }
  a:focus-visible, button:focus-visible, summary:focus-visible {
    outline-width: 3px;
  }
  .chip, .match-mode, .team-tag, .live-pill { border: 1px solid currentColor; }
}
