:root {
  /* DragonLog brand system v1.0 — see docs/firebase-schema.md siblings for
     the source brand doc. Deep Water is the default surface; Bone is paper/
     knockout; Dragon Red stays under 10% of any screen.
     Dark is the default look. Light overrides below via prefers-color-scheme
     (system default, no explicit choice) and [data-theme] (explicit toggle,
     always wins in either direction — see theme.js). */
  --bg: #0e2a33;             /* deep water */
  --panel: #14313b;          /* deep water, one step lighter — card surfaces */
  --panel-2: #1a3844;        /* deep water, two steps lighter — toasts/modals */
  --ink: #f2ede4;            /* bone */
  --ink-dim: #a9bac0;
  --ink-faint: #6e8891;
  --accent: #d93a1e;         /* dragon red */
  --accent-2: #ffb800;       /* warning/caution only — not a brand color, never decorative */
  --ok: #2ecc71;
  --warn: #d93a1e;
  --border: #23404a;
  --grid: rgba(255,255,255,.035);
  --water: rgba(150,205,220,.15); /* trim gauge sea — see .trim-water */
}

/* ---------- LIGHT THEME ----------
   Same brand hues, re-tuned for a paper surface. --accent-2 and --ok get
   darker variants here specifically because both are used as direct TEXT
   color (config-warning, anon-nudge, rsvp/balance chips) — the dark-mode
   values are AA-contrast against Deep Water but fail against a light page. */
@media (prefers-color-scheme: light) {
  :root { --bg: #f4f1ea; --panel: #ffffff; --panel-2: #ede8dd; --ink: #16262b;
    --ink-dim: #4b5f65; --ink-faint: #7c8f94; --accent-2: #96690a; --ok: #1e8449;
    --border: #ddd6c8; --grid: rgba(20,49,59,.05); --water: rgba(22,70,90,.12); }
}
:root[data-theme="light"] { --bg: #f4f1ea; --panel: #ffffff; --panel-2: #ede8dd; --ink: #16262b;
  --ink-dim: #4b5f65; --ink-faint: #7c8f94; --accent-2: #96690a; --ok: #1e8449;
  --border: #ddd6c8; --grid: rgba(20,49,59,.05); --water: rgba(22,70,90,.12); }
:root[data-theme="dark"] { --bg: #0e2a33; --panel: #14313b; --panel-2: #1a3844; --ink: #f2ede4;
  --ink-dim: #a9bac0; --ink-faint: #6e8891; --accent-2: #ffb800; --ok: #2ecc71;
  --border: #23404a; --grid: rgba(255,255,255,.035); --water: rgba(150,205,220,.15); }
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: 'Archivo', system-ui, sans-serif;
  font-weight: 500;
  overscroll-behavior: none;
  height: 100%;
}
body {
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 32px 32px, 32px 32px;
}

/* ---------- HEADER ---------- */
header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px 8px;
  border-bottom: 1px solid var(--border);
}
.brand { display: flex; align-items: center; gap: 10px; }
.mark { width: 26px; height: 26px; flex: none; }
.mark svg { width: 100%; height: 100%; fill: var(--ink); }
.brand-text {
  font-size: 20px; letter-spacing: -0.015em;
}
.brand-text .wm-dragon { font-weight: 500; }
.brand-text .wm-log { font-weight: 800; }
.brand-text em { color: var(--ink-faint); font-style: normal; font-weight: 600; font-size: 12px; letter-spacing: .2em; margin-left: 2px; }
.theme-toggle {
  width: 34px; height: 34px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; line-height: 1; border-radius: 3px;
}
.header-right { display: flex; align-items: center; gap: 10px; }
.team-badge {
  font-weight: 600;
  font-size: 10px; letter-spacing: .2em;
  color: var(--ink-dim);
  border: 1px solid var(--border);
  background: var(--panel);
  padding: 4px 8px; border-radius: 3px;
  font-family: inherit;
  cursor: pointer;
}

/* ---------- TEAM PICKER ----------
   The badge is the switcher, and it carries the caret ALWAYS — not only once a
   second team exists. Hiding it until then was meant to avoid advertising a
   choice that wasn't there, but the menu is never empty: JOIN OR CREATE and
   LEAVE are in it from the first team onward. The cost was that a paddler in
   one crew saw a plain label, learned it was a label, and never clicked it
   again — so the day they joined a second crew the switcher was already
   invisible to them. */
.team-switch { position: relative; }
.team-badge::after { content: ' ▾'; color: var(--ink-faint); }
.team-badge:hover { border-color: var(--ink-faint); color: var(--ink); }
.team-badge[aria-expanded="true"] { border-color: var(--ink-faint); color: var(--ink); }

.team-menu {
  display: none;
  position: absolute; right: 0; top: calc(100% + 6px);
  min-width: 200px; z-index: 60;
  background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 4px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
  padding: 4px;
}
.team-menu.open { display: block; }

.team-menu-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; text-align: left;
  background: none; border: 0; border-radius: 3px;
  padding: 8px 10px;
  font-family: inherit; font-size: 11px; letter-spacing: .12em; font-weight: 600;
  color: var(--ink);
  cursor: pointer;
}
.team-menu-item:hover { background: var(--panel); }
/* The active team is marked with a check, NOT with red. Red is reserved for
   the destructive row: when both used --accent, the only thing separating "the
   crew you are in" from "resign from it" was reading the label. */
.team-menu-item.active { color: var(--ink); font-weight: 700; }
.team-menu-item.active .team-menu-check { visibility: visible; }
.team-menu-check { visibility: hidden; flex: none; width: 12px; color: var(--ink); }
.team-menu-item.danger { color: var(--accent); }
.team-menu-name { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.team-menu-role {
  font-size: 9px; letter-spacing: .16em;
  color: var(--ink-faint);
  border: 1px solid var(--border); border-radius: 2px;
  padding: 1px 5px;
}
.team-menu-rule {
  height: 1px; margin: 4px 6px;
  background: var(--border);
}

/* ---------- TABS ---------- */
nav.tabs {
  /* One row, however many tabs there are — auto-fit keeps them even without
     hard-coding a column count (the old repeat(2,1fr) wrapped 4 tabs to 2+2). */
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  letter-spacing: .18em;
  font-size: 14px;
}
nav.tabs button {
  background: transparent; color: var(--ink-dim);
  border: none; padding: 14px 4px; cursor: pointer;
  position: relative;
  font-family: inherit; font-size: inherit;
  /* Tighten tracking on narrow screens so four labels still fit one line. */
  letter-spacing: .12em;
  white-space: nowrap;
}
@media (max-width: 420px) {
  nav.tabs { font-size: 12px; }
  nav.tabs button { letter-spacing: .04em; padding: 13px 2px; }
}
nav.tabs button.active { color: var(--ink); }
nav.tabs button.active::after {
  content: ''; position: absolute; left: 30%; right: 30%; bottom: -1px;
  height: 2px; background: var(--accent);
}

main { padding: 16px; max-width: 1100px; margin: 0 auto; }
.view { display: none; }
.view.active { display: block; animation: fade .3s ease; }
@keyframes fade {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

/* ---------- BUTTONS ---------- */
.btn {
  font-weight: 600;
  font-size: 12px; letter-spacing: .12em;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--panel);
  color: var(--ink-dim);
  padding: 12px 18px;
  cursor: pointer;
}
.btn:hover { border-color: var(--ink-faint); color: var(--ink); }
.btn:disabled { opacity: .4; cursor: default; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 700; }
.btn-primary:hover { color: #fff; filter: brightness(1.1); }
.btn-gold { color: var(--accent-2); border-color: rgba(255,184,0,.3); }
.btn-ghost { background: transparent; }
.btn-compact { padding: 7px 12px; font-size: 10px; }
.btn-block { display: block; width: 100%; margin-top: 14px; }
.danger-btn { color: var(--warn); border-color: rgba(217,58,30,.3); }
/* --warn and --accent are the same red, so .danger-btn's colour on top of
   .btn-primary's background (it wins on source order, equal specificity) made
   the label invisible — which is how "DELETE FOREVER" in the delete-account
   modal rendered as an empty red slab. On a filled primary button the danger
   intent is already carried by the fill; keep the text legible. */
.btn-primary.danger-btn { color: #fff; border-color: var(--accent); }
.btn-primary.danger-btn:hover { color: #fff; }

/* ---------- LOGIN ---------- */
.login-panel {
  max-width: 420px; margin: 8vh auto 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 28px 24px;
}

/* The boot splash. Deliberately the quietest screen in the app — it is shown
   for a few hundred milliseconds on a good connection, and anything with more
   weight than this reads as a flash of the wrong thing. */
.boot-panel {
  display: flex; align-items: center; justify-content: center; gap: 12px;
}
.boot-panel .hint { margin: 0; }
.boot-spinner {
  width: 16px; height: 16px; flex: none;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: boot-spin .7s linear infinite;
}
@keyframes boot-spin { to { transform: rotate(360deg); } }
/* A spinner is decoration; the copy beside it already says what is happening. */
@media (prefers-reduced-motion: reduce) {
  .boot-spinner { animation: none; }
}
/* Shown by the inline failsafe in index.html when the splash is still up after
   10 s. Not a modal and not a toast: at this point nothing else on the page is
   running, so it has to be plain markup that was already in the document. */
.boot-failed h2 { margin-bottom: 10px; }
.boot-failed .hint { margin: 0 0 14px; }
.boot-failed .hint:last-child { margin-bottom: 0; }
.boot-actions {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px;
}
.login-panel h2 {
  font-weight: 700; font-size: 20px;
  letter-spacing: -0.01em; margin: 0 0 8px;
}
.hint { color: var(--ink-dim); font-size: 13px; line-height: 1.5; }
/* Inline links in body copy (e.g. the privacy-policy link in the delete
   modal) — the browser default blue is unreadable on these dark panels. */
.hint a { color: var(--accent-2); text-decoration: underline; }
.hint a:hover { color: var(--ink); }
.config-warning {
  background: rgba(255,184,0,.08);
  border: 1px solid rgba(255,184,0,.35);
  color: var(--accent-2);
  font-size: 12px; line-height: 1.5;
  border-radius: 3px; padding: 10px 12px; margin: 12px 0;
}
.config-warning code { font-weight: 600; font-size: 11px; }
/* The good-news twin of .config-warning — "reset link sent" on the sign-in screen. */
.auth-notice {
  background: color-mix(in srgb, var(--ok) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--ok) 35%, transparent);
  color: var(--ok);
  font-size: 12px; line-height: 1.5;
  border-radius: 3px; padding: 10px 12px; margin: 12px 0;
}
.field-hint { text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--ink-faint); }
.field-label {
  display: block;
  font-weight: 600;
  font-size: 9px; letter-spacing: .2em;
  color: var(--ink-faint);
  margin: 18px 0 6px;
}
input[type="text"], input[type="number"], input[type="email"],
input[type="password"], input[type="datetime-local"], select {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 3px;
  color: var(--ink);
  font-weight: 600;
  font-size: 14px;
  padding: 11px 12px;
  outline: none;
}
input:focus, select:focus { border-color: var(--accent); }
.normalized-preview {
  font-weight: 600;
  font-size: 11px; color: var(--warn);
  min-height: 18px; margin-top: 6px;
}
.normalized-preview.ok { color: var(--ok); }

/* ---------- COMMAND STRIP ---------- */
.command-strip {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 12px 14px;
  margin-bottom: 14px;
}
.strip-label {
  font-weight: 600;
  font-size: 10px; letter-spacing: .2em; color: var(--ink-faint);
}
.strip-buttons { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------- ROSTER ---------- */
.roster-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
}
.paddler-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 14px;
  cursor: pointer;
  transition: border-color .15s;
}
.paddler-card:hover { border-color: var(--ink-faint); }
.paddler-card.in-session { border-color: rgba(217,58,30,.5); }
.paddler-card.offline { opacity: .45; }
.p-head { display: flex; justify-content: space-between; align-items: center; }
.p-name {
  color: var(--ink);
  font-weight: 600;
  font-size: 12px; letter-spacing: .1em;
  text-transform: uppercase;
}
.p-status {
  font-weight: 600;
  font-size: 8px; letter-spacing: .15em;
  padding: 3px 6px; border-radius: 2px;
  border: 1px solid var(--border); color: var(--ink-faint);
}
.p-status.online { color: var(--ok); border-color: rgba(46,204,113,.35); }
.p-status.in-session { color: var(--accent); border-color: rgba(217,58,30,.4); }

/* ---------- MEMBER ACTIONS ON A CARD ----------
   Granting coach/admin and removing someone were a second roster on the
   Schedule tab. They are here now, on the card for the person being acted on.

   The button is deliberately quiet until you go looking for it: the Live tab is
   something a coach watches during a practice, and a row of controls competing
   with the SPM readout would be the wrong thing loud. It comes up on hover, on
   focus, and whenever its menu is open — that last one matters for touch, where
   there is no hover to reveal it and the menu would otherwise sit under a
   button that had faded back out. */
.p-head-right { display: flex; align-items: center; gap: 6px; }
.p-role {
  font-weight: 700;
  font-size: 8px; letter-spacing: .15em;
  padding: 3px 6px; border-radius: 2px;
  border: 1px solid var(--border); color: var(--ink-faint);
}
.p-menu-wrap { position: relative; display: flex; }
.p-menu-btn {
  background: none; border: 0; border-radius: 3px;
  padding: 0 4px; margin: -2px -4px -2px 0;
  font-size: 15px; line-height: 1.2;
  color: var(--ink-faint);
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s, color .15s;
}
.paddler-card:hover .p-menu-btn,
.p-menu-btn:focus-visible,
.p-menu-btn[aria-expanded="true"] { opacity: 1; }
.p-menu-btn:hover, .p-menu-btn[aria-expanded="true"] { color: var(--ink); }
/* Touch has no hover to reveal it with, and an action you cannot find is the
   same as one that isn't there. */
@media (hover: none) { .p-menu-btn { opacity: 1; } }

.p-menu {
  display: none;
  position: absolute; right: 0; top: calc(100% + 6px);
  min-width: 180px; z-index: 60;
  background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 4px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
  padding: 4px;
  cursor: default;
}
.p-menu.open { display: block; }
.p-menu-item {
  display: block; width: 100%; text-align: left;
  background: none; border: 0; border-radius: 3px;
  padding: 8px 10px;
  font-family: inherit; font-size: 11px; letter-spacing: .12em; font-weight: 600;
  color: var(--ink);
  cursor: pointer;
}
.p-menu-item:hover { background: var(--panel); }
/* Same rule as the team menu: red is reserved for the row that destroys
   something, so it cannot be confused with the ones that hand out a job. */
.p-menu-item.danger { color: var(--accent); }

.coach-claim-hint {
  margin-top: 8px;
  font-size: 11px; color: var(--ink-faint);
}
.p-main { display: flex; align-items: center; gap: 14px; margin: 10px 0 8px; }
.p-spm {
  font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
  font-size: 46px; line-height: 1; color: var(--ink);
}
.p-spm-label {
  font-size: 12px; color: var(--ink-faint); margin-left: 4px; letter-spacing: .1em;
}
.p-sub {
  font-weight: 600;
  font-size: 10px; color: var(--ink-dim);
  display: grid; gap: 3px;
}
.p-sub b { color: var(--ink); font-weight: 500; }
.p-bpm { color: var(--accent); }
.p-chart svg { width: 100%; height: 36px; display: block; }
.live-empty {
  grid-column: 1 / -1;
  text-align: center; color: var(--ink-faint);
  font-weight: 600;
  font-size: 12px; line-height: 1.8;
  padding: 40px 16px;
  border: 1px dashed var(--border); border-radius: 4px;
}

/* ---------- PADDLER DETAIL ---------- */
.detail-header { display: flex; align-items: center; gap: 14px; margin-bottom: 12px; }
.detail-header h2 {
  font-weight: 700;
  letter-spacing: -0.01em; margin: 0; font-size: 26px;
}
/* Weight field and its kg/lb toggle read as one control. */
.weight-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.weight-row input { flex: 0 1 120px; }
.weight-row .opt-row { flex: 0 0 auto; }

.detail-statusrow {
  display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap; margin-bottom: 12px;
}
.detail-lastseen {
  font-weight: 600;
  font-size: 10px; letter-spacing: .2em; color: var(--ink-faint);
}
.detail-status {
  display: inline-block;
  font-weight: 600;
  font-size: 10px; letter-spacing: .2em;
  padding: 4px 10px; border-radius: 2px;
  border: 1px solid var(--border); color: var(--ink-faint);
}
.detail-status.online { color: var(--ok); border-color: rgba(46,204,113,.35); }
.detail-status.in-session { color: var(--accent); border-color: rgba(217,58,30,.4); }
.detail-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
  margin-bottom: 14px;
}
.stat-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 14px 16px;
}
/* Brand system §05: no gradients. The hero card earns its emphasis from the
   red border and the size/weight of its value, not a second surface. */
.stat-card.hero {
  grid-column: 1 / -1;
  background: var(--panel);
  border-color: rgba(217,58,30,.3);
}
.stat-card .v {
  font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
  font-size: 34px; line-height: 1;
}
.stat-card.hero .v { font-size: 64px; color: var(--accent); }
/* Parenthetical beside a stat value, e.g. the attendance percentage. Was an
   inline style; here so it picks up the theme's dim ink in both schemes. */
.stat-card .stat-note {
  font-size: .6em; font-weight: 400; color: var(--ink-dim);
}
/* Profile cells hold words ("Left / Right", "Dragonboat"), not figures — at the
   numeric 34px they wrap to three lines and ragged the grid. */
.stat-card.text .v {
  font-size: 18px; font-weight: 700; line-height: 1.25;
  letter-spacing: 0; overflow-wrap: anywhere;
}
.stat-card .u { font-size: 16px; color: var(--ink-dim); margin-left: 3px; }
/* Coach: change a paddler's side for this team, from the paddler panel. */
.stat-card .stat-edit {
  margin-left: 8px; padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; letter-spacing: .2em; color: var(--accent);
}
.stat-card .coach-note { font-size: 11px; color: var(--ink-dim); margin-top: 4px; }
.side-override {
  background: var(--panel); border: 1px solid var(--border); border-radius: 4px;
  padding: 14px 16px; margin: -4px 0 14px;
}
.side-override-title {
  font-size: 9px; font-weight: 600; letter-spacing: .2em; color: var(--ink-faint);
  margin-bottom: 10px;
}
.side-override-title .field-hint { letter-spacing: 0; text-transform: none; }
.side-override .opt:disabled { opacity: .6; cursor: default; }
.side-override .help-link { text-align: left; margin-top: 8px; }
.stat-card .l {
  font-weight: 600;
  font-size: 9px; letter-spacing: .2em; color: var(--ink-faint);
  margin-top: 6px;
}
.detail-charts { display: grid; gap: 10px; margin-bottom: 14px; }
.paddler-chart-container {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 10px 12px;
}
.paddler-chart-container svg { width: 100%; display: block; }
.chart-label {
  font-weight: 600;
  font-size: 9px; letter-spacing: .2em; color: var(--ink-faint);
  margin-bottom: 6px;
}
.section-title {
  font-weight: 600;
  letter-spacing: .18em; font-size: 13px;
  color: var(--ink-dim); margin: 18px 0 10px;
}
.section-head {
  display: flex; align-items: center; justify-content: space-between;
}

/* ---------- SESSION CARDS ---------- */
.session-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 14px;
  margin-bottom: 10px;
}
.session-date {
  font-size: 12px; color: var(--ink-dim); margin-bottom: 10px;
}
.session-profile {
  color: var(--ink-dim);
  font-weight: 600;
  font-size: 10px; letter-spacing: .1em;
  border: 1px solid var(--border);
  padding: 2px 6px; border-radius: 2px; margin-left: 6px;
}
.session-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.session-stat .l {
  font-weight: 600;
  font-size: 8px; letter-spacing: .18em; color: var(--ink-faint);
}
.session-stat .v {
  font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
  font-size: 22px; margin-top: 2px;
}
.history-splits { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
.history-split-chip {
  font-weight: 600;
  font-size: 9px; color: var(--ink-dim);
  border: 1px solid var(--border);
  padding: 3px 7px; border-radius: 2px;
}

/* ---------- WORKOUTS ---------- */
.workout-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 12px 14px;
  margin-bottom: 10px;
}
.workout-row-name {
  font-weight: 600;
  font-size: 13px; color: var(--ink);
}
.workout-row-summary {
  font-weight: 600;
  font-size: 10px; color: var(--ink-faint); margin-top: 4px;
}
.workout-row-actions { display: flex; gap: 6px; flex-shrink: 0; }
.workout-row-by {
  font-size: 10px; color: var(--ink-faint); margin-top: 3px;
}
.workout-section-title {
  font-weight: 600;
  letter-spacing: .2em; font-size: 10px;
  color: var(--ink-faint); margin: 18px 0 8px;
}
.workout-section-title:first-child { margin-top: 4px; }
/* Looks like the sign-in/join tabs but must NOT share their .auth-tab class:
   app.js binds every .auth-tab to setAuthMode, so a click here would reset the
   sign-in form's mode and clear this toggle's own selection. */
.save-to-toggle { display: flex; gap: 6px; margin: 0 0 6px; }
.save-to-tab {
  flex: 1; padding: 9px; border-radius: 6px; cursor: pointer;
  background: transparent; border: 1px solid var(--border);
  color: var(--ink-faint); font-family: inherit;
  font-size: 11px; font-weight: 600; letter-spacing: .1em;
}
.save-to-tab.active { border-color: var(--accent); color: var(--ink); }
/* A coach's personal row carries four actions (PUSH, SHARE, EDIT, ✕), which
   don't fit beside the name on a phone — drop them onto their own line there
   rather than squeezing the name to nothing. */
.workout-row-info { min-width: 0; }
@media (max-width: 480px) {
  .workout-row { flex-wrap: wrap; }
  .workout-row-actions { flex-wrap: wrap; }
}
.workout-empty {
  text-align: center; color: var(--ink-faint);
  font-weight: 600;
  font-size: 12px;
  padding: 32px 16px;
  border: 1px dashed var(--border); border-radius: 4px;
}

/* ---------- MODAL ---------- */
.modal {
  position: fixed; inset: 0;
  display: none; align-items: center; justify-content: center;
  background: rgba(6,14,17,.8);
  backdrop-filter: blur(3px);
  z-index: 50; padding: 16px;
}
.modal.active { display: flex; }
.modal-box {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 20px;
  width: 100%; max-width: 520px;
  max-height: 85vh; overflow-y: auto;
}
.modal-box h3 {
  font-weight: 700; font-size: 18px;
  letter-spacing: -0.01em; margin: 0 0 4px;
}
.modal-actions {
  display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px;
}
.interval-list { margin-top: 14px; display: grid; gap: 8px; }
.interval-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr 70px auto auto;
  gap: 6px; align-items: center;
}
.interval-row select, .interval-row input { padding: 8px; font-size: 11px; }
.iv-ps-wrap { display: flex; align-items: center; gap: 4px; }
.iv-ps-label {
  font-weight: 600;
  font-size: 9px; color: var(--ink-faint);
}
.iv-ps { width: 52px; }
.iv-unit {
  font-weight: 600;
  font-size: 10px; color: var(--ink-faint);
}

/* ---------- TOAST ---------- */
.toast {
  position: fixed; left: 50%; bottom: 28px;
  transform: translate(-50%, 20px);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--ink);
  font-weight: 600;
  font-size: 12px;
  padding: 12px 18px;
  opacity: 0; pointer-events: none;
  transition: all .25s ease;
  z-index: 60;
  max-width: 90vw;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

@media (max-width: 480px) {
  .session-stats { grid-template-columns: repeat(2, 1fr); }
  .interval-row { grid-template-columns: 1fr auto 1fr 60px auto auto; }
}

/* ---------- BIG CHOICE CARDS / AUTH ----------
   Named for the role picker these were built for. That screen is gone (the
   role comes from the team now), but the card itself is still what the no-team
   screen offers JOIN and CREATE with, so the component stays. */
.role-grid { display: grid; gap: 12px; margin: 18px 0 6px; }
.role-card {
  display: flex; flex-direction: column; gap: 6px; text-align: left;
  padding: 18px; border-radius: 10px; cursor: pointer;
  background: var(--panel); border: 1px solid var(--border);
  color: var(--ink); font-family: inherit;
  transition: border-color .15s ease;
}
/* hover:hover so a touch device doesn't leave a card stuck in the hover state
   after a tap. Tap highlight is transparent globally (see the reset at the top
   of this file), so on a phone this border WAS the only feedback a tap gave —
   and it stayed lit afterwards, which reads as "selected". When these cards
   were the role picker and a JS error was eating the click, that stuck border
   was precisely what made two dead buttons look like two working ones. */
@media (hover: hover) {
  .role-card:hover { border-color: var(--accent); }
}
.role-card:active { border-color: var(--accent); }
.role-name { font-weight: 700; font-size: 15px; letter-spacing: .08em; }
.role-desc { color: var(--ink-dim); font-size: 13px; line-height: 1.5; font-weight: 400; }

.auth-toggle { display: flex; gap: 6px; margin: 16px 0 10px; }
.auth-tab {
  flex: 1; padding: 9px; border-radius: 6px; cursor: pointer;
  background: transparent; border: 1px solid var(--border);
  color: var(--ink-faint); font-family: inherit;
  font-size: 11px; font-weight: 600; letter-spacing: .1em;
}
.auth-tab.active { border-color: var(--accent); color: var(--ink); }

/* Used on both <a> and <button> (the join screen's "I don't have a team yet"
   is an action, not a link) — so the button chrome has to be reset here or it
   renders as a boxed control among plain text links. */
.help-link {
  display: block; text-align: center; margin-top: 16px;
  color: var(--ink-faint); font-size: 12px; text-decoration: none;
  width: 100%; padding: 0; border: 0; background: none;
  font-family: inherit; font-weight: 500; cursor: pointer;
}
.help-link:hover { color: var(--ink-dim); }
/* Row of legal/help links. .help-link is display:block with its own top
   margin, so it's neutralised inside the row to keep the pair on one line. */
.help-links {
  display: flex; justify-content: center; align-items: center; gap: 8px;
  margin-top: 16px; color: var(--ink-faint); font-size: 12px;
}
.help-links .help-link { display: inline; margin-top: 0; }

.danger-zone { margin-top: 32px; padding-top: 18px; border-top: 1px solid var(--border); }

/* ---------- PRACTICES ---------- */
.coach-claim {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 4px 0 14px; padding: 10px 12px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
  color: var(--ink); font-size: 13px;
}
.coach-claim input { accent-color: var(--accent); width: 16px; height: 16px; }
.hint-inline { color: var(--ink-faint); font-size: 12px; }

.practice-section {
  margin: 18px 0 8px; color: var(--ink-faint);
  font-weight: 600; font-size: 11px; letter-spacing: 2px;
}
.practice-card {
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px; margin-bottom: 12px;
}
.practice-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
}
.practice-title { font-weight: 700; font-size: 16px; color: var(--ink); }
.practice-when { color: var(--ink-dim); font-size: 13px; margin-top: 2px; }
/* ---------- RSVP ROSTER ----------
   Was three rows of undifferentiated name pills behind tiny colour-coded
   labels, which forced the coach to read every name to work out who was in.
   Now: one bar for the split, then a column per status, each paddler carrying
   an initials disc tinted to their status. */
.tally { margin-top: 12px; }
.tally-bar {
  display: flex; height: 6px; border-radius: 3px; overflow: hidden;
  background: var(--bg); border: 1px solid var(--border);
}
.tally-bar .seg { transition: width .45s cubic-bezier(.3,.9,.4,1); }
.tally-bar .seg.go    { background: var(--ok); }
.tally-bar .seg.no    { background: var(--accent); }
.tally-bar .seg.maybe { background: var(--ink-faint); }
.tally-nums {
  margin-top: 6px; font-size: 12px; color: var(--ink-dim); font-weight: 600;
  display: flex; align-items: center; gap: 6px;
}
.tally-nums b { color: var(--ink); }
.tally-sep { color: var(--ink-faint); }

.rgroups {
  margin-top: 12px; display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  /* start, not the default stretch: a folded group should be a header-high
     strip, not a full-height card with nothing in it. */
  align-items: start;
}
.rgroup {
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 8px; padding: 9px 10px 10px;
}
.rgroup.empty { opacity: .6; }
/* <summary> carries the group header. The default disclosure triangle is
   replaced by .rchev so the marker sits with the count on the right, where the
   eye already is, rather than shoving the label off its left edge. Both the
   webkit pseudo-element and `display` are needed — neither alone removes it
   everywhere. */
.rgroup-head {
  display: flex; align-items: center; gap: 6px;
  font-size: 9px; font-weight: 700; letter-spacing: 1.5px; color: var(--ink-dim);
  cursor: pointer; list-style: none; user-select: none;
  border-radius: 4px; padding: 2px;
}
.rgroup-head::-webkit-details-marker { display: none; }
.rgroup[open] .rgroup-head { margin-bottom: 8px; }
.rgroup-head:hover { color: var(--ink); }
.rgroup-head:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }
.rgroup-head b {
  margin-left: auto; font-size: 13px; letter-spacing: 0; color: var(--ink);
}
.rchev {
  width: 9px; height: 6px; flex: none; fill: none;
  stroke: var(--ink-faint); stroke-width: 1.6; stroke-linecap: round;
  transition: transform .18s ease;
}
.rgroup[open] .rchev { transform: rotate(180deg); }
.rdot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.rgroup.go    .rdot { background: var(--ok); }
.rgroup.no    .rdot { background: var(--accent); }
.rgroup.maybe .rdot { background: var(--ink-faint); }
.rgroup-list { display: flex; flex-direction: column; gap: 4px; }
.rgroup-none { font-size: 12px; color: var(--ink-faint); padding: 2px 0; }

.paddler {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 4px 6px 4px 4px; border-radius: 999px; text-align: left;
  font-family: inherit; font-size: 13px; color: var(--ink);
  background: transparent; border: 1px solid transparent;
}
.pav {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 10px; font-weight: 700; letter-spacing: .3px;
}
.rgroup.go    .pav { background: rgba(46,204,113,.15); color: var(--ok); }
.rgroup.no    .pav { background: rgba(217,58,30,.15);  color: var(--accent); }
.rgroup.maybe .pav { background: rgba(110,136,145,.18); color: var(--ink-dim); }
.pname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The override a click performs, revealed on the pill itself rather than left
   in a title attribute nothing on a touch screen will ever show. */
.pact {
  margin-left: auto; flex: none; font-size: 9px; font-weight: 700;
  letter-spacing: 1px; color: var(--ink-faint);
  opacity: 0; transition: opacity .15s;
}
.paddler.act { cursor: pointer; }
.paddler.act:hover, .paddler.act:focus-visible {
  background: var(--panel-2); border-color: var(--border);
}
.paddler.act:hover .pact, .paddler.act:focus-visible .pact { opacity: 1; }
.rgroup.go .paddler.act:hover .pact { color: var(--accent); }
.rgroup.no .paddler.act:hover .pact,
.rgroup.maybe .paddler.act:hover .pact { color: var(--ok); }
@media (prefers-reduced-motion: reduce) {
  .tally-bar .seg, .pact, .rchev { transition: none; }
}
.practice-actions {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border);
}
.release-toggle {
  display: flex; align-items: center; gap: 6px; margin-right: auto;
  color: var(--ink-dim); font-size: 12px; cursor: pointer;
}
.release-toggle input { accent-color: var(--ok); width: 15px; height: 15px; }
.release-badge {
  margin-top: 12px; color: var(--ok);
  font-weight: 600; font-size: 11px; letter-spacing: 1px;
}

.header-controls { display: flex; align-items: center; gap: 10px; }

/* ---------- ME (paddler profile + attendance) ---------- */
.anon-nudge {
  background: rgba(255,184,0,.08); border: 1px solid rgba(255,184,0,.3);
  color: var(--accent-2); border-radius: 8px; padding: 10px 12px;
  font-size: 12px; margin-bottom: 14px;
}
.me-form { display: flex; flex-direction: column; gap: 4px; max-width: 520px; }
.me-form input {
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
  color: var(--ink); padding: 10px 12px; font-size: 14px; font-family: inherit;
  margin-bottom: 6px;
}
.me-form input:focus { outline: none; border-color: var(--accent); }
.opt-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.opt {
  background: var(--panel); border: 1px solid var(--border); border-radius: 6px;
  color: var(--ink-dim); padding: 8px 14px; font-size: 12px; cursor: pointer;
  font-family: inherit; letter-spacing: .5px;
}
.opt.on { background: var(--accent); border-color: var(--accent); color: #fff; }

#meAttendance .practice-card { max-width: 560px; }
.my-seat {
  margin: 8px 0; color: var(--ok); font-weight: 600;
  font-size: 13px; letter-spacing: 1px;
}
.att-row { display: flex; gap: 8px; margin-top: 10px; }
.att-btn {
  flex: 1; padding: 10px; border-radius: 6px; cursor: pointer; font-family: inherit;
  font-size: 12px; letter-spacing: 1px; border: 1px solid var(--border);
  background: var(--bg); color: var(--ink-dim);
}
.att-btn:disabled { opacity: .5; cursor: not-allowed; }
.att-btn.go.on { background: rgba(46,204,113,.15); border-color: var(--ok); color: var(--ok); }
.att-btn.no.on { background: rgba(217,58,30,.15); border-color: var(--accent); color: var(--accent); }
.att-hint { margin-top: 8px; font-size: 11px; color: var(--ink-faint); }
.lock-note { margin-top: 8px; font-size: 12px; color: var(--ink-dim); }

/* ---------- SEATING / BOAT LINEUP ---------- */
.seating-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
}
.seating-head .section-title { margin: 0; flex: 1 1 auto; }
.seating-actions { display: flex; gap: 8px; }
/* ---------- TRIM GAUGE ----------
   The hull heels by --tilt; the two meters fill out from centre by --lr and
   --bs. All three are set from JS after the subtree is rebuilt (see
   renderSeating), which is what gives them something to animate between. */
.trim {
  --tilt: 0deg; --lr: 0%; --bs: 0%;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 12px 16px 14px; margin-bottom: 14px;
  display: grid; gap: 4px 14px; align-items: center;
  /* auto, NOT 1fr, on the two number columns: 1fr let them grow and squeezed
     the hull out of existence on a phone, which is the one element here that
     has to survive a narrow screen. */
  grid-template-columns: auto minmax(120px, 1fr) auto;
  grid-template-areas: "left stage right" "status status status" "meters meters meters";
}
.trim-side { display: flex; flex-direction: column; gap: 0; }
.trim-side.l { grid-area: left; align-items: flex-end; text-align: right; }
.trim-side.r { grid-area: right; align-items: flex-start; }
.trim-cap { font-size: 9px; letter-spacing: 1.5px; color: var(--ink-faint); font-weight: 600; }
.trim-side b { font-size: 22px; font-weight: 700; color: var(--ink); line-height: 1.15; }
.trim-side i { font-size: 10px; font-style: normal; color: var(--ink-faint); }
/* The heavy side is the one the coach has to move somebody off, so it is the
   one that gets named — but only once the list is past the trim threshold. */
.trim.warn.heavy-left  .trim-side.l b,
.trim.warn.heavy-right .trim-side.r b { color: var(--accent-2); }

.trim-stage {
  grid-area: stage; position: relative;
  height: 100px; width: 100%; max-width: 520px; margin: 0 auto;
  /* Clipped, so a hard-over hull sinks INTO the water rather than hanging out
     below it. The extra headroom above the hull is what keeps the same clip
     from lopping the raised gunwale off at full heel. */
  overflow: hidden; border-radius: 4px;
}
/* aspect-ratio, not a top/bottom box: an SVG scales to its WIDTH under the
   default preserveAspectRatio, so a box of the wrong shape just overflows it
   and leaves the real size of the hull up to chance. Sized here, clipped by the
   stage on purpose. */
.trim-hull {
  position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
  width: min(250px, 100%); height: auto; aspect-ratio: 148 / 58; overflow: visible;
}
.hull-pivot {
  transform: rotate(var(--tilt)); transform-origin: 74px 34px;
  transition: transform .7s cubic-bezier(.34, 1.3, .55, 1);
}
.hull-shell { fill: var(--panel-2); stroke: var(--ink-dim); stroke-width: 2; stroke-linejoin: round; }
.hull-gunwale { stroke: var(--ink); stroke-width: 3; stroke-linecap: round; }
.hull-stripe { stroke: var(--accent); stroke-width: 2; stroke-linecap: round; opacity: .8; }

/* The water sits in FRONT of the hull, so the low gunwale visibly dips into it
   as the boat heels. Flat wash plus one very low-contrast ripple: at any more
   contrast than this the band stops reading as water and starts reading as a
   striped plank the boat is balanced on. */
.trim-water {
  position: absolute; left: 0; right: 0; bottom: 0; height: 30px;
  border-top: 2px solid var(--ok);
  background-color: var(--water);
  background-image: repeating-linear-gradient(100deg,
    rgba(255,255,255,.045) 0 16px, rgba(0,0,0,0) 16px 38px);
  border-radius: 3px;
  transition: border-color .4s, background-color .4s;
  animation: trim-drift 6s linear infinite;
}
.trim.warn .trim-water { border-top-color: var(--accent-2); }
@keyframes trim-drift { to { background-position: 38px 0; } }

.trim-status {
  grid-area: status; display: flex; justify-content: center; align-items: center;
  gap: 8px; margin-top: 4px; flex-wrap: wrap;
}
.trim-badge {
  font-size: 10px; font-weight: 700; letter-spacing: 1.5px;
  padding: 3px 9px; border-radius: 999px;
}
.trim.ok   .trim-badge { color: var(--ok);       background: rgba(46,204,113,.12); }
.trim.lean .trim-badge { color: var(--ink-dim);  background: var(--panel-2); }
.trim.warn .trim-badge { color: var(--accent-2); background: rgba(255,184,0,.12);
  animation: trim-pulse 2s ease-in-out infinite; }
.trim-note {
  font-size: 9px; font-weight: 600; letter-spacing: 1px; color: var(--ink-faint);
}
@keyframes trim-pulse { 50% { background-color: rgba(255,184,0,.3); } }
.trim-delta { font-size: 11px; font-weight: 600; color: var(--ink-dim); }

.trim-meters { grid-area: meters; display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.meter { display: flex; align-items: center; gap: 8px; }
.meter-end {
  flex: 0 0 auto; min-width: 66px; font-size: 9px; letter-spacing: 1px;
  color: var(--ink-faint); font-weight: 600;
  display: flex; align-items: baseline; gap: 4px;
}
.meter-end:first-child { justify-content: flex-end; }
.meter-end:last-child { justify-content: flex-start; }
.meter-end b { font-size: 12px; color: var(--ink-dim); font-weight: 600; letter-spacing: 0; }
.meter-track {
  position: relative; flex: 1 1 auto; height: 6px; border-radius: 3px;
  background: var(--bg); border: 1px solid var(--border); overflow: hidden;
}
/* Fills out from dead centre TOWARDS THE HEAVY END — so it grows under the
   label of the side carrying the weight — which makes "level" an empty track,
   the one state worth confirming without reading a number. */
.meter-fill {
  position: absolute; top: 0; bottom: 0; border-radius: 3px;
  background: var(--ok);
  transition: left .6s cubic-bezier(.3,.9,.4,1), width .6s cubic-bezier(.3,.9,.4,1), background-color .4s;
}
.meter-fill.lr { left: calc(50% - max(var(--lr), 0%)); width: max(var(--lr), calc(-1 * var(--lr))); }
.meter-fill.bs { left: calc(50% - max(var(--bs), 0%)); width: max(var(--bs), calc(-1 * var(--bs))); }
.meter.lean .meter-fill { background: var(--ink-dim); }
.meter.warn .meter-fill { background: var(--accent-2); }
/* How far off centre the boat may sit and still come out level once the caller
   and steer settle. A fill inside this band is not something to go and fix. */
.meter-band {
  position: absolute; top: 0; bottom: 0; left: 50%; transform: translateX(-50%);
  border-radius: 3px; background: var(--panel-2);
  /* Edges, not just a wash: where the tolerance ENDS is the whole point, and
     the band's fill is deliberately too quiet to mark it on its own. */
  border-left: 1px solid var(--border); border-right: 1px solid var(--border);
  transition: width .6s cubic-bezier(.3,.9,.4,1);
}
.meter-centre {
  position: absolute; left: 50%; top: -1px; bottom: -1px; width: 1px;
  background: var(--ink-faint); opacity: .55;
}

@media (max-width: 560px) {
  .trim { padding: 12px 10px; gap: 4px 10px; }
  .trim-side b { font-size: 18px; }
  .trim-stage { height: 88px; }
  .trim-hull { width: min(210px, 100%); top: 8px; }
  .meter-end { min-width: 58px; }
}
/* A hull that heels and water that drifts are decoration on top of numbers that
   are already correct, so both come off entirely here. */
@media (prefers-reduced-motion: reduce) {
  .hull-pivot, .meter-fill, .meter-band, .tally-bar .seg { transition: none; }
  .trim-water, .trim.warn .trim-badge { animation: none; }
}

.seating-body { display: grid; grid-template-columns: minmax(260px, 380px) 1fr; gap: 20px; align-items: start; }
.boat {
  background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 60px 60px 40px 40px;
  padding: 14px 10px; display: flex; flex-direction: column; gap: 6px;
}
.boat-end { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 4px 0; }
.end-label { font-size: 8px; letter-spacing: 2px; color: var(--ink-faint); font-weight: 600; }
.boat-row { display: grid; grid-template-columns: 1fr 24px 1fr; align-items: center; gap: 6px; }
.row-num { text-align: center; font-size: 10px; color: var(--ink-faint); font-weight: 600; }
.seat {
  min-height: 40px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--border); background: var(--bg); color: var(--ink);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 4px 6px; font-family: inherit; transition: border-color .12s, background .12s;
}
.seat.empty { color: var(--ink-faint); border-style: dashed; }
.seat.empty .seat-idx { font-size: 11px; font-weight: 600; }
.seat.empty.armed { border-color: var(--accent); color: var(--accent); }
.seat.filled { background: var(--panel); border-color: var(--accent); }
.seat.filled:hover { border-color: var(--warn); }
.seat-name { font-size: 12px; font-weight: 600; line-height: 1.1; text-align: center; }
.seat-meta { font-size: 9px; color: var(--ink-dim); font-weight: 600; }
.boat-end .seat { min-width: 120px; }

.seat-pool { display: flex; flex-direction: column; gap: 8px; }
.pool-title { font-size: 10px; letter-spacing: 1px; color: var(--ink-faint);
  font-weight: 600; margin-bottom: 2px; }
.pool-chip {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  text-align: left; cursor: pointer; width: 100%;
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
  padding: 8px 12px; color: var(--ink); font-family: inherit;
}
.pool-chip.selected { border-color: var(--accent); background: rgba(217,58,30,.08); }
.chip-name { font-size: 13px; font-weight: 600; }
.chip-meta { font-size: 11px; color: var(--ink-dim); font-weight: 600; }

/* Drag to move. The long-press that starts a drag on a phone would otherwise
   select the name or raise the iOS callout sheet. */
.seat, .pool-chip { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.seat.filled, .pool-chip { cursor: grab; }
.seat.drag-src, .pool-chip.drag-src { opacity: .35; }
.seat.drop-over { border-color: var(--accent); border-style: solid; background: rgba(217,58,30,.14); }
.seat-pool.drop-over { outline: 1px dashed var(--accent); outline-offset: 6px; border-radius: 8px; }
/* Sits above the finger rather than under it, so the name stays readable. */
.seat-ghost {
  position: fixed; left: 0; top: 0; z-index: 1000; pointer-events: none;
  margin: -46px 0 0 -60px; min-width: 120px; text-align: center;
  padding: 8px 12px; border-radius: 6px;
  background: var(--panel); border: 1px solid var(--accent); color: var(--ink);
  font-size: 12px; font-weight: 600; box-shadow: 0 8px 22px rgba(0,0,0,.35);
}
body.seat-dragging, body.seat-dragging * { cursor: grabbing !important; }
/* A side the coach set rather than the paddler. */
.by-coach { text-decoration: underline dotted; text-underline-offset: 2px; color: var(--ink); }

@media (max-width: 640px) {
  .seating-body { grid-template-columns: 1fr; }
}

/* ---------- FIRST-RUN SETUP ----------
   One question per screen. The panel is a little wider than the login panel it
   shares a class with, because the choice cards carry a line of explanation
   each — at 420px those wrap to three lines and the screen stops looking like
   a single question. */
.setup-panel { max-width: 480px; }
.setup-panel h2 { margin-top: 4px; }

.setup-progress {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 18px;
}
.setup-dots { display: flex; gap: 6px; align-items: center; }
.setup-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--border); transition: background .2s ease, transform .2s ease;
}
.setup-dot.done { background: var(--ink-faint); }
.setup-dot.on { background: var(--accent); transform: scale(1.4); }
.setup-count {
  font-size: 10px; font-weight: 600; letter-spacing: .12em; color: var(--ink-faint);
}

.setup-choices { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; }
.setup-card {
  display: flex; flex-direction: column; gap: 4px; text-align: left;
  padding: 14px 16px; border-radius: 10px; cursor: pointer;
  background: var(--bg); border: 1px solid var(--border);
  color: var(--ink); font-family: inherit; width: 100%;
  transition: border-color .15s ease, background .15s ease;
}
.setup-card:hover { border-color: var(--accent); }
.setup-card.on { border-color: var(--accent); background: rgba(217,58,30,.08); }
.setup-card-label { font-weight: 700; font-size: 13px; letter-spacing: .08em; }
.setup-card-desc { color: var(--ink-dim); font-size: 12.5px; line-height: 1.45; font-weight: 400; }

/* SKIP sits opposite BACK rather than under the primary button: it should be
   findable without competing with the answer the screen is actually asking
   for. */
.setup-nav {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-top: 10px;
}

.setup-tabs { display: flex; gap: 6px; margin-top: 16px; }
.setup-tab {
  flex: 1; padding: 9px; border-radius: 6px; cursor: pointer;
  background: transparent; border: 1px solid var(--border);
  color: var(--ink-faint); font-family: inherit;
  font-size: 11px; font-weight: 600; letter-spacing: .1em;
}
.setup-tab.active { border-color: var(--accent); color: var(--ink); }

/* Six bands, two columns — one column makes the list feel like a form to work
   through, three squeezes the range label out. */
.size-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px;
}
.size-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 12px 14px; border-radius: 10px; cursor: pointer;
  background: var(--bg); border: 1px solid var(--border);
  color: var(--ink); font-family: inherit;
  transition: border-color .15s ease, background .15s ease;
}
.size-card:hover { border-color: var(--accent); }
.size-card.on { border-color: var(--accent); background: rgba(217,58,30,.08); }
.size-letter { font-weight: 700; font-size: 15px; letter-spacing: .06em; }
.size-range { font-size: 11px; color: var(--ink-dim); font-weight: 500; }

.input-error { border-color: var(--warn) !important; }

/* ---------- PROFILE: SIZE ESTIMATE ---------- */
.est-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.est-label {
  font-weight: 600; font-size: 9px; letter-spacing: .2em; color: var(--ink-faint);
}
.est-row .opt-row { margin-bottom: 0; }
.est-note {
  font-size: 11.5px; line-height: 1.5; color: var(--ink-dim);
  margin-top: 6px; padding-left: 10px; border-left: 2px solid var(--border);
}

/* ---------- INCOMPLETE-PROFILE NUDGE ----------
   --accent-2, not --accent: this is a "worth doing" prompt, and Dragon Red is
   reserved for the live/destructive controls. */
.setup-nudge {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 0 0 18px; padding: 12px 14px;
  background: rgba(255,184,0,.08);
  border: 1px solid rgba(255,184,0,.35);
  border-radius: 8px;
}
.setup-nudge-text { flex: 1 1 220px; font-size: 13px; line-height: 1.5; color: var(--ink); }
.setup-nudge-text b { font-weight: 700; }

/* ---------- INVITE-YOUR-COACH LINE ---------- */
.invite-copy {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 12px; margin-top: 8px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 8px;
}
.invite-copy code {
  flex: 1 1 200px; font-size: 11.5px; line-height: 1.5;
  color: var(--ink-dim); word-break: break-word; font-family: inherit;
}

@media (max-width: 480px) {
  .size-grid { grid-template-columns: 1fr; }
  .setup-panel { max-width: none; }
}

/* ---------- START A CREW / JOIN A CREW ----------
   The path question, the team-name screens and the invite page. Everything
   tappable here is at least 56px tall, like the run panel: the person on the
   other end of an invite is as likely to be on the dock as at a desk. */
.setup-card-big { min-height: 72px; justify-content: center; padding: 16px 18px; }
.setup-card-big .setup-card-label { font-size: 14px; }

/* "You've been invited to X" — the one thing the invited paddler has to read,
   so it carries the gold "worth doing" treatment rather than being a hint. */
.invite-banner {
  margin: 4px 0 12px; padding: 12px 14px;
  background: rgba(255,184,0,.08);
  border: 1px solid rgba(255,184,0,.35);
  border-radius: 8px;
  font-size: 14px; line-height: 1.45; color: var(--ink);
}
.invite-banner b { color: var(--accent-2); letter-spacing: .04em; }
.team-error { font-size: 13px; }

.invite-panel { text-align: left; }
.invite-kicker { margin-top: 0; }
.invite-panel h2.invite-team {
  font-size: 30px; font-weight: 800; letter-spacing: .02em;
  margin: 0 0 10px; overflow-wrap: anywhere;
}
/* Always black on white, whatever the theme: scanners want dark modules on a
   light field with a quiet zone around it, and a dark-mode inversion is the
   classic reason a code on a screen won't read. The quiet zone is in the image
   itself, so this frame is only there to keep it off the panel colour. */
.invite-qr {
  display: flex; justify-content: center;
  margin: 16px auto 14px; padding: 0;
  background: #fff; border-radius: 10px;
  width: min(100%, 328px);
}
.invite-qr img {
  display: block; width: 100%; height: auto; min-width: 240px;
  image-rendering: pixelated;
  border-radius: 10px;
}
.invite-link code { font-size: 12.5px; color: var(--ink); user-select: all; }
.invite-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px; }
.invite-actions .btn:only-child { grid-column: 1 / -1; }

/* ---------- NEW-TEAM CHECKLIST (top of the Live tab) ---------- */
.checklist-card {
  margin: 0 0 14px; padding: 14px 16px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
}
.checklist-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.checklist-title { font-weight: 700; font-size: 15px; }
.checklist-progress { font-size: 11px; font-weight: 600; letter-spacing: .1em; color: var(--ink-faint); margin-top: 2px; }
.checklist-bar { height: 4px; border-radius: 2px; background: var(--border); margin: 12px 0 8px; overflow: hidden; }
.checklist-bar span { display: block; height: 100%; background: var(--ok); transition: width .3s ease; }
.checklist-items {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 4px 12px;
}
.checklist-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 44px; padding: 8px 6px; text-align: left;
  background: none; border: 0; border-radius: 6px;
  color: var(--ink); font: inherit; font-size: 13.5px; font-weight: 600;
}
button.checklist-item { cursor: pointer; }
@media (hover: hover) { button.checklist-item:hover { background: var(--panel-2, rgba(255,255,255,.04)); } }
.checklist-item.done { color: var(--ink-faint); font-weight: 500; }
.checklist-tick {
  flex: none; width: 20px; height: 20px; border-radius: 50%;
  border: 1.5px solid var(--ink-faint);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800;
}
.checklist-item.done .checklist-tick { background: var(--ok); border-color: var(--ok); color: #fff; }
.checklist-go { margin-left: auto; color: var(--ink-faint); font-size: 18px; }

/* Read by a screen reader, not drawn — for state a tick only shows. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- PRACTICE PLANS ----------
   The builder modal, the practice page, the Run practice panel and the
   "practice running" banner. A piece carries the red rule down its left edge
   wherever a plan is listed, so pieces (the steps that load on the boat) stand
   out from drills at a glance. */
textarea {
  width: 100%; resize: vertical; min-height: 60px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 3px;
  color: var(--ink); font-family: inherit; font-weight: 500; font-size: 14px;
  padding: 10px 12px; outline: none;
}
textarea:focus { border-color: var(--accent); }
.modal-wide { max-width: 640px; }
.form-problem {
  margin-top: 12px; padding: 8px 10px; border-radius: 3px;
  border: 1px solid rgba(217,58,30,.35); background: rgba(217,58,30,.08);
  color: var(--ink); font-size: 12px; line-height: 1.5;
}
.form-problem[hidden] { display: none; }

.pb-steps {
  list-style: none; margin: 10px 0 4px; padding: 0;
  display: flex; gap: 6px; flex-wrap: wrap;
}
.pb-step-ind {
  display: flex; align-items: center; gap: 6px;
  background: transparent; border: 1px solid var(--border); border-radius: 999px;
  color: var(--ink-faint); font-family: inherit; font-size: 10px; font-weight: 700;
  letter-spacing: .12em; padding: 5px 10px 5px 5px; cursor: pointer;
}
.pb-step-ind:disabled { cursor: default; opacity: .6; }
.pb-step-ind.on { border-color: var(--accent); color: var(--ink); }
.pb-step-ind.done { color: var(--ink-dim); }
.pb-step-num {
  width: 18px; height: 18px; border-radius: 50%; display: grid; place-items: center;
  background: var(--bg); border: 1px solid var(--border); font-size: 10px; letter-spacing: 0;
}
.pb-step-ind.on .pb-step-num { background: var(--accent); border-color: var(--accent); color: #fff; }
.pb-body[hidden] { display: none; }
.pb-body .hint { margin: 12px 0; }

.plan-list { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 6px; }
.plan-step, .pb-row, .pb-form {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--bg); border: 1px solid var(--border);
  border-left: 3px solid var(--border); border-radius: 4px;
  padding: 10px 12px;
}
.practice-card .plan-step, .practice-card .pb-row { background: var(--panel); }
.plan-step.piece, .pb-row.piece, .pb-form.piece { border-left-color: var(--accent); }
.plan-step.now { border-color: var(--ok); }
.plan-step.now.piece { border-left-color: var(--accent); }
.plan-num {
  flex: none; min-width: 18px; padding-top: 1px;
  color: var(--ink-faint); font-weight: 700; font-size: 12px; font-variant-numeric: tabular-nums;
}
.plan-body, .pb-info { flex: 1; min-width: 0; }
.plan-title { font-weight: 600; font-size: 14px; color: var(--ink); overflow-wrap: anywhere; }
.plan-detail { margin-top: 3px; font-weight: 600; font-size: 11px; color: var(--ink-dim); }
.plan-notes { margin-top: 4px; font-size: 12px; color: var(--ink-dim); line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }
.plan-tag {
  display: inline-block; margin-left: 8px; vertical-align: 2px;
  font-size: 9px; font-weight: 700; letter-spacing: .14em; color: var(--ink-faint);
  border: 1px solid var(--border); border-radius: 2px; padding: 1px 5px;
}
.plan-tag.now { color: var(--ok); border-color: var(--ok); }
.plan-step .btn { flex: none; align-self: center; }

.pb-row-actions { display: flex; gap: 4px; flex: none; }
.pb-row-actions .btn { padding: 6px 9px; }
.pb-form { flex-direction: column; align-items: stretch; gap: 0; }
.pb-form .field-label { margin-top: 12px; }
.pb-form-head { font-size: 10px; font-weight: 700; letter-spacing: .16em; color: var(--ink-faint); margin-bottom: 4px; }
.pb-form-actions { display: flex; justify-content: flex-end; gap: 6px; margin-top: 10px; }
.pb-add { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
.pb-totals {
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border);
  font-weight: 600; font-size: 12px; color: var(--ink-dim);
}
.pb-picker-head { display: flex; align-items: center; justify-content: space-between; margin-top: 12px; }
.pb-picker-head .field-label { margin: 0; }
.pb-picker { display: grid; gap: 6px; margin-top: 8px; max-height: 260px; overflow-y: auto; }
.pb-pick {
  display: flex; flex-direction: column; gap: 2px; text-align: left; cursor: pointer;
  background: var(--bg); border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 4px; padding: 9px 12px; font-family: inherit;
}
.pb-pick:hover, .pb-pick:focus-visible { border-color: var(--ink-faint); border-left-color: var(--accent); }
.pb-review-head { margin: 12px 0 4px; }
.pb-release { margin-top: 16px; font-size: 14px; color: var(--ink); }
.pb-release-hint { margin: 6px 0 0; font-size: 12px; }
@media (max-width: 480px) {
  .pb-row { flex-wrap: wrap; }
  .pb-row-actions { width: 100%; justify-content: flex-end; }
}

/* A summary row / card title that opens the practice page. A real <button>,
   reset to look like the card it sits in. */
.practice-open {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: transparent; border: 0; padding: 0; margin: 0;
  text-align: left; font-family: inherit; color: inherit; cursor: pointer;
}
.practice-card.practice-open { background: var(--panel); border: 1px solid var(--border); padding: 14px; }
.practice-open:hover .practice-title, .practice-open:focus-visible .practice-title { text-decoration: underline; }
.practice-open:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }
.practice-open-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.practice-open-chev { flex: none; color: var(--ink-faint); font-size: 22px; line-height: 1; }
.practice-row-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.practice-row-meta .tally-nums { margin-top: 0; }
.plan-hint {
  display: inline-block; margin-top: 6px;
  font-size: 11px; font-weight: 600; letter-spacing: .06em; color: var(--ink-dim);
}
.practice-row-meta .plan-hint { margin-top: 0; }
.plan-hint.ok { color: var(--ok); }
.not-released {
  display: inline-block; margin-left: 6px;
  font-size: 9px; font-weight: 700; letter-spacing: .14em; color: var(--accent-2);
  border: 1px solid rgba(255,184,0,.35); border-radius: 2px; padding: 1px 5px;
}
.run-badge {
  display: inline-block; margin-left: 8px; vertical-align: 3px;
  font-size: 9px; font-weight: 700; letter-spacing: .14em; color: #fff;
  background: var(--accent); border-radius: 2px; padding: 2px 6px;
}

/* Practice page */
.pd-head { margin-bottom: 14px; }
.pd-title { font-weight: 700; font-size: 26px; letter-spacing: -0.01em; margin: 0 0 4px; overflow-wrap: anywhere; }
.pd-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.pd-actions .btn-big { flex: 1 1 240px; }
.pd-section-head { gap: 12px; flex-wrap: wrap; }
.pd-section-head .section-title { margin-bottom: 4px; }
.pd-totals { color: var(--ink-faint); letter-spacing: .06em; }
.pd-toggle { margin-right: 0; margin-top: 10px; }
.pd-attendance .tally { margin-top: 0; }
.pd-lineup { margin-top: 0; padding-top: 0; border-top: 0; }
.pd-rsvp { max-width: 560px; }

/* Big, full-width buttons: the run panel is meant for wet hands on the water,
   so every primary control is at least 56px tall. */
.btn-big { min-height: 56px; font-size: 14px; letter-spacing: .14em; padding: 14px 18px; }

/* Run practice */
#view-run { max-width: 640px; margin: 0 auto; }
.run-top { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.run-top-text { flex: 1; min-width: 0; text-align: center; }
.run-practice { font-weight: 700; font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.run-progress { font-weight: 600; font-size: 12px; letter-spacing: .12em; color: var(--ink-dim); margin-top: 2px; }
.run-now, .run-next {
  background: var(--panel); border: 1px solid var(--border);
  border-left: 4px solid var(--border); border-radius: 6px;
}
.run-now { padding: 18px 18px 16px; }
.run-now.piece, .run-next.piece { border-left-color: var(--accent); }
.run-label { font-size: 10px; font-weight: 700; letter-spacing: .2em; color: var(--ink-faint); margin-bottom: 6px; }
.run-now .run-label { color: var(--ok); }
.run-step-title { font-weight: 800; font-size: 30px; line-height: 1.15; letter-spacing: -0.01em; overflow-wrap: anywhere; }
.run-detail { margin-top: 6px; font-weight: 600; font-size: 14px; color: var(--ink-dim); }
.run-notes { margin-top: 10px; font-size: 15px; line-height: 1.5; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; }
.run-intervals {
  margin: 12px 0 0; padding: 10px 0 0 22px; border-top: 1px solid var(--border);
  display: grid; gap: 4px; font-size: 14px; color: var(--ink-dim);
}
.run-intervals b { color: var(--ink); font-weight: 700; letter-spacing: .06em; }
.run-buttons { display: grid; gap: 10px; margin: 12px 0; }
.run-buttons .btn-big { width: 100%; }
.run-start { color: var(--ok); border-color: var(--ok); font-weight: 700; }
.run-start:hover { color: var(--ok); border-color: var(--ok); filter: brightness(1.1); }
.run-next { padding: 12px 16px; margin-top: 12px; }
.run-next-title { font-weight: 700; font-size: 17px; overflow-wrap: anywhere; }
.run-next .run-detail { font-size: 12px; }
.run-nav { display: flex; gap: 12px; margin-top: 18px; }
.run-nav .btn-big { flex: 1; }
/* Smaller than NEXT on purpose, but still a real target. */
.run-back { flex: 0 0 30%; min-height: 56px; }
.run-hint { text-align: center; margin: 8px 0 0; font-size: 12px; }

/* Practice running banner */
.run-banner {
  display: flex; align-items: center; gap: 10px; width: 100%;
  margin: 0 0 12px; padding: 9px 12px; cursor: pointer; text-align: left;
  background: var(--panel); border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 4px; font-family: inherit; font-size: 12px; color: var(--ink-dim);
}
.run-banner b { color: var(--ink); letter-spacing: .12em; font-weight: 700; }
.run-banner:hover { border-color: var(--ink-faint); border-left-color: var(--accent); color: var(--ink); }
.run-banner-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.run-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex: none; animation: run-pulse 1.6s ease-in-out infinite; }
@keyframes run-pulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .run-dot { animation: none; } }
/* Secondary to NEXT STEP, which already loads each piece as the boat arrives
   at it — this is the re-send, for a phone that joined late. Kept off the red
   so the screen has one obvious next move. */
.run-load { color: var(--ink); border-color: var(--ink-faint); font-weight: 700; }
