/* ============================================================
   UBC Player Lab — app styles
   Committed light theme: this is a coaching tool whose end
   product is a printed page; screen and paper share one look.
   ============================================================ */

:root {
  /* ---------- brand ---------- */
  --navy: #002145;        /* UBC primary */
  --navy-2: #0B3665;
  --navy-3: #123A66;      /* raised navy, for panels sitting on navy */
  --gold: #F2A900;        /* UBC gold */
  --gold-ink: #8A5F00;
  --gold-line: #E4C36A;

  /* ---------- surface ramp ----------
     Four steps, all cool-biased toward the navy. The page ground sits a shade
     under white so a card separates by CONTRAST, not by a drop shadow — that
     is what keeps the cards feeling set into the page rather than floating. */
  --ice: #E9EEF4;         /* application ground */
  --card: #FFFFFF;        /* primary surface */
  --surface-2: #F5F8FC;   /* tinted panel sitting ON a card */
  --surface-3: #EFF3F9;   /* control ground */
  --selected: #E2EAF4;    /* quiet selected state */

  /* ---------- ink ---------- */
  --ink: #14202F;
  --ink-2: #2C3E55;       /* secondary value text */
  --sub: #5F6E85;
  --sub-2: #7C8A9E;       /* tertiary: captions, axis labels */

  /* ---------- lines ----------
     One hairline for structure, one softer for internal rhythm, one stronger
     for the few places that genuinely need to hold a column together. */
  --line: #DEE5EE;
  --line-soft: #EAEFF5;
  --line-strong: #C9D4E1;

  --green: #1E8A5A;
  --green-bg: #E7F4EE;
  --red: #C24444;
  --red-bg: #FAECEC;
  --amber: #B07A12;
  --amber-bg: #FBF3DF;
  --pink: #D655A2;

  --display: "Avenir Next Condensed", "Arial Narrow", "Helvetica Neue", sans-serif;
  --body: -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, monospace;

  /* ---------- spacing ----------
     One 4px-based scale. Every gap, pad and margin in this file comes from it,
     so vertical rhythm is a decision made once instead of 200 times. */
  --s-1: 0.25rem;   /* 4  */
  --s-2: 0.5rem;    /* 8  */
  --s-3: 0.75rem;   /* 12 */
  --s-4: 1rem;      /* 16 */
  --s-5: 1.25rem;   /* 20 */
  --s-6: 1.75rem;   /* 28 */
  --s-7: 2.25rem;   /* 36 */
  --s-8: 3rem;      /* 48 */

  /* ---------- radii ----------
     Three steps only. Controls are tighter than cards; nothing is a pill
     except things that are genuinely pill-shaped. */
  --r-ctl: 8px;
  --r-tile: 8px;
  --r-card: 10px;
  --r-pill: 999px;

  /* ---------- elevation ----------
     Deliberately almost invisible. Separation is the surface ramp's job; this
     only stops a white card from looking pasted flat onto a white-ish ground. */
  --elev-1: 0 1px 1px rgba(0, 33, 69, .04), 0 2px 6px -2px rgba(0, 33, 69, .05);
  --elev-2: 0 1px 2px rgba(0, 33, 69, .05), 0 14px 28px -16px rgba(0, 33, 69, .22);

  /* ---------- control metrics ---------- */
  --ctl-h: 2rem;          /* 32px — compact controls */
  --ctl-h-lg: 2.25rem;    /* 36px — primary buttons */

  /* Motion. One curve and two durations for the whole app, so a press feels the
     same everywhere and a chart redraw settles the same way every time.
     --ease-settle overshoots nothing: it arrives fast and stops clean. */
  --ease-settle: cubic-bezier(.32, .72, 0, 1);
  --ease-out: cubic-bezier(.23, 1, .32, 1);
  --t-press: 90ms;
  --t-settle: 260ms;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* Root stays at the browser's own size, so a coach who has raised their default
   text size gets a larger app. Body steps down to the app's reading size, and
   everything below is expressed relative to one of the two. */
html { font-size: 100%; -webkit-text-size-adjust: 100%; }

body {
  background: var(--ice);
  color: var(--ink);
  font-family: var(--body);
  font-size: 0.9375rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--navy-2); }
button { font: inherit; cursor: pointer; }

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

/* ---------------- press feedback ----------------
   Every control acknowledges the pointer going DOWN, not the click coming back
   up. On a dugout iPad there is no hover at all, so without this a tap has no
   feedback until the re-render lands. The scale is deliberately small — this is
   an acknowledgement, not an animation. */

.btn, .seg button, .am-filter button, .zone-toggle, .lock-btn,
.topnav a, .brand, .pcard {
  -webkit-tap-highlight-color: transparent;  /* we draw our own, no grey flash */
  touch-action: manipulation;                /* drops the legacy double-tap delay */
}

/* The selects keep the platform tap highlight — opening the native picker is
   their feedback, and we are not drawing a substitute for it. */
.lvl-select { touch-action: manipulation; }

.btn, .seg button, .am-filter button, .zone-toggle, .lock-btn, .brand {
  transition: transform var(--t-press) var(--ease-out),
              background-color var(--t-press) var(--ease-out),
              border-color var(--t-press) var(--ease-out);
}

/* Transform only. The active pill is gold and the resting link is transparent,
   so transitioning background-color here fades the pill through a muddy olive
   on every page change. The page state snaps; only the press moves. */
.topnav a { transition: transform var(--t-press) var(--ease-out); }

/* applyRoleChrome() hides the links a player has no business following by
   setting `hidden`. The browser's own `[hidden] { display: none }` is a weaker
   selector than `.topnav a { display: flex }`, so it lost — and a player was
   shown the coach-only Manage tab. The route and the API both refuse them, but
   an offer that gets refused is still an offer. */
.topnav a[hidden] { display: none; }

.btn:active, .seg button:active, .am-filter button:active,
.zone-toggle:active, .lock-btn:active { transform: scale(.97); }
.topnav a:active { transform: scale(.96); }
.brand:active { transform: scale(.99); }

/* A card is a surface, so pressing it puts it back down on the page rather than
   shrinking it — the inverse of the hover lift. */
.pcard:active { transform: translateY(0); box-shadow: var(--elev-1); }

/* ---------------- top bar ---------------- */

/* A floating layer rather than an opaque strip: content passes under it and
   stays faintly readable through the navy, which is what makes the header read
   as a pane of the app instead of a band pasted on top. The solid colour below
   is the fallback; the translucent version only applies where it is supported. */
.topbar {
  background: var(--navy);
  color: #fff;
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-2) var(--s-5);
  min-height: 3.5rem;
  position: sticky;
  top: 0;
  z-index: 10;
  flex-wrap: wrap;
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, .07);
}

.demo-banner[hidden] { display: none; }
.demo-banner {
  flex: 1 0 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-ctl);
  background: var(--gold);
  color: var(--navy);
  font-size: 0.6875rem;
  line-height: 1.35;
  letter-spacing: .01em;
  text-align: center;
}
.demo-banner strong {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  white-space: nowrap;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .topbar {
    background: rgba(0, 33, 69, .86);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
            backdrop-filter: blur(20px) saturate(160%);
  }
}

.brand-title { white-space: nowrap; }
.brand-sub { white-space: nowrap; }

.brand { display: flex; align-items: center; gap: var(--s-3); text-decoration: none; color: #fff; }
.brand-logo {
  width: 2.375rem;
  height: 2.375rem;
  border-radius: 6px;
  display: block;
  flex: none;
}
.brand-text { display: flex; flex-direction: column; line-height: 1.1; }
.brand-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.3125rem;
  text-transform: uppercase;
  letter-spacing: .045em;
}
.brand-sub {
  font-size: 0.625rem;
  color: #A9BCD4;
  letter-spacing: .1em;
  text-transform: uppercase;
  margin-top: 1px;
}

.topnav { display: flex; gap: var(--s-1); margin-left: var(--s-2); }
.topnav a {
  color: #C9D6E6;
  text-decoration: none;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: .005em;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-ctl);
  line-height: 1;
  display: flex;
  align-items: center;
}
.topnav a:hover { color: #fff; background: rgba(255, 255, 255, .1); }
.topnav a.active { color: var(--navy); background: var(--gold); }
.topnav a.active:hover { color: var(--navy); background: var(--gold); }

.topbar-right { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }
.lvl-label {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: #A9BCD4;
  font-weight: 600;
}
.lvl-select {
  background: rgba(255, 255, 255, .08);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, .18);
  border-radius: var(--r-ctl);
  padding: var(--s-1) var(--s-2);
  font-family: var(--body);
  font-size: 0.8125rem;
  min-height: var(--ctl-h);
}
.lvl-select:hover { border-color: rgba(255, 255, 255, .32); }

/* ---------------- layout ---------------- */

main { max-width: 71.25rem; margin: 0 auto; padding: var(--s-6) var(--s-5) var(--s-8); }

.foot {
  max-width: 71.25rem;
  margin: 0 auto;
  padding: var(--s-4) var(--s-5) var(--s-7);
  color: var(--sub-2);
  font-size: 0.6875rem;
  font-family: var(--mono);
  letter-spacing: .01em;
}

/* The rule after the title is a hairline, not a divider — it should register as
   alignment, not as a border. */
.section-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.3125rem;
  text-transform: uppercase;
  letter-spacing: .045em;
  line-height: 1.15;
  color: var(--navy);
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin: var(--s-7) 0 var(--s-3);
}
.section-title::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.section-title:first-child { margin-top: 0; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: var(--s-4) var(--s-5);
  box-shadow: var(--elev-1);
}

/* ---------------- chips, scores ---------------- */

.chip {
  display: inline-flex;
  align-items: center;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: .05em;
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface-3);
  color: var(--ink-2);
  text-transform: uppercase;
  line-height: 1.4;
}
.chip.gold { background: var(--amber-bg); border-color: var(--gold-line); color: var(--gold-ink); }
.chip.navy { background: var(--selected); border-color: #B9CCE3; color: var(--navy-2); }

/* Metric values are read in columns, so they are tabular and tightened — a
   proportional 1 next to a proportional 8 breaks the column. */
.score {
  display: inline-block;
  min-width: 2.5rem;
  text-align: center;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: -.01em;
  padding: 2px var(--s-2);
  border-radius: 6px;
}
.score.s-elite { background: var(--green-bg); color: var(--green); }
.score.s-good  { background: var(--selected); color: var(--navy-2); }
.score.s-avg   { background: var(--amber-bg); color: var(--amber); }
.score.s-low   { background: var(--red-bg); color: var(--red); }

.delta-up { color: var(--green); font-weight: 700; font-size: 0.75rem; font-variant-numeric: tabular-nums; }

/* ---------------- roster ---------------- */

/* Deliberately quiet. This is available, not important: the roster below it is
   the page. The dashed 2px box it replaced pulled the eye first on every load. */
.upload-zone {
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface-2);
  padding: var(--s-3) var(--s-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
  color: var(--sub);
  font-size: 0.8125rem;
  margin-bottom: var(--s-5);
}
/* The one moment it should shout: a file is over the target. */
.upload-zone.dragover {
  border-color: var(--gold);
  background: var(--amber-bg);
  box-shadow: inset 0 0 0 1px var(--gold);
}
.upload-zone strong { color: var(--ink); font-weight: 600; }
.upload-actions { margin-top: 0; display: flex; gap: var(--s-2); justify-content: flex-end; flex-wrap: wrap; }
/* The ingest result takes the full width under the row, and takes no space at
   all until there is something to say. */
#upload-msg { flex: 1 0 100%; }
#upload-msg:empty { display: none; }

/* Roster-key strip: the state of the file that re-identifies this roster.
   Sits under the upload row on the same surface, not as a second card. */
.key-bar {
  flex: 1 0 100%;
  display: flex;
  align-items: center;
  gap: var(--s-2) var(--s-3);
  flex-wrap: wrap;
  border-top: 1px solid var(--line);
  padding-top: var(--s-3);
  margin-top: var(--s-2);
}
.key-state {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--sub-2); white-space: nowrap;
}
/* Linked is a good state, so it reads as one — but quietly, in the UBC green
   already used for a positive delta, not as a badge competing with the roster. */
.key-state.on { color: var(--green); }
.key-state.on::before {
  content: "●"; font-size: 8px; vertical-align: middle;
  margin-right: var(--s-1); position: relative; top: -1px;
}
.key-detail { font-size: 0.75rem; color: var(--sub); flex: 1 1 18rem; }
.key-detail b { color: var(--ink-2); font-family: var(--mono); font-size: 0.6875rem; }
.key-bar .btn { min-height: var(--ctl-h); font-size: 0.75rem; padding: 0 var(--s-3); }

/* Why the roster reads P-001 and where the names went. Quiet, but always
   present once a roster exists without a key to unlock it. */
.anon-note {
  flex: 1 0 100%;
  font-size: 0.75rem;
  line-height: 1.55;
  color: var(--sub);
  border-top: 1px solid var(--line);
  padding-top: var(--s-2);
  margin-top: var(--s-1);
  max-width: 80ch;
}

.btn {
  background: var(--navy);
  color: #fff;
  border: 1px solid var(--navy);
  border-radius: var(--r-ctl);
  padding: 0 var(--s-4);
  min-height: var(--ctl-h-lg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: .005em;
  text-decoration: none;
  white-space: nowrap;
}
.btn:hover { background: var(--navy-2); border-color: var(--navy-2); }
.btn.ghost { background: var(--card); color: var(--navy); border-color: var(--line-strong); }
.btn.ghost:hover { background: var(--surface-3); border-color: var(--navy-2); }
.btn.gold { background: var(--gold); color: var(--navy); border-color: var(--gold); }
.btn.gold:hover { background: #FFB800; border-color: #FFB800; }

.roster-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr));
  gap: var(--s-3);
}

/* The data is the hero: the name is quiet, the metadata quieter still, and the
   Stuff+ column is the only thing with real weight. */
.pcard {
  display: block;
  text-decoration: none;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line);
  border-top: 3px solid var(--navy);
  border-radius: var(--r-card);
  padding: var(--s-4);
  box-shadow: var(--elev-1);
  transition: box-shadow 150ms var(--ease-out), transform 150ms var(--ease-out),
              border-color 150ms var(--ease-out);
}
.pcard:hover { box-shadow: var(--elev-2); transform: translateY(-1px); border-color: var(--line-strong); }
.pcard-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.1875rem;
  line-height: 1.1;
  text-transform: uppercase;
  letter-spacing: .015em;
  color: var(--navy);
}
.pcard-meta {
  color: var(--sub-2);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: .07em;
  font-weight: 600;
  margin: var(--s-1) 0 var(--s-3);
}
.pcard-rows { display: flex; flex-direction: column; gap: var(--s-2); }
.pcard-row { display: flex; align-items: center; gap: var(--s-2); font-size: 0.75rem; }
.pcard-row .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.pcard-row .pt { width: 4.5rem; flex: none; color: var(--sub); letter-spacing: .005em; }
.pcard-row .bar-track {
  flex: 1;
  height: 5px;
  background: var(--line-soft);
  border-radius: var(--r-pill);
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(0, 33, 69, .03);
}
/* display:block is load-bearing: the fill is a <span>, and height has no effect
   on an inline box — the track has been rendering empty. */
.pcard-row .bar { display: block; height: 100%; border-radius: var(--r-pill); }
.pcard-row .sc {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 0.8125rem;
  color: var(--ink);
  width: 2.125rem;
  text-align: right;
  letter-spacing: -.01em;
}

.empty-note { color: var(--sub); padding: var(--s-7) 0; text-align: center; }

/* ---------------- report ---------------- */

.report-head { display: flex; align-items: flex-start; gap: var(--s-4); flex-wrap: wrap; margin-bottom: var(--s-2); }
.report-logo { width: 3.5rem; height: 3.5rem; border-radius: var(--r-tile); flex: none; }
.report-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 2.625rem;
  line-height: 1;
  text-transform: uppercase;
  color: var(--navy);
  letter-spacing: .005em;
  /* This is an <h1>, so the browser's own heading margin has to be turned off
     — every size here is set deliberately and none of them is an em of it. */
  margin: 0;
}
.report-chips { display: flex; gap: var(--s-2); flex-wrap: wrap; align-items: center; padding-top: var(--s-2); }
/* The note is the last child of a flex row, so it needs to claim a whole line
   rather than compete for space with the name and the buttons. It happens to
   wrap onto its own line at today's widths because the row above is already
   full — that is luck, not layout, and it would break the moment a shorter
   name or one fewer chip left room beside the actions. */
.report-head-note { flex: 1 0 100%; max-width: 68ch; }
.report-actions { margin-left: auto; display: flex; gap: var(--s-2); align-items: center; padding-top: var(--s-1); }

.level-strip {
  display: flex;
  gap: var(--s-5);
  align-items: center;
  flex-wrap: wrap;
  background: var(--navy);
  color: #C7D6E8;
  border-radius: var(--r-card);
  padding: var(--s-3) var(--s-4);
  margin: var(--s-4) 0 var(--s-2);
  font-size: 0.8125rem;
}
.level-strip b { color: #fff; font-weight: 600; }
.level-strip .gold-num { color: var(--gold); font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 700; }
.level-strip .focus { flex: 1 1 20rem; min-width: 16rem; }

.tbl-wrap { overflow-x: auto; }
table.arsenal { border-collapse: collapse; width: 100%; font-size: 0.8125rem; min-width: 43.75rem; }
.arsenal th {
  text-align: left;
  font-size: 0.625rem;
  text-transform: uppercase;
  letter-spacing: .09em;
  font-weight: 700;
  color: var(--sub-2);
  border-bottom: 1px solid var(--line-strong);
  padding: var(--s-2) var(--s-2);
  white-space: nowrap;
}
.arsenal td { padding: var(--s-2) var(--s-2); border-bottom: 1px solid var(--line-soft); white-space: nowrap; }
.arsenal tbody tr:last-child td { border-bottom: 0; }
.arsenal td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.01em; color: var(--ink-2); }
.arsenal .ptype { font-weight: 600; color: var(--ink); }
.arsenal .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: var(--s-2); }

.charts-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); }
.chart-card h3 {
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .055em;
  line-height: 1.2;
  color: var(--navy);
  margin-bottom: 0;
}
.chart-card .hint { color: var(--sub); font-size: 0.75rem; margin-bottom: var(--s-2); }
.chart-card svg { width: 100%; height: auto; display: block; }

.dev-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); gap: var(--s-3); }
.dev-card { border-left: 3px solid var(--line); }
.dev-card .dev-head { display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-2); }
.dev-card .dev-pitch {
  font-family: var(--display); font-weight: 700; font-size: 1.125rem;
  text-transform: uppercase; letter-spacing: .03em; color: var(--navy);
}
.dev-card .sens {
  font-size: 0.6875rem; color: var(--sub); font-family: var(--mono);
  font-variant-numeric: tabular-nums; margin: var(--s-1) 0 var(--s-2);
}
.lever { padding: var(--s-2) 0; border-top: 1px solid var(--line-soft); }
.lever-title { font-weight: 600; font-size: 0.8125rem; }
.lever-title .gain { color: var(--green); font-variant-numeric: tabular-nums; }
.lever-cue { color: var(--sub); font-size: 0.75rem; line-height: 1.5; }

.bp-head { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-1); }
.bp-name {
  font-family: var(--display); font-weight: 700; font-size: 1.5rem;
  text-transform: uppercase; letter-spacing: .02em; line-height: 1.1; color: var(--navy);
}
.bp-phil { color: var(--sub); font-size: 0.8125rem; line-height: 1.55; margin-bottom: var(--s-3); max-width: 70ch; }
.bp-item { display: flex; gap: var(--s-3); padding: var(--s-2) 0; border-top: 1px solid var(--line-soft); font-size: 0.8125rem; }
.bp-check { font-weight: 700; width: 1.125rem; flex: none; text-align: center; }
.bp-check.yes { color: var(--green); }
.bp-check.no { color: var(--amber); }
.bp-target { color: var(--sub); }

.notes-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(17.5rem, 1fr)); gap: var(--s-3); }
.note-card {
  border-radius: var(--r-card);
  border: 1px solid var(--line);
  background: var(--card);
  padding: var(--s-3) var(--s-4);
  box-shadow: var(--elev-1);
}
.note-kind { font-size: 0.625rem; font-weight: 700; text-transform: uppercase; letter-spacing: .11em; margin-bottom: var(--s-1); }
.note-kind.strength { color: var(--green); }
.note-kind.fix { color: var(--amber); }
.note-kind.note { color: var(--sub-2); }
.note-title { font-weight: 700; font-size: 0.8125rem; margin-bottom: 2px; letter-spacing: -.005em; }
.note-body { font-size: 0.75rem; line-height: 1.55; color: var(--ink-2); }

.bias-why { margin-top: var(--s-2); }
.bias-why li { list-style: none; font-size: 0.8125rem; line-height: 1.5; padding: var(--s-1) 0 var(--s-1) var(--s-4); position: relative; }
.bias-why li::before { content: "\25CF"; color: var(--gold); position: absolute; left: 0; font-size: 8px; top: 9px; }
.bias-caveat { font-size: 0.6875rem; line-height: 1.55; color: var(--sub-2); margin-top: var(--s-2); }

/* ---------------- arm slot & release panel ---------------- */

.slot-panel {
  background: var(--navy);
  border-radius: var(--r-card);
  padding: var(--s-4);
  display: grid;
  grid-template-columns: 11.875rem 16.25rem 1fr;
  gap: var(--s-4);
  align-items: start;
}
/* Cap both graphics: stretched to a full grid column the release scatter
   balloons, which is exactly the "tight cluster" signal we're trying to show. */
.slot-panel .slot-figure svg { width: 100%; max-width: 11.25rem; height: auto; display: block; }
.slot-panel .slot-release svg { width: 100%; max-width: 15.625rem; height: auto; display: block; }
.slot-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.25rem, 1fr));
  gap: var(--s-2);
}
.slot-tile {
  background: var(--navy-3);
  border: 1px solid rgba(255, 255, 255, .09);
  border-radius: var(--r-tile);
  padding: var(--s-2) var(--s-3);
}
.slot-tile .st-l { font-size: 0.625rem; color: #93AAC7; letter-spacing: .07em; text-transform: uppercase; font-weight: 600; }
.slot-tile .st-v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 0.9375rem; font-weight: 700; color: #fff; margin-top: 2px; letter-spacing: -.01em;
}
.slot-tile .st-pm { font-size: 0.6875rem; color: #93AAC7; font-weight: 400; }
.slot-note { grid-column: 1 / -1; font-size: 0.6875rem; line-height: 1.55; color: #93AAC7; }

/* ---------------- chart headings, legend, zones ---------------- */

.chart-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); margin-bottom: var(--s-2); }
.hint-inline {
  font-family: var(--body); font-size: 0.6875rem; font-weight: 400;
  color: var(--sub-2); text-transform: none; letter-spacing: .01em;
}
.zone-toggle {
  border: 1px solid var(--line);
  background: var(--surface-3);
  color: var(--sub);
  border-radius: var(--r-ctl);
  padding: 0 var(--s-3);
  min-height: var(--ctl-h);
  display: inline-flex;
  align-items: center;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}
.zone-toggle:hover { border-color: var(--line-strong); color: var(--ink-2); }
.zone-toggle.on { background: var(--amber-bg); border-color: var(--gold-line); color: var(--gold-ink); }
.legend { display: flex; flex-wrap: wrap; gap: var(--s-3); margin: var(--s-2) 0 var(--s-1); }
.lg-item { display: flex; align-items: center; gap: var(--s-1); font-size: 0.6875rem; color: var(--sub); font-weight: 500; }
.lg-item .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.title-note {
  font-family: var(--body); font-size: 0.75rem; font-weight: 400;
  color: var(--sub-2); text-transform: none; letter-spacing: 0;
}

/* Explanatory copy: the quietest text in the app, and the one place leading
   opens up, because it is read in sentences rather than scanned. */
.hint { color: var(--sub); font-size: 0.75rem; line-height: 1.6; }

/* ---------------- bias card ---------------- */

.bias-call {
  font-family: var(--display); font-weight: 700; font-size: 1.625rem;
  text-transform: none; letter-spacing: -.015em; line-height: 1.1;
  color: var(--navy); margin-bottom: var(--s-2);
}
.eff-bar { margin-bottom: var(--s-2); }
.eff-track { display: flex; height: 10px; border-radius: var(--r-pill); overflow: hidden; }
.eff-seg { display: block; }
.eff-labels { display: flex; justify-content: space-between; gap: var(--s-2); font-size: 0.6875rem; margin-top: var(--s-1); flex-wrap: wrap; }
.eff-labels .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink); }
.axis-dev { font-size: 0.8125rem; color: var(--ink-2); margin-bottom: var(--s-2); }

/* ---------------- projector ---------------- */

.proj-level { display: flex; align-items: center; gap: var(--s-2); margin: var(--s-2) 0 var(--s-3); font-size: 0.8125rem; }
.lvl-select.light {
  background: var(--card); color: var(--ink);
  border-color: var(--line-strong);
}
.lvl-select.light:hover { border-color: var(--navy-2); }

/* Grades live above the fold — watching them move IS the tool.
   Kept on the light card surface so the score colours (which are designed for
   light grounds) stay legible; on navy the darker bands sank into the panel. */
.proj-hero {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-4);
  box-shadow: var(--elev-1);
}
.ph-inner { display: flex; align-items: center; gap: var(--s-2) var(--s-5); flex-wrap: wrap; }

/* Cells keep their intrinsic width and the row wraps whole cells instead —
   otherwise the mono shape text gets squeezed and stacks one word per line. */
.ph-cell { display: flex; align-items: center; gap: var(--s-2); flex: 0 0 auto; }
.ph-label {
  font-size: 0.6875rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--sub-2); white-space: nowrap;
}
.ph-score {
  font-family: var(--display); font-weight: 700; font-size: 1.625rem; line-height: 1;
  letter-spacing: -.005em;
  padding: var(--s-1) var(--s-2); border-radius: var(--r-tile); white-space: nowrap;
}
.ph-shape {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 0.6875rem; color: var(--sub); white-space: nowrap;
}

/* Platoon sides. The stronger matchup is emphasised, since "who is this
   pitch actually for" is the coaching question. */
.ph-split {
  display: flex; flex-direction: column; gap: 1px;
  font-size: 0.625rem; color: var(--sub-2); white-space: nowrap;
  border-left: 1px solid var(--line); padding-left: var(--s-2);
}
.ph-split b { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 0.75rem; color: var(--ink-2); }
.ph-split b.hi { color: var(--navy); }

.ph-meta { margin-left: auto; font-size: 0.6875rem; color: var(--sub-2); white-space: nowrap; }
.ph-meta b { color: var(--ink); }

/* On a phone there is not enough width for a whole cell on one line, and the
   rule above — cells at intrinsic width, the ROW wrapping between them — made
   the page scroll sideways instead, clipping the shape text mid-sentence.
   Below this width each pitch takes its own row and the shape text moves to a
   line of its own inside it. That keeps the reason for the original rule: the
   mono text still gets a full line to itself and never stacks one word high. */
@media (max-width: 560px) {
  .ph-cell { flex: 1 1 100%; flex-wrap: wrap; }
  .ph-shape { flex: 1 0 100%; }
  .ph-meta { margin-left: 0; }
}

.ps-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }

/* Velocity + spin lock */
.lock-group {
  position: relative; border-left: 2px solid transparent;
  padding-left: var(--s-3); margin-left: calc(var(--s-3) * -1 - 2px);
  transition: border-color 150ms var(--ease-out);
}
.lock-group.locked { border-left-color: var(--gold); }
.lock-btn {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-ctl);
  padding: 0 var(--s-3); min-height: var(--ctl-h);
  display: inline-flex; align-items: center; gap: var(--s-1);
  font-size: 0.75rem; font-weight: 600; color: var(--sub);
  margin-bottom: var(--s-2); white-space: nowrap;
}
.lock-btn:hover { border-color: var(--line-strong); color: var(--ink-2); }
.lock-btn.on { background: var(--amber-bg); border-color: var(--gold-line); color: var(--gold-ink); }
.lock-note { font-size: 0.6875rem; color: var(--sub); margin: 0 0 var(--s-3); line-height: 1.55; }
.lock-note b { color: var(--ink); font-family: var(--mono); font-variant-numeric: tabular-nums; }

.proj-grid { display: grid; grid-template-columns: 20rem 1fr; gap: var(--s-4); align-items: start; }
.slider-row { margin-bottom: var(--s-3); }
.slider-row .sl-head { display: flex; justify-content: space-between; align-items: baseline; font-size: 0.8125rem; margin-bottom: var(--s-1); }
.slider-row .sl-val {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-weight: 700; color: var(--navy); letter-spacing: -.01em;
}
.slider-row input[type="range"] { width: 100%; accent-color: var(--navy); }

/* Segmented control: one continuous surface, dividers between segments rather
   than a border around each — the selected segment is the only filled thing. */
.seg {
  display: flex; border: 1px solid var(--line); border-radius: var(--r-ctl);
  overflow: hidden; margin-bottom: var(--s-3); background: var(--surface-3);
}
.seg button {
  flex: 1; padding: 0 var(--s-3); min-height: var(--ctl-h);
  background: transparent; border: none; border-left: 1px solid var(--line);
  font-weight: 600; font-size: 0.8125rem; color: var(--sub);
}
.seg button:first-child { border-left: 0; }
.seg button:hover { color: var(--ink-2); background: rgba(0, 33, 69, .04); }
.seg button.on { background: var(--navy); color: #fff; border-left-color: var(--navy); }
.seg button.on:hover { background: var(--navy-2); }

/* ---------------- glossary ---------------- */

.gloss { display: grid; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); gap: var(--s-4) var(--s-5); }
.gloss dt {
  font-weight: 700; font-family: var(--display); font-size: 1rem;
  text-transform: uppercase; letter-spacing: .04em; color: var(--navy);
}
.gloss dd { color: var(--ink-2); font-size: 0.8125rem; line-height: 1.55; margin-top: 2px; }

/* Shown only when scripts don't run — a preview pane, or JS disabled.
   Without this the page is genuinely blank, since every report is built in JS. */
.noscript-note {
  max-width: 40rem;
  margin: var(--s-8) auto;
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 4px solid var(--gold);
  border-radius: var(--r-card);
  padding: var(--s-5) var(--s-6);
  box-shadow: var(--elev-1);
}
.noscript-note h2 {
  font-family: var(--display);
  font-size: 1.375rem;
  text-transform: uppercase;
  letter-spacing: .045em;
  color: var(--navy);
  margin-bottom: var(--s-2);
}
.noscript-note p { margin-bottom: var(--s-2); color: var(--ink-2); }

/* ---------------- pitch-type map ---------------- */

.am-controls {
  display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; margin-bottom: var(--s-3);
}
.am-controls .seg { flex: 0 0 auto; width: 9.375rem; margin: 0; }
.am-controls .lock-btn { margin: 0; flex: 0 0 auto; }
.am-filter { display: flex; gap: var(--s-1); flex-wrap: wrap; margin-left: auto; }

/* Hover readout — fixed minimum height so the chart never shifts under the
   cursor as names appear and disappear. */
.am-readout {
  display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap;
  min-height: 2.25rem; padding: var(--s-2) var(--s-3); margin-bottom: var(--s-3);
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-tile);
}
.am-ro-empty { font-size: 0.75rem; color: var(--sub-2); }
.am-ro-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; align-self: center; }
.am-ro-name { font-size: 0.875rem; color: var(--ink); letter-spacing: -.005em; }
.am-ro-nums { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 0.6875rem; color: var(--sub); }
.am-ro-note { font-size: 0.75rem; line-height: 1.55; color: var(--ink-2); flex: 1 1 100%; }
.am-filter button {
  display: inline-flex; align-items: center; gap: var(--s-1);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 0 var(--s-3); min-height: var(--ctl-h);
  font-size: 0.75rem; font-weight: 600; color: var(--sub); white-space: nowrap;
}
.am-filter button:hover { border-color: var(--line-strong); color: var(--ink-2); }
.am-filter button.on { background: var(--navy); border-color: var(--navy); color: #fff; }
.am-filter .dot { width: 7px; height: 7px; border-radius: 50%; }

.am-group { margin-bottom: var(--s-5); }
.am-group-head {
  display: flex; align-items: center; gap: var(--s-2);
  font-family: var(--display); font-weight: 700; font-size: 0.9375rem;
  text-transform: uppercase; letter-spacing: .055em; color: var(--navy);
  margin-bottom: var(--s-2);
}
.am-group-head .dot { width: 9px; height: 9px; border-radius: 50%; }
.am-table { min-width: 40rem; }
.am-table td.am-note { white-space: normal; color: var(--sub); font-size: 0.75rem; line-height: 1.5; min-width: 16.25rem; }

/* ---------------- fastball profile ---------------- */

.ff-card { border-left-color: var(--red); }
.ff-borderline {
  font-size: 0.75rem; line-height: 1.55; color: var(--gold-ink); background: var(--amber-bg);
  border: 1px solid var(--gold-line); border-radius: var(--r-tile);
  padding: var(--s-2) var(--s-3); margin-bottom: var(--s-3);
}
.ch-axis.ff-above { border-color: #A8D8BF; background: var(--green-bg); }
.ch-axis.ff-above .ch-axis-v { color: var(--green); }
.ff-slot-note { font-size: 0.8125rem; line-height: 1.6; color: var(--ink-2); max-width: 72ch; margin-bottom: var(--s-2); }
.ff-examples { font-size: 0.75rem; color: var(--sub); margin-bottom: var(--s-2); }
.ff-examples b { color: var(--ink-2); }

/* ---------------- changeup profile ---------------- */

.ch-card { border-left: 3px solid var(--pink); }
.ch-head { display: flex; align-items: baseline; gap: var(--s-3); flex-wrap: wrap; margin-bottom: var(--s-3); }
.ch-name {
  font-family: var(--display); font-weight: 700; font-size: 1.5rem;
  text-transform: uppercase; letter-spacing: .02em; line-height: 1.1; color: var(--navy);
}
.ch-usage { font-size: 0.6875rem; color: var(--sub-2); margin-left: auto; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.chip.ch-verdict { text-transform: uppercase; }
.chip.ch-verdict.elite,
.chip.ch-verdict.excellent { background: var(--green-bg); color: var(--green); border-color: #A8D8BF; }
.chip.ch-verdict.good { background: var(--selected); color: var(--navy-2); border-color: #B9CCE3; }
.chip.ch-verdict.average,
.chip.ch-verdict.fair { background: var(--amber-bg); color: var(--gold-ink); border-color: var(--gold-line); }
.chip.ch-verdict.poor,
.chip.ch-verdict.worst { background: var(--red-bg); color: var(--red); border-color: #E4A9A9; }

.ch-axes { display: grid; grid-template-columns: repeat(auto-fit, minmax(13.75rem, 1fr)); gap: var(--s-2); margin-bottom: var(--s-3); }
.ch-axis { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-tile); padding: var(--s-3); }
.ch-axis-l { font-size: 0.625rem; text-transform: uppercase; letter-spacing: .09em; font-weight: 600; color: var(--sub-2); }
.ch-axis-v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.375rem; font-weight: 700; color: var(--ink); margin: 2px 0; letter-spacing: -.02em;
}
.ch-axis-v span { font-size: 0.8125rem; color: var(--sub); font-weight: 400; letter-spacing: 0; }
.ch-axis-b { font-size: 0.6875rem; line-height: 1.5; color: var(--sub-2); }
.ch-summary { font-size: 0.875rem; line-height: 1.6; max-width: 72ch; }
.ch-fix { font-size: 0.8125rem; line-height: 1.6; color: var(--ink-2); max-width: 72ch; margin-top: var(--s-2); }

/* ---------------- hitting ---------------- */

.hcard { border-top-color: var(--green); }
.damage-line { display: flex; align-items: center; gap: var(--s-2); margin: 2px 0 var(--s-3); }
.damage-lab { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: .07em; color: var(--sub-2); font-weight: 700; }

.damage-hero {
  display: grid;
  grid-template-columns: auto auto auto 1fr;
  gap: var(--s-4);
  align-items: center;
  background: var(--navy);
  border-radius: var(--r-card);
  padding: var(--s-4) var(--s-5);
  margin-bottom: var(--s-2);
}
.dh-score { text-align: center; }
.dh-num {
  font-family: var(--display);
  font-weight: 700;
  font-size: 2.875rem;
  line-height: 1;
  letter-spacing: -.01em;
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-tile);
  display: block;
}
.dh-lab { font-size: 0.625rem; text-transform: uppercase; letter-spacing: .1em; color: #93AAC7; margin-top: var(--s-1); font-weight: 600; }
.dh-arrow { color: #5D7DA6; font-size: 1.375rem; }
.dh-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: var(--s-2); }

.comp-row { padding: var(--s-3) 0; border-bottom: 1px solid var(--line-soft); }
.comp-row:last-child { border-bottom: 0; }
.comp-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-2); margin-bottom: var(--s-2); }
.comp-label { font-weight: 600; font-size: 0.875rem; letter-spacing: -.005em; }
.comp-weight { font-size: 0.6875rem; color: var(--sub-2); text-transform: uppercase; letter-spacing: .07em; font-weight: 600; }
.comp-track {
  position: relative; height: 8px; background: var(--line-soft);
  border-radius: var(--r-pill); overflow: visible;
  box-shadow: inset 0 0 0 1px rgba(0, 33, 69, .03);
}
.comp-fill { display: block; height: 100%; border-radius: var(--r-pill); }
.comp-target {
  position: absolute; top: -4px; width: 2px; height: 16px;
  background: var(--navy); border-radius: 1px;
}
.comp-foot {
  display: flex; justify-content: space-between; gap: var(--s-2);
  font-size: 0.6875rem; color: var(--sub); margin-top: var(--s-1); flex-wrap: wrap;
}
.comp-foot .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink); }
.comp-foot .pos { color: var(--green); font-weight: 700; }
.comp-foot .neg { color: var(--amber); font-weight: 700; }

/* ---------------- responsive ---------------- */

@media (max-width: 980px) {
  .slot-panel { grid-template-columns: 9.375rem 1fr; }
  .slot-tiles { grid-column: 1 / -1; }
}
@media (max-width: 900px) {
  .brand-sub { display: none; }
  /* Hidden from view, not from assistive tech: display:none would drop the
     select's accessible name along with the visible text. This keeps the
     label in the accessibility tree while taking up no visual space. */
  .lvl-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
}
@media (max-width: 860px) {
  .charts-row { grid-template-columns: 1fr; }
  .proj-grid { grid-template-columns: 1fr; }
}
@media (max-width: 780px) {
  .damage-hero { grid-template-columns: auto auto auto; }
  .dh-tiles { grid-column: 1 / -1; }
}

/* Phone: the header was taking a fifth of the screen because five nav items
   wrapped onto three rows. Brand and level pickers hold row one; the nav gets
   row two to itself and scrolls sideways. Every destination stays a tap away —
   no hamburger, no hidden pages — and the header halves in height. */
@media (max-width: 760px) {
  .topbar {
    padding: var(--s-2) var(--s-3);
    gap: var(--s-2);
    row-gap: var(--s-2);
    min-height: 0;
  }
  .brand-logo { width: 1.875rem; height: 1.875rem; }
  .brand-title { font-size: 1.0625rem; }
  .brand { gap: var(--s-2); }
  .topbar-right { gap: var(--s-1); }
  .lvl-select { font-size: 0.75rem; padding: 2px var(--s-1); min-height: 1.75rem; max-width: 7rem; }

  .topnav {
    order: 3;
    flex: 1 0 100%;
    margin: 0 calc(var(--s-3) * -1);
    padding: 0 var(--s-3);
    overflow-x: auto;
    flex-wrap: nowrap;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    /* Fade at both ends so a cut-off item reads as "scroll", not as "broken". */
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--s-3), #000 calc(100% - var(--s-3)), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 var(--s-3), #000 calc(100% - var(--s-3)), transparent 100%);
  }
  .topnav::-webkit-scrollbar { display: none; }
  .topnav a { white-space: nowrap; flex: none; padding: var(--s-2) var(--s-3); }
  /* The mask above only reads as "scroll" once an item is actually caught
     mid-fade at the edge — the nav items happen to end almost flush with the
     container here, so nothing is ever visibly cut off and the hint never
     fires. A standing vignette after the last item is a simpler, reliable
     "this strip scrolls" cue that doesn't depend on exactly where the items
     happen to land. */
  .topnav::after {
    content: "";
    display: block;
    order: 99;
    flex: none;
    align-self: stretch;
    width: 1.25rem;
    pointer-events: none;
    background: linear-gradient(to right, transparent, rgba(0, 22, 46, .85));
  }

  main { padding: var(--s-5) var(--s-4) var(--s-7); }
  .foot { padding: var(--s-3) var(--s-4) var(--s-6); }
  .section-title { margin-top: var(--s-6); }
  .card { padding: var(--s-3) var(--s-4); }
  .report-name { font-size: 2rem; }
  /* Buttons run left-to-right from the prompt instead of hugging the right
     edge, so a wrapped third button lines up under the first two. */
  .upload-zone { justify-content: flex-start; }
  .upload-actions { margin-left: 0; justify-content: flex-start; flex: 1 0 100%; }
}
@media (max-width: 560px) {
  .slot-panel { grid-template-columns: 1fr; }
  .demo-banner { flex-direction: column; gap: 0; }
}
@media (max-width: 460px) {
  .damage-hero { grid-template-columns: 1fr 1fr; }
  .dh-arrow { display: none; }
}

/* ---------------- sign in ----------------
   The signed-out screens hide the chrome entirely: no nav, no level pickers,
   nothing that implies a page the visitor cannot reach. */

body.signed-out .topnav,
body.signed-out .topbar-right { display: none; }
body.signed-out .topbar { justify-content: center; }
body.signed-out main { padding-top: var(--s-8); }

.auth-wrap { max-width: 24rem; margin: 0 auto; }
.auth-card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: var(--s-6) var(--s-5); box-shadow: var(--elev-1); text-align: center;
}
.auth-logo { width: 3.25rem; height: 3.25rem; border-radius: var(--r-tile); margin-bottom: var(--s-3); }
.auth-title {
  font-family: var(--display); text-transform: uppercase; letter-spacing: .04em;
  font-size: 1.625rem; font-weight: 700; color: var(--navy); line-height: 1.1; margin-bottom: var(--s-2);
}
.auth-sub { font-size: 0.8125rem; color: var(--sub); line-height: 1.55; margin-bottom: var(--s-5); }
.auth-sub b { color: var(--ink); }
.auth-id { font-family: var(--mono); font-size: 0.75rem; color: var(--navy-2); }

.auth-form { display: flex; flex-direction: column; gap: var(--s-3); text-align: left; }
.auth-field { display: flex; flex-direction: column; gap: var(--s-1); }
.auth-field > span {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--sub);
}
.auth-field input {
  font-family: var(--body); font-size: 0.9375rem; color: var(--ink);
  background: var(--surface-2); border: 1px solid var(--line-strong);
  border-radius: var(--r-ctl); padding: 0 var(--s-3); min-height: var(--ctl-h-lg);
  width: 100%;
}
.auth-field input:focus { border-color: var(--navy-2); background: var(--card); }
.auth-field small { font-size: 0.6875rem; color: var(--sub-2); }
.auth-submit { width: 100%; justify-content: center; margin-top: var(--s-2); }

.auth-error {
  background: var(--red-bg); border: 1px solid #E4A9A9; color: var(--red);
  border-radius: var(--r-ctl); padding: var(--s-2) var(--s-3);
  font-size: 0.8125rem; line-height: 1.45;
}
.auth-alt { margin-top: var(--s-4); font-size: 0.75rem; color: var(--sub); }
.auth-foot {
  margin-top: var(--s-4); font-size: 0.6875rem; line-height: 1.55;
  color: var(--sub-2); text-align: center;
}

/* Who is signed in, and the way out. */
.whoami { display: flex; align-items: center; gap: var(--s-2); }
.whoami-role {
  font-size: 0.625rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  color: var(--navy); background: var(--gold); border-radius: var(--r-pill);
  padding: 2px var(--s-2); line-height: 1.5;
}
.whoami-email { font-size: 0.6875rem; color: #A9BCD4; font-family: var(--mono); }
.whoami .btn { min-height: 1.75rem; font-size: 0.6875rem; padding: 0 var(--s-2); }
@media (max-width: 760px) { .whoami-email { display: none; } }

/* ---------------- reduced motion / transparency ----------------
   Reduced motion does not mean no feedback. Presses still acknowledge, they
   just stop moving: the scale becomes a dim. Chart redraws stop travelling
   across the plot (flipRedraw in dom.js checks the same query and skips
   straight to the new frame). */

@media (prefers-reduced-motion: reduce) {
  .btn, .seg button, .am-filter button, .zone-toggle, .lock-btn,
  .topnav a, .brand, .pcard, .lock-group { transition-duration: 1ms; }

  .btn:active, .seg button:active, .am-filter button:active,
  .zone-toggle:active, .lock-btn:active, .topnav a:active,
  .brand:active, .pcard:hover, .pcard:active { transform: none; }

  /* The press still reads, as a darkening rather than a movement. */
  .btn:active, .seg button:active, .am-filter button:active,
  .zone-toggle:active, .lock-btn:active, .brand:active { filter: brightness(.92); }

  .am-dot, .am-label, .pp-dot, .pp-label { transition: none !important; }
}

/* The header is the one genuinely translucent surface, so it goes solid first;
   the tinted panels lose their transparency-adjacent softness alongside it. */
@media (prefers-reduced-transparency: reduce) {
  .topbar {
    background: var(--navy);
    -webkit-backdrop-filter: none;
            backdrop-filter: none;
  }
  .topnav a:hover { background: var(--navy-3); }
  .lvl-select { background: var(--navy-2); border-color: #2A4F80; }
  .am-readout, .ch-axis { background: var(--card); }
}

/* ---------------- print ---------------- */

@page { size: letter; margin: 0.5in 0.55in; }

@media print {
  body { background: #fff; font-size: 12px; }
  .no-print, .topbar, .foot, .report-actions { display: none !important; }
  main { max-width: none; padding: 0; }
  .card { box-shadow: none; border-color: #BBB; break-inside: avoid; }
  .pcard, .note-card, .proj-hero { box-shadow: none; }
  .section-title { break-after: avoid; margin-top: 18px; }
  .charts-row { grid-template-columns: 1fr 1fr; }
  .dev-grid, .notes-grid { grid-template-columns: 1fr 1fr; }
  .report-name { font-size: 30px; }
  .level-strip, .slot-panel, .damage-hero {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .damage-hero { break-inside: avoid; }
  .slot-panel { break-inside: avoid; }
  .zone-toggle { display: none !important; }
  .arsenal th { color: #333; }
  a { text-decoration: none; color: inherit; }
  .print-footer { display: block !important; }
}

.print-footer {
  display: none;
  margin-top: var(--s-5);
  padding-top: var(--s-2);
  border-top: 1px solid #BBB;
  font-size: 9.5px;
  color: #555;
  font-family: var(--mono);
}

/* The stable id, kept beside a coach-visible name on roster cards. */
.pcard-id { font-family: var(--mono); letter-spacing: 0; color: var(--navy-2); }

/* A player has no roster, so the report's way back to one is meaningless.
   Their profile IS the landing page. */
body.role-player .report-actions a[href="#"] { display: none; }

/* ---------------- roster admin ----------------
   A working table, not a report: controls sit inline in the row because the
   coach's task is scanning for who still needs an invite and acting on the spot. */

.adm-add { margin-bottom: var(--s-4); }
.adm-add-form { display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: flex-end; }
.adm-f { display: flex; flex-direction: column; gap: var(--s-1); }
.adm-f > span {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--sub);
}
.adm-f input[type="text"] {
  font-family: var(--body); font-size: 0.875rem; color: var(--ink);
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--r-ctl); padding: 0 var(--s-3); min-height: var(--ctl-h);
  min-width: 14rem;
}
.adm-f-check { align-self: center; padding-bottom: var(--s-1); }
.adm-note { font-size: 0.75rem; color: var(--sub-2); margin-top: var(--s-3); max-width: 70ch; }

.adm-msg { font-size: 0.8125rem; margin-top: var(--s-3); }
.adm-msg:empty { display: none; }
.adm-msg.ok { color: var(--green); }
.adm-msg.bad { color: var(--red); }

.adm-table td { vertical-align: middle; white-space: nowrap; }
.adm-table .lvl-select { min-height: 1.75rem; font-size: 0.75rem; }
.adm-name { font-weight: 600; }
.adm-sub { display: block; font-size: 0.6875rem; color: var(--sub-2); }
.adm-check { display: inline-flex; align-items: center; gap: var(--s-1); font-size: 0.75rem; color: var(--sub); }
.adm-check input { accent-color: var(--navy); }

/* Inactive athletes stay visible but recede — they are history, not noise. */
.row-off { opacity: .55; }

/* Access is the widest column because it is the reason the page exists. */
.adm-access { white-space: normal; min-width: 20rem; }
.acc-state {
  display: inline-block; font-size: 0.625rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em; margin-right: var(--s-2);
}
.acc-state.on { color: var(--green); }
.acc-state.pending { color: var(--amber); }
.acc-state.off { color: var(--sub-2); }
.acc-state.minor { color: var(--sub-2); }
.acc-hint { font-size: 0.6875rem; color: var(--sub-2); margin-right: var(--s-2); }
.acc-code {
  font-family: var(--mono); font-size: 0.8125rem; font-weight: 700; letter-spacing: .04em;
  background: var(--amber-bg); border: 1px solid var(--gold-line); color: var(--gold-ink);
  border-radius: var(--r-ctl); padding: 1px var(--s-2); margin-right: var(--s-2);
}
.acc-btn { min-height: 1.75rem; font-size: 0.6875rem; padding: 0 var(--s-2); margin-right: var(--s-1); }

/* The code, once, big enough to read aloud without squinting. */
.invite-result {
  border: 1px solid var(--gold-line); background: var(--amber-bg);
  border-radius: var(--r-card); padding: var(--s-3) var(--s-4); margin-top: var(--s-2);
}
.ir-head { font-size: 0.8125rem; color: var(--gold-ink); }
.ir-code {
  font-family: var(--mono); font-size: 1.5rem; font-weight: 700; letter-spacing: .12em;
  color: var(--navy); margin: var(--s-2) 0; user-select: all;
}
.ir-note { font-size: 0.75rem; color: var(--gold-ink); line-height: 1.55; max-width: 60ch; }

/* ============================================================
   Phase 2 — the athlete's file
   Sub-tabs, session history, assessments and trends.
   ============================================================ */

/* ---------------- sub-tabs ----------------
   A second level of navigation under the top nav, so it is deliberately
   quieter: an underline rather than a filled pill, because two competing
   selected states on one screen makes neither read as current. */

.ptabs {
  display: flex;
  gap: var(--s-1);
  border-bottom: 1px solid var(--line);
  margin: var(--s-5) 0 var(--s-5);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.ptabs::-webkit-scrollbar { display: none; }

.ptab {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 0 var(--s-3);
  min-height: 2.5rem;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  color: var(--sub);
  font-weight: 600;
  font-size: 0.8125rem;
  white-space: nowrap;
  transition: color var(--t-press) var(--ease-out);
}
.ptab:hover { color: var(--ink-2); }
.ptab.on { color: var(--navy); border-bottom-color: var(--gold); }
.ptab-n {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
  color: var(--sub-2);
  background: var(--surface-3);
  border-radius: var(--r-pill);
  padding: 0 var(--s-2);
  line-height: 1.5;
}
.ptab.on .ptab-n { background: var(--selected); color: var(--navy-2); }

/* ---------------- session history rail ----------------
   The dates are the interface. Newest first and selected by default, because
   the commonest arrival is "we just did this". */

.hist-rail {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: var(--s-2) var(--s-3);
  margin-bottom: var(--s-3);
}
.hist-head { display: flex; align-items: baseline; gap: var(--s-2); }
.hist-label {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--sub-2);
}
.hist-count {
  font-family: var(--mono); font-size: 0.6875rem; color: var(--sub-2);
}
.hist-chips {
  display: flex; gap: var(--s-1); flex: 1; overflow-x: auto;
  -webkit-overflow-scrolling: touch; scrollbar-width: none; padding: 2px;
}
.hist-chips::-webkit-scrollbar { display: none; }

.hist-chip {
  display: inline-flex; flex-direction: column; align-items: flex-start;
  gap: 1px; padding: var(--s-1) var(--s-3);
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-ctl); color: var(--sub);
  white-space: nowrap; line-height: 1.2;
}
.hist-chip:hover { border-color: var(--line-strong); color: var(--ink-2); }
.hist-chip.on {
  background: var(--navy); border-color: var(--navy); color: #fff;
}
.hc-date { font-size: 0.8125rem; font-weight: 700; }
.hc-year { font-family: var(--mono); font-size: 0.625rem; opacity: .7; }
.hc-tag {
  font-size: 0.5625rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--gold-ink);
}
.hist-chip.on .hc-tag { color: var(--gold); }
.hist-del { min-height: 1.75rem; font-size: 0.6875rem; padding: 0 var(--s-2); }

/* What you are looking at, in one line under the rail. */
.sess-meta {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4);
  align-items: baseline; margin-bottom: var(--s-4); font-size: 0.75rem;
}
.sess-when { font-weight: 700; color: var(--navy); font-size: 0.875rem; }
.sess-cover, .sess-prev { color: var(--sub); }

/* ---------------- change marks ----------------
   Direction is the model's call, never the sign's: a sprint that got faster is
   a negative number and an improvement. */

.delta-since {
  font-family: var(--mono); font-size: 0.625rem; font-weight: 700;
  margin-left: 3px; letter-spacing: -.02em;
}
.delta-since.d-up { color: var(--green); }
.delta-since.d-down { color: var(--red); }

.chg {
  display: inline-flex; align-items: center;
  font-family: var(--mono); font-size: 0.75rem; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.chg.up { color: var(--green); }
.chg.down { color: var(--red); }
.chg.flat, .chg.none { color: var(--sub-2); font-family: var(--body); font-weight: 400; font-size: 0.6875rem; }

.trend-delta {
  font-family: var(--mono); font-size: 0.75rem; font-weight: 700;
  margin-left: auto; white-space: nowrap;
}
.trend-delta.up { color: var(--green); }
.trend-delta.down { color: var(--red); }

.trend-svg { width: 100%; height: auto; display: block; }
.trend-empty {
  color: var(--sub); font-size: 0.8125rem; line-height: 1.6;
  padding: var(--s-5) 0; text-align: center; max-width: 60ch; margin: 0 auto;
}
.spark { width: 4.875rem; height: 1.375rem; display: block; }
.spark-none { color: var(--sub-2); font-size: 0.75rem; }

/* ---------------- movement screen ---------------- */

.scr-pill {
  display: inline-flex; align-items: center;
  font-size: 0.625rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; padding: 1px var(--s-2);
  border-radius: var(--r-pill); border: 1px solid var(--line);
  background: var(--surface-3); color: var(--sub-2);
}
.scr-pill.green { background: var(--green-bg); border-color: #A8D8BF; color: var(--green); }
.scr-pill.yellow { background: var(--amber-bg); border-color: var(--gold-line); color: var(--gold-ink); }
.scr-pill.red { background: var(--red-bg); border-color: #E4A9A9; color: var(--red); }

.scr-tally {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: var(--s-3); margin-bottom: var(--s-3);
}
.scr-t-cell {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: var(--s-3) var(--s-4); display: flex; flex-direction: column; gap: 2px;
}
.scr-t-cell.wide { grid-column: span 2; }
.scr-t-cell span { font-size: 0.75rem; color: var(--sub); }
.scr-n {
  font-family: var(--display); font-size: 1.625rem; font-weight: 700;
  line-height: 1; color: var(--navy);
}
.scr-n.green { color: var(--green); }
.scr-n.yellow { color: var(--amber); }
.scr-n.red { color: var(--red); }

.scr-asym { border-left: 3px solid var(--amber); margin-bottom: var(--s-3); }
.scr-asym-head {
  font-family: var(--display); font-size: 1rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--navy);
  display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-2);
}
.scr-asym-row {
  display: grid; grid-template-columns: minmax(9rem, 1fr) auto; gap: var(--s-1) var(--s-3);
  padding: var(--s-2) 0; border-top: 1px solid var(--line-soft);
}
.scr-asym-name { font-weight: 600; font-size: 0.8125rem; color: var(--ink); }
.scr-asym-sides { font-size: 0.6875rem; color: var(--sub-2); display: flex; gap: var(--s-2); align-items: center; }
.scr-asym-why { grid-column: 1 / -1; font-size: 0.75rem; color: var(--sub); line-height: 1.55; }

.scr-card { padding: 0; overflow: hidden; }
.scr-group + .scr-group { border-top: 1px solid var(--line); }
.scr-group-head {
  background: var(--surface-2); padding: var(--s-2) var(--s-4);
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--sub-2);
}
.scr-row {
  display: grid; grid-template-columns: minmax(8rem, 1fr) auto;
  gap: var(--s-1) var(--s-3); padding: var(--s-3) var(--s-4);
  border-top: 1px solid var(--line-soft); border-left: 3px solid transparent;
}
.scr-row.yellow { border-left-color: var(--gold-line); }
.scr-row.red { border-left-color: var(--red); background: rgba(194, 68, 68, .025); }
.scr-name { font-weight: 600; font-size: 0.8125rem; color: var(--ink); }
.scr-codes { display: flex; gap: var(--s-2); align-items: center; }
.scr-side { font-size: 0.625rem; color: var(--sub-2); display: inline-flex; gap: 3px; align-items: center; }
.scr-why { grid-column: 1 / -1; font-size: 0.75rem; color: var(--sub); line-height: 1.55; max-width: 70ch; }

/* Every screen at once: tests down, dates across. A restriction that has been
   there all year looks completely different from one that just appeared. */
.scr-grid th:first-child { text-align: left; }
.scr-grid td { text-align: center; }
.grid-cell {
  display: inline-block; width: 1.125rem; height: 1.125rem;
  border-radius: 3px; border: 1px solid var(--line);
  background: var(--surface-3);
}
.grid-cell.green { background: var(--green); border-color: var(--green); }
.grid-cell.yellow { background: var(--gold); border-color: var(--gold); }
.grid-cell.red { background: var(--red); border-color: var(--red); }
.grid-cell.none { background: repeating-linear-gradient(45deg, #fff, #fff 3px, var(--surface-3) 3px, var(--surface-3) 6px); }

/* ---------------- measured tests ---------------- */

.kpi-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: var(--s-3); margin-bottom: var(--s-4);
}
.kpi-card {
  background: var(--card); border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--r-card); padding: var(--s-3) var(--s-4);
  box-shadow: var(--elev-1);
}
.kpi-card.elite { border-left-color: var(--green); }
.kpi-card.good { border-left-color: var(--navy-2); }
.kpi-card.fair { border-left-color: var(--gold); }
.kpi-card.poor { border-left-color: var(--red); }
.kpi-label {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--sub-2); margin-bottom: var(--s-1);
}
.kpi-value {
  font-family: var(--display); font-size: 1.75rem; font-weight: 700;
  line-height: 1; color: var(--navy); font-variant-numeric: tabular-nums;
}
.kpi-unit { font-size: 0.8125rem; color: var(--sub); margin-left: 3px; font-family: var(--body); font-weight: 400; }
.kpi-track {
  position: relative; height: 5px; border-radius: var(--r-pill);
  background: var(--surface-3); margin: var(--s-2) 0 var(--s-1); overflow: hidden;
}
.kpi-fill { display: block; height: 100%; background: var(--navy-2); border-radius: var(--r-pill); }
.kpi-mark {
  position: absolute; top: -2px; bottom: -2px; width: 2px;
  background: var(--gold-ink); opacity: .55;
}
.kpi-foot { font-size: 0.6875rem; color: var(--sub); }
.kpi-none { font-size: 0.6875rem; color: var(--sub-2); margin-top: var(--s-2); }
.kpi-band { font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }

.meas-group { margin-bottom: var(--s-4); }
.meas-group-head {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--sub-2); margin-bottom: var(--s-2);
}
.meas-table { min-width: 34rem; }
.meas-row { cursor: pointer; }
.meas-row:hover { background: var(--surface-2); }
.meas-row.on { background: var(--selected); }
.meas-row.on .meas-name { color: var(--navy); }
.meas-name { font-weight: 600; color: var(--ink); white-space: normal; max-width: 22rem; }
.meas-why {
  display: block; font-weight: 400; font-size: 0.6875rem;
  color: var(--sub-2); line-height: 1.45; margin-top: 2px;
}
.meas-val { font-family: var(--mono); font-weight: 700; color: var(--navy) !important; }
.meas-unit { font-family: var(--body); font-weight: 400; color: var(--sub-2); font-size: 0.6875rem; margin-left: 2px; }
.meas-spark { width: 5.5rem; }

/* ---------------- recording a session ---------------- */

.rec-form { margin-top: var(--s-6); }
.rec-head {
  display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: flex-end;
  justify-content: space-between; padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
}
.rec-title {
  font-family: var(--display); font-size: 1.125rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--navy);
}
.rec-blurb { font-size: 0.75rem; color: var(--sub); max-width: 62ch; line-height: 1.55; margin-top: 2px; }
.rec-date {
  display: flex; flex-direction: column; gap: var(--s-1);
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--sub-2);
}

.rec-group { border: 0; padding: 0; margin: var(--s-4) 0 0; }
.rec-group legend {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--sub-2); padding: 0;
}
.rec-fields {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--s-2) var(--s-4); margin-top: var(--s-2);
}
.rec-f {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3); padding: var(--s-1) 0; border-bottom: 1px solid var(--line-soft);
}
.rec-l { font-size: 0.8125rem; color: var(--ink-2); }
.rec-num { display: inline-flex; align-items: center; gap: var(--s-1); }
.rec-unit { font-size: 0.6875rem; color: var(--sub-2); min-width: 1.75rem; }
.rec-sides { display: inline-flex; align-items: center; gap: var(--s-1); }
.rec-side { font-size: 0.625rem; font-weight: 700; color: var(--sub-2); }

input.rec-in {
  width: 5rem; min-height: var(--ctl-h); text-align: right;
  border: 1px solid var(--line-strong); border-radius: var(--r-ctl);
  background: var(--card); color: var(--ink); font-family: var(--mono);
  font-size: 0.8125rem; padding: 0 var(--s-2);
}
input.rec-in:focus { outline: 2px solid var(--navy-2); outline-offset: 1px; }
select.rec-in { min-width: 6.5rem; }

.rec-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3);
  margin-top: var(--s-5); padding-top: var(--s-3); border-top: 1px solid var(--line);
}
.rec-note { font-size: 0.75rem; color: var(--sub); }

/* ---------------- overview ---------------- */

/* The development summary: what athleteSummary() already computes for the
   take-home sheet, read live. Same auto-fit approach as .ov-grid below it —
   three columns wide, one narrow, no separate breakpoint needed. */
.dev-summary {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--s-5) var(--s-6); margin-bottom: var(--s-4);
}
.dev-col { display: flex; flex-direction: column; gap: var(--s-3); min-width: 0; }
.dev-h {
  font-family: var(--display); font-size: 0.8125rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--navy); margin: 0;
}
.dev-h.good { color: var(--green); }
.dev-h.work { color: var(--amber); }
.dev-line { border-left: 3px solid var(--line); padding-left: var(--s-3); }
.dev-line.good { border-left-color: var(--green); }
.dev-line.work { border-left-color: var(--gold); }
.dev-line-h { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-2); }
.dev-line-t { font-weight: 700; font-size: 0.8125rem; color: var(--navy); }
.dev-line-a { font-size: 0.6875rem; color: var(--sub-2); white-space: nowrap; }
.dev-line-b { font-size: 0.75rem; color: var(--ink-2); line-height: 1.45; margin-top: 1px; }
.dev-steps { margin: 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: var(--s-3); }
.dev-steps li::marker { font-family: var(--display); font-weight: 700; color: var(--gold-ink); }
.dev-step-t { font-weight: 700; font-size: 0.8125rem; color: var(--navy); }
.dev-step-b { font-size: 0.75rem; color: var(--ink-2); line-height: 1.45; }
.dev-step-w { font-size: 0.6875rem; color: var(--sub); line-height: 1.4; margin-top: 1px; }

.ov-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--s-3);
}
.ov-card {
  text-align: left; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: var(--s-3) var(--s-4);
  box-shadow: var(--elev-1); display: flex; flex-direction: column; gap: var(--s-1);
  transition: border-color var(--t-press) var(--ease-out);
}
.ov-card:hover { border-color: var(--line-strong); }
.ov-card.empty { background: var(--surface-2); box-shadow: none; }
.ov-c-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-2); }
.ov-c-label {
  font-family: var(--display); font-size: 1.0625rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--navy);
}
.ov-c-n {
  font-family: var(--mono); font-size: 0.6875rem; color: var(--navy-2);
  background: var(--selected); border-radius: var(--r-pill); padding: 0 var(--s-2);
}
.ov-c-none { font-size: 0.6875rem; color: var(--sub-2); }
.ov-c-when { font-size: 0.75rem; color: var(--sub); }
.ov-c-lead { font-size: 0.875rem; font-weight: 600; color: var(--ink); }
.ov-delta { font-family: var(--mono); font-size: 0.75rem; font-weight: 700; }
.ov-delta.up { color: var(--green); }
.ov-delta.down { color: var(--red); }
.ov-flags { font-size: 0.75rem; color: var(--sub); display: flex; gap: var(--s-3); align-items: baseline; }
.ov-flags .scr-n { font-size: 1rem; }
.ov-head-metric { font-size: 0.75rem; color: var(--sub); }
.ov-head-metric b { font-family: var(--mono); color: var(--ink); }

.ov-arsenal { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: var(--s-2) var(--s-4); }
.ov-pitch { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-1) 0; }
.ov-pitch .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.ov-p-type { font-weight: 600; font-size: 0.8125rem; color: var(--ink); flex: 1; }
.ov-p-velo { font-family: var(--mono); font-size: 0.75rem; color: var(--sub); }

.ov-log { display: flex; flex-direction: column; }
.ov-log-row {
  display: flex; gap: var(--s-4); align-items: baseline; text-align: left;
  padding: var(--s-2) 0; border-bottom: 1px solid var(--line-soft);
  background: transparent; border-left: 0; border-right: 0; border-top: 0;
}
.ov-log-row:last-child { border-bottom: 0; }
.ov-log-row:hover .ov-log-what { color: var(--navy); }
.ov-log-when { font-family: var(--mono); font-size: 0.75rem; color: var(--sub); min-width: 8rem; }
.ov-log-what { font-weight: 600; font-size: 0.8125rem; color: var(--ink-2); }

/* ---------------- roster: athletes with no bullpen ---------------- */

.noball-list { padding: 0; overflow: hidden; }
.noball-row {
  display: flex; align-items: baseline; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line-soft);
  text-decoration: none;
}
.noball-row:hover { background: var(--surface-2); }
.noball-id { font-size: 0.75rem; color: var(--sub-2); min-width: 3.5rem; }
.noball-name { font-weight: 600; font-size: 0.875rem; color: var(--navy); flex: 1; }
.noball-meta { font-size: 0.75rem; color: var(--sub); }
.noball-list .hint { padding: var(--s-3) var(--s-4); }

/* ---------------- narrow screens ---------------- */

@media (max-width: 40rem) {
  .scr-t-cell.wide { grid-column: span 2; }
  .scr-row, .scr-asym-row { grid-template-columns: 1fr; }
  .scr-codes { justify-content: flex-start; }
  .rec-f { flex-wrap: wrap; }
  .ov-log-when { min-width: 6.5rem; }
  .hist-rail { padding: var(--s-2); }
  .meas-name { max-width: none; }
}

/* ============================================================
   The athlete sheet — three A4 pages that leave the building
   ============================================================ */

@page { size: A4 portrait; margin: 12mm; }

.sh-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4); flex-wrap: wrap;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: var(--s-3) var(--s-4); margin-bottom: var(--s-4);
}
.sh-bar-t {
  font-family: var(--display); font-size: 1.125rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--navy);
}
.sh-bar-n {
  display: block; font-family: var(--body); font-size: 0.75rem; font-weight: 400;
  text-transform: none; letter-spacing: 0; color: var(--sub); margin-top: 2px;
}

.sheets { display: flex; flex-direction: column; align-items: center; gap: var(--s-6); }

/* On screen a sheet is a real A4 page, so what you see is the pagination you
   get. Print strips the page furniture and lets @page own the margins. */
.sheet {
  width: 210mm;
  min-height: 297mm;
  padding: 12mm 14mm;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: var(--elev-2);
  color: #14202F;
  font-size: 9.5pt;
  line-height: 1.45;
  display: flex;
  flex-direction: column;
}

.sh-head {
  display: flex; align-items: center; gap: var(--s-4);
  border-bottom: 2px solid var(--navy); padding-bottom: var(--s-2); margin-bottom: var(--s-3);
}
.sh-logo { height: 34px; width: auto; }
.sh-who { flex: 1; }
.sh-name {
  font-family: var(--display); font-size: 20pt; font-weight: 700;
  text-transform: uppercase; letter-spacing: .02em; color: var(--navy); line-height: 1;
}
.sh-meta { font-size: 8.5pt; color: #5F6E85; margin-top: 2px; }
.sh-page { text-align: right; }
.sh-page-n {
  font-family: var(--mono); font-size: 7.5pt; text-transform: uppercase;
  letter-spacing: .08em; color: #7C8A9E;
}
.sh-page-t {
  font-family: var(--display); font-size: 12pt; font-weight: 700;
  text-transform: uppercase; letter-spacing: .03em; color: var(--gold-ink);
}

.sh-when { font-size: 8.5pt; color: #5F6E85; margin-bottom: var(--s-3); }

.sh-h2 {
  font-family: var(--display); font-size: 12pt; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--navy);
  margin: var(--s-4) 0 var(--s-2); padding-bottom: 2px;
  border-bottom: 1px solid #DEE5EE;
}
.sh-h2:first-of-type { margin-top: 0; }
.sh-h2.good { color: var(--green); border-bottom-color: #A8D8BF; }
.sh-h2.work { color: var(--amber); border-bottom-color: var(--gold-line); }

.sh-foot {
  margin-top: auto; padding-top: var(--s-2); border-top: 1px solid #DEE5EE;
  font-size: 7.5pt; color: #7C8A9E; font-family: var(--mono);
}
.sh-empty, .sh-none {
  font-size: 9pt; color: #5F6E85; padding: var(--s-3) 0; font-style: italic;
}

/* ---------------- page 1 ---------------- */

.sh-hero {
  background: var(--navy); color: #fff; border-radius: var(--r-card);
  padding: var(--s-3) var(--s-4); margin-bottom: var(--s-3);
}
.sh-hero-l {
  font-size: 7.5pt; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--gold); margin-bottom: 4px;
}
.sh-hero-row { display: flex; gap: var(--s-5); flex-wrap: wrap; align-items: flex-end; }
.sh-stat { display: flex; flex-direction: column; }
.sh-stat b { font-family: var(--display); font-size: 22pt; font-weight: 700; line-height: 1; }
.sh-stat span { font-size: 7.5pt; text-transform: uppercase; letter-spacing: .06em; color: #A9C0DC; margin-top: 2px; }
.sh-stat-score { margin-left: auto; text-align: right; }
.sh-stat-score b { color: var(--gold); }
.sh-hero-note { font-size: 8pt; color: #A9C0DC; margin-top: var(--s-2); }

.sh-table { width: 100%; border-collapse: collapse; font-size: 8.5pt; }
.sh-table th {
  text-align: left; font-size: 7.5pt; text-transform: uppercase; letter-spacing: .06em;
  color: #5F6E85; border-bottom: 1px solid #C9D4E1; padding: 3px 5px; font-weight: 700;
}
.sh-table td { padding: 4px 5px; border-bottom: 1px solid #EAEFF5; }
.sh-table .num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.sh-table th.num { text-align: right; }
.sh-pt { font-weight: 700; }
.sh-pt .dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; margin-right: 5px; }

.sh-chg { font-family: var(--mono); font-weight: 700; font-size: 8pt; }
.sh-chg.up { color: var(--green); }
.sh-chg.down { color: var(--red); }
.sh-chg.flat, .sh-chg.none { color: #7C8A9E; font-weight: 400; }

.sh-split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); margin-top: var(--s-3); }
.sh-plot svg { width: 100%; height: auto; }
.sh-caption { font-size: 7.5pt; color: #5F6E85; line-height: 1.5; margin-top: 4px; }

.sh-key dl { margin: 0; }
.sh-key dt {
  font-weight: 700; font-size: 8.5pt; color: var(--navy); margin-top: var(--s-2);
}
.sh-key dt:first-child { margin-top: 0; }
.sh-key dd { margin: 1px 0 0; font-size: 8pt; color: #2C3E55; line-height: 1.5; }
.sh-key-wide { margin-top: var(--s-4); }
.sh-key-wide dl { columns: 2; column-gap: var(--s-5); }
.sh-key-wide dd { break-inside: avoid; }

/* ---------------- page 2 ---------------- */

.sh-tally { display: flex; gap: var(--s-3); margin-bottom: var(--s-3); }
.sh-t {
  flex: 1; border: 1px solid #DEE5EE; border-radius: var(--r-tile);
  padding: 4px var(--s-3); display: flex; flex-direction: column;
}
.sh-t b { font-family: var(--display); font-size: 18pt; font-weight: 700; line-height: 1; color: var(--navy); }
.sh-t span { font-size: 7.5pt; text-transform: uppercase; letter-spacing: .06em; color: #5F6E85; }
.sh-t.green { border-left: 3px solid var(--green); } .sh-t.green b { color: var(--green); }
.sh-t.yellow { border-left: 3px solid var(--gold); } .sh-t.yellow b { color: var(--amber); }
.sh-t.red { border-left: 3px solid var(--red); } .sh-t.red b { color: var(--red); }

.sh-scr-list { columns: 2; column-gap: var(--s-5); }
.sh-scr-row {
  display: flex; justify-content: space-between; gap: var(--s-2);
  font-size: 8.5pt; padding: 2px 0 2px 5px; border-left: 3px solid #DEE5EE;
  break-inside: avoid; margin-bottom: 2px;
}
.sh-scr-row.green { border-left-color: var(--green); }
.sh-scr-row.yellow { border-left-color: var(--gold); }
.sh-scr-row.red { border-left-color: var(--red); background: #FAECEC; }
.sh-scr-name { color: #14202F; }
.sh-scr-code { color: #5F6E85; white-space: nowrap; font-size: 7.5pt; text-transform: uppercase; letter-spacing: .04em; }
.sh-scr-code em { font-style: normal; color: #7C8A9E; }

.sh-flag {
  border: 1px solid var(--gold-line); background: #FBF3DF;
  border-radius: var(--r-tile); padding: var(--s-2) var(--s-3);
  font-size: 8pt; line-height: 1.5; margin-top: var(--s-3); color: #4A3A10;
}

.sh-kpis { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2) var(--s-4); }
.sh-kpi { border-left: 3px solid #C9D4E1; padding-left: var(--s-2); break-inside: avoid; }
.sh-kpi.elite { border-left-color: var(--green); }
.sh-kpi.good { border-left-color: var(--navy-2); }
.sh-kpi.fair { border-left-color: var(--gold); }
.sh-kpi.poor { border-left-color: var(--red); }
.sh-kpi-top { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-2); }
.sh-kpi-l { font-size: 8pt; color: #2C3E55; }
.sh-kpi-v { font-family: var(--mono); font-size: 10pt; font-weight: 700; color: var(--navy); white-space: nowrap; }
.sh-kpi-v em { font-style: normal; font-size: 7.5pt; color: #7C8A9E; }
.sh-kpi-track {
  position: relative; height: 4px; border-radius: var(--r-pill);
  background: #EFF3F9; margin: 3px 0 2px; overflow: hidden;
}
.sh-kpi-fill { display: block; height: 100%; background: var(--navy-2); }
.sh-kpi-mark { position: absolute; top: -1px; bottom: -1px; width: 2px; background: var(--gold-ink); }
.sh-kpi-foot { font-size: 7pt; color: #7C8A9E; }

.sh-meas-cols { columns: 2; column-gap: var(--s-5); margin-top: var(--s-3); }
.sh-meas-group { break-inside: avoid; margin-bottom: var(--s-2); }
.sh-meas-group h3 {
  font-size: 7.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
  color: #7C8A9E; margin: 0 0 2px;
}
.sh-meas {
  display: flex; justify-content: space-between; gap: var(--s-2);
  font-size: 8.5pt; padding: 1px 0; border-bottom: 1px solid #EAEFF5;
}
.sh-meas-l { color: #2C3E55; }
.sh-meas-v { font-family: var(--mono); font-weight: 700; color: var(--navy); white-space: nowrap; }
.sh-meas-v em { font-style: normal; font-weight: 400; font-size: 7.5pt; color: #7C8A9E; margin-left: 1px; }

/* ---------------- page 3 ---------------- */

.sh-lines { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2) var(--s-4); }
.sh-line { border-left: 3px solid #DEE5EE; padding-left: var(--s-3); break-inside: avoid; }
.sh-line.good { border-left-color: var(--green); }
.sh-line.work { border-left-color: var(--gold); }
.sh-line-h { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-2); }
.sh-line-t { font-weight: 700; font-size: 9pt; color: var(--navy); }
.sh-line-a {
  font-size: 6.5pt; text-transform: uppercase; letter-spacing: .08em;
  color: #7C8A9E; white-space: nowrap;
}
.sh-line-b { font-size: 8pt; color: #2C3E55; line-height: 1.45; margin-top: 1px; }

.sh-steps { margin: 0; padding-left: 18px; }
.sh-steps li { margin-bottom: var(--s-3); break-inside: avoid; }
.sh-steps li::marker { font-family: var(--display); font-weight: 700; color: var(--gold-ink); }
.sh-step-t { font-weight: 700; font-size: 9.5pt; color: var(--navy); }
.sh-step-b { font-size: 8.5pt; color: #2C3E55; line-height: 1.45; }
.sh-step-w { font-size: 7.5pt; color: #7C8A9E; line-height: 1.4; margin-top: 1px; }

.sh-close {
  margin-top: var(--s-4); padding: var(--s-3);
  background: #F5F8FC; border-radius: var(--r-tile);
  font-size: 8pt; color: #2C3E55; line-height: 1.5;
}

/* ---------------- narrow screens ----------------
   A 210mm page does not fit a laptop column, let alone a phone. The preview
   reflows; @page still decides what actually prints. */

@media (max-width: 900px) {
  .sheet { width: 100%; min-height: 0; padding: var(--s-5); font-size: 0.875rem; }
  .sh-split, .sh-kpis, .sh-lines { grid-template-columns: 1fr; }
  .sh-scr-list, .sh-meas-cols, .sh-key-wide dl { columns: 1; }
  .sh-name { font-size: 1.375rem; }
  .sh-stat b { font-size: 1.5rem; }
}

/* ---------------- printing ---------------- */

@media print {
  /* On the sheet tab, the three pages are the whole document. */
  body.sheet-mode .report-head,
  body.sheet-mode .ptabs,
  body.sheet-mode .sh-bar,
  body.sheet-mode #foot { display: none !important; }

  body.sheet-mode .sheets { display: block; gap: 0; }
  body.sheet-mode .sheet {
    width: auto; min-height: 0; max-width: none;
    padding: 0; border: 0; box-shadow: none;
    break-after: page; page-break-after: always;
  }
  body.sheet-mode .sheet:last-child { break-after: auto; page-break-after: auto; }

  /* Colour is load-bearing here: red means restricted and green means passed,
     and a greyscale print of this page says nothing. */
  .sheet, .sh-hero, .sh-scr-row, .sh-t, .sh-flag, .sh-close, .sh-kpi-track, .sh-kpi-fill {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .sh-foot { margin-top: 12px; }
}

/* "8.4" glove" — the number is the measurement, the word is the direction. */
.sh-table .num em, .sh-stat b em {
  font-style: normal; font-family: var(--body); color: #7C8A9E;
  font-size: 7.5pt; margin-left: 2px; font-weight: 400;
}
.sh-stat b em { color: #A9C0DC; font-size: 8pt; }

/* The slider variant, beside the tag it hides under. */
.chip.sl-code {
  background: var(--selected); border-color: #B9CCE3; color: var(--navy-2);
  letter-spacing: .06em;
}
.sl-card { border-left: 3px solid var(--navy-2); }
.sl-notes {
  margin: var(--s-2) 0 0; padding-left: var(--s-4);
  font-size: 0.8125rem; color: var(--ink-2); line-height: 1.6;
}
.sl-notes li { margin-bottom: var(--s-1); }

/* A curveball is the pitch most constrained by what else is in the arsenal. */
.cb-card { border-left: 3px solid var(--green); }
.cb-pairing {
  border: 1px solid var(--gold-line); background: var(--amber-bg);
  border-radius: var(--r-tile); padding: var(--s-2) var(--s-3);
  font-size: 0.8125rem; line-height: 1.6; color: var(--gold-ink);
  margin-top: var(--s-3);
}

/* A cutter is judged by the job it does, not by its own grade. */
.ct-card { border-left: 3px solid var(--navy-2); }
.ct-role {
  border: 1px solid var(--line); background: var(--surface-2);
  border-radius: var(--r-tile); padding: var(--s-2) var(--s-3); margin-top: var(--s-3);
}
.ct-role-h {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--sub-2); margin-bottom: var(--s-1);
}
.ct-role-row {
  font-size: 0.8125rem; line-height: 1.6; color: var(--ink-2);
  padding: var(--s-1) 0 var(--s-1) var(--s-3); border-left: 3px solid var(--line-strong);
  margin-bottom: 2px;
}
.ct-role-row.bridge { border-left-color: var(--green); }
.ct-role-row.gap, .ct-role-row.redundant { border-left-color: var(--gold); }
.ct-role-row.fastball, .ct-role-row.mislabelled { border-left-color: var(--navy-2); }
.ct-role-row.split-zone, .ct-role-row.crowds-changeup { border-left-color: var(--gold); }
.ct-role-row.cut-heater { border-left-color: var(--navy-2); }

/* A sinker runs the other way: less carry is better, and the seams do the work. */
.si-card { border-left: 3px solid var(--gold); }
/* Carry is a COST here, so it gets the warning colour and depth gets the green. */
.ch-axis.si-carry { border-color: var(--gold-line); background: var(--amber-bg); }
.ch-axis.si-carry .ch-axis-v { color: var(--gold-ink); }
.si-seam {
  border: 1px solid var(--line); background: var(--surface-2);
  border-radius: var(--r-tile); padding: var(--s-2) var(--s-3); margin-top: var(--s-3);
}
.si-seam-h {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--sub-2); margin-bottom: var(--s-2);
}
.si-seam-row {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4);
  font-size: 0.8125rem; color: var(--ink-2);
}
.si-seam-row b { color: var(--ink); font-variant-numeric: tabular-nums; }
.si-seam-b {
  margin-top: var(--s-2); font-size: 0.75rem; line-height: 1.6; color: var(--sub-2);
}
/* The slot is a prerequisite for some shapes and a credit for others. */
.si-slot {
  border-radius: var(--r-tile); padding: var(--s-2) var(--s-3); margin-top: var(--s-3);
  font-size: 0.8125rem; line-height: 1.6;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-2);
}
.si-slot.unavailable {
  border-color: var(--gold-line); background: var(--amber-bg); color: var(--gold-ink);
}
.si-slot.rare, .si-slot.met { border-color: #A8D8BF; background: var(--green-bg); }

/* ============================================================
   The take-home card
   ------------------------------------------------------------
   A coach's controls on the left; on the right the exact page
   the athlete receives, at true A4 proportions. The preview
   being the real page — not an impression of it — is what stops
   a coach designing something that breaks in the printer.
   ============================================================ */

.cd-wrap {
  display: grid;
  grid-template-columns: minmax(20rem, 25rem) 1fr;
  gap: 1.75rem;
  align-items: start;
}

.cd-editor { min-width: 0; margin: 0; padding: 0; border: 0; }

.cd-panel { padding: 1rem 1.125rem 1.125rem; margin-bottom: 1rem; }
.cd-panel h3 { margin: 0 0 .625rem; font-size: .9375rem; letter-spacing: .01em; }

.cd-panel-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: .75rem;
  margin-bottom: .625rem;
}
.cd-panel-head h3 { margin: 0; }

.cd-tips {
  margin: 0 0 .875rem; padding: .625rem .75rem .625rem 1.75rem;
  background: var(--surface-2); border-radius: var(--r-ctl);
  font-size: .8125rem; color: var(--sub); line-height: 1.5;
}
.cd-tips li { margin: .1875rem 0; }
.cd-tips b { color: var(--ink-2); }

.cp-group { margin-bottom: .875rem; }
.cp-group h4 {
  margin: 0 0 .25rem; font-size: .6875rem; text-transform: uppercase;
  letter-spacing: .07em; color: var(--sub-2);
}

.cp-row {
  display: grid; grid-template-columns: auto 1fr auto auto;
  align-items: center; gap: .5rem;
  padding: .375rem .5rem; border-radius: var(--r-ctl);
  font-size: .8125rem; cursor: pointer;
}
.cp-row:hover { background: var(--surface-3); }
.cp-row.on { background: var(--selected); }
.cp-row.full { opacity: .45; cursor: not-allowed; }
.cp-name { color: var(--ink-2); }
.cp-val { color: var(--sub); font-variant-numeric: tabular-nums; }
.cp-why {
  font-size: .625rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--gold-ink); background: #FDF3DC;
  padding: .0625rem .375rem; border-radius: var(--r-pill);
}

.cd-f { display: block; margin-bottom: .75rem; }
.cd-f > span {
  display: block; margin-bottom: .25rem;
  font-size: .75rem; color: var(--sub); letter-spacing: .01em;
}
.cd-f > span em { font-style: normal; color: var(--sub-2); }
.cd-f input[type="text"], .cd-f textarea, .cd-ai textarea {
  width: 100%; padding: .5rem .625rem;
  border: 1px solid var(--line); border-radius: var(--r-ctl);
  background: var(--card); color: var(--ink);
  font: inherit; font-size: .875rem; line-height: 1.5; resize: vertical;
}
.cd-f input:focus, .cd-f textarea:focus, .cd-ai textarea:focus {
  outline: 2px solid var(--gold); outline-offset: -1px; border-color: transparent;
}

.cd-ai { margin-top: .875rem; padding-top: .875rem; border-top: 1px solid var(--line-soft); }
.cd-check { display: flex; align-items: center; gap: .5rem; font-size: .875rem; cursor: pointer; }
.cd-ai-note { margin: .25rem 0 .625rem; font-size: .75rem; color: var(--sub-2); line-height: 1.45; }
.cd-ai-btns { display: flex; gap: .5rem; margin-top: .5rem; }

/* ---------------- the quick-add focus list ---------------- */

.cd-chosen { list-style: none; margin: .5rem 0 .75rem; padding: 0; }
.cd-chosen li {
  display: flex; align-items: flex-start; gap: .5rem;
  padding: .4375rem .5rem; margin-bottom: .25rem;
  background: var(--surface-2); border-radius: var(--r-ctl);
  font-size: .8125rem; line-height: 1.45; color: var(--ink-2);
}
.cd-chosen li span { flex: 1; }
.cd-x {
  flex: none; border: 0; background: none; cursor: pointer;
  color: var(--sub-2); font-size: 1.125rem; line-height: 1; padding: 0 .125rem;
}
.cd-x:hover { color: var(--ink); }

.cd-sugg h4 {
  margin: .5rem 0 .375rem; font-size: .6875rem; text-transform: uppercase;
  letter-spacing: .07em; color: var(--sub-2);
}
/* Each suggestion is a whole sentence plus why it was offered, so a coach who
   does not know which numbers matter can still pick a real one. */
.cd-add {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: .4375rem .5625rem; margin-bottom: .25rem;
  border: 1px solid var(--line); border-radius: var(--r-ctl);
  background: var(--card); font: inherit;
}
.cd-add:hover { border-color: var(--gold); background: #FFFDF7; }
.cd-add span { display: block; font-size: .8125rem; color: var(--ink-2); line-height: 1.4; }
.cd-add em {
  display: block; margin-top: .125rem; font-style: normal;
  font-size: .6875rem; color: var(--sub-2);
}

.cd-actions { display: flex; align-items: center; gap: .625rem; flex-wrap: wrap; }
.cd-saved { font-size: .75rem; color: var(--sub-2); }
.cd-saved.error { color: var(--red); }

.cd-preview-label {
  margin-bottom: .5rem;
  font-size: .6875rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--sub-2);
}

/* ---------------- A4 ----------------
   Fixed geometry, scaled to whatever space the pane has. `zoom` rather than a
   transform so the shrunk page still takes its real height in the layout —
   `transform: scale()` leaves the original box behind and the panel below it
   ends up a page-length away. */

.cd-page, .cd-solo {
  width: 210mm;
  transform-origin: top left;
  zoom: var(--cd-zoom, 1);
}
/* Both wrappers, not just .cd-page. A player gets the card with no editor
   beside it and no .cd-page around it — scaling only the
   coach's preview left the athlete's own view stuck at a fixed 210mm and
   scrolling sideways on a phone, which is the one device they will open it on. */
@media (max-width: 1500px) { .cd-page, .cd-solo { --cd-zoom: .86; } }
@media (max-width: 1320px) { .cd-page, .cd-solo { --cd-zoom: .74; } }
@media (max-width: 1180px) { .cd-page, .cd-solo { --cd-zoom: .62; } }

.cd-sheet {
  box-sizing: border-box;
  width: 210mm; min-height: 297mm;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(20, 32, 47, .06), 0 8px 24px rgba(20, 32, 47, .07);
  padding: 16mm 15mm 12mm;
  display: flex; flex-direction: column;
}
.cd-solo { margin: 0 auto; }

/* ---------------- the card itself ---------------- */

.cd-head {
  display: flex; align-items: center; gap: 1rem;
  padding-bottom: .875rem;
  border-bottom: 2.5px solid var(--navy);
}
.cd-photo {
  width: 4.25rem; height: 4.25rem; border-radius: var(--r-pill);
  object-fit: cover; flex: none; border: 2px solid var(--line);
}
.cd-who { flex: 1; min-width: 0; }
.cd-who h1 {
  margin: 0; font-size: 2rem; line-height: 1.05; color: var(--navy);
  letter-spacing: -.022em;
}
.cd-sub { margin: .25rem 0 0; font-size: .8125rem; color: var(--sub); letter-spacing: .01em; }

/* The wordmark, stacked so it reads as a mark rather than a caption. */
.cd-mark {
  flex: none; text-align: right; line-height: 1.15;
  font-size: .5625rem; letter-spacing: .18em; color: var(--sub-2);
}
.cd-mark span {
  display: block; font-size: .875rem; letter-spacing: .06em;
  color: var(--navy); font-weight: 700;
}

.cd-headline {
  margin: .875rem 0 0; font-size: 1.125rem; font-weight: 600;
  color: var(--navy-2); letter-spacing: -.01em;
}

.cd-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: .5rem; margin: .875rem 0 0;
}

.cw-tile {
  margin: 0; padding: .75rem .8125rem .875rem;
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  display: flex; flex-direction: column; gap: .1875rem;
  min-height: 8.75rem;
}
.cw-empty {
  align-items: center; justify-content: center;
  border: 1px dashed var(--line-strong); background: transparent;
  color: var(--sub-2); font-size: 1.5rem;
}

/* Two lines reserved whether the label needs them or not, so the big numbers
   sit on the same line across a row instead of stepping down it. */
.cw-top {
  display: flex; align-items: baseline; justify-content: space-between; gap: .375rem;
  min-height: 1.75rem;
}
.cw-label {
  font-size: .625rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--sub); line-height: 1.35; min-width: 0;
}
.cw-badge {
  flex: none;
  font-size: .5rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--green); background: var(--green-bg);
  padding: .09375rem .3125rem; border-radius: var(--r-pill); white-space: nowrap;
}

.cw-value { display: flex; align-items: baseline; gap: .1875rem; }
.cw-value b {
  font-size: 2.125rem; line-height: 1; color: var(--navy);
  font-variant-numeric: tabular-nums; letter-spacing: -.03em;
}
.cw-unit { font-size: .75rem; color: var(--sub); }
.cw-delta { margin-left: auto; font-size: .75rem; color: var(--green); font-weight: 600; }

.cw-spark { display: block; width: 100%; height: 26px; margin-top: .25rem; }

/* Pushed to the bottom so the tiles line up whatever the label above did. */
.cw-plain {
  font-size: .6875rem; color: var(--sub); line-height: 1.4;
  margin-top: auto; padding-top: .3125rem;
}
/* ---------------- progression chart ---------------- */

.cd-chart { margin-top: .875rem; }
.cg-wrap {
  margin: 0; padding: .75rem .875rem .5rem;
  background: var(--surface-2); border: 1px solid var(--line-soft); border-radius: 12px;
}
.cg-head { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; }
.cg-title {
  font-size: .625rem; text-transform: uppercase; letter-spacing: .07em; color: var(--sub);
}
.cg-span { font-size: .625rem; color: var(--sub-2); }
.cg-svg { display: block; width: 100%; height: auto; margin-top: .25rem; }
.cg-ax { font-size: 8px; fill: var(--sub-2); font-variant-numeric: tabular-nums; }

/* ---------------- focus + note ---------------- */

.cd-focus {
  margin-top: .875rem; padding: .75rem .9375rem;
  background: #FFFCF4; border: 1px solid var(--gold-line); border-radius: 10px;
}
.cd-focus h2, .cd-note h2 {
  margin: 0 0 .375rem; font-size: .625rem; text-transform: uppercase;
  letter-spacing: .08em; color: var(--sub-2);
}
.cd-focus ul { margin: 0; padding-left: 1.125rem; }
.cd-focus li { font-size: .8125rem; line-height: 1.55; color: var(--ink-2); margin: .1875rem 0; }

.cd-note {
  margin-top: .875rem; padding: .875rem 1rem;
  background: var(--surface-2); border-left: 3px solid var(--gold);
  border-radius: 0 10px 10px 0;
}
.cd-note p { margin: 0 0 .5rem; font-size: .875rem; line-height: 1.6; color: var(--ink-2); }
.cd-note p:last-child { margin-bottom: 0; }

.cd-foot {
  margin-top: auto; padding-top: .75rem; border-top: 1px solid var(--line-soft);
  font-size: .625rem; color: var(--sub-2); text-align: center; letter-spacing: .04em;
}

@media (max-width: 68rem) {
  .cd-wrap { grid-template-columns: 1fr; }
  .cd-page, .cd-solo { --cd-zoom: .58; }
}
@media (max-width: 40rem) {
  .cd-page, .cd-solo { --cd-zoom: .42; }
}

/* ---------------- printing the card ----------------
   One A4 page, and only the card on it. The controls, the app chrome and the
   preview label are scaffolding for building the thing, not part of it. */

/* Named so the zero-margin card cannot change ordinary reports or the existing
   three-page athlete sheet. */
@page athlete-card { size: A4 portrait; margin: 0; }

@media print {
  body.card-mode .report-head,
  body.card-mode .ptabs,
  body.card-mode .cd-controls,
  body.card-mode .cd-preview-label,
  body.card-mode #foot { display: none !important; }

  body.card-mode .cd-wrap { display: block; }
  body.card-mode .cd-page,
  body.card-mode .cd-solo { width: auto; zoom: 1; --cd-zoom: 1; }
  body.card-mode .cd-sheet {
    page: athlete-card;
    width: auto; min-height: 0; height: 297mm;
    border: 0; border-radius: 0; box-shadow: none;
    padding: 14mm 14mm 10mm;
    break-inside: avoid; page-break-inside: avoid;
  }

  /* The gold rule, the green badges and the amber focus lines all carry
     meaning; a greyscale card loses which number was worth being proud of. */
  .cd-sheet, .cd-head, .cd-note, .cd-focus, .cw-tile, .cw-badge, .cw-delta,
  .cg-wrap, .cd-mark span {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
}

/* ---------------- connection failure ----------------
   Shown in place of a roster the app could not fetch. Deliberately not styled
   as a destructive error: the message is that nothing is lost, so it reads as
   an interruption rather than an alarm. */

.conn-error {
  max-width: 34rem;
  margin: 3rem auto;
  padding: 1.5rem 1.75rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 3px solid var(--gold);
  border-radius: var(--r-card);
}
.conn-error h2 { margin: 0 0 .5rem; font-size: 1.125rem; color: var(--navy); }
.conn-error p { margin: 0 0 .75rem; font-size: .875rem; line-height: 1.6; color: var(--ink-2); }
.conn-detail { color: var(--sub); font-size: .8125rem !important; }
