/* grades.css — the performance grade sheet and the pad that fills it in.

   Part of the Teleport stylesheet, split by concern. index.html links these
   in source order; keep that order, the cascade depends on it. This one sits
   after scenarios.css and before news.css — it borrows .shell, .blank, .btn,
   .search and .seg from earlier slices and adds nothing they read. */

/* ─── Grade tones ───────────────────────────────────────────────────────────
   Five steps, mapped onto the tokens the rest of the app already grades with,
   so a 5 here is the same green as a top tier on the board. **5 is best** —
   see the note at the top of js/grade-sessions.js, and do not reverse these
   without reversing that.

   Declared once, as a pair of custom properties per tone, so a cell, the key in
   the hero and a row in the pad can all be the same colour by carrying the same
   class rather than by three rules agreeing with each other. */
.tone-great { --gt: var(--green); --gt-bg: var(--green-light); }
.tone-good  { --gt: var(--blue);  --gt-bg: var(--blue-light);  }
.tone-okay  { --gt: var(--slate); --gt-bg: var(--slate-light); }
.tone-poor  { --gt: var(--gold);  --gt-bg: var(--gold-light);  }
.tone-bad   { --gt: var(--red);   --gt-bg: var(--red-light);   }

/* No width override. At twenty-two columns this shell was widened to 1500px to
   keep the sheet from scrolling; thirteen games fit the app's ordinary 1240px
   with room to spare, so it goes back to being the same width as every other
   screen — which is worth more than the extra columns were. */

/* ─── Hero ──────────────────────────────────────────────────────────────────
   The mark, the title, three numbers, and the key. The key is not decoration:
   1–5 is a direction with no inherent meaning, and the staff's own spreadsheet
   printed its legend across the top for exactly this reason. */
.grades-hero {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 16px 20px;
  padding: 20px 22px;
  margin-bottom: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-sm);
}
.grades-hero-mark { display: flex; }
.grades-hero-title {
  font-size: 22px; font-weight: 800; letter-spacing: -0.02em; color: var(--label);
}
.grades-hero-sub { margin-top: 2px; font-size: 13px; color: var(--label-2); }

.grades-hero-stats { display: flex; gap: 26px; }
.grades-stat { text-align: right; }
.grades-stat-n {
  font-size: 22px; font-weight: 800; color: var(--label);
  letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.grades-stat-of { font-size: 14px; font-weight: 600; color: var(--label-3); }
.grades-stat-l {
  margin-top: 1px; font-size: 10px; font-weight: 700; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--label-3);
}

.grades-key {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; gap: 6px 18px;
  padding-top: 14px; border-top: 1px solid var(--border-2);
}
.grades-key-item { display: inline-flex; align-items: center; gap: 7px; }
.grades-key-dot {
  display: grid; place-items: center;
  width: 20px; height: 20px; border-radius: var(--r-sm);
  background: var(--gt-bg); color: var(--gt);
  font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.grades-key-label { font-size: 12px; font-weight: 600; color: var(--label-2); }

/* ─── Toolbar ───────────────────────────────────────────────────────────── */
.grades-toolbar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  margin-bottom: 12px;
}
.grades-toolbar-spacer { flex: 1 1 auto; }
.grades-room-select { width: auto; min-width: 190px; }
.grades-search { width: 240px; }

/* ─── The grid ──────────────────────────────────────────────────────────────
   One table for the whole sheet, scrolling inside its own container so the
   header row and the player column can both stick. Two sticky axes at once is
   why this is a table and not a CSS grid: the corner cell needs to outrank both
   and `z-index` on a `<th>` is the least surprising way to say so. */
.grades-scroll {
  position: relative;
  overflow: auto;
  max-height: calc(100vh - var(--nav-h) - 260px);
  min-height: 320px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  /* Momentum scrolling without the browser also claiming the gesture for
     navigation — a sheet is dragged sideways constantly and a back-swipe
     mid-column would lose the coach his place. */
  overscroll-behavior: contain;
}

/* `table-layout: fixed` is the rule that keeps the columns where this file puts
   them. Under the default `auto`, a table column is as wide as its widest cell
   *whatever* the CSS says — and the room band's "INTERIOR OFFENSIVE LINE" is
   `nowrap`, so it quietly pushed the player column from 220px to 260px and
   opened a gap between the names and the first game. Fixed layout reads the
   widths off the header row and nothing below it gets a vote.

   `width: 100%` then spends the leftover space across the columns instead of
   leaving it in a pile at one edge, and `min-width` is what still makes the
   sheet scroll rather than crush itself on a narrow screen. */
.grades-grid {
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
  width: 100%;
  min-width: 1160px;
}

/* Column widths are fixed rather than content-derived: a column that resized
   itself when its first grade landed would shift every column right of it,
   under a pointer that is on its way to one of them.

   66px per game, not the 46px that twenty-two columns forced — the sheet is a
   grid of tap targets and thirteen columns leave room to make them comfortable
   ones. These add up to `min-width` on the table above; below that the sheet
   scrolls, above it they share the slack evenly.

   Only the header row's widths matter under `table-layout: fixed`, but the
   body's are declared alongside them so the two can't drift into disagreeing
   about what the column is. */
.grades-grid th, .grades-grid td { padding: 0; }
.gr-corner, .gr-name { width: 240px; }
.gr-head, .gr-cell-wrap { width: 66px; }
.gr-avg-head, .gr-avg { width: 62px; }

/* ── Header row ── */
.grades-grid thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--label-3);
  white-space: nowrap;
}
/* Both of these are written `thead th.x` rather than `.x`. They have to beat
   `.grades-grid thead th` above, which is (0,1,2) to a bare class's (0,1,0) —
   so the z-index written here was losing to that rule's `2` and the corners
   were tying with the ordinary header cells. Equal z-index means DOM order
   decides, and every session header comes *after* the corner, so scrolling
   sideways slid them over the top of it. */
.grades-grid thead th.gr-corner {
  left: 0; z-index: 5;
  text-align: left; padding: 0;
  border-right: 1px solid var(--border);
}
.gr-corner-in { padding: 0 14px; }
.gr-head {
  height: 46px; padding: 0 2px !important;
  border-right: 1px solid var(--border-2);
  cursor: default;
}
.gr-head-label { display: block; font-size: 10.5px; color: var(--label-2); }
/* The column's own average, under its label. Small on purpose — it is context
   for the column, not a number anybody came here to read. */
.gr-head-avg {
  display: block; margin-top: 1px;
  font-size: 10px; font-weight: 700; color: var(--label-3);
  font-variant-numeric: tabular-nums; letter-spacing: 0;
}
/* No per-column tint. It existed to separate games from practices when the two
   shared the header row; with practices gone every column is a game, so tinting
   them all would just be a coloured stripe that distinguishes nothing. */
.grades-grid thead th.gr-avg-head {
  right: 0; z-index: 5; text-align: center; border-left: 1px solid var(--border);
}

/* ── Room bands ── */
.gr-room > * {
  position: sticky; top: 46px; z-index: 1;
  height: 32px;
  background: var(--bg-2);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.gr-room-name {
  left: 0; z-index: 3;
  text-align: left; padding: 0;
  border-right: 1px solid var(--border);
}
/* Clipped rather than allowed to widen the column. Under `table-layout: fixed`
   it cannot widen it anyway, so without this a long room name would simply
   spill over the first game column. The code chip is the part that has to
   survive — it is what a coach reads — so the label is what gives way. */
.gr-room-in {
  display: flex; align-items: center; height: 100%;
  padding: 0 14px; min-width: 0;
  white-space: nowrap; overflow: hidden;
}
/* The code first, because that is what a coach calls the room, then the name
   spelled out for anyone who doesn't live in the abbreviations. */
.gr-room-code {
  flex: none;
  padding: 2px 6px; border-radius: var(--r-sm);
  background: var(--label); color: var(--surface);
  font-size: 9.5px; font-weight: 800; letter-spacing: 0.06em;
}
.gr-room-label {
  margin-left: 7px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis;
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--label-2);
}
.gr-room-count {
  flex: none;
  margin-left: 7px; padding: 1px 6px; border-radius: var(--r-full);
  background: var(--surface); border: 1px solid var(--border);
  font-size: 10px; font-weight: 700; color: var(--label-3);
}
.gr-room-avg {
  right: 0; z-index: 3;
  text-align: center;
  border-left: 1px solid var(--border);
  font-size: 11.5px; font-weight: 800; color: var(--label-2);
  font-variant-numeric: tabular-nums;
}

/* ── Player rows ── */
.gr-row:hover .gr-name,
.gr-row:hover .gr-avg { background: var(--surface-2); }
/* ── The name cell ───────────────────────────────────────────────────────────
   **The flex box is the inner div, never the `<th>` itself.** `display: flex`
   on a table cell overrides its `display: table-cell`, so the element stops
   being a cell at all: the table wraps it in an anonymous cell, sizes *that* to
   the column, and leaves the flex box sitting at its own width inside it. That
   is what put 40px of dead space between every player's name and his first
   grade. The same trap applies to the room band and the corner, so all three
   carry an inner wrapper. */
.gr-name {
  position: sticky; left: 0; z-index: 1;
  height: 36px;
  background: var(--surface);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border-2);
  text-align: left; font-weight: 500;
  transition: background .12s var(--ease-out);
}
.gr-name-in {
  display: flex; align-items: center; gap: 9px;
  height: 100%; padding: 0 14px;
}
.gr-num {
  flex: none; min-width: 22px;
  font-size: 11px; font-weight: 800; color: var(--label-3);
  font-variant-numeric: tabular-nums; text-align: right;
}
/* `0 1 auto`, not `1 1 auto`: the name shrinks (and ellipses) when it has to,
   but never *grows* to fill the column. Growing pushed the class chip to the far
   right, which put a river of white space after every short name — the same
   thing the column gap looked like, one element in. Packed left, the leftover
   width sits at the column edge where it reads as padding. The room band above
   is laid out the same way for the same reason. */
.gr-player {
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 13px; font-weight: 600; color: var(--label);
  text-decoration: none;
}
.gr-player:hover { color: var(--accent); text-decoration: underline; }
.gr-year {
  flex: none; padding: 1px 5px; border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px solid var(--border-2);
  font-size: 9.5px; font-weight: 700; color: var(--label-3);
}

.gr-cell-wrap { border-bottom: 1px solid var(--border-2); border-right: 1px solid var(--border-2); }
.gr-avg {
  position: sticky; right: 0; z-index: 1;
  height: 36px; text-align: center;
  background: var(--surface);
  border-left: 1px solid var(--border);
  border-bottom: 1px solid var(--border-2);
  font-size: 12.5px; font-weight: 800; color: var(--label);
  font-variant-numeric: tabular-nums;
  transition: background .12s var(--ease-out);
}

/* ── One cell ───────────────────────────────────────────────────────────────
   Fills its box edge to edge, so the grid reads as a sheet of boxes rather than
   as buttons floating in cells. The tint is the value: a filled cell is its own
   colour and an empty one is a faint dotted well, which is what makes an
   ungraded column legible as a gap from across the room. */
.gr-cell {
  position: relative;          /* the pending bar below is absolute against this */
  display: grid; place-items: center;
  width: 100%; height: 36px;
  border: 0; background: transparent; cursor: pointer;
  font-family: inherit;
  font-size: 13.5px; font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--gt, var(--label-3));
  background: var(--gt-bg, transparent);
  transition: background .14s var(--ease-out), box-shadow .14s var(--ease-out);
}
.gr-cell:hover { box-shadow: inset 0 0 0 2px var(--gt, var(--border)); }
.gr-cell:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--accent);
}
.gr-cell.is-blank {
  background:
    radial-gradient(circle at center, var(--border) 1.2px, transparent 1.3px);
}
.gr-cell.is-na .gr-val {
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.03em;
  color: var(--label-3);
}

/* In flight. Deliberately quiet — a grade sheet is filled in fast and a cell
   that flashed on every keystroke would strobe. The bar along the bottom says
   "still going" without competing with the number above it. */
.gr-cell.is-pending::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--accent);
  animation: gr-pending 1s var(--ease-out) infinite;
}
.gr-cell-wrap { position: relative; }
@keyframes gr-pending {
  0%   { opacity: .25; transform: scaleX(.3); }
  50%  { opacity: .9;  transform: scaleX(1);  }
  100% { opacity: .25; transform: scaleX(.3); }
}

/* Refused. The value has already been rolled back to what it was, so this is
   the only thing on screen saying the keystroke didn't take — it has to be
   loud enough to catch on the way past and carries the reason on its title. */
.gr-cell.is-failed {
  box-shadow: inset 0 0 0 2px var(--red);
  background: var(--red-light);
}

/* ═══ The pad ══════════════════════════════════════════════════════════════
   Anchored to the cell, and small — six targets. It names the scale in words,
   which is the one thing the keyboard path cannot do. */
.gpad {
  position: fixed; z-index: 90;
  width: 214px; padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  opacity: 0; transform: translateY(-4px) scale(.97);
  transform-origin: top center;
  transition: opacity .16s var(--ease-out), transform .16s var(--ease-out);
}
.gpad.is-above { transform-origin: bottom center; transform: translateY(4px) scale(.97); }
.gpad.is-in { opacity: 1; transform: none; }

.gpad-head {
  padding: 5px 8px 7px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--label-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border-bottom: 1px solid var(--border-2); margin-bottom: 4px;
}
.gpad-rows { display: flex; flex-direction: column; gap: 2px; }
.gpad-row {
  display: flex; align-items: center; gap: 9px;
  width: 100%; padding: 6px 8px;
  border: 0; border-radius: var(--r-sm); background: transparent;
  cursor: pointer; font-family: inherit; text-align: left;
  transition: background .12s var(--ease-out);
}
.gpad-row:hover { background: var(--surface-2); }
.gpad-row.is-on { background: var(--gt-bg); }
.gpad-n {
  display: grid; place-items: center; flex: none;
  width: 22px; height: 22px; border-radius: var(--r-sm);
  background: var(--gt-bg); color: var(--gt);
  font-size: 12px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.gpad-label { flex: 1 1 auto; font-size: 13px; font-weight: 600; color: var(--label); }
.gpad-tick { display: none; flex: none; color: var(--gt); }
.gpad-tick svg { width: 15px; height: 15px; display: block; }
.gpad-row.is-on .gpad-tick { display: block; }

.gpad-foot {
  display: flex; gap: 4px; align-items: center;
  margin-top: 5px; padding-top: 5px;
  border-top: 1px solid var(--border-2);
}
.gpad-alt {
  display: flex; align-items: center; gap: 8px;
  flex: 1 1 auto; padding: 6px 8px;
  border: 0; border-radius: var(--r-sm); background: transparent;
  cursor: pointer; font-family: inherit; text-align: left;
  font-size: 12px; font-weight: 600; color: var(--label-2);
  transition: background .12s var(--ease-out);
}
.gpad-alt:hover { background: var(--surface-2); }
.gpad-alt.is-on { background: var(--slate-light); color: var(--label); }
.gpad-alt-n {
  display: grid; place-items: center; flex: none;
  width: 22px; height: 22px; border-radius: var(--r-sm);
  background: var(--slate-light); color: var(--slate);
  font-size: 9px; font-weight: 800;
}
.gpad-clear {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  padding: 6px 9px; border: 0; border-radius: var(--r-sm);
  background: transparent; cursor: pointer; font-family: inherit;
  font-size: 11.5px; font-weight: 650; color: var(--label-3);
  transition: background .12s var(--ease-out), color .12s var(--ease-out);
}
.gpad-clear:hover { background: var(--red-light); color: var(--red); }
.gpad-clear svg { width: 13px; height: 13px; }
