/* ============================================================
   VECQUA: LANELINE ENGINE — theme.css
   One custom-property block per theme (C1/C5):
     - chill-mode   : default (light, faint borders, subtle shadows)
     - deck-mode     : body.deck-mode (deep slate, neon-cyan glow, volt accents)
     - outdoor-deck  : body.deck-mode.outdoor-deck (light ultra-contrast for sun)
   Theme switching is ONLY via classList.add/remove('deck-mode') on <body>.
   System font stacks only (D4) — zero web-font bytes, fully offline.

   ┌─ TO RESTYLE (single source of truth) ──────────────────────────────────┐
   │ Colours, spacing, radius, fonts live entirely in the CSS variable blocks │
   │ below (:root = chill, body.deck-mode = deck, body.deck-mode.outdoor-deck │
   │ = outdoor). Change a value once there and it flows through every screen. │
   │ Brand colours: --brand-cyan / --brand-volt. Card look: --radius-card,    │
   │ --card-border, --card-shadow, --card-glow. No colours are hard-coded in  │
   │ the component rules — always reference var(--…).                         │
   └─────────────────────────────────────────────────────────────────────────┘
   ============================================================ */

/* ---- Font stacks (system, offline) ---- */
:root {
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "SFMono-Regular", "Cascadia Code", "Roboto Mono", "Consolas", "Liberation Mono", Menlo, monospace;

  /* Brand constants */
  --brand-cyan: #22d3ee;
  --brand-volt: #a3e635;

  /* Layout constants */
  --nav-height: 68px;
  --radius-card: 12px;
  --data-size: 1rem;

  /* ---- CHILL MODE (light) — default tokens ----
     Neutrals carry a teal bias on purpose. Deck's whole identity is the
     accent-outlined panel; a pure-slate chill read as "deck with the lights
     off", so chill gets the same structural signal in a daylight register:
     a visible teal-tinted edge and a teal-tinted (never grey) shadow. */
  --bg: #eaf2f5;
  --surface: #ffffff;
  --surface-2: #f0f6f8;
  --card-border: #c5dbe3;
  --card-shadow: 0 1px 2px rgba(12, 74, 91, 0.07), 0 10px 24px -14px rgba(12, 74, 91, 0.35);
  --card-glow: none;
  --text: #0f172a;
  --text-muted: #475569;
  --text-faint: #64748b;
  --accent: #0e7490;          /* dark cyan — AA on light */
  --accent-strong: #155e75;
  --positive: #4d7c0f;        /* dark volt — AA on light */
  --positive-glow: none;
  --neutral: #475569;         /* neutral slate for negative deltas (never red) */
  --danger: #dc2626;          /* data-entry errors ONLY (Law 1) */
  --nav-bg: rgba(255, 255, 255, 0.92);
  --nav-border: #e2e8f0;
  --toggle-bg: rgba(255, 255, 255, 0.55);
  --toggle-border: rgba(148, 163, 184, 0.45);
  --focus-ring: #0e7490;
  --overlay: rgba(15, 23, 42, 0.55);
  /* Effort/urgency accents (amber→orange; NEVER red — Law 1). Chill values are darkened to
     clear WCAG AA on the light surface; deck/outdoor override below. */
  --effort-mid: #b45309;      /* RPE threshold zone */
  --effort-high: #c2410c;     /* RPE terminal zone */
  --urgent: #c2410c;          /* pipeline-clock urgency */
}

/* ---- DECK MODE (dark, meet session) ---- */
body.deck-mode {
  --bg: #020617;
  --surface: #0f172a;
  --surface-2: #1e293b;
  --card-border: #22d3ee;
  --card-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
  --card-glow: 0 0 0 2px rgba(34, 211, 238, 0.35), 0 0 18px rgba(34, 211, 238, 0.18);
  --text: #e2e8f0;
  --text-muted: #94a3b8;
  --text-faint: #64748b;
  --accent: #22d3ee;
  --accent-strong: #67e8f9;
  --positive: #a3e635;
  --positive-glow: 0 0 12px rgba(163, 230, 53, 0.5);
  --neutral: #94a3b8;
  --danger: #f87171;
  --nav-bg: rgba(2, 6, 23, 0.94);
  --nav-border: rgba(34, 211, 238, 0.28);
  --toggle-bg: rgba(15, 23, 42, 0.55);
  --toggle-border: rgba(34, 211, 238, 0.4);
  --focus-ring: #22d3ee;
  --overlay: rgba(2, 6, 23, 0.7);
  --data-size: 1.25rem;       /* deck-mode data text ≥20px (C12) */
  --effort-mid: #f0b64d;      /* brighter on dark slate */
  --effort-high: #fb923c;
  --urgent: #fb923c;
}

/* ---- OUTDOOR DECK VARIANT (light ultra-contrast, sun-readable, C1) ---- */
body.deck-mode.outdoor-deck {
  --bg: #ffffff;
  --surface: #ffffff;
  --surface-2: #f1f5f9;
  --card-border: #0f172a;
  --card-shadow: none;
  --card-glow: 0 0 0 2px #0f172a;
  --text: #000000;
  --text-muted: #1e293b;
  --text-faint: #334155;
  --accent: #0e7490;
  --accent-strong: #155e75;
  --positive: #3f6212;
  --positive-glow: none;
  --neutral: #1e293b;
  --danger: #b91c1c;
  --nav-bg: #ffffff;
  --nav-border: #0f172a;
  --toggle-bg: rgba(255, 255, 255, 0.8);
  --toggle-border: #0f172a;
  --focus-ring: #0e7490;
  --effort-mid: #9a3412;      /* dark on ultra-contrast white */
  --effort-high: #9a3412;
  --urgent: #9a3412;
}

/* ============================================================
   RESET / BASE
   ============================================================ */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
/* The `hidden` attribute must always win. Any rule that sets `display` (e.g. .btn's
   inline-flex) otherwise silently beats the UA default and el.hidden = true does
   nothing — which is how the landing page briefly showed its Install button AND its
   "install manually" fallback at the same time. */
[hidden] { display: none !important; }
body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 16px;                 /* body text ≥16px (C12) */
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  transition: background-color 0.3s ease, color 0.3s ease;
  -webkit-font-smoothing: antialiased;
  padding-bottom: env(safe-area-inset-bottom);
}
body.deck-mode { font-size: 17px; }

button { font-family: inherit; cursor: pointer; }
input, select, button { font-size: 16px; }   /* ≥16px prevents iOS zoom */

:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 4px;
}

.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ============================================================
   TAB LAYOUT
   ============================================================ */
#tab-host {
  min-height: 100vh;
  padding: 0 16px calc(var(--nav-height) + 24px);
  max-width: 720px;
  margin: 0 auto;
}
.tab-content { padding-top: max(20px, env(safe-area-inset-top)); }
.tab-content[hidden] { display: none; }

.tab-header { padding: 12px 4px 20px; }
/* v34 — 1.5rem/800 read chunky. Elegance is a smaller, lighter, tighter
   headline that lets the content below carry the page. */
.section-title {
  font-size: 1.32rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0;
}
.section-subtitle {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin: 4px 0 0;
}
h3 { font-size: 1rem; font-weight: 700; letter-spacing: -0.01em; margin: 0 0 8px; }

/* ---- Cards ---- */
.card {
  background: var(--surface);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-card);
  padding: 20px;
  margin-bottom: 16px;
  box-shadow: var(--card-shadow), var(--card-glow);
}

/* ---- Empty states (S-4) ---- */
.empty-state {
  text-align: center;
  padding: 48px 20px;
  color: var(--text-muted);
}
.empty-glyph { font-size: 2.6rem; margin-bottom: 12px; opacity: 0.85; }
.empty-title { font-size: 1.1rem; font-weight: 700; color: var(--text); margin: 0 0 6px; }
.empty-hint { font-size: 0.9rem; margin: 0; }

/* ============================================================
   BOTTOM NAV (fixed, 68px)
   ============================================================ */
.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  height: var(--nav-height);
  display: flex;
  background: var(--nav-bg);
  border-top: 1px solid var(--nav-border);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  z-index: 900;
  padding-bottom: env(safe-area-inset-bottom);
}
.nav-btn {
  flex: 1;
  min-height: 44px;               /* touch target ≥44px */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border: none;
  background: transparent;
  color: var(--text-faint);
  padding: 6px 0;
}
/* v32 — line-icons. Geometry-only symbols; stroke language lives here so every
   icon is one consistent weight and inherits the button's colour (faint → accent
   when active). */
.nav-btn .nav-icon {
  width: 25px; height: 25px;
  fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.nav-btn.active .nav-icon { stroke-width: 2; }
/* Empty-state badge icon: sits inside the dashed circle, brand-tinted but calm. */
.eg-ico {
  width: 38px; height: 38px;
  fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  color: var(--accent); opacity: 0.85;
}
.nav-btn .nav-label { font-size: 0.68rem; font-weight: 600; letter-spacing: 0.2px; }
.nav-btn.active { color: var(--accent); }
.nav-btn.active .nav-label { color: var(--accent); }

/* ============================================================
   GLASSMORPHIC THEME TOGGLE
   ============================================================ */
.theme-toggle {
  position: fixed;
  bottom: 84px;
  right: 16px;
  z-index: 998;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--toggle-border);
  background: var(--toggle-bg);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--text);
  font-size: 1.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
}
.theme-toggle-glyph { line-height: 1; }

/* ============================================================
   FIRST-RUN WIZARD
   ============================================================ */
.first-run {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.first-run[hidden] { display: none; }
.wizard-card {
  width: 100%;
  max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--card-border);
  border-radius: 16px;
  padding: 28px 24px;
  box-shadow: var(--card-shadow);
}
.wizard-brand {
  font-size: 1.6rem;
  font-weight: 800;
  letter-spacing: -0.5px;
  margin: 0 0 4px;
}
.wizard-brand .accent { color: var(--accent); }
.wizard-step-count { font-size: 0.78rem; color: var(--text-muted); margin: 0 0 22px; }
.wizard-label { display: block; font-size: 1.05rem; font-weight: 700; margin-bottom: 6px; }
.wizard-hint { font-size: 0.85rem; color: var(--text-muted); margin: 0 0 16px; }
.wizard-input, .wizard-select {
  width: 100%;
  padding: 14px;
  min-height: 48px;
  border: 1px solid var(--card-border);
  border-radius: 10px;
  background: var(--surface-2);
  color: var(--text);
  margin-bottom: 8px;
}
.wizard-progress {
  display: flex;
  gap: 6px;
  margin-bottom: 24px;
}
.wizard-dot {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: var(--card-border);
}
.wizard-dot.done { background: var(--accent); }

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 12px 22px;
  border: none;
  /* v36 — 10px was blocky, a full pill was too full. 14px is the considered
     middle: unmistakably round, but with enough straight edge left that the
     shape reads as drawn rather than defaulted. */
  border-radius: 14px;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.012em;
  background: var(--accent);
  color: #ffffff;
  width: 100%;
}
/* Solid buttons only — ghosts must keep their accent text, or deck-mode renders
   near-black-on-dark (found via screenshot review, v27). */
body.deck-mode .btn:not(.btn-ghost) { color: #041016; box-shadow: var(--positive-glow); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-ghost {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--card-border);
}
body.deck-mode .btn-ghost { color: var(--accent); border-color: rgba(34, 211, 238, 0.45); }

/* ---- Inline data-entry error (red permitted here ONLY, Law 1) ---- */
.field-error {
  color: var(--danger);
  font-size: 0.82rem;
  margin: 4px 0 0;
}

/* ============================================================
   UPDATE CHIP (S-6) + DEV BADGE
   ============================================================ */
.update-chip {
  position: fixed;
  left: 50%;
  bottom: calc(var(--nav-height) + 16px);
  transform: translateX(-50%);
  z-index: 999;
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--surface);
  border: 1px solid var(--card-border);
  border-radius: 999px;
  padding: 10px 12px 10px 18px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.2);
  font-size: 0.9rem;
}
.update-chip[hidden] { display: none; }
.update-chip button {
  border: none;
  background: var(--accent);
  color: #fff;
  border-radius: 999px;
  padding: 8px 16px;
  font-weight: 700;
}
.dev-test-badge {
  position: fixed;
  top: 8px;
  left: 8px;
  z-index: 1001;
  background: var(--danger);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  padding: 4px 8px;
  border-radius: 6px;
}
.dev-test-badge[hidden] { display: none; }
.dev-test-badge.pass { background: var(--positive); color: #041016; }

/* ============================================================
   TAB 1 — MEET PREP STATION
   ============================================================ */
.field-label { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; color: var(--text-muted); margin: 14px 0 6px; }
.field-hint { font-size: 0.82rem; color: var(--text-muted); margin: 6px 0 0; }

/* Segmented control */
/* v36 — the same considered radius as the buttons, nested one step tighter
   so the selected segment sits inside its track rather than matching it. */
.seg { display: flex; gap: 6px; background: var(--surface-2); border-radius: 14px; padding: 4px; }
.seg-btn {
  flex: 1; min-height: 44px; border: none; border-radius: 10px; background: transparent;
  color: var(--text-muted); font-weight: 700; font-size: 0.95rem; letter-spacing: 0.008em;
}
.seg-btn.on { background: var(--surface); color: var(--accent); box-shadow: var(--card-shadow); }
body.deck-mode .seg-btn.on { background: rgba(34,211,238,0.15); color: var(--accent-strong); box-shadow: none; }

/* Health switch */
.hsw { display: flex; align-items: center; justify-content: space-between; padding: 12px 0; border-bottom: 1px solid var(--card-border); }
.hsw:last-of-type { border-bottom: none; }
.hsw-label { font-size: 0.95rem; font-weight: 600; }
.hsw-toggle {
  position: relative; width: 52px; height: 30px; min-height: 30px; border-radius: 999px;
  border: 1px solid var(--card-border); background: var(--surface-2); transition: background 0.15s;
}
.hsw-toggle.on { background: var(--accent); border-color: var(--accent); }
.hsw-knob { position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%; background: #fff; transition: left 0.15s; }
.hsw-toggle.on .hsw-knob { left: 25px; }
.nested { margin-top: 4px; padding-left: 14px; border-left: 2px solid var(--accent); }

.t1-input {
  width: 100%; padding: 14px; min-height: 48px; font-size: 1.15rem;
  border: 1px solid var(--card-border); border-radius: 10px; background: var(--surface-2); color: var(--text);
  text-align: center; letter-spacing: 0.5px;
}

/* Goal-mode: standard cut picker */
.cut-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 6px; }
.cut-chip {
  display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 62px;
  padding: 8px 12px; border-radius: 10px; border: 1px solid var(--card-border); background: var(--surface-2); color: var(--text);
}
.cut-chip.on { border-color: var(--accent); background: rgba(34,211,238,0.12); color: var(--accent); }
.cut-chip .cut-tier { font-size: 0.7rem; font-weight: 800; letter-spacing: 0.5px; color: var(--text-muted); }
.cut-chip.on .cut-tier { color: var(--accent); }
.cut-chip .mono { font-size: 0.9rem; font-weight: 700; }
.goal-tag { font-size: 0.9rem; font-weight: 700; color: var(--positive); background: rgba(163,230,53,0.1); border-radius: 8px; padding: 8px 12px; margin-bottom: 12px; }

/* Notices */
.notice { border-radius: 8px; padding: 10px 12px; font-size: 0.85rem; margin-top: 12px; }
.notice.amber { background: rgba(234,179,8,0.12); color: #92600a; border: 1px solid rgba(234,179,8,0.4); }
body.deck-mode .notice.amber { color: #fde68a; }
.notice.slate { background: var(--surface-2); color: var(--text-muted); border: 1px solid var(--card-border); }

/* Coaching alert banner (S-2) */
.coaching-alert {
  background: var(--surface-2); border: 1px solid var(--card-border); border-left: 4px solid var(--accent);
  border-radius: 10px; padding: 14px 16px; font-size: 0.92rem; line-height: 1.45; margin-bottom: 16px; color: var(--text);
}

/* Calibrate button + theater */
#t1-action { margin-top: 8px; }
#t1-theater { padding: 20px 4px; }
.theater-track { width: 100%; height: 6px; border-radius: 3px; background: var(--surface-2); overflow: hidden; }
.theater-fill { height: 100%; background: var(--accent); box-shadow: var(--positive-glow); transition: width 0.12s linear; }
.theater-pct { text-align: right; font-size: 0.9rem; color: var(--accent); margin-top: 6px; font-weight: 700; }
.theater-line { font-size: 0.9rem; color: var(--text-muted); margin: 10px 0 0; min-height: 2.6em; font-family: var(--font-mono); }

/* Result frame */
.result-frame {
  background: var(--surface); border: 1px solid var(--card-border); border-radius: var(--radius-card);
  padding: 24px 20px; text-align: center; box-shadow: var(--card-shadow), var(--card-glow);
}
.result-banner { font-size: 0.72rem; font-weight: 800; letter-spacing: 2px; color: var(--accent); }
.cue-token {
  font-size: 2.2rem; font-weight: 800; letter-spacing: 0.5px; color: var(--positive);
  text-shadow: var(--positive-glow); margin: 12px 0; line-height: 1.1;
}
body.deck-mode.outdoor-deck .cue-token { color: var(--positive); text-shadow: none; }
.result-divider { height: 2px; background: var(--card-border); margin: 12px auto; width: 60%; }
.directive { font-size: 1.1rem; font-weight: 600; line-height: 1.45; margin-bottom: 16px; }
.projection { font-size: 1.5rem; font-weight: 800; letter-spacing: 0.5px; }
.split-list { margin-top: 16px; text-align: left; }
.split-row { display: flex; justify-content: space-between; padding: 8px 12px; border-bottom: 1px solid var(--card-border); }
.split-row:last-child { border-bottom: none; }
.split-lap { color: var(--text-muted); font-size: 0.9rem; }
.split-val { font-size: 1.05rem; font-weight: 700; }
.result-meta { font-size: 0.72rem; color: var(--text-faint); margin-top: 16px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 14px;
  padding: 8px 14px; border-radius: 999px; border: 1px solid var(--accent);
  background: transparent; color: var(--accent); font-weight: 700; font-size: 0.82rem;
}

/* ============================================================
   TAB 2 — RACE LOGGER
   ============================================================ */
.t2-input {
  width: 100%; padding: 13px; min-height: 48px; font-size: 1.1rem;
  border: 1px solid var(--card-border); border-radius: 10px; background: var(--surface-2); color: var(--text);
  text-align: center; margin-bottom: 4px;
}
.split-inputs { display: flex; gap: 8px; flex-wrap: wrap; }
.t2-split { flex: 1; min-width: 80px; padding: 12px; min-height: 48px; text-align: center; border: 1px solid var(--card-border); border-radius: 10px; background: var(--surface-2); color: var(--text); }
.disclosure { background: none; border: none; color: var(--accent); font-weight: 700; font-size: 0.9rem; padding: 12px 0; }
.advanced-panel { border-top: 1px solid var(--card-border); padding-top: 10px; }

/* DQ entry link (low-friction: clean-log is default, DQ is one tap away) */
.dq-link { display: block; width: 100%; text-align: center; background: none; border: none; color: var(--text-faint); font-size: 0.85rem; font-weight: 600; padding: 14px 0 4px; }
.dq-link:hover { color: var(--accent); }

/* DQ cards */
.dq-cards { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.dq-card {
  min-height: 56px; border: 1px solid var(--card-border); border-radius: 10px; background: var(--surface-2);
  color: var(--text); font-size: 1.05rem; font-weight: 600; text-align: left; padding: 0 18px;
}
.dq-card:active { background: var(--surface); }

/* Ledger */
.ledger-row { padding: 12px 0; border-bottom: 1px solid var(--card-border); }
.ledger-row:last-child { border-bottom: none; }
.ledger-row.dq { opacity: 0.6; }
.lr-main { display: flex; justify-content: space-between; align-items: baseline; }
.lr-evt { font-weight: 700; font-size: 0.95rem; }
.lr-time { font-size: 1.15rem; font-weight: 800; }
.lr-dq { font-size: 0.85rem; color: var(--neutral); }
.lr-meta { display: flex; align-items: center; gap: 10px; margin-top: 6px; color: var(--text-muted); }
.lr-date { font-size: 0.75rem; color: var(--text-faint); font-weight: 600; white-space: nowrap; }
.delta { font-size: 0.85rem; font-weight: 700; padding: 2px 8px; border-radius: 6px; }
.delta.up { color: var(--positive); background: rgba(163,230,53,0.12); }
.delta.down { color: var(--neutral); background: var(--surface-2); }   /* behind plan = neutral slate, NEVER red */
.sparkline { color: var(--accent); }
.lr-action { margin-left: auto; background: none; border: none; color: var(--text-faint); font-size: 0.8rem; padding: 4px 6px; }
.lr-action + .lr-action { margin-left: 0; }
.pb-badge { color: var(--positive); font-size: 0.75rem; font-weight: 800; margin-left: 6px; }
.blowup-tag { margin-left: 4px; }
.amended-flag { font-size: 0.7rem; color: var(--text-faint); font-weight: 400; }
.blowup-offer p { font-size: 0.9rem; margin: 0 0 12px; }

/* Inline amend editor (replaces the native prompt) */
.amend-box { margin-top: 10px; padding: 14px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--card-border); }
.amend-input { margin-bottom: 0; }
.amend-actions { display: flex; gap: 10px; margin-top: 12px; }
.amend-actions .btn { flex: 1; }

/* Progress strip — encouraging "unlock next" hints */
.progress-strip { margin-bottom: 14px; padding: 12px 14px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--card-border); }
.progress-line { font-size: 0.85rem; color: var(--text-muted); padding: 4px 0; }
.progress-line strong { color: var(--text); }
.progress-line + .progress-line { border-top: 1px solid var(--card-border); }

/* PB pulse — one-time 600ms volt border (reduced-motion → static color swap) */
@keyframes pbpulse { 0% { box-shadow: 0 0 0 0 rgba(163,230,53,0.7); } 100% { box-shadow: 0 0 0 6px rgba(163,230,53,0); } }
.pb-pulse { animation: pbpulse 600ms ease-out 1; border-radius: 8px; }
@media (prefers-reduced-motion: reduce) { .pb-pulse { animation: none; background: rgba(163,230,53,0.12); } }

/* ---- Post-log success feedback: toast chip + ledger-row flash ---- */
.log-toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--nav-height) + 16px);
  transform: translateX(-50%);
  z-index: 998;               /* below the update chip (999): "new version" always outranks it */
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--card-border);
  border-left: 4px solid var(--positive);
  border-radius: 999px;
  padding: 10px 18px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.2);
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--text);
  pointer-events: none;       /* purely informational — never blocks a tap */
  white-space: nowrap;
  max-width: calc(100vw - 24px);
  overflow: hidden;
  text-overflow: ellipsis;    /* the standards chip is the tail — trims gracefully on tiny screens */
  animation: logtoast 4200ms ease forwards;
}
.log-toast .log-toast-time { font-family: var(--font-mono); color: var(--positive); }
@keyframes logtoast {
  0%   { opacity: 0; transform: translateX(-50%) translateY(14px); }
  8%   { opacity: 1; transform: translateX(-50%) translateY(0); }
  85%  { opacity: 1; transform: translateX(-50%) translateY(0); }
  100% { opacity: 0; transform: translateX(-50%) translateY(6px); }
}
@keyframes loggedrow { 0% { background: rgba(163,230,53,0.30); } 100% { background: transparent; } }
.just-logged { animation: loggedrow 1400ms ease-out 1; border-radius: 8px; }
.log-toast .log-toast-std { font-weight: 600; color: var(--text-muted); }

/* PB toast — a longer, volt-glowing moment (celebration is earned; Law 1: joy, never red) */
@keyframes logtoastpb {
  0%   { opacity: 0; transform: translateX(-50%) translateY(14px); }
  6%   { opacity: 1; transform: translateX(-50%) translateY(0); }
  90%  { opacity: 1; transform: translateX(-50%) translateY(0); }
  100% { opacity: 0; transform: translateX(-50%) translateY(6px); }
}
@keyframes pbglow {
  0%   { box-shadow: 0 4px 18px rgba(0, 0, 0, 0.2), 0 0 0 0 rgba(163, 230, 53, 0.55); }
  100% { box-shadow: 0 4px 18px rgba(0, 0, 0, 0.2), 0 0 0 14px rgba(163, 230, 53, 0); }
}
.log-toast.pb {
  border-left-color: var(--brand-volt);
  animation: logtoastpb 5600ms ease forwards, pbglow 1100ms ease-out 4;
}

/* Delete-Undo toast — interactive (sticky): JS owns its lifetime, so only an entry animation */
@keyframes logtoastin { from { opacity: 0; transform: translateX(-50%) translateY(14px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
.log-toast.undo { pointer-events: auto; animation: logtoastin 240ms ease; border-left-color: var(--neutral); }
.log-toast-undo {
  border: none;
  background: var(--accent);
  color: #fff;
  border-radius: 999px;
  padding: 6px 14px;
  font-weight: 700;
  margin-left: 8px;
  font-size: 0.88rem;
}

@media (prefers-reduced-motion: reduce) {
  .log-toast, .log-toast.pb, .log-toast.undo { animation: none; }     /* JS timer removes them */
  .just-logged { animation: none; background: rgba(163,230,53,0.12); }
}

/* ---- Ledger: expandable per-lap race detail ---- */
.lr-expand { cursor: pointer; }
.lr-chev { color: var(--text-faint); font-size: 0.8em; }
.race-detail { margin: 8px 0 4px; padding: 10px 12px; background: var(--surface-2); border: 1px solid var(--card-border); border-radius: 8px; }
.rd-row { display: flex; align-items: center; gap: 8px; margin: 4px 0; }
.rd-lap { flex: 0 0 44px; font-size: 0.78rem; color: var(--text-muted); }
.rd-track { flex: 1 1 auto; position: relative; height: 10px; background: var(--bg); border-radius: 999px; overflow: hidden; }
.rd-fill { height: 100%; background: var(--accent); border-radius: 999px; }
.rd-target { position: absolute; top: -1px; bottom: -1px; width: 2px; background: var(--brand-volt); }
.rd-time { flex: 0 0 auto; font-size: 0.82rem; }
.rd-actions { margin-top: 8px; text-align: right; }

/* ---- Styled modal (VecquaModal — replaces window.confirm/alert) ---- */
.vq-modal {
  position: fixed; inset: 0; z-index: 1003;   /* above the compact-log modal */
  background: var(--overlay);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.vq-card {
  width: 100%; max-width: 420px; max-height: 92vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--card-border);
  border-radius: 16px; padding: 20px;
  box-shadow: var(--card-shadow), var(--card-glow);
}
.vq-title { margin: 0 0 10px; font-size: 1.1rem; letter-spacing: -0.2px; }
.vq-body { font-size: 0.92rem; color: var(--text-muted); line-height: 1.5; }
.vq-body strong { color: var(--text); }
.vq-list { margin: 0; padding-left: 18px; }
.vq-list li { margin: 4px 0; }
.vq-actions { display: flex; gap: 10px; margin-top: 18px; }
.vq-actions .btn { flex: 1; }

/* ---- Meet summary rows (inside the modal) ---- */
.ms-headline { margin: 0 0 12px; font-weight: 700; color: var(--text); }
.ms-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 7px 0; border-top: 1px solid var(--card-border); }
.ms-evt { font-weight: 600; color: var(--text); }
.ms-res { white-space: nowrap; }
.ms-outcome { font-size: 0.82rem; color: var(--text-faint); font-style: italic; }

/* ---- Collapsible hub sections (Profile) ---- */
.collapse-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 0; border: none; background: transparent; cursor: pointer;
  color: var(--text); text-align: left;
}
.collapse-title { font-size: 1.02rem; font-weight: 800; letter-spacing: -0.2px; }
.collapse-chev { color: var(--text-faint); }
.collapse-head + .field-hint { margin-bottom: 0; }

/* ---- Theater skip ---- */
.theater-skip { margin-top: 8px; }

/* ---- Profile: season progress chart ---- */
.season-chart { width: 100%; height: auto; display: block; margin-top: 4px; }
.sc-line { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.sc-area { fill: var(--accent); opacity: 0.07; stroke: none; }
.sc-grid { stroke: var(--card-border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.sc-dot { fill: var(--accent); stroke: var(--surface); stroke-width: 2; vector-effect: non-scaling-stroke; }
.sc-dot.pb { fill: var(--brand-volt); }
.sc-stats { display: flex; gap: 10px; margin: 12px 0 6px; }
.sc-stat { flex: 1; background: var(--surface-2); border: 1px solid var(--card-border); border-radius: 10px; padding: 8px 12px; }
.sc-stat-label { display: block; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-faint); }
.sc-stat-val { display: block; font-size: 1.05rem; font-weight: 700; margin-top: 2px; }
.sc-stat-val.volt { color: var(--positive); }
.sc-range { display: flex; justify-content: space-between; align-items: baseline; font-size: 0.75rem; color: var(--text-faint); margin-top: 4px; }
.sc-hint { font-size: 0.72rem; }
.sc-select { width: 100%; padding: 10px 12px; border-radius: 8px; border: 1px solid var(--card-border); background: var(--surface-2); color: var(--text); font-size: 0.92rem; }

/* ---- Profile: install card (icon · text · action row) ---- */
.ic-row { display: flex; align-items: center; gap: 14px; }
.ic-glyph { font-size: 1.7rem; line-height: 1; }
.ic-text { flex: 1 1 auto; min-width: 0; }
.ic-title { font-size: 1.02rem; font-weight: 800; letter-spacing: -0.2px; }
.ic-sub { font-size: 0.82rem; color: var(--text-muted); margin-top: 3px; }
.btn.ic-btn { width: auto; flex: 0 0 auto; min-height: 44px; padding: 10px 24px; }
.ic-steps { font-size: 0.85rem; color: var(--text-muted); margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--card-border); }

/* ============================================================
   TAB 3 — PRACTICE COMPANION
   ============================================================ */
.push-banner {
  background: rgba(231, 111, 81, 0.1); border-left: 4px solid #e76f51; border-radius: 8px;
  padding: 12px 14px; font-size: 0.85rem; line-height: 1.4; margin-bottom: 14px; color: var(--text);
}

/* RPE slider */
.rpe-value { text-align: center; font-size: 2.6rem; font-weight: 800; color: var(--accent); line-height: 1.1; transition: color 0.2s ease, text-shadow 0.2s ease; }
.rpe-value.z-recovery { color: var(--accent); }
.rpe-value.z-cruise   { color: var(--positive); text-shadow: var(--positive-glow); }
.rpe-value.z-threshold{ color: var(--effort-mid); }
.rpe-value.z-terminal { color: var(--effort-high); text-shadow: 0 0 12px rgba(224, 122, 63, 0.4); }
.rpe-slider { width: 100%; height: 40px; accent-color: var(--accent); -webkit-appearance: none; appearance: none; background: transparent; }
.rpe-slider::-webkit-slider-runnable-track { height: 8px; border-radius: 5px; background: var(--surface-2); border: 1px solid var(--card-border); }
.rpe-slider::-moz-range-track { height: 8px; border-radius: 5px; background: var(--surface-2); border: 1px solid var(--card-border); }
.rpe-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 26px; height: 26px; margin-top: -10px; border-radius: 50%; background: var(--accent); border: 3px solid var(--surface); box-shadow: var(--positive-glow); cursor: pointer; }
.rpe-slider::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; background: var(--accent); border: 3px solid var(--surface); box-shadow: var(--positive-glow); cursor: pointer; }
.benchmark { font-size: 0.86rem; color: var(--text-muted); text-align: center; min-height: 2.6em; margin: 10px 0 0; padding: 10px 12px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--card-border); }

/* Integrity Streak meter (segmented tier bar toward the next badge) */
.streak-meter { padding: 14px 16px; border-radius: 12px; background: var(--surface-2); border: 1px solid var(--card-border); margin-bottom: 14px; }
.streak-meter.lit { border-color: var(--accent); }
.streak-meter-head { display: flex; justify-content: space-between; align-items: center; }
.streak-meter-label { font-size: 0.9rem; font-weight: 700; }
.streak-badge { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--accent); background: var(--surface); border: 1px solid var(--card-border); border-radius: 999px; padding: 3px 10px; }
.streak-row { display: flex; align-items: center; gap: 12px; margin: 10px 0 6px; }
.streak-count { font-size: 2.1rem; font-weight: 800; color: var(--accent); min-width: 1.4em; text-align: center; }
.streak-meter.lit .streak-count { text-shadow: var(--positive-glow); }
.streak-track { flex: 1; height: 10px; border-radius: 5px; background: var(--surface); border: 1px solid var(--card-border); overflow: hidden; }
.streak-fill { height: 100%; border-radius: 5px 0 0 5px; background: linear-gradient(90deg, var(--accent), var(--positive)); box-shadow: var(--positive-glow); transition: width 0.5s ease; }
.streak-caption { font-size: 0.76rem; color: var(--text-faint); font-weight: 600; }

/* Honesty box (slide-down) */
.honesty-box { margin-top: 14px; padding: 14px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--card-border); }
.honesty-box[hidden] { display: none; }
.honesty-header { font-size: 0.85rem; font-weight: 700; color: var(--accent); margin: 0 0 10px; }
.honesty-opt { display: flex; align-items: flex-start; gap: 10px; padding: 10px 0; font-size: 0.92rem; cursor: pointer; }
.honesty-opt input { margin-top: 3px; width: 18px; height: 18px; accent-color: var(--accent); }

/* Trend strip */
.trend-strip { display: flex; align-items: flex-end; gap: 4px; height: 48px; margin: 4px 0 4px; padding: 6px 8px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--card-border); }
.trend-bar { flex: 1; background: var(--accent); border-radius: 3px; min-height: 4px; opacity: 0.85; transition: height 0.3s ease; }
.trend-bar.hot { background: #e07a3f; box-shadow: 0 0 8px rgba(224, 122, 63, 0.4); opacity: 1; }
.trend-bar.empty { background: var(--card-border); opacity: 0.4; }
.trend-bar.today { background: var(--positive); box-shadow: var(--positive-glow); opacity: 1; }
.trend-caption { display: flex; justify-content: space-between; font-size: 0.68rem; color: var(--text-faint); margin: 0 0 14px; font-weight: 600; }
.trend-today { color: var(--positive); }

/* Away row */
.away-row { display: flex; gap: 10px; align-items: center; margin-top: 16px; }
.away-chip { white-space: nowrap; }

/* Committed "today's training" view (RPE locked after logging) — one clean confirmation card */
.logged-card { border: 1px solid var(--card-border); border-radius: 12px; padding: 16px; background: var(--surface-2); margin: 6px 0 10px; }
.logged-badge { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; color: var(--positive); margin-bottom: 12px; }
.logged-main { display: flex; align-items: center; gap: 14px; }
.logged-rpe-big { font-size: 2.6rem; font-weight: 800; line-height: 1; min-width: 1.2em; text-align: center; color: var(--accent); }
.logged-rpe-big.z-recovery { color: var(--accent); }
.logged-rpe-big.z-cruise   { color: var(--positive); }
.logged-rpe-big.z-threshold{ color: var(--effort-mid); }
.logged-rpe-big.z-terminal { color: var(--effort-high); }
.logged-mid { flex: 1; display: flex; flex-direction: column; gap: 7px; align-items: flex-start; min-width: 0; }
.logged-effort { font-size: 0.95rem; font-weight: 700; color: var(--text); }
.logged-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.logged-tag { font-size: 0.78rem; font-weight: 600; color: var(--text-muted); background: var(--surface); border: 1px solid var(--card-border); border-radius: 999px; padding: 3px 10px; }
.logged-when { font-size: 0.78rem; color: var(--text-faint); align-self: flex-start; white-space: nowrap; }
.logged-more { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--card-border); font-size: 0.8rem; color: var(--text-faint); }

/* Prominent optional practice-time add button */
.add-sample { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 50px; margin-top: 16px; padding: 12px; border: 1.5px dashed var(--accent); border-radius: 10px; background: transparent; color: var(--accent); font-weight: 700; font-size: 0.98rem; }
.add-sample.open { border-style: solid; background: var(--surface-2); }
.add-sample-opt { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-faint); border: 1px solid var(--card-border); border-radius: 999px; padding: 2px 8px; }

/* Recent practice times (single-time capability samples) */
.sample-row { display: flex; align-items: baseline; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--card-border); }
.sample-row:last-of-type { border-bottom: none; }
.sample-evt { font-weight: 700; font-size: 0.92rem; }
.sample-time { font-size: 1.05rem; font-weight: 800; color: var(--accent); }
.sample-when { margin-left: auto; font-size: 0.75rem; color: var(--text-faint); }

/* ============================================================
   TAB 4 — QUICK-TRANSLATE TERMINAL
   ============================================================ */
.subtab-strip { display: flex; gap: 6px; margin-bottom: 16px; background: var(--surface-2); border-radius: 14px; padding: 4px; }
.subtab { flex: 1; min-height: 44px; border: none; border-radius: 10px; background: transparent; color: var(--text-muted); font-weight: 700; letter-spacing: 0.008em; }
.subtab.on { background: var(--surface); color: var(--accent); box-shadow: var(--card-shadow); }
body.deck-mode .subtab.on { background: rgba(34,211,238,0.15); color: var(--accent-strong); box-shadow: none; }

.convert-fields { margin: 14px 0; display: flex; flex-direction: column; gap: 10px; }
.cf-row { display: flex; align-items: center; gap: 12px; }
.cf-label { width: 44px; font-weight: 800; color: var(--accent); font-size: 0.9rem; }
.convert-input { flex: 1; margin: 0; }
.relay-toggle { display: flex; align-items: flex-start; gap: 10px; font-size: 0.85rem; color: var(--text-muted); padding: 8px 0; cursor: pointer; }
.relay-toggle input { margin-top: 2px; width: 18px; height: 18px; accent-color: var(--accent); }
.ladder-chip { margin-top: 12px; display: inline-block; padding: 8px 14px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--card-border); font-size: 0.85rem; font-weight: 700; color: var(--accent); }
.ladder-chip[hidden] { display: none; }

.solve-result { margin-top: 14px; padding: 14px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--card-border); }
.solve-result[hidden] { display: none; }
.solve-line { font-size: 1.05rem; }
.solve-line strong { color: var(--accent); font-size: 1.3rem; }
.solve-line.factory { margin-top: 8px; font-size: 0.9rem; color: var(--text-muted); }

.std-scroll { overflow-x: auto; margin-top: 12px; }
.std-table { border-collapse: collapse; width: 100%; font-size: 0.8rem; }
.std-table th, .std-table td { padding: 6px 8px; text-align: right; white-space: nowrap; font-family: var(--font-mono); }
.std-table thead th { color: var(--text-muted); border-bottom: 1px solid var(--card-border); font-family: var(--font-ui); }
.std-table th:first-child, .std-table td:first-child { position: sticky; left: 0; text-align: left; font-family: var(--font-ui); font-weight: 600; background: var(--surface); z-index: 1; }
.std-table thead th:first-child { z-index: 2; }
.std-table td.met { color: var(--positive); font-weight: 700; }
.std-table td.pb-cell { color: var(--accent); font-weight: 700; border-left: 1px solid var(--card-border); }

/* ============================================================
   TAB 5 — PROFILE HUB
   ============================================================ */
.dash-head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 18px; }
.dash-mastery { font-size: 2.8rem; font-weight: 800; line-height: 1; color: var(--accent); }
.dash-mastery .pct { font-size: 1.2rem; }
/* v32 — tier badge reads as a status light: a leading pip in the tier's own
   colour + tracked caps, so the tier is legible at a glance, not just a pill. */
.tier-chip { display: inline-flex; align-items: center; gap: 8px; padding: 8px 15px; border-radius: 999px; font-weight: 800; font-size: 0.8rem; letter-spacing: 0.02em; border: 1px solid var(--card-border); white-space: nowrap; }
.tier-chip::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: currentColor; box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 22%, transparent); flex: none; }
.tier-launch-phase { color: var(--text-muted); background: var(--surface-2); }
.tier-streamline { color: var(--accent); background: rgba(34,211,238,0.12); border-color: var(--accent); }
.tier-pace-lock { color: var(--accent-strong); background: rgba(34,211,238,0.18); border-color: var(--accent); }
.tier-elite-kinematic { color: var(--positive); background: rgba(163,230,53,0.15); border-color: var(--positive); font-weight: 800; }

/* Guided-tour launcher card */
.tour-card { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.tour-card-title { font-weight: 800; font-size: 1rem; }
.tour-card-sub { font-size: 0.82rem; color: var(--text-muted); margin-top: 2px; }
.tour-card .btn { width: auto; flex: 0 0 auto; min-height: 44px; padding: 10px 18px; white-space: nowrap; }

.ci-meter { margin-bottom: 14px; }
.ci-meter-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 5px; font-size: 0.9rem; font-weight: 600; }
.ci-weight { font-size: 0.72rem; color: var(--text-faint); font-weight: 700; }
.ci-val { font-size: 1.05rem; font-weight: 800; }
.ci-track { height: 8px; border-radius: 4px; background: var(--surface-2); overflow: hidden; }
.ci-fill { height: 100%; background: var(--accent); border-radius: 4px; transition: width 0.4s ease; }
/* UNMEASURED, not zero. A component with no data reads as an em dash over a hollow,
   hairline-ruled track — visibly a different state from a low score, never a verdict. */
.ci-val.is-pending { color: var(--text-faint); font-weight: 700; letter-spacing: 0.04em; }
/* Mixed down rather than using --card-border directly: in deck mode that token is a bright
   cyan, and a dashed cyan rule shouted louder than the real filled meter below it. */
.ci-track.is-pending { background: transparent; border: 1px dashed color-mix(in srgb, var(--text-faint) 50%, transparent); height: 8px; }
.dash-pending-note { margin: -6px 0 16px; }
.streak-note { margin-top: 8px; font-size: 0.85rem; color: var(--text-muted); }

/* ---- Integrity badges. One family, escalating interiors; locked cells stay in place so
   the wall always shows the road ahead rather than an empty shelf. ---- */
.badge-wall { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--card-border); }
/* Six across on a 390px phone without wrapping — a ladder that breaks onto two rows stops
   reading as one progression. Sized from the narrowest target, not the widest. */
.badge-row { display: flex; gap: 7px; }
.badge {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 7px 0 5px; border-radius: 11px;
  border: 1px solid var(--card-border); background: var(--surface-2);
  color: var(--text-faint); opacity: 0.55;
  transition: opacity 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}
.badge .badge-ico { width: 24px; height: 24px; display: block; }
.badge-n { font-size: 0.64rem; font-weight: 700; letter-spacing: 0.04em; }
.badge.got { color: var(--accent); border-color: var(--accent); opacity: 1; background: var(--surface); }
.badge-caption { margin: 10px 0 0; }
/* The earn moment: one settle, then done. Nothing loops — an ambient pulse in a dashboard
   is noise, and this screen is read on deck. */
@keyframes badgeEarn {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.22); }
  70%  { transform: scale(0.97); }
  100% { transform: scale(1); }
}
.badge.just-earned { animation: badgeEarn 0.62s var(--ease); box-shadow: var(--positive-glow); }

/* ---- Dev hotbar (localhost / ?dev=1 only — see Dev in app.js). Intentionally utilitarian:
   it is scaffolding, and dressing it up would risk it reading as product. ---- */
.dev-rail { position: fixed; right: 0; top: 44%; z-index: 900; display: flex; align-items: flex-start; }
.dev-tab {
  background: #0f172a; color: #7dd3fc; border: none; cursor: pointer;
  font-size: 15px; line-height: 1; padding: 10px 7px; border-radius: 8px 0 0 8px;
  box-shadow: 0 4px 14px -6px rgba(0,0,0,0.6); opacity: 0.55;
}
.dev-tab:hover { opacity: 1; }
.dev-tools {
  background: #0f172a; border-radius: 8px 0 0 8px; padding: 9px 10px;
  display: flex; flex-direction: column; gap: 5px; min-width: 108px;
  box-shadow: 0 10px 28px -12px rgba(0,0,0,0.8);
}
.dev-tools[hidden] { display: none; }
.dev-tools .dev-h {
  font-family: var(--font-mono); font-size: 0.56rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: #64748b; margin-top: 4px;
}
.dev-tools button {
  background: #1e293b; color: #e2e8f0; border: 1px solid #334155; border-radius: 6px;
  font-size: 0.72rem; padding: 5px 8px; cursor: pointer; text-align: left;
}
.dev-tools button:hover { background: #334155; }
.dev-tools button:disabled { opacity: 0.5; }

/* Erase — set apart by a rule and a label rather than by shouting. --danger is reserved
   for data-entry errors (Law 1), so the button borrows it only on its edge and text; a
   solid red block here would read as an error state on a screen that has no error. */
.danger-zone { margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--card-border); }
.danger-label {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--text-faint); margin-bottom: 8px;
}
.btn.btn-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 42%, transparent); }
.btn.btn-danger:hover { background: color-mix(in srgb, var(--danger) 8%, transparent); }

.coef-row { padding: 12px 0; border-bottom: 1px solid var(--card-border); }
.coef-row:last-child { border-bottom: none; }
.coef-name { font-weight: 700; font-size: 0.92rem; }
.coef-factory { font-size: 0.82rem; color: var(--text-muted); margin: 3px 0; }
.coef-learned { font-size: 0.82rem; color: var(--accent); }

.season-card { padding: 12px 14px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--card-border); margin-bottom: 10px; }
.season-label { font-weight: 800; font-size: 0.95rem; }
.season-meta { font-size: 0.75rem; color: var(--text-muted); margin-top: 4px; }

/* Strategy Forge cards (M9 / III-5) — token-driven; founder will polish */
.forge-card { padding: 12px 14px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--card-border); border-left: 3px solid var(--accent); margin-bottom: 10px; }
.forge-evt { font-weight: 800; font-size: 0.95rem; margin-bottom: 4px; }
.forge-target { font-size: 0.95rem; font-weight: 700; color: var(--accent); }
.forge-lever { font-size: 0.9rem; color: var(--text); margin-top: 8px; line-height: 1.4; }
.forge-focus { display: inline-block; font-size: 0.66rem; font-weight: 800; letter-spacing: 0.07em; text-transform: uppercase; color: var(--accent); margin-right: 8px; vertical-align: 1px; }
.forge-why { font-size: 0.8rem; color: var(--text-faint); margin-top: 5px; line-height: 1.45; }
.forge-hold { font-size: 0.9rem; color: var(--text-muted); }
.forge-horizon { font-size: 0.72rem; color: var(--text-faint); margin-top: 6px; }
.forge-chip { display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; margin-left: 8px; padding: 8px 14px; border-radius: 999px; border: 1px solid var(--card-border); background: var(--surface-2); color: var(--text); font-size: 0.78rem; font-weight: 600; cursor: pointer; }

/* ============================================================
   M8 — MEET DAY OS (Meet Queue · Deck Mode Pro · Recap Queue)
   ============================================================ */
/* Recap banner (S-5) */
.recap-banner {
  display: block; width: 100%; text-align: left; border: none; cursor: pointer;
  background: linear-gradient(90deg, rgba(34,211,238,0.16), rgba(163,230,53,0.12));
  border-bottom: 1px solid var(--card-border);
  padding: 14px 18px; font-size: 0.95rem; font-weight: 700; color: var(--text);
}
body.deck-mode .recap-banner { background: linear-gradient(90deg, rgba(34,211,238,0.22), rgba(163,230,53,0.14)); }

/* Meet Queue */
.mq-wrap { padding-bottom: 14px; }
.mq-head { display: flex; align-items: baseline; justify-content: space-between; }
.mq-head h3 { margin: 0; }
.mq-count { font-size: 0.75rem; font-weight: 800; letter-spacing: 0.4px; color: var(--accent); text-transform: uppercase; }
.mq-scroll { display: flex; gap: 12px; overflow-x: auto; padding: 12px 2px 6px; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; }
.mq-card {
  scroll-snap-align: start; flex: 0 0 78%; max-width: 300px;
  border: 1px solid var(--card-border); border-radius: 14px; padding: 16px; background: var(--surface-2);
  box-shadow: var(--card-glow);
}
body.deck-mode .mq-card { border-color: var(--accent); }
.mq-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.mq-event { font-weight: 800; font-size: 0.95rem; }
.mq-finals { font-size: 0.6rem; font-weight: 800; letter-spacing: 1px; color: var(--positive); background: rgba(163,230,53,0.15); padding: 2px 6px; border-radius: 5px; vertical-align: middle; }
.mq-clock { font-size: 0.72rem; font-weight: 700; color: var(--text-muted); font-family: var(--font-mono); white-space: nowrap; }
.mq-clock.urgent { color: var(--urgent); }
.mq-token { font-size: 1.1rem; font-weight: 800; color: var(--positive); text-shadow: var(--positive-glow); margin-bottom: 6px; }
.mq-proj { font-size: 1.25rem; font-weight: 800; margin-bottom: 12px; }
.mq-actions { display: flex; flex-direction: column; gap: 8px; }
.mq-actions .btn { min-height: 44px; }

/* Deck Mode Pro — one-thumb sunlight surface */
.deck-pro { padding: 24px 16px calc(var(--nav-height) + 24px); text-align: center; min-height: 80vh; display: flex; flex-direction: column; justify-content: center; }
.dp-strip { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.dp-event { font-size: 1.3rem; font-weight: 800; letter-spacing: -0.3px; }
.dp-count { font-size: 0.85rem; font-weight: 700; color: var(--text-muted); font-family: var(--font-mono); }
.dp-token { font-size: 2.8rem; font-weight: 800; line-height: 1.05; color: var(--positive); text-shadow: var(--positive-glow); margin: 18px 0 8px; }
.dp-proj { font-size: 2rem; font-weight: 800; }
.dp-band { font-size: 0.5em; font-weight: 700; color: var(--text-muted); letter-spacing: 0; }
.dp-clock { font-size: 0.9rem; font-weight: 700; color: var(--text-muted); font-family: var(--font-mono); margin: 6px 0 26px; }
.dp-clock.urgent { color: var(--urgent); }
.deck-pro .dp-log { min-height: 72px; font-size: 1.4rem; letter-spacing: 1px; }
.deck-pro .dp-next { min-height: 60px; font-size: 1.1rem; margin-top: 12px; }
.deck-pro .dq-link { margin-top: 22px; }

/* Recap cards (Tab 2) */
.recap-scroll { display: flex; gap: 10px; overflow-x: auto; padding: 12px 2px 4px; scroll-snap-type: x mandatory; }
.recap-card {
  scroll-snap-align: start; flex: 0 0 auto; min-width: 150px; text-align: left; cursor: pointer;
  display: flex; flex-direction: column; gap: 4px; padding: 12px 14px; border-radius: 12px;
  border: 1px solid var(--card-border); background: var(--surface-2); color: var(--text);
}
.recap-card.on { border-color: var(--accent); background: rgba(34,211,238,0.1); }
.recap-evt { font-weight: 800; font-size: 0.9rem; }
.recap-target { font-size: 0.78rem; color: var(--text-muted); }

/* ============================================================
   COACH SNAPSHOT MODAL (M10 / D7)
   ============================================================ */
.snapshot-modal {
  position: fixed; inset: 0; z-index: 1002;
  background: var(--overlay);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.snapshot-card {
  width: 100%; max-width: 440px; max-height: 92vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--card-border);
  border-radius: 16px; padding: 20px;
  box-shadow: var(--card-shadow), var(--card-glow);
}
.snapshot-title { font-size: 1.05rem; font-weight: 800; margin: 0 0 14px; }
.snapshot-canvas {
  display: block; width: 100%; height: auto;
  border-radius: 12px; border: 1px solid var(--card-border);
}
.snapshot-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }

/* ============================================================
   COMPACT DECK LOG MODAL — focused "Log result" surface over Meet Prep
   ============================================================ */
.cl-modal {
  position: fixed; inset: 0; z-index: 1002;
  background: var(--overlay);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.cl-card {
  width: 100%; max-width: 420px; max-height: 92vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--card-border);
  border-radius: 16px; padding: 20px;
  box-shadow: var(--card-shadow), var(--card-glow);
}
.cl-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.cl-evt { font-size: 1.15rem; font-weight: 800; letter-spacing: -0.2px; }
.cl-target { font-size: 0.82rem; color: var(--text-muted); white-space: nowrap; }
.cl-split { flex: 1; min-width: 80px; padding: 12px; min-height: 48px; text-align: center; border: 1px solid var(--card-border); border-radius: 10px; background: var(--surface-2); color: var(--text); }
.cl-actions { display: flex; gap: 10px; margin-top: 16px; }
.cl-actions .btn { flex: 1; }
.cl-modal .dq-link { margin-top: 10px; }
.cl-result { text-align: center; padding: 6px 0; }
.cl-result .logged-badge { justify-content: center; }
.cl-result-evt { font-size: 1.1rem; font-weight: 800; margin: 4px 0 6px; }
.cl-result-time { font-size: 2rem; font-weight: 800; letter-spacing: 0.5px; }
.cl-result-delta { margin-top: 10px; font-size: 0.85rem; color: var(--text-muted); }

/* ============================================================
   INSTALL NUDGE (B.3) — earned after the 2nd completed calibration
   ============================================================ */
.install-nudge {
  position: fixed; left: 50%; bottom: calc(var(--nav-height) + 16px);
  transform: translateX(-50%); z-index: 999; width: calc(100% - 32px); max-width: 420px;
  display: flex; align-items: center; gap: 12px;
  background: var(--surface); border: 1px solid var(--card-border);
  border-radius: 14px; padding: 14px 16px;
  box-shadow: 0 6px 22px rgba(0,0,0,0.22);
}
.install-nudge[hidden] { display: none; }
.install-nudge .in-text { flex: 1; font-size: 0.86rem; line-height: 1.35; color: var(--text); }
.install-nudge .in-text strong { font-weight: 800; }
.install-nudge .in-install { border: none; background: var(--accent); color: #fff; border-radius: 999px; padding: 9px 16px; font-weight: 700; font-size: 0.85rem; white-space: nowrap; }
body.deck-mode .install-nudge .in-install { color: #041016; }
.install-nudge .in-dismiss { border: none; background: none; color: var(--text-faint); font-size: 1.3rem; line-height: 1; padding: 4px 6px; }
/* Keep the floating theme toggle from colliding with the nudge while it's up. */
body.nudge-open .theme-toggle { display: none; }

/* ============================================================
   ONBOARDING TUTORIAL (coach-marks)
   ============================================================ */
.tut-overlay { position: fixed; inset: 0; z-index: 1100; }
.tut-overlay.tut-dim { background: var(--overlay); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); }

/* Spotlight: a transparent window whose huge outer shadow dims everything else. */
.tut-spot {
  position: fixed; border-radius: 14px; pointer-events: none;
  border: 2px solid var(--brand-cyan);
  box-shadow: 0 0 0 9999px rgba(2, 6, 23, 0.74), 0 0 18px rgba(34, 211, 238, 0.55);
  transition: left 0.28s ease, top 0.28s ease, width 0.28s ease, height 0.28s ease;
}

/* Callout card */
.tut-callout {
  position: fixed; z-index: 1101; width: min(340px, calc(100vw - 32px));
  background: var(--surface); color: var(--text);
  border: 2px solid var(--accent); border-radius: 16px;
  padding: 18px 18px 14px; box-shadow: 0 12px 34px rgba(0, 0, 0, 0.34);
}
.tut-badge { font-size: 0.7rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent); margin: 0 0 6px; }
.tut-title { font-size: 1.1rem; font-weight: 800; margin: 0 0 8px; letter-spacing: -0.2px; }
.tut-body { font-size: 0.92rem; line-height: 1.5; color: var(--text-muted); margin: 0; }
.tut-body strong { color: var(--text); font-weight: 700; }

/* Connected pointer (two stacked triangles → accent border + surface fill) */
.tut-arrow { position: absolute; width: 22px; height: 12px; }
.tut-arrow.down { bottom: -12px; }
.tut-arrow.down::before { content: ''; position: absolute; left: 0; top: 0; border-left: 11px solid transparent; border-right: 11px solid transparent; border-top: 12px solid var(--accent); }
.tut-arrow.down::after { content: ''; position: absolute; left: 2px; top: -1px; border-left: 9px solid transparent; border-right: 9px solid transparent; border-top: 10px solid var(--surface); }
.tut-arrow.up { top: -12px; }
.tut-arrow.up::before { content: ''; position: absolute; left: 0; top: 0; border-left: 11px solid transparent; border-right: 11px solid transparent; border-bottom: 12px solid var(--accent); }
.tut-arrow.up::after { content: ''; position: absolute; left: 2px; top: 3px; border-left: 9px solid transparent; border-right: 9px solid transparent; border-bottom: 10px solid var(--surface); }

/* Progress dots + actions */
.tut-dots { display: flex; gap: 6px; margin: 14px 0 12px; }
.tut-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--card-border); }
.tut-dot.done { background: var(--accent); opacity: 0.5; }
.tut-dot.on { background: var(--accent); box-shadow: var(--positive-glow); }
.tut-actions { display: flex; align-items: center; gap: 8px; }
.tut-spacer { flex: 1; }
.tut-skip { background: none; border: none; color: var(--text-faint); font-size: 0.85rem; font-weight: 600; padding: 8px 4px; }
.tut-actions .btn { width: auto; min-height: 40px; padding: 8px 18px; }
.tut-back:disabled { opacity: 0.4; }

/* ============================================================
   UI SHARPENING PASS (v25) — micro-interactions + crispness.
   Token-level only: no layout changes; deck-mode keeps its glow.
   ============================================================ */

/* Press + state-change feedback on every tappable control. */
.btn, .seg-btn, .subtab, .dq-card, .cut-chip, .recap-card, .nav-btn,
.hsw-toggle, .chip, .forge-chip, .collapse-head, .lr-action, .theme-toggle {
  transition: transform 0.15s ease, background-color 0.15s ease, color 0.15s ease,
              border-color 0.15s ease, box-shadow 0.15s ease;
}
.btn:active, .seg-btn:active, .subtab:active, .dq-card:active,
.cut-chip:active, .recap-card:active, .chip:active { transform: scale(0.98); }

/* Hover affordances — pointer devices only, so touch never sees a stuck hover state. */
@media (hover: hover) {
  .btn-ghost:hover, .cut-chip:hover, .recap-card:hover { border-color: var(--accent); }
  .mq-card:hover { border-color: var(--accent); }
  .collapse-head:hover .collapse-title, .collapse-head:hover .collapse-chev { color: var(--accent); }
  .ledger-row .lr-expand:hover .lr-evt { color: var(--accent); }
  .lr-action:hover { color: var(--accent); }
  .seg-btn:hover:not(.on) { color: var(--text); }
}

/* All progress fills share one gradient language (matches .streak-fill). */
.ci-fill, .theater-fill { background: linear-gradient(90deg, var(--accent), var(--positive)); }

/* Card section headers get a small accent tick for scannability. */
.card > h3::before, .mq-head h3::before {
  content: '';
  display: inline-block;
  width: 4px;
  height: 0.85em;
  border-radius: 2px;
  background: var(--accent);
  margin-right: 8px;
  vertical-align: -0.08em;
}

/* Calibration payoff lands with a soft rise-in (reduced-motion nukes it globally below). */
@keyframes frameIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.result-frame { animation: frameIn 0.35s ease; }

/* Profile mastery ring — conic progress around the headline number (value via --mv 0–100). */
.mastery-wrap { text-align: center; }
.mastery-ring {
  --mv: 0;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  padding: 6px;
  margin: 0 auto 6px;
  /* v32 — the filled arc sweeps accent→volt, matching the meter fills below, so
     the ring reads as the same instrument family (was a flat single-colour arc). */
  background: conic-gradient(var(--accent), var(--positive) calc(var(--mv) * 1%), var(--surface-2) 0);
  box-shadow: var(--card-shadow);
}
/* Nothing earned yet: an empty track, no arc, no glow — the ring is a socket waiting
   for a score rather than a dial reporting one. */
.mastery-ring.is-pending { background: var(--surface-2); box-shadow: none; }
.dash-mastery.is-pending { color: var(--text-muted); font-size: 2.6rem; letter-spacing: 0.04em; }
.mastery-ring-inner {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
}
.mastery-ring .dash-mastery { font-size: 1.75rem; }
.mastery-ring .dash-mastery .pct { font-size: 0.9rem; }
body.deck-mode .mastery-ring { background: conic-gradient(var(--accent), var(--positive) calc(var(--mv) * 1%), rgba(34, 211, 238, 0.12) 0); box-shadow: var(--card-glow); }

/* Post-log toast lifts above the update chip / install nudge when either occupies the slot. */
.log-toast.raised { bottom: calc(var(--nav-height) + 100px); }

/* ============================================================
   v26 COMPONENTS — finals offer row · standing goal · ledger scaling ·
   chart overlays · trend tap detail
   ============================================================ */
/* Meet Queue: logged prelim keeping its "Swimming finals?" offer */
.mq-done-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 2px; border-top: 1px solid var(--card-border); margin-top: 8px; }
.mq-done-evt { font-weight: 700; font-size: 0.9rem; color: var(--text-muted); }
.mq-done-row .mq-finals-btn { width: auto; min-height: 40px; padding: 8px 14px; font-size: 0.85rem; white-space: nowrap; }

/* Standing goal chip (Meet Prep) */
.goal-standing .dq-link { text-align: left; width: auto; display: inline-block; }

/* Ledger month dividers + refinement chips */
.ledger-month { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-faint); padding: 14px 0 4px; border-bottom: 1px solid var(--card-border); }
.ledger-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.lchip { border: 1px solid var(--card-border); background: var(--surface-2); color: var(--text-muted); border-radius: 999px; padding: 6px 12px; font-size: 0.8rem; font-weight: 700; min-height: 32px; }
.lchip.on { border-color: var(--accent); background: rgba(34, 211, 238, 0.12); color: var(--accent); }

/* Season chart: plan overlay + standards cut lines */
.sc-target { fill: none; stroke: var(--brand-volt); stroke-width: 1.5; stroke-dasharray: 5 4; opacity: 0.75; vector-effect: non-scaling-stroke; }
.sc-cut { stroke: var(--text-faint); stroke-width: 1; stroke-dasharray: 2 4; opacity: 0.7; vector-effect: non-scaling-stroke; }
.sc-cutlegend { font-size: 0.75rem; color: var(--text-muted); margin-top: 6px; }

/* Trend strip: tap detail */
.trend-bar { cursor: pointer; }
.trend-bar.picked { outline: 2px solid var(--accent); outline-offset: 1px; }
.trend-info { color: var(--text-muted); font-size: 0.7rem; }

/* ============================================================
   v26 MOTION PASS — one shared easing language. CSS-first, zero layout
   changes; the global reduced-motion block below neutralizes all of it.
   ============================================================ */
:root { --ease: cubic-bezier(0.22, 1, 0.36, 1); --dur: 0.22s; }

/* Tab entry: the freshly shown panel slides in from the side it "came from"
   (v31 — switchTab sets --tab-dir to +/- the travel direction, so moving right
   along the nav pulls the next panel in from the right and vice versa; a
   direct jump keeps the plain rise). Class re-triggered by switchTab. */
@keyframes tabIn {
  from { opacity: 0; transform: translate(var(--tab-dir, 0px), 6px); }
  to   { opacity: 1; transform: none; }
}
.tab-content.tab-in { animation: tabIn 0.4s var(--ease); }

/* v31.1 — the panel slide IS the transition. Letting each card also run its
   own staggered cardIn on top of it stacked two motions and read as a stutter
   ("cuts"). tab-in stays on the visible panel, so its cards ride the panel as
   one object and never pop independently — not on entry, not on re-render.
   Reveal-on-demand surfaces (result frame, disclosure panels, split rows,
   meet-queue cards) keep their OWN entrances; only the generic card pop goes. */
.tab-content.tab-in .tab-body > .card { animation: none; }

/* The title's brand bar draws itself on every tab entry — a small, cheap
   "you arrived somewhere" signal that costs no layout. */
.tab-content.tab-in .section-title::after {
  transform-origin: left center;
  animation: growX 0.55s var(--ease) 0.08s both;
}

/* Card entrance: quick, subtle rise with a 2-step stagger cap (re-renders stay unobtrusive). */
@keyframes cardIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
.tab-body > .card { animation: cardIn 0.18s var(--ease) both; }
.tab-body > .card:nth-child(2) { animation-delay: 35ms; }
.tab-body > .card:nth-child(n+3) { animation-delay: 70ms; }

/* Disclosure content lands the same way (height animation would need both states rendered). */
.collapse-body, .advanced-panel, .race-detail, .away-panel { animation: cardIn 0.18s var(--ease); }

/* Modals: overlay fade + card scale-in; .vq-closing runs the reverse before JS removes the node. */
@keyframes overlayIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes modalIn { from { opacity: 0; transform: scale(0.96) translateY(6px); } to { opacity: 1; transform: none; } }
.vq-modal, .cl-modal, .snapshot-modal { animation: overlayIn 0.15s ease; }
.vq-card, .cl-card, .snapshot-card { animation: modalIn 0.18s var(--ease); }
.vq-closing { animation: none; opacity: 0; transition: opacity 0.12s ease; pointer-events: none; }
.vq-closing .vq-card, .vq-closing .cl-card, .vq-closing .snapshot-card { animation: none; }

/* Mastery ring: --mv registered so the conic fill can SWEEP to its value (set by tab5 post-paint).
   Browsers without @property simply jump — honest fallback. */
@property --mv { syntax: '<number>'; inherits: false; initial-value: 0; }
.mastery-ring { transition: --mv 0.9s var(--ease); }

/* Theme toggle: the glyph turns over as the mode flips. */
.theme-toggle-glyph { display: inline-block; transition: transform 0.45s var(--ease); }
body.deck-mode .theme-toggle-glyph { transform: rotate(180deg); }

/* Active nav icon pops once on selection (class re-add only happens on a real tab change). */
@keyframes navPop { 0% { transform: scale(1); } 45% { transform: scale(1.14); } 100% { transform: scale(1); } }
.nav-btn.active .nav-icon { animation: navPop 0.22s var(--ease); }

/* ============================================================
   v27 SHARPENING — brand presence on the dull surfaces. Token-level;
   deck-mode keeps its own glow language (chill gets the depth).
   ============================================================ */
/* Tab headers: a small brand gradient bar anchors every page title. */
.section-title::after {
  content: '';
  display: block;
  width: 30px;
  height: 2px;                    /* v34 — a finer rule under a finer headline */
  border-radius: 2px;
  margin-top: 9px;
  background: linear-gradient(90deg, var(--accent), var(--positive));
}

/* Bottom nav: a gradient indicator marks the active tab (color alone was easy
   to miss). v31 — it is now ONE shared element that TRAVELS between tabs
   instead of five that scale in place, so the nav shows you where you moved.
   Slot maths only (every .nav-btn is flex:1), so nothing needs measuring:
   app.js sets --nav-i to the active index and --nav-n to the tab count. */
.nav-btn { position: relative; }
.nav-ind {
  position: absolute;
  top: 6px;
  left: 0;
  width: calc(100% / var(--nav-n, 5));
  height: 3px;
  display: flex;
  justify-content: center;
  pointer-events: none;
  transform: translateX(calc(var(--nav-i, 0) * 100%));
  transition: transform 0.34s var(--ease);
}
.nav-ind::before {
  content: '';
  width: 22px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--positive));
}

/* Chill-mode buttons. v34 — the v31 treatment (3-stop diagonal ramp with a
   specular band that SLID on hover, over a saturated glow) read as polished
   metal. Elegance here is restraint: one quiet vertical gradient, a crisp
   edge for definition, and a shadow that grounds rather than gleams.
   Ghost buttons keep their outline look; outdoor-deck keeps its own. */
body:not(.deck-mode) .btn:not(.btn-ghost) {
  background: linear-gradient(180deg, var(--accent), var(--accent-strong));
  /* v35 — the hard dark inset ring made every button look like a keycap.
     A hairline of light along the top edge gives dimension instead, and the
     lift comes from one soft accent-tinted shadow rather than a hard border. */
  /* v36 — the lift tightened up: a shorter, less diffuse shadow keeps the
     silhouette crisp instead of letting it bloom. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 1px 2px rgba(12, 74, 91, 0.12),
    0 5px 14px -9px rgba(14, 116, 144, 0.5);
  transition: background-color 0.2s var(--ease), transform 0.15s ease,
              box-shadow 0.2s var(--ease), filter 0.2s var(--ease);
}
/* Deck keeps its vibrancy, minus the metal: a flat cyan face lit along its top
   edge, so the glow comes from the theme and not from the button. */
body.deck-mode .btn:not(.btn-ghost) {
  background: var(--accent);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), var(--positive-glow);
}

/* Empty states: the glyph sits in a dashed badge instead of floating on the page. */
.empty-glyph {
  width: 84px;
  height: 84px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: var(--surface);
  border: 1.5px dashed var(--card-border);
  font-size: 2.2rem;
}

/* Focused inputs pick up the accent border (the outline ring alone left fields flat). */
.t1-input:focus, .t2-input:focus, .t2-split:focus, .cl-split:focus,
.wizard-input:focus, .wizard-select:focus, .sc-select:focus { border-color: var(--accent); }

/* Wizard: brand hairline on the first thing a new athlete ever sees. */
.wizard-card { border-top: 3px solid var(--accent); }

/* Progress strip: same left-accent language as the Forge cards. */
.progress-strip { border-left: 3px solid var(--accent); }

/* Horizontal scrollers: thin branded scrollbars instead of the chunky default. */
.mq-scroll, .recap-scroll, .std-scroll { scrollbar-width: thin; scrollbar-color: var(--card-border) transparent; }
.mq-scroll::-webkit-scrollbar, .recap-scroll::-webkit-scrollbar, .std-scroll::-webkit-scrollbar { height: 5px; }
.mq-scroll::-webkit-scrollbar-thumb, .recap-scroll::-webkit-scrollbar-thumb, .std-scroll::-webkit-scrollbar-thumb {
  background: var(--card-border);
  border-radius: 3px;
}
.mq-scroll::-webkit-scrollbar-thumb:hover, .recap-scroll::-webkit-scrollbar-thumb:hover, .std-scroll::-webkit-scrollbar-thumb:hover { background: var(--accent); }

/* Update chip: session-dismiss ✕ */
.uc-dismiss { border: none; background: none; color: var(--text-faint); font-size: 1.15rem; line-height: 1; padding: 2px 4px; }

/* ============================================================
   v28 MICRO-MOTION + SMOOTHING — small, fast, tokenized. Nothing moves
   more than a few px; the reduced-motion block below neutralizes all of it.
   ============================================================ */
html { scroll-behavior: smooth; }

/* Theme flips crossfade everywhere, not just on <body> — cards, inputs, and the nav
   used to snap between chill/deck while the page faded around them. */
.card, .notice, .seg, .bottom-nav, .advanced-panel, .race-detail,
.t1-input, .t2-input, .t2-split, .cl-split, .wizard-input, .wizard-select, .sc-select {
  transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
}

/* Bars GROW to their value instead of appearing pre-filled. */
@keyframes growX { from { transform: scaleX(0); } }
@keyframes growY { from { transform: scaleY(0); } }
.rd-fill { transform-origin: left; animation: growX 0.4s var(--ease); }
.streak-fill { transform-origin: left; animation: growX 0.5s var(--ease); }
.trend-bar { transform-origin: bottom; animation: growY 0.45s var(--ease); }

/* Calibration payoff: cue token lands with a soft settle, split rows follow in sequence. */
@keyframes cueIn { from { opacity: 0; transform: scale(0.94); } to { opacity: 1; transform: none; } }
.cue-token { animation: cueIn 0.4s var(--ease); }
.split-list .split-row { animation: cardIn 0.25s var(--ease) both; }
.split-list .split-row:nth-child(2) { animation-delay: 40ms; }
.split-list .split-row:nth-child(3) { animation-delay: 80ms; }
.split-list .split-row:nth-child(4) { animation-delay: 120ms; }

/* Meet Queue cards ease into the rail. */
.mq-card { animation: cardIn 0.25s var(--ease) both; }
.mq-card:nth-child(2) { animation-delay: 35ms; }
.mq-card:nth-child(n+3) { animation-delay: 70ms; }

/* Reveal-on-demand surfaces get the same soft entrance (display:none → block restarts these). */
.solve-result, .ladder-chip, .cl-result { animation: cardIn 0.2s var(--ease); }
.update-chip:not([hidden]), .install-nudge:not([hidden]) { animation: logtoastin 0.28s var(--ease); }

/* Pointer-device lift on primary buttons (press-down scale still wins while clicking). */
@media (hover: hover) {
  .btn:not(.btn-ghost):hover { transform: translateY(-1px); }
  /* v34: a quiet deepening on hover — no travelling highlight, no flash. */
  body:not(.deck-mode) .btn:not(.btn-ghost):hover { filter: brightness(0.96); }
  .btn:not(.btn-ghost):active { transform: scale(0.98); }
}
.lchip { transition: transform 0.15s ease, background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease; }
.lchip:active { transform: scale(0.96); }

/* Softer geometry: dividers fade at the edges; toggles ease with the shared curve;
   tiny sparklines get rounded joints instead of miter spikes. */
.result-divider { background: linear-gradient(90deg, transparent, var(--card-border) 18%, var(--card-border) 82%, transparent); }
.hsw-toggle { transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease); }
.hsw-knob { transition: left 0.2s var(--ease); }
.sparkline polyline { stroke-linecap: round; stroke-linejoin: round; }
.sc-target { stroke-linecap: round; }

/* RPE readout ticks as the slider moves (class re-triggered from tab3). */
@keyframes rpeTick { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } }
.rpe-value.tick { animation: rpeTick 0.18s var(--ease); }

/* ============================================================
   v29 CHILL ENRICHMENT — chill read as a stripped-down fallback next to
   deck's neon. It now carries the same brand language (ambient tint, depth,
   gradient accents) in a daylight register. Scoped `body:not(.deck-mode)`
   so deck AND the sun-readable outdoor variant are untouched.
   ============================================================ */

/* Ambient brand wash instead of flat slate — fixed so it never scrolls away. */
body:not(.deck-mode) {
  background-image:
    radial-gradient(1100px 560px at 50% -12%, rgba(34, 211, 238, 0.13), transparent 62%),
    radial-gradient(820px 480px at 108% 104%, rgba(163, 230, 53, 0.10), transparent 58%);
  background-attachment: fixed;
}

/* Cards: soft vertical sheen + layered lift (was flat white on grey).
   v31 — the inset white line is the daylight equivalent of deck's neon rim:
   it lights the top edge so a card reads as a raised panel, not a shape that
   happens to be whiter than the page. The drop shadow is teal-tinted so the
   depth belongs to the brand rather than to a generic grey UI kit. */
body:not(.deck-mode) .card {
  background-image: linear-gradient(180deg, #ffffff, #fafdfe);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    0 1px 2px rgba(12, 74, 91, 0.07),
    0 14px 30px -18px rgba(12, 74, 91, 0.5);
}

/* The calibration payoff earns real presence in daylight too. */
body:not(.deck-mode) .result-frame {
  /* Cyan-led and fading out by the midpoint — a volt tail over the split rows read muddy. */
  background-image: linear-gradient(168deg, rgba(34, 211, 238, 0.13), rgba(34, 211, 238, 0.04) 38%, transparent 62%);
  border-color: rgba(14, 116, 144, 0.28);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05), 0 16px 34px -20px rgba(14, 116, 144, 0.45);
}

/* Cue tokens / queue tokens: gradient-filled type replaces the deck glow. */
body:not(.deck-mode) .cue-token,
body:not(.deck-mode) .dp-token,
body:not(.deck-mode) .mq-token {
  background: linear-gradient(135deg, var(--accent-strong), var(--positive));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  text-shadow: none;
}

/* Segmented + subtab selection gets tint and lift, not just a colour swap.
   v31.1 — the track keeps its native teal-tinted --surface-2 (a grey wash here
   dulled the whole Event card); the selected option earns its presence from an
   accent ring instead, so it still reads next to deck's filled cyan block. */
/* v34 — was a white→tint gradient inside an outer ring plus a drop shadow:
   three effects stacked into a glossy lozenge. One flat face, one inset
   hairline, one whisper of a shadow. Sharper, and it recedes properly. */
body:not(.deck-mode) .seg-btn.on,
body:not(.deck-mode) .subtab.on {
  background-image: none;
  background-color: #ffffff;
  color: var(--accent-strong);
  box-shadow:
    inset 0 0 0 1px rgba(14, 116, 144, 0.24),
    0 1px 2px rgba(12, 74, 91, 0.10);
}

/* Meet-day surfaces carry an accent edge so a live meet reads at a glance. */
body:not(.deck-mode) .mq-card {
  border-left: 3px solid var(--accent);
  background-image: linear-gradient(180deg, #ffffff, #f6fbfc);
}
body:not(.deck-mode) .recap-card.on { background-image: linear-gradient(180deg, rgba(34, 211, 238, 0.14), rgba(34, 211, 238, 0.06)); }

/* Dashboard: tinted meter tracks + a ring halo (the ring floated on white before). */
body:not(.deck-mode) .ci-track { background: #e8eef4; }
body:not(.deck-mode) .mastery-ring { box-shadow: 0 6px 18px -8px rgba(14, 116, 144, 0.45); }

/* Streak + trend surfaces pick up the same wash. */
body:not(.deck-mode) .streak-meter,
body:not(.deck-mode) .trend-strip { background-image: linear-gradient(180deg, #ffffff, #f4f8fb); }

/* Nav + floating toggle: frosted brand tint rather than plain white. */
body:not(.deck-mode) .bottom-nav { background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.86), rgba(240, 247, 250, 0.96)); }
body:not(.deck-mode) .theme-toggle { box-shadow: 0 4px 14px -4px rgba(14, 116, 144, 0.45); }

/* ============================================================
   v29 THEME CONTROL — the floating toggle was the ONLY way to switch,
   and a bare ◐ glyph never said what it did. Profile now owns a labelled
   control; the floating button keeps its place as the on-deck shortcut.
   ============================================================ */
.theme-card-row { display: flex; gap: 10px; margin-top: 12px; }
.theme-opt {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 12px 14px;
  min-height: 64px;
  border-radius: 12px;
  border: 1.5px solid var(--card-border);
  background: var(--surface-2);
  color: var(--text);
  text-align: left;
}
.theme-opt.on { border-color: var(--accent); background: rgba(34, 211, 238, 0.10); }
.theme-opt-name { font-weight: 800; font-size: 0.95rem; }
.theme-opt.on .theme-opt-name { color: var(--accent); }
.theme-opt-sub { font-size: 0.75rem; color: var(--text-muted); line-height: 1.35; }
.theme-swatch { display: flex; gap: 3px; margin-bottom: 2px; }
.theme-swatch span { width: 16px; height: 8px; border-radius: 2px; border: 1px solid rgba(148, 163, 184, 0.35); }

/* First-launch hint ring on the floating toggle — shown once, then dismissed. */
@keyframes togglePulse {
  0% { box-shadow: 0 0 0 0 rgba(34, 211, 238, 0.55); }
  100% { box-shadow: 0 0 0 14px rgba(34, 211, 238, 0); }
}
.theme-toggle.hint { animation: togglePulse 1.6s ease-out 3; }

/* ============================================================
   LANDING PAGE — the front door at the domain. Deck-flavoured on purpose:
   it's the brand's first impression, independent of the user's theme
   (which they haven't chosen yet). Scrolls on short screens.
   ============================================================ */
.landing {
  position: fixed;
  inset: 0;
  z-index: 1200;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  background:
    radial-gradient(900px 520px at 50% -10%, rgba(34, 211, 238, 0.20), transparent 60%),
    radial-gradient(760px 460px at 108% 106%, rgba(163, 230, 53, 0.14), transparent 58%),
    linear-gradient(180deg, #0b1220, #020617);
  color: #e2e8f0;
}
.landing[hidden] { display: none; }
body.landing-open { overflow: hidden; }

.landing-inner {
  max-width: 560px;
  margin: 0 auto;
  padding: max(40px, env(safe-area-inset-top)) 22px calc(40px + env(safe-area-inset-bottom));
  animation: cardIn 0.4s var(--ease);
}

.lp-wordmark { font-size: 2.1rem; font-weight: 800; letter-spacing: -0.6px; margin: 0; color: #f1f5f9; }
.lp-wordmark .accent { color: var(--brand-cyan); }
.lp-kicker { font-size: 0.7rem; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #64748b; margin: 4px 0 26px; }
.lp-headline { font-size: 1.95rem; line-height: 1.15; font-weight: 800; letter-spacing: -0.7px; margin: 0 0 14px; color: #ffffff; }
.lp-sub { font-size: 1rem; line-height: 1.55; color: #94a3b8; margin: 0 0 28px; }

.lp-features { list-style: none; margin: 0 0 30px; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.lp-features li {
  display: flex;
  gap: 13px;
  align-items: flex-start;
  padding: 14px 16px;
  border-radius: 13px;
  background: rgba(15, 23, 42, 0.6);
  border: 1px solid rgba(34, 211, 238, 0.18);
  font-size: 0.9rem;
  line-height: 1.5;
  color: #94a3b8;
}
.lp-features strong { color: #e2e8f0; font-weight: 700; }
.lp-ico { font-size: 1.2rem; line-height: 1.3; flex: 0 0 auto; }

.lp-cta { text-align: center; }
.lp-cta-line { font-size: 1.12rem; font-weight: 800; color: #ffffff; margin: 0 0 16px; letter-spacing: -0.2px; }
.btn.lp-install {
  background: linear-gradient(135deg, var(--brand-cyan), var(--brand-volt));
  color: #041016;
  font-size: 1.05rem;
  min-height: 54px;
  box-shadow: 0 10px 30px -10px rgba(34, 211, 238, 0.7);
}
.lp-steps {
  font-size: 0.88rem;
  line-height: 1.5;
  color: #94a3b8;
  background: rgba(15, 23, 42, 0.6);
  border: 1px solid rgba(34, 211, 238, 0.18);
  border-radius: 12px;
  padding: 13px 15px;
  margin: 0;
}
.lp-steps strong { color: #e2e8f0; }
.lp-steps[hidden] { display: none; }
.lp-skip {
  display: block;
  width: 100%;
  margin-top: 14px;
  padding: 12px;
  background: none;
  border: none;
  color: var(--brand-cyan);
  font-size: 0.92rem;
  font-weight: 700;
}
.lp-foot { text-align: center; font-size: 0.76rem; color: #475569; margin: 26px 0 0; }

@media (min-width: 620px) {
  .lp-headline { font-size: 2.3rem; }
}

/* ============================================================
   v31 CHILL PARITY — deck's identity is the accent-outlined, glowing panel.
   Chill had the same content with none of that structure, so it read as the
   "off" state of the real theme. Every rule here gives chill its OWN version
   of a deck signal in daylight terms: a defined teal edge where deck has a
   neon rim, a tinted lift where deck has a glow. Scoped body:not(.deck-mode)
   so deck AND the sun-readable outdoor variant stay untouched.
   ============================================================ */

/* Ghost buttons were a hairline on white — the least confident control in the
   app. They now sit on a tinted face with a genuine accent border. */
/* v34 — flat face; the border does the work. */
body:not(.deck-mode) .btn-ghost {
  border-color: rgba(14, 116, 144, 0.30);
  background: #ffffff;
}
@media (hover: hover) {
  body:not(.deck-mode) .btn-ghost:hover { border-color: var(--accent); background: #f4fafb; }
}

/* Inputs read as fields, not as painted rectangles: a recessed inner edge is
   the light-mode counterpart of deck's glowing border. */
body:not(.deck-mode) .t1-input,
body:not(.deck-mode) .t2-input,
body:not(.deck-mode) .t2-split,
body:not(.deck-mode) .cl-split,
body:not(.deck-mode) .wizard-input,
body:not(.deck-mode) .wizard-select,
body:not(.deck-mode) .sc-select {
  background: #f6fafc;
  box-shadow: inset 0 1px 2px rgba(12, 74, 91, 0.08);
}
body:not(.deck-mode) .t1-input:focus,
body:not(.deck-mode) .t2-input:focus,
body:not(.deck-mode) .t2-split:focus,
body:not(.deck-mode) .cl-split:focus,
body:not(.deck-mode) .wizard-input:focus,
body:not(.deck-mode) .wizard-select:focus,
body:not(.deck-mode) .sc-select:focus {
  background: #ffffff;
  box-shadow: inset 0 1px 2px rgba(12, 74, 91, 0.05), 0 0 0 3px rgba(14, 116, 144, 0.14);
}

/* The floating theme toggle is the one always-on-screen control. In chill it
   was a pale disc on a pale page; give it the accent gradient it deserves. */
body:not(.deck-mode) .theme-toggle {
  background: #ffffff;                       /* v34 — flat, not a polished disc */
  border-color: rgba(14, 116, 144, 0.30);
  color: var(--accent-strong);
}

/* Modal + wizard cards are surfaces the .card rules never reach. */
body:not(.deck-mode) .vq-card,
body:not(.deck-mode) .cl-card,
body:not(.deck-mode) .snapshot-card,
body:not(.deck-mode) .wizard-card {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    0 24px 60px -24px rgba(12, 74, 91, 0.6);
}

/* Slate notices carried no brand at all — a left accent rule ties them to the
   same family as the Forge cards and the meet-queue rail. */
body:not(.deck-mode) .notice.slate {
  border-left: 3px solid rgba(14, 116, 144, 0.45);
  background: linear-gradient(90deg, rgba(14, 116, 144, 0.07), var(--surface-2) 60%);
}

/* Stacked segmented controls (Translate pairs distance + stroke) ran flush
   into each other once the track picked up a real tint. */
.seg + .seg { margin-top: 8px; }

/* The practice push-banner's flat terracotta wash went muddy over a tinted
   page. It's advice, not an error — so it now reads as a card with a warm
   accent edge rather than a stain. */
body:not(.deck-mode) .push-banner {
  background: linear-gradient(90deg, rgba(231, 111, 81, 0.14), rgba(255, 255, 255, 0.85) 65%);
  box-shadow: 0 1px 2px rgba(12, 74, 91, 0.07), 0 10px 22px -16px rgba(12, 74, 91, 0.4);
}
body:not(.deck-mode) .notice.amber {
  background: linear-gradient(90deg, rgba(234, 179, 8, 0.18), rgba(255, 255, 255, 0.8) 70%);
}

/* Progress tracks: a tinted, inset channel so a part-filled meter still shows
   its full extent (the flat grey track vanished into the card). */
body:not(.deck-mode) .ci-track,
body:not(.deck-mode) .streak-track,
body:not(.deck-mode) .theater-track {
  background: #dceaf0;
  box-shadow: inset 0 1px 2px rgba(12, 74, 91, 0.12);
}

/* ============================================================
   v31 MOTION — attention details, all sub-half-second and all
   neutralized by the reduced-motion block below.
   ============================================================ */

/* The active nav icon keeps a soft accent halo, so the tab you're on reads
   from the corner of your eye and not only from the label colour. */
.nav-btn.active .nav-icon { filter: drop-shadow(0 0 6px rgba(34, 211, 238, 0.45)); }

/* Cue token: after it settles, the gradient fill drifts once across the type —
   the calibration payoff is the single moment worth a flourish. */
@keyframes cueDrift {
  from { background-position: 0% 50%; }
  to   { background-position: 100% 50%; }
}
body:not(.deck-mode) .cue-token,
body:not(.deck-mode) .dp-token,
body:not(.deck-mode) .mq-token {
  background-size: 220% 100%;
  animation: cueIn 0.4s var(--ease), cueDrift 1.6s var(--ease) 0.4s both;
}

/* Toasts and the PB moment already pulse; the ledger's newest row now also
   slides in from the edge it was written at. */
@keyframes rowIn { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: none; } }
.ledger-row.just-logged { animation: loggedrow 1400ms ease-out 1, rowIn 0.3s var(--ease); }

/* ============================================================
   v32 SHARPENING — SVG icons (top of file), tier badge + ring (above),
   plus: meter tier-lines, a bigger Deck Mode Pro, and a calibration payoff.
   ============================================================ */

/* Meter tier-boundary lines. The CI components (PP/TC/CI) are 0–100; the tier
   bands break at 50 / 70 / 90, so faint gridlines at those marks let you read
   each component against the tiers ("PP is past the elite line, TC isn't").
   Drawn OVER the fill so a full bar clearly clears every line. */
:root { --meter-tick: rgba(15, 23, 42, 0.15); }
body.deck-mode { --meter-tick: rgba(226, 232, 240, 0.22); }
body.deck-mode.outdoor-deck { --meter-tick: rgba(15, 23, 42, 0.28); }
.ci-track { position: relative; }
.ci-track::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(var(--meter-tick), var(--meter-tick)) 50% 0 / 1px 100% no-repeat,
    linear-gradient(var(--meter-tick), var(--meter-tick)) 70% 0 / 1px 100% no-repeat,
    linear-gradient(var(--meter-tick), var(--meter-tick)) 90% 0 / 1px 100% no-repeat;
}

/* Deck Mode Pro: the on-deck, arm's-length surface. Bigger cue + projection,
   more air between them, a heavier LOG button — readable in sun without leaning in. */
.dp-event { font-size: 1.4rem; }
.dp-token { font-size: 3.5rem; margin: 24px 0 12px; letter-spacing: -0.5px; }
.dp-proj { font-size: 2.5rem; }
.dp-clock { margin: 8px 0 30px; font-size: 0.95rem; letter-spacing: 0.04em; }
.deck-pro .dp-log { min-height: 78px; font-size: 1.55rem; }

/* Calibration payoff: when the result frame lands, a brand accent bar draws
   across its top (same language as the tab-title bar) and the cue token gets a
   single light sweep. Trust-safe — purely visual, no red / sound / vibration. */
.result-frame { position: relative; overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .result-frame::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--accent), var(--positive));
    transform: scaleX(0); transform-origin: center;
    animation: growX 0.6s var(--ease) 0.08s both;
  }
  body:not(.deck-mode) .result-frame .cue-token {
    background-size: 220% 100%;
    animation: cueIn 0.4s var(--ease), cueSheen 1.5s var(--ease) 0.4s 1 both;
  }
  @keyframes cueSheen { from { background-position: 0% 50%; } to { background-position: 100% 50%; } }
}

/* ============================================================
   v33 FEATURES — Meet Sheet, PB progression, Season goal tracker.
   ============================================================ */

/* Meet Sheet: the full-width opener + the read-only summary modal. */
.mq-sheet-btn { margin-top: 4px; }
.meet-sheet { text-align: left; }
.ms-sub { font-size: 0.82rem; color: var(--text-muted); margin: 0 0 14px; }
.ms-event { padding: 15px 0; border-top: 1px solid var(--card-border); }
.ms-event:first-of-type { border-top: none; padding-top: 2px; }
.ms-ev-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.ms-ev-name { font-weight: 800; font-size: 0.98rem; }
.ms-ev-clock { font-size: 0.72rem; color: var(--text-faint); flex: none; }
.ms-cue { font-weight: 700; color: var(--accent); font-size: 1.05rem; letter-spacing: 0.03em; margin: 7px 0 2px; }
.ms-proj { font-size: 1.25rem; font-weight: 800; }
.ms-band { font-size: 0.58em; color: var(--text-muted); font-weight: 700; }
.ms-splits { display: flex; flex-wrap: wrap; gap: 6px 8px; margin-top: 9px; }
.ms-split { display: flex; gap: 7px; background: var(--surface-2); border-radius: 8px; padding: 5px 10px; font-size: 0.8rem; }
.ms-split span:first-child { color: var(--text-muted); }
.ms-split .mono { font-weight: 700; }
body:not(.deck-mode) .ms-cue {
  background: linear-gradient(135deg, var(--accent-strong), var(--positive));
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}

/* Personal Records wall */
.rec-list { display: flex; flex-direction: column; }
.rec-row {
  display: grid; grid-template-columns: minmax(0,1fr) auto auto; align-items: center; gap: 12px;
  width: 100%; text-align: left; background: none; border: none;
  border-top: 1px solid var(--card-border); padding: 12px 2px; color: var(--text);
}
.rec-row:first-child { border-top: none; }
.rec-row.rec-flat { cursor: default; }
.rec-evt { font-weight: 700; font-size: 0.95rem; }
.rec-mid { display: flex; align-items: center; gap: 10px; justify-self: end; }
.rec-spark { width: 104px; height: 30px; fill: none; flex: none; }
.rec-spark polyline { fill: none; stroke: var(--accent); stroke-width: 2; vector-effect: non-scaling-stroke; stroke-linecap: round; stroke-linejoin: round; }
.rec-spark circle { fill: var(--positive); stroke: none; }
.rec-nospark { font-size: 0.72rem; color: var(--text-faint); font-family: var(--font-mono); }
.rec-drop { font-size: 0.72rem; color: var(--positive); font-weight: 700; }
.rec-time { font-size: 1.05rem; font-weight: 800; color: var(--accent); }
@media (hover: hover) { .rec-row:not(.rec-flat):hover .rec-evt { color: var(--accent); } }
.rec-row:not(.rec-flat):active { transform: scale(0.995); }

/* Season goal tracker */
.goal-row { padding: 13px 0; border-top: 1px solid var(--card-border); }
.goal-row:first-of-type { border-top: none; padding-top: 2px; }
.goal-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.goal-evt { font-weight: 700; font-size: 0.95rem; }
.goal-target { font-size: 0.82rem; color: var(--text-muted); }
.goal-track { height: 8px; border-radius: 4px; background: var(--surface-2); overflow: hidden; }
.goal-fill { height: 100%; border-radius: 4px; background: linear-gradient(90deg, var(--accent), var(--positive)); transition: width 0.5s var(--ease); }
.goal-fill.met { background: var(--positive); box-shadow: var(--positive-glow); }
.goal-meta { font-size: 0.8rem; color: var(--text-muted); margin-top: 7px; }
.goal-met { color: var(--positive); font-weight: 700; }
body:not(.deck-mode) .goal-track { background: #dceaf0; box-shadow: inset 0 1px 2px rgba(12, 74, 91, 0.12); }

/* ============================================================
   REDUCED MOTION (C12)
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
