@import './fonts.css';

:root {
  /* Surfaces — a deliberate elevation ramp, deeper and cooler than the
     GitHub-derived palette this replaced. Each step is a real level:
     bg (app) → panel (chrome) → surface-2 (cards) → surface-3 (hover). */
  --bg: #080B11;
  --panel: #10151E;
  --surface-2: #171E2A;
  --surface-3: #1F2836;
  --border: #232C3B;

  --text: #EDF2F8;
  --muted: #8494A8;
  --faint: #5C6B7E;

  /* Brand: warmer and more saturated than the old #f97316, and far enough
     from Strava's red-orange to read as its own mark. */
  --accent: #FF7A18;
  --accent-2: #FFA24D;
  --accent-dim: rgba(255, 122, 24, 0.14);

  --green: #35D07F;
  --red: #FF5A5A;
  --blue: #4C9AFF;

  --shadow-1: 0 2px 8px rgba(0, 0, 0, 0.40);
  --shadow-2: 0 8px 28px rgba(0, 0, 0, 0.55);
  --ease: cubic-bezier(.2, .8, .2, 1);
}

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

/* Icons inherit colour and sit on the text baseline of their button. */
.icon { display: inline-block; vertical-align: -0.18em; flex: none; }
button > .icon:not(:only-child), span[data-icon] + * { margin-right: 2px; }
button, .chip-btn, .primary-btn, .secondary-btn, .modal-cancel {
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: background-color .12s var(--ease), border-color .12s var(--ease),
              color .12s var(--ease), transform .12s var(--ease),
              box-shadow .12s var(--ease), opacity .12s var(--ease);
}
button:active:not(:disabled) { transform: translateY(1px); }

/* The login modal is summoned FROM the sign-in gate (z-index 4000), so it
   must outrank it — every other modal lives beneath the gate on purpose. */
#login { z-index: 4100; }

/* Every dropdown starts dark. Three shipped white before this rule existed
   (the climb band, the units picker, and the one before them) because each
   new select had to remember to join a styled group; now forgetting is
   harmless. Component rules are more specific and still win. */
select {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 5px 7px;
  font-family: inherit;
  font-size: 13px;
}
select:focus { outline: none; border-color: var(--accent); }

/* Modals: fade the scrim, lift the card. */
.modal { animation: scrim .16s var(--ease); }
.modal .modal-card { animation: rise .18s var(--ease); }
@keyframes scrim { from { opacity: 0 } to { opacity: 1 } }
@keyframes rise {
  from { opacity: 0; transform: translateY(10px) scale(.985) }
  to   { opacity: 1; transform: none }
}

/* The rider dot glides between the engine's 2 Hz position updates instead
   of teleporting. */
.leaflet-interactive { transition: none; }
#map path.leaflet-interactive[stroke="#fff"] {
  transition: transform .45s linear;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}

html, body {
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: 'Inter', -apple-system, "Segoe UI", Roboto, sans-serif;
  font-feature-settings: 'cv05' 1, 'ss03' 1;   /* single-storey l, rounder a */
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

/* Every live-updating number: condensed athletic figures, fixed-width digits
   so the layout never shifts as values change. */
.metric-value,
#gear-number,
#wp-target,
#ramp-ftp,
.wp-times span,
#ride-stats span,
#summary-stats .tile b,
.wpb-watts, .wpb-dur {
  font-family: 'Barlow Condensed', 'Inter', sans-serif;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

body { display: flex; flex-direction: column; }

.hidden { display: none !important; }

/* ---- top bar ---- */
/* The top bar doubles as the window's drag handle on macOS, where the
   title bar is hidden; its buttons opt back out. */
#topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 16px 12px;
  padding-left: 92px;              /* clear of the inset traffic lights */
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  -webkit-app-region: drag;
}
#topbar button, #topbar input { -webkit-app-region: no-drag; }

#brand {
  font-weight: 700;
  font-size: 16px;
  margin-right: 8px;
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  gap: 8px;
}
#brand .icon { color: var(--accent); }

#devices { display: flex; gap: 8px; flex: 1; }

.dev-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 6px 14px;
  font-size: 13px;
  cursor: pointer;
}
.dev-btn:hover { border-color: var(--muted); }

.dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--red);
  transition: background 0.2s;
}
.dot.on { background: var(--green); }

#profile {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 6px 14px;
  font-size: 13px;
  cursor: pointer;
}
#profile:hover { border-color: var(--muted); }
#profile.signed-in { border-color: var(--green); }

/* ---- main layout ---- */
main { display: flex; flex: 1; min-height: 0; }

/* The column never scrolls: everything is sized to fit, and the settings
   that used to live down here now open in their own modal. */
#metrics {
  width: 210px;
  background: var(--panel);
  border-right: 1px solid var(--border);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
}

.metric { text-align: center; }
.metric-value { font-size: 34px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.05; }
.metric-power { padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.metric-power .metric-value { font-size: 62px; font-weight: 700; color: var(--accent); }
.metric-grade .metric-value { font-size: 30px; color: var(--blue); }

/* secondary metrics share two columns so the column stays short */
.metric-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 6px; }
.metric-grid .metric-value { font-size: 30px; }
.metric-grid .metric-label { font-size: 10px; letter-spacing: 1px; }

#btn-settings {
  margin-top: auto;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 8px;
  padding: 8px;
  font-size: 12px;
  cursor: pointer;
}
#btn-settings:hover { color: var(--text); border-color: var(--muted); }
.metric-label { font-size: 11px; letter-spacing: 1.5px; color: var(--muted); }
.metric-sub { font-size: 10px; color: var(--muted); opacity: 0.75; margin-top: 2px; }

#gearbox {
  text-align: center;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px;
}
#gear-number { font-size: 38px; font-weight: 800; color: var(--green); line-height: 1.05; }
#gear-ticks {
  display: flex;
  gap: 2px;
  justify-content: center;
  margin: 6px 0 3px;
}
#gear-ticks span {
  width: 4px; height: 11px;
  background: var(--border);
  border-radius: 2px;
}
#gear-ticks span.lit { background: var(--green); }

/* Fixed power's stand-in for the gear box. Same border, radius and padding;
   applyFixedPower() pins its min-height to the gear box's measured height so
   swapping modes never reflows the column. */
#fixedbox {
  text-align: center;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
}
#fixed-value { font-size: 38px; font-weight: 800; color: var(--accent); line-height: 1.05; }
#fixed-avg { font-size: 11px; color: var(--muted); min-height: 14px; }

#ride-stats {
  display: flex;
  justify-content: space-around;
  border-top: 1px solid var(--border);
  padding-top: 10px;
}
#ride-stats span { font-size: 26px; font-weight: 700; display: block; text-align: center; font-variant-numeric: tabular-nums; }
#ride-stats label { font-size: 11px; color: var(--muted); display: block; text-align: center; }

#settings .modal-card { gap: 2px; }
.set-row { display: flex; align-items: center; gap: 6px; margin-top: 10px; }
.set-row label { flex: 1; font-size: 13px; color: var(--text); }
.set-row input {
  width: 58px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 5px 7px;
  font-size: 12px;
  text-align: right;
}
.set-unit { font-size: 11px; color: var(--muted); width: 18px; }
.set-note { font-size: 11px; color: var(--muted); opacity: 0.75; margin: 4px 0 0 2px; }
.set-note.provisional { color: var(--accent-2); opacity: 1; }

/* "I don't know my FTP" — a text-weight affordance, not a competing button */
.linkish {
  background: none;
  border: 0;
  padding: 2px;
  margin: 2px 0 0 2px;
  font-size: 11px;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color 120ms var(--ease);
}
.linkish:hover { color: var(--accent-2); }

.ftp-est {
  margin: 8px 0 2px;
  padding: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.ftp-est .modal-hint { margin: 0 0 8px; }
.ftp-levels { display: flex; flex-direction: column; gap: 6px; }
.ftp-level {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  text-align: left;
  width: 100%;
  padding: 8px 10px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  cursor: pointer;
  transition: border-color 120ms var(--ease), background 120ms var(--ease);
}
.ftp-level:hover { border-color: var(--accent); background: var(--accent-dim); }
.ftp-level b { font-size: 12px; }
.ftp-level i { display: block; font-style: normal; font-size: 11px; color: var(--faint); }
.ftp-level .ftp-level-w {
  font-family: 'Barlow Condensed', sans-serif;
  font-size: 18px;
  font-weight: 600;
  color: var(--accent);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

#keys-details { margin-top: 2px; }
#keys-details summary {
  cursor: pointer;
  font-size: 11px;
  color: var(--muted);
  opacity: 0.8;
  list-style-position: inside;
}
#keys-details summary:hover { color: var(--text); }
#keys-details input {
  width: 100%;
  margin-top: 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 6px 8px;
  font-size: 12px;
}

/* ---- stage / map ---- */
#stage { flex: 1; position: relative; min-width: 0; }
#map { position: absolute; inset: 0; background: var(--bg); }

#route-banner {
  position: absolute;
  top: 12px; left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  background: rgba(8, 11, 17, 0.92);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
  min-width: 340px;
}
/* Live ride stats on the banner: big enough to read from the saddle. */
#banner-live {
  justify-content: space-around;
  gap: 18px;
  padding-top: 2px;
  border-top: 1px solid var(--border);
}
#banner-live .bl { text-align: center; }
#banner-live .bl b {
  display: block;
  font-size: 20px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
#banner-live .bl label { font-size: 10px; color: var(--muted); letter-spacing: 1px; }
.banner-row { display: flex; gap: 14px; align-items: center; justify-content: space-between; }
#route-name { font-weight: 600; }
#route-facts { color: var(--muted); }
#segment-row { display: none; }
#segment-row.active { display: flex; }
#segment-facts { color: var(--accent); font-weight: 600; }
#segment-row .chip-btn { padding: 3px 10px; font-size: 11px; }
.banner-hint { font-size: 10.5px; color: var(--muted); opacity: 0.7; }

/* ---- footer ---- */
footer {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--panel);
  border-top: 1px solid var(--border);
  padding: 10px 16px;
  height: 150px;
}

#elevation-wrap { flex: 1; height: 100%; position: relative; }

#controls {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  width: 440px;
  flex: none;
}
.ctrl-row { display: flex; gap: 8px; }
.ctrl-row + .ctrl-row { margin-top: 6px; }
/* Every secondary destination on one line, each an equal share of the width.
   Five buttons in a 320px column overflowed the footer; the fix is to let the
   row own its width rather than to keep shaving the labels. */
.ctrl-secondary { display: flex; gap: 6px; }
.ctrl-secondary button { flex: 1 1 0; min-width: 0; }
.ctrl-row button {
  flex: 1;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
}
.ctrl-row button:hover:not(:disabled) { border-color: var(--muted); }
.ctrl-row button:disabled { opacity: 0.35; cursor: default; }
.ctrl-row button.primary {
  background: var(--accent);
  border-color: var(--accent);
  font-weight: 700;
  flex: 1.5;
}
/* Choose ride sits at Start Ride's scale — the two halves of one decision —
   but outlined, so the filled orange stays the single "go" in the row. */
.ctrl-row button.choose {
  border-color: var(--accent);
  color: var(--accent-2);
  font-weight: 700;
}
.ctrl-row button.choose:hover { background: var(--accent-dim); border-color: var(--accent); }
.ctrl-secondary button {
  background: transparent;
  color: var(--muted);
  font-size: 11.5px;
  padding: 7px 4px;
  letter-spacing: -0.01em;
}
.ctrl-secondary button:hover { color: var(--text); border-color: var(--accent); }

/* ---- modals (BLE picker, route library, rides, summary) ---- */
.modal {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
}
.modal-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 22px;
  width: 380px;
  max-height: 72vh;
  display: flex;
  flex-direction: column;
}
.modal-card.modal-wide { width: 640px; }
/* Builder needs room to breathe — roughly twice the standard wide modal. */
.modal-card.modal-xl { width: min(1240px, 95vw); max-height: 90vh; }
.modal-card h3 { font-size: 15px; margin-bottom: 4px; }
.modal-hint { font-size: 12px; color: var(--muted); margin-bottom: 12px; }
.modal-list { list-style: none; overflow-y: auto; flex: 1; }
.modal-list li {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 6px;
  cursor: pointer;
  font-size: 14px;
}
.modal-list li:hover { border-color: var(--accent); }
.modal-list li .sub { display: block; font-size: 11px; color: var(--muted); margin-top: 2px; }
.modal-list .empty { border: none; color: var(--muted); cursor: default; text-align: center; }
.modal-cancel {
  margin-top: 10px;
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 6px;
  padding: 8px;
  cursor: pointer;
}
.modal-actions { display: flex; gap: 8px; margin-top: 10px; }
.modal-actions button { flex: 1; }
.primary-btn {
  margin-top: 10px;
  background: var(--accent);
  border: 1px solid var(--accent);
  color: #fff;
  font-weight: 600;
  border-radius: 6px;
  padding: 8px;
  cursor: pointer;
}
#namer-input, .modal-input {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 9px 10px;
  font-size: 14px;
}
.modal-input { width: 100%; margin-bottom: 8px; }

/* ---- auth modal: labels, inline errors, checklist, password reveal ---- */
.auth-label {
  display: block; font-size: 11.5px; font-weight: 600; letter-spacing: 0.04em;
  color: var(--muted); margin: 8px 0 3px;
}
#login-form .auth-label:first-of-type,
#signup-form .auth-label:first-of-type,
#recover-form .auth-label:first-of-type { margin-top: 4px; }

/* An error a rider cannot miss and cannot outrun: persistent, red, with a
   glyph so colour is never the only signal. Sits under its field, tied to it
   by aria-describedby. */
.field-error {
  color: var(--red); font-size: 12px; line-height: 1.35;
  margin: -4px 0 8px; display: flex; gap: 6px; align-items: flex-start;
}
.field-error::before { content: '⚠'; flex: none; }
.field-error[hidden] { display: none; }
.modal-input.invalid { border-color: var(--red); }
.modal-input.invalid:focus { border-color: var(--red); }

/* Reveal button lives inside the field's right edge. */
.pw-wrap { position: relative; }
.pw-wrap .modal-input { padding-right: 40px; }
.pw-toggle {
  position: absolute; top: 0; right: 0; height: calc(100% - 8px);
  width: 38px; margin: 0; padding: 0; border: none; background: none;
  color: var(--muted); cursor: pointer; display: grid; place-items: center;
}
.pw-toggle:hover { color: var(--text); }
.pw-toggle::before { content: '👁'; font-size: 15px; opacity: 0.8; }
.pw-toggle[aria-pressed="true"]::before { content: '🚫'; }

/* The live checklist: grey until met, green with a check when satisfied. */
.pw-reqs { list-style: none; margin: 2px 0 8px; padding: 8px 10px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; }
.pw-reqs .pw-req-title { font-size: 11.5px; color: var(--muted);
  margin-bottom: 4px; font-weight: 600; }
.pw-reqs li[data-req] { display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; color: var(--faint); padding: 1px 0; }
.pw-reqs li[data-req] .req-mark {
  flex: none; width: 15px; height: 15px; border-radius: 50%;
  border: 1.5px solid var(--faint); display: grid; place-items: center;
  font-size: 10px; line-height: 1; }
.pw-reqs li.met { color: var(--green); }
.pw-reqs li.met .req-mark { border-color: var(--green); background: var(--green);
  color: var(--bg); }
.pw-reqs li.met .req-mark::before { content: '✓'; }

/* The strength meter: a bar that fills and warms red → green with the score,
   the shape every rider recognises. */
.pw-meter-row { display: flex; align-items: center; gap: 10px; padding: 3px 0; }
.pw-meter {
  flex: 1; height: 6px; border-radius: 999px; overflow: hidden;
  background: var(--surface-1, #171E2A);
  border: 1px solid var(--border);
}
.pw-meter > span {
  display: block; height: 100%; width: 0;
  border-radius: 999px; transition: width .18s ease, background-color .18s ease;
}
.pw-meter[data-score="1"] > span { width: 25%;  background: #FF5A5A; }
.pw-meter[data-score="2"] > span { width: 55%;  background: #FF9A3D; }
.pw-meter[data-score="3"] > span { width: 80%;  background: #F5C518; }
.pw-meter[data-score="4"] > span { width: 100%; background: var(--green); }
.pw-meter-label { font-size: 12px; color: var(--faint); white-space: nowrap; }
.pw-meter-label b { color: var(--text); font-weight: 600; }

/* "Check your email" — the one instruction that matters, given room. */
.auth-sent { text-align: center; padding: 8px 4px 0; }
.auth-sent-icon { font-size: 34px; margin-bottom: 8px; }
.auth-sent h4 { font-size: 17px; margin-bottom: 8px; }
.auth-sent .modal-hint { margin-bottom: 8px; }
.auth-sent-spam { font-size: 11.5px; color: var(--faint); margin: 4px 0 4px; }
.auth-done { color: var(--green); font-size: 13px; font-weight: 600;
  margin: 6px 0; }
.auth-done[hidden] { display: none; }

/* Keyboard users must see where they are, and a disabled button must look it. */
.modal-input:focus-visible,
.primary-btn:focus-visible, .secondary-btn:focus-visible,
.pw-toggle:focus-visible, .modal-cancel:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px;
}
.primary-btn:disabled, .secondary-btn:disabled {
  opacity: 0.55; cursor: not-allowed;
}

.secondary-btn {
  margin-top: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 8px;
  cursor: pointer;
  width: 100%;
}
.secondary-btn:hover { border-color: var(--muted); }
.google-btn { margin-top: 4px; }
.login-user { font-size: 14px; font-weight: 600; margin-bottom: 6px; }
#library-strava { margin-bottom: 10px; margin-top: 0; }

/* ---- ride summary ---- */
#summary-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 12px;
}
#summary-stats .tile {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px;
  text-align: center;
}
#summary-stats .tile b { display: block; font-size: 22px; }
#summary-stats .tile span { font-size: 10px; letter-spacing: 1px; color: var(--muted); }
/* The chart keeps its box no matter how long the ride was. Both it and the
   laps table are flex children of a 72vh column: without these rules the
   chart was the only element willing to shrink, so a long laps table crushed
   it to a sliver. The laps scroll instead. */
#summary-chart-wrap { flex: 0 0 200px; height: 200px; min-height: 200px; position: relative; }
#summary-laps { min-height: 130px; overflow-y: auto; }

/* ---- friends & chat ---- */
#btn-social {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 6px 14px;
  font-size: 13px;
  cursor: pointer;
  margin-right: 8px;
}
#btn-social:hover { border-color: var(--muted); }

.social-grid { display: flex; gap: 14px; min-height: 320px; max-height: 52vh; }
.social-left { width: 220px; display: flex; flex-direction: column; }
.friend-add-row { display: flex; gap: 6px; margin-bottom: 8px; }
.friend-add-row input { margin-bottom: 0; }
.social-left .modal-list { flex: 1; }
.social-left .modal-list li.active { border-color: var(--accent); }

.social-right {
  flex: 1;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px;
  min-width: 0;
}
#chat-header { font-weight: 700; font-size: 14px; margin-bottom: 8px; }
#chat-messages { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; }
.chat-msg {
  max-width: 80%;
  padding: 7px 11px;
  border-radius: 12px;
  font-size: 13px;
  word-wrap: break-word;
}
.chat-msg.mine { align-self: flex-end; background: var(--accent); color: #fff; }
.chat-msg.theirs { align-self: flex-start; background: var(--surface-2); border: 1px solid var(--border); }
.chat-input-row { display: flex; gap: 6px; margin-top: 8px; }
.chat-input-row input { margin-bottom: 0; flex: 1; }

.chip-btn {
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
.chip-btn:hover { border-color: var(--accent); }
.chat-msg.mine .chip-btn { background: rgba(255,255,255,0.15); border-color: rgba(255,255,255,0.4); color: #fff; }

/* ---- structured training ---- */
#ftp-input {
  width: 100%;
  margin-top: 4px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 6px 8px;
  font-size: 12px;
}
.band-row { display: flex; gap: 6px; margin-top: 4px; }
.band-row input {
  width: 50%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 6px 8px;
  font-size: 12px;
}
#m-power-band.clamped { color: var(--accent); font-weight: 700; opacity: 1; }

/* Scroll affordance: always-visible themed scrollbars on every scrolling
   list, plus a bottom fade on the workout grid hinting at more content. */
#workout-grid::-webkit-scrollbar, #wp-blocks::-webkit-scrollbar,
.modal-list::-webkit-scrollbar, #builder-blocks::-webkit-scrollbar,
#chat-messages::-webkit-scrollbar {
  width: 9px;
}
#workout-grid::-webkit-scrollbar-track, #wp-blocks::-webkit-scrollbar-track,
.modal-list::-webkit-scrollbar-track, #builder-blocks::-webkit-scrollbar-track,
#chat-messages::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.03);
  border-radius: 5px;
}
#workout-grid::-webkit-scrollbar-thumb, #wp-blocks::-webkit-scrollbar-thumb,
.modal-list::-webkit-scrollbar-thumb, #builder-blocks::-webkit-scrollbar-thumb,
#chat-messages::-webkit-scrollbar-thumb {
  background: var(--surface-3);
  border-radius: 5px;
  border: 2px solid var(--panel);
}
#workout-grid::-webkit-scrollbar-thumb:hover, #wp-blocks::-webkit-scrollbar-thumb:hover,
.modal-list::-webkit-scrollbar-thumb:hover, #builder-blocks::-webkit-scrollbar-thumb:hover,
#chat-messages::-webkit-scrollbar-thumb:hover {
  background: var(--accent);
}

/* Fixed height, not min/max: otherwise the modal resized every time the tab
   changed — one ramp-test card collapsed it to the minimum while a category
   of five expanded it to the maximum. The grid scrolls inside instead. */
.workout-grid-wrap {
  display: flex;
  gap: 12px;
  height: 50vh;          /* + ~130px of modal chrome stays inside the 72vh cap,
                            even at the 700px minimum window height */
  min-height: 300px;
  position: relative;
}
/* fade at the grid's bottom edge = "there is more below" */
.workout-grid-wrap::after {
  content: '';
  position: absolute;
  left: 162px; right: 10px; bottom: 0;
  height: 30px;
  background: linear-gradient(to bottom, transparent, var(--panel));
  pointer-events: none;
}
#workout-tabs { display: flex; flex-direction: column; gap: 4px; width: 150px; }
#workout-tabs button {
  background: none;
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 12px;
  cursor: pointer;
  text-align: left;
}
#workout-tabs button.active { border-color: var(--accent); color: var(--accent); font-weight: 600; }
#workout-grid {
  flex: 1;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  grid-auto-rows: max-content;     /* cards keep their own height */
  gap: 10px;
  overflow-y: auto;
  align-content: start;
  padding-right: 4px;              /* room for the scrollbar, always reserved */
  scrollbar-gutter: stable;
}
.workout-card {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.workout-card:hover { border-color: var(--muted); }
.wc-name { font-weight: 700; font-size: 13px; }
.wc-profile svg { width: 100%; height: 56px; background: var(--bg); border-radius: 6px; }
.wc-meta { font-size: 11px; color: var(--muted); }
.wc-actions { display: flex; gap: 6px; }
.wc-actions .primary-btn { margin-top: 0; flex: 1; padding: 6px; font-size: 12px; }
#workout-grid .empty { color: var(--muted); grid-column: 1/-1; text-align: center; padding: 30px; }

/* ramp-test tab */
.test-intro {
  grid-column: 1 / -1;
  font-size: 12px;
  line-height: 1.55;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  padding: 10px 12px;
}
.test-intro b { color: var(--text); }
.test-firsttime { color: var(--accent-2); }
.workout-card.recommended {
  border-color: var(--accent);
  background: linear-gradient(to bottom, var(--accent-dim), transparent 60%);
}
.wc-source { font-size: 10px; color: var(--faint); font-weight: 500; }
.wc-badge {
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--bg);
  background: var(--accent);
  border-radius: 4px;
  padding: 2px 6px;
  margin-left: 6px;
  vertical-align: 1px;
}
.wc-est { color: var(--faint); }

/* builder */
#builder-blocks {
  display: flex;
  flex-direction: column;
  gap: 14px;                 /* generous air between cards */
  max-height: 34vh;
  overflow-y: auto;
  padding: 4px 4px 4px 0;
}
.blk-row {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  position: relative;
  /* Each block is an obvious card: raised dark surface, thick zone-coloured
     left edge, and a wash of that zone colour bleeding in from the left. */
  background:
    linear-gradient(to right,
      color-mix(in srgb, var(--zone-color, var(--surface-3)) 26%, transparent),
      transparent 55%),
    var(--surface-2);
  border: 1px solid color-mix(in srgb, var(--zone-color, var(--surface-3)) 55%, var(--border));
  border-left: 10px solid var(--zone-color, var(--border));
  border-radius: 10px;
  padding: 12px 12px 12px 14px;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.45);
}
.blk-row:hover {
  border-color: var(--zone-color, var(--muted));
  box-shadow: 0 5px 16px rgba(0, 0, 0, 0.6);
  transform: translateY(-1px);
}
/* zone palette — click a chip to append that kind of block */
.builder-palette-label { font-size: 11px; color: var(--muted); margin: 10px 0 6px; }
#zone-palette { display: grid; grid-template-columns: repeat(7, 1fr); gap: 7px; }
.zone-chip {
  border: 1px solid color-mix(in srgb, var(--zone-color) 60%, var(--border));
  border-top: 4px solid var(--zone-color);
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--zone-color) 20%, transparent), var(--surface-2));
  border-radius: 9px;
  padding: 9px 6px;
  cursor: pointer;
  color: var(--text);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  transition: transform 0.12s, box-shadow 0.12s;
}
.zone-chip:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.5);
  border-color: var(--zone-color);
}
.zone-chip b { font-size: 15px; font-weight: 800; color: var(--zone-color); line-height: 1; }
.zone-chip span { font-size: 11px; font-weight: 600; }
.zone-chip em { font-style: normal; text-align: center; }
.zone-chip .zc-range { font-size: 11px; font-weight: 700; color: var(--text); }
.zone-chip .zc-watts { font-size: 10px; color: var(--muted); }
.zone-chip .zc-add {
  font-size: 9.5px;
  color: var(--zone-color);
  margin-top: 3px;
  padding-top: 3px;
  border-top: 1px dashed color-mix(in srgb, var(--zone-color) 45%, transparent);
  width: 100%;
}

/* labelled fields inside a block card */
.blk-field { display: flex; flex-direction: column; gap: 3px; }
.blk-lbl { font-size: 9.5px; letter-spacing: 0.8px; text-transform: uppercase; color: var(--muted); }
.blk-input { display: flex; align-items: center; gap: 4px; }
.blk-input em {
  font-style: normal; font-size: 10.5px; color: var(--muted);
  min-width: 30px;
}
.blk-row select, .blk-row input { margin: 0; }
.blk-kind-field select { width: 96px; }
.blk-spacer { flex: 1; }
.blk-zone {
  color: var(--bg); font-size: 10px; font-weight: 800;
  border-radius: 5px; padding: 4px 8px; white-space: nowrap;
}

/* Numbered badge — anchors each card and shows plan order at a glance. */
.blk-num {
  width: 22px; height: 22px;
  flex: none;
  border-radius: 50%;
  background: var(--zone-color, var(--surface-3));
  color: var(--bg);
  font-size: 11px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}
.blk-row select, .blk-row input {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 6px;
  font-size: 12px;
}
.blk-row input { width: 62px; }
.blk-unit { color: var(--muted); font-size: 11px; }
.blk-zone {
  color: #fff; font-size: 10px; font-weight: 700;
  border-radius: 4px; padding: 3px 6px; min-width: 26px; text-align: center;
}
#builder-preview { margin-top: 12px; }
#builder-preview svg { width: 100%; height: 140px; background: var(--bg); border-radius: 8px; }

/* Per-block labels on the builder profile: watts above the bar, duration
   below the baseline. Hidden automatically when a bar is too narrow. */
.pf-power, .pf-dur {
  text-anchor: middle;
  font-family: 'Barlow Condensed', sans-serif;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.pf-power { font-size: 11px; font-weight: 600; fill: var(--text); }
.pf-dur   { font-size: 10px; fill: var(--faint); }
#builder-blocks { margin-top: 10px; }

/* share-code modal */
#share-text {
  width: 100%;
  min-height: 88px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--accent);
  font-family: Consolas, "SF Mono", monospace;
  font-size: 13px;
  letter-spacing: 0.5px;
  padding: 10px;
  resize: vertical;
  word-break: break-all;
}

/* player panel */
#workout-panel {
  position: absolute;
  top: 12px; right: 12px; bottom: 12px;
  width: 290px;
  z-index: 1100;
  background: rgba(8, 11, 17, 0.94);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
#wp-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
#wp-name { font-weight: 700; font-size: 14px; }
#wp-target-wrap { text-align: center; }
#wp-target { font-size: 64px; font-weight: 700; font-variant-numeric: tabular-nums; }
/* The live-power readout only exists on the expanded player; the compact
   panel keeps today's exact look. */
#wp-actual-wrap { display: none; }
#wp-actual { font-variant-numeric: tabular-nums; }
#wp-actual.wp-on { color: var(--green); }
#wp-actual.wp-under { color: var(--muted); }
#wp-actual.wp-over { color: var(--accent-2); }
#wp-main { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 10px; }
/* Ride stats and the road picker belong to the expanded player; the compact
   panel leans on the metrics sidebar instead. */
.wp-times .wp-stat { display: none; }
#wp-road { display: none; align-items: center; justify-content: center; gap: 6px; }
#wp-road label { font-size: 10px; color: var(--muted); letter-spacing: 1px; margin-right: 4px; }
#wp-road .chip-btn.active {
  border-color: var(--accent);
  background: var(--accent-dim);
  color: var(--text);
}
#wp-road-pct {
  width: 48px;
  padding: 4px 6px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 12px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  /* Native spinners are white chrome on a dark panel; the themed −/+
     buttons beside the box do their job instead — same convention as the
     route-builder's order inputs. */
  -moz-appearance: textfield; appearance: textfield;
}
#wp-road-pct::-webkit-inner-spin-button,
#wp-road-pct::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
#wp-road-pct.active { border-color: var(--accent); background: var(--accent-dim); }
.wp-road-unit { font-size: 11px; color: var(--muted); }
#wp-road-down, #wp-road-up { min-width: 26px; text-align: center; }
#wp-actions { display: flex; justify-content: center; gap: 8px; }
#wp-actions button { flex: 1; max-width: 260px; }
#wp-head .modal-x { margin-left: 4px; }
.wp-unit { color: var(--muted); font-size: 12px; margin-left: 6px; }
.wp-times { display: flex; justify-content: space-around; }
.wp-times span { font-size: 26px; font-weight: 700; display: block; text-align: center; font-variant-numeric: tabular-nums; }
.wp-times label { font-size: 10px; color: var(--muted); display: block; text-align: center; letter-spacing: 1px; }
#wp-profile { position: relative; }
#wp-profile svg { width: 100%; height: 44px; background: var(--bg); border-radius: 6px; }
#wp-cursor {
  position: absolute; top: 0; bottom: 0; width: 2px;
  background: #fff; opacity: 0.9;
}
#wp-blocks { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.wp-block {
  display: flex; justify-content: space-between; gap: 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 9px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.wp-block.current { border-color: var(--accent); background: var(--accent-dim); }
.wp-block.done { opacity: 0.5; }
.wp-block.done .wpb-done { color: var(--green); font-weight: 700; }
.wpb-dur { color: var(--muted); }

/* ---- expanded player ----
   Workouts never use the map (ERG ignores route and grade), so while one is
   armed or running the panel may take the whole stage. Compact mode is the
   original right-hand column, one class apart, for riders who want the map
   animating behind ("Show map"). */
#workout-panel.expanded { left: 12px; width: auto; }
#workout-panel.expanded #wp-target-wrap {
  display: flex; align-items: baseline; justify-content: center; gap: 8px;
  flex-wrap: wrap;
}
#workout-panel.expanded #wp-target { font-size: clamp(64px, 11vh, 118px); line-height: 1.05; }
#workout-panel.expanded #wp-actual-wrap { display: inline-block; margin-left: 36px; }
#workout-panel.expanded #wp-actual { font-size: clamp(64px, 11vh, 118px); font-weight: 700; line-height: 1.05; }
#workout-panel.expanded .wp-times { flex-wrap: wrap; row-gap: 4px; }
#workout-panel.expanded .wp-times span { font-size: clamp(20px, 2.6vw, 34px); }
#workout-panel.expanded .wp-times > div { min-width: 90px; }
/* Blocks read as a text column on the left; the zone-colored profile owns
   the rest. row-reverse keeps the compact DOM order (profile first) intact. */
#workout-panel.expanded #wp-main { flex-direction: row-reverse; gap: 12px; }
#workout-panel.expanded #wp-blocks { flex: 0 0 190px; }
#workout-panel.expanded #wp-profile { flex: 1; min-width: 0; }
#workout-panel.expanded #wp-profile svg { height: 100%; }
#workout-panel.expanded .wp-times .wp-stat { display: block; }
#workout-panel.expanded #wp-road { display: flex; }

/* Live power trace over the profile. Non-scaling stroke keeps it hairline
   however far the fixed viewBox is stretched. */
#wp-trace {
  fill: none; stroke: var(--text); stroke-opacity: 0.85; stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}

/* Block-transition countdown: the last five seconds before a different
   target, painted over the player. pointer-events:none so End stays
   clickable underneath. */
#wp-countdown {
  display: none; position: absolute; inset: 0; z-index: 2;
  align-items: center; justify-content: center; flex-direction: column;
  gap: 6px; background: rgba(8, 11, 17, 0.72); border-radius: 12px;
  pointer-events: none;
}
#wp-countdown.on { display: flex; }
#wp-cd-num {
  font-size: clamp(72px, 18vh, 150px); font-weight: 800; line-height: 1;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
#wp-cd-next { font-size: 26px; font-weight: 700; }

.ramp-big { font-size: 54px; font-weight: 800; color: var(--accent); text-align: center; margin: 8px 0; }

/* ---- street view ---- */
#streetview-wrap {
  position: absolute;
  right: 12px;
  bottom: 12px;
  z-index: 1000;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.5);
}
#streetview { display: block; width: 320px; height: 192px; object-fit: cover; }

/* ---- toast ---- */
#toast {
  position: fixed;
  bottom: 170px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 11px 20px;
  font-size: 13px;
  z-index: 6100;              /* above everything — an invisible toast is
                                 indistinguishable from silence, which is how
                                 a wrong password looked like nothing at all */
  box-shadow: var(--shadow-2);
  animation: toastIn .22s var(--ease);
}
@keyframes toastIn {
  from { opacity: 0; transform: translate(-50%, 14px) }
  to   { opacity: 1; transform: translate(-50%, 0) }
}

/* Ride name + visibility on the finish dialog */
.save-row { display: flex; gap: 12px; margin: 12px 0 4px; }
.save-field { display: flex; flex-direction: column; gap: 4px; flex: 1; }
.save-field > span { font-size: 11px; color: var(--muted); }
.save-field input, .save-field select {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 7px 9px;
  font-size: 13px;
}
.save-field input:focus, .save-field select:focus {
  outline: none; border-color: var(--accent);
}
.save-vis { flex: 0 0 170px; }


/* Close-range elevation: the road immediately ahead, banded by gradient. */
#zoom-wrap {
  position: absolute;
  left: 12px;
  bottom: 12px;
  z-index: 1000;
  width: 320px;
  height: 132px;
  display: flex;
  flex-direction: column;
  background: rgba(8, 11, 17, 0.92);
  backdrop-filter: blur(4px);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 6px 9px 4px;
  box-shadow: var(--shadow-2);
}
#zoom-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 2px;
}
/* Fixed width, so the − and + do not slide sideways every time the label
   changes between "NEXT 500 M" and "NEXT 16 KM". The buttons are a target the
   rider is aiming at repeatedly; a target that moves after every press is a
   target you have to re-find after every press. */
.zoom-title {
  font-size: 10px; letter-spacing: 1.4px; color: var(--muted);
  width: 84px; flex: none;
  white-space: nowrap;
}
#zoom-grade {
  font-family: 'Barlow Condensed', 'Inter', sans-serif;
  font-variant-numeric: tabular-nums;
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
}
#elev-zoom { flex: 1; width: 100%; min-height: 0; }

/* Ride mode: the rider's first choice, on the ride screen rather than buried
   in settings — free riding on terrain, or holding a power range. */
#ride-mode {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 7px;
}
.mode-tabs { display: flex; gap: 4px; }
.mode-tab {
  flex: 1;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--muted);
  padding: 6px 4px;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
}
.mode-tab:hover { color: var(--text); border-color: var(--muted); }
.mode-tab.active {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
}
#mode-fields {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 7px;
}
#mode-fields input {
  width: 100%;
  min-width: 0;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 5px 6px;
  font-size: 12px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
#mode-fields input:focus { outline: none; border-color: var(--accent); }
.mode-dash, .mode-unit { font-size: 11px; color: var(--muted); flex: none; }
#mode-hint {
  font-size: 10px;
  line-height: 1.3;
  color: var(--faint);
  margin-top: 6px;
  text-align: center;
}

/* Short screens: the sidebar must never scroll or clip, so on anything under
   ~880px tall the type steps down and the spacing tightens. Every element
   stays — nothing is hidden, it is just set smaller. */
@media (max-height: 880px) {
  #metrics { gap: 7px; padding: 10px; }
  .metric-power .metric-value { font-size: 46px; }
  .metric-power { padding-bottom: 5px; }
  .metric-grid { gap: 7px 6px; }
  .metric-grid .metric-value { font-size: 25px; }
  .metric-grade .metric-value { font-size: 24px; }
  .metric-label { font-size: 10px; letter-spacing: 1.2px; }
  #gearbox, #fixedbox { padding: 6px; }
  #gear-number, #fixed-value { font-size: 30px; }
  #gear-ticks { margin: 4px 0 2px; }
  #gear-ticks span { height: 9px; }
  #ride-mode { padding: 6px; }
  .mode-tab { padding: 5px 3px; }
  #mode-fields { margin-top: 5px; }
  #mode-hint { margin-top: 4px; }
  #ride-stats { padding-top: 7px; }
  #ride-stats span { font-size: 20px; }
  #btn-settings { padding: 6px; }
}

/* Builder duration: whole minutes and seconds, so a 10-second sprint is typed
   as 0 / 10 rather than as 0.17 of a minute. */
.blk-dur { display: flex; align-items: center; gap: 3px; }
.blk-dur input { width: 46px; }
.blk-dur em {
  font-style: normal;
  font-size: 10px;
  color: var(--muted);
  margin-right: 4px;
}

/* Surface selector on the route banner, and riding position in settings. */
#terrain-row { gap: 8px; align-items: center; }
#terrain-row label { font-size: 11px; color: var(--muted); }
#terrain-select, .set-wide {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 3px 6px;
  font-size: 12px;
  font-family: inherit;
}
#terrain-select:focus, .set-wide:focus { outline: none; border-color: var(--accent); }
.set-wide { width: 140px; text-align: left; padding: 5px 7px; }
#rider-units { width: 176px; text-align: left; }   /* "Metric (km, m, kg)" */
#terrain-detail { font-size: 11px; color: var(--faint); }

/* Route completion: warms from grey through to the brand orange as the ride
   closes in. Deliberately a different colour language from the zone colours
   (intensity) and the gradient bands (terrain) — this one reads as heat. */
#m-done { transition: color .6s var(--ease); }

/* Final-stretch banner — one calm statement, not a burst of confetti. */
#final-stretch {
  position: absolute;
  top: 12px; left: 50%;
  transform: translateX(-50%);
  z-index: 1001;
  display: flex; align-items: baseline; gap: 10px;
  background: rgba(8, 11, 17, 0.94);
  backdrop-filter: blur(4px);
  border: 1px solid var(--accent);
  border-radius: 10px;
  padding: 9px 15px;
  box-shadow: var(--shadow-2);
  animation: fsIn .4s var(--ease);
}
#final-stretch .fs-title {
  font-size: 13px; font-weight: 650; color: var(--accent);
  letter-spacing: 0.01em;
}
#final-stretch #fs-left {
  font-size: 13px; color: var(--text);
  font-variant-numeric: tabular-nums;
}
@keyframes fsIn {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
/* The route banner sits top-centre too; nudge it down while this is showing. */
#stage:has(#final-stretch:not(.hidden)) #route-banner { top: 58px; }

/* Minimap zoom controls — small, out of the way, and inert when at a limit. */
#zoom-head { gap: 8px; }
.zoom-ctrls { display: flex; gap: 3px; margin-right: auto; }
.zoom-ctrls button {
  width: 18px; height: 18px;
  padding: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}
.zoom-ctrls button:hover:not(:disabled) { color: var(--text); border-color: var(--muted); }
.zoom-ctrls button:disabled { opacity: 0.3; cursor: default; }
#elev-zoom { cursor: ns-resize; }

/* ---- My progress ---- */
/* No top padding: the sticky header supplies its own, so nothing scrolls
   through the gap above it. */
#pg-card { max-height: 88vh; overflow-y: auto; padding-top: 0; }
#pg-body { display: flex; flex-direction: column; gap: 22px; margin: 8px 0 4px; }
#pg-body .empty { color: var(--muted); text-align: center; padding: 44px 0; }

.pg-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; }
.pg-tile {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 10px;
  text-align: center;
}
.pg-tile b {
  display: block;
  font-family: 'Barlow Condensed', 'Inter', sans-serif;
  font-variant-numeric: tabular-nums;
  font-size: 27px; font-weight: 600; color: var(--text); line-height: 1.05;
}
.pg-tile span { display: block; font-size: 10px; letter-spacing: 1.2px; color: var(--muted); margin-top: 3px; }
.pg-tile i { display: block; font-style: normal; font-size: 10px; color: var(--faint); margin-top: 4px; }

.pg-section h4 { font-size: 14px; font-weight: 650; margin-bottom: 2px; }
.pg-section .modal-hint { margin-bottom: 10px; }
.pg-chart { height: 240px; position: relative; }
.pg-chart-short { height: 190px; }

.pg-zones { display: flex; flex-direction: column; gap: 5px; }
.pg-zone { display: flex; align-items: center; gap: 10px; font-size: 12px; }
/* Wide enough for "Z2 Endurance · 112–129 bpm" on one line — the heart-rate
   rows carry their range, and a wrapped label pushes every bar out of line. */
.pg-zone-name { width: 186px; color: var(--muted); flex: none; white-space: nowrap; }
.pg-zone-bar { flex: 1; height: 9px; background: var(--surface-2); border-radius: 5px; overflow: hidden; }
.pg-zone-bar i { display: block; height: 100%; border-radius: 5px; transition: width .5s var(--ease); }
.pg-zone-pct { width: 42px; text-align: right; color: var(--text); font-variant-numeric: tabular-nums; flex: none; }

.pg-map { background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 8px; }
.pg-map svg { display: block; }
.pg-countries { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.pg-country {
  font-size: 11px; color: var(--accent);
  background: var(--accent-dim);
  border: 1px solid var(--accent);
  border-radius: 20px; padding: 3px 10px;
}

.pg-deltas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 6px;
  margin-top: 12px;
}
.pg-delta {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: 8px;
  padding: 7px 9px;
}
.pg-delta.up   { border-left-color: var(--green); }
.pg-delta.down { border-left-color: var(--red); }
.pg-delta.flat { border-left-color: var(--faint); }
.pg-delta-win { display: block; font-size: 10px; letter-spacing: .8px; color: var(--muted); }
.pg-delta b {
  display: block; margin-top: 2px;
  font-family: 'Barlow Condensed', 'Inter', sans-serif;
  font-variant-numeric: tabular-nums;
  font-size: 19px; font-weight: 600;
}
.pg-delta.up b   { color: var(--green); }
.pg-delta.down b { color: var(--red); }
.pg-delta.flat b { color: var(--muted); }
.pg-delta i { font-style: normal; font-size: 11px; color: var(--faint); }

.pg-months { width: 100%; border-collapse: collapse; margin-top: 14px; font-size: 12px; }
.pg-months th {
  text-align: left; font-weight: 500; font-size: 10px; letter-spacing: 1px;
  text-transform: uppercase; color: var(--muted);
  padding: 0 8px 7px; border-bottom: 1px solid var(--border);
}
.pg-months th + th, .pg-months td.num { text-align: right; }
.pg-months td { padding: 7px 8px; border-bottom: 1px solid var(--border); font-variant-numeric: tabular-nums; }
.pg-months tbody tr:last-child td { border-bottom: none; }
.pg-months tbody tr:hover { background: var(--surface-2); }
.pg-months tr.off td { color: var(--faint); }

/* ---- focus mode ---- */
/* Nothing but the numbers, on the darkest surface the app has. The point is
   that the rider can put something else on the screen behind it — a film, a
   race — and still see what they are doing at a glance from the bike. */
#focus {
  /* Above everything, including Leaflet's own panes — the map container does
     not create a stacking context, so its internal z-indices (up to 800)
     compete directly with anything fixed on the page. */
  position: fixed; inset: 0; z-index: 5000;
  background: #000;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 26px;
  padding: 40px;
}
#focus-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px 40px;
  width: min(1100px, 100%);
}
.focus-cell { text-align: center; }
.focus-cell b {
  display: block;
  font-family: 'Barlow Condensed', 'Inter', sans-serif;
  font-variant-numeric: tabular-nums;
  font-size: clamp(44px, 7vw, 96px);
  font-weight: 600; line-height: 0.95; color: var(--text);
}
.focus-cell span {
  display: block; margin-top: 6px;
  font-size: 12px; letter-spacing: 3px; color: var(--faint);
}
.focus-hero { grid-column: 1 / 3; }
.focus-hero b { font-size: clamp(90px, 17vw, 230px); color: var(--accent); }
.focus-hero span { font-size: 14px; letter-spacing: 5px; }
/* W/kg rides shotgun on the hero row: same accent, sized between the hero
   and the ordinary cells, centred against the big number's baseline. */
.focus-wkg { align-self: center; }
.focus-wkg b { font-size: clamp(48px, 7vw, 96px); color: var(--accent); }

#focus-target {
  font-size: 17px; color: var(--accent-2);
  border: 1px solid var(--accent); border-radius: 24px;
  padding: 9px 22px;
}

/* Dim until the mouse comes near, so it is reachable without ever being part
   of what the rider is looking at. */
#focus-exit {
  position: absolute; bottom: 22px; right: 22px;
  background: transparent; border: 1px solid var(--border);
  color: var(--faint); border-radius: 20px;
  padding: 8px 16px; font-size: 12px; cursor: pointer;
  opacity: 0.25;
}
#focus-exit:hover { opacity: 1; color: var(--text); border-color: var(--muted); }

/* ---- modal sticky header ---- */
/* A long scrolling modal must not bury its own close button at the bottom. */
.modal-sticky {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  /* Pulled flush with the card's own 22px padding so the bar spans the full
     width and nothing scrolls out from underneath its corners. */
  margin: 0 -22px 4px;
  padding: 20px 22px 12px;
  border-radius: 12px 12px 0 0;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
.modal-sticky h3 { margin-bottom: 0; }
.modal-x {
  background: transparent; border: none;
  color: var(--muted); cursor: pointer;
  font-size: 26px; line-height: 1;
  width: 34px; height: 34px; border-radius: 8px;
  flex: none;
}
.modal-x:hover { background: var(--surface-2); color: var(--text); }

/* ---- laps ---- */
.laps { width: 100%; border-collapse: collapse; font-size: 12px; }
.laps th {
  text-align: right; font-weight: 500; font-size: 10px; letter-spacing: 1px;
  text-transform: uppercase; color: var(--muted);
  padding: 0 8px 7px; border-bottom: 1px solid var(--border);
}
.laps th:first-child, .laps td:first-child { text-align: left; }
.laps td {
  text-align: right; padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  font-variant-numeric: tabular-nums;
}
.laps tbody tr:last-child td { border-bottom: none; }
.laps tbody tr:hover { background: var(--surface-2); }
.lap-auto { color: var(--faint); font-size: 10px; margin-left: 5px; }

/* ---- explanation icons ---- */
/* Deliberately quiet. A rider who already knows what watts are should be able
   to look straight past these; a rider who does not should find them the
   moment they go looking. */
.explain-btn {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 14px; height: 14px;
  margin-left: 5px;
  vertical-align: -1px;
  padding: 0;
  border: 1px solid var(--faint);
  border-radius: 50%;
  background: transparent;
  color: var(--faint);
  font-size: 9px; font-weight: 700; line-height: 1;
  font-family: 'Inter', sans-serif;
  letter-spacing: 0;
  cursor: help;
  flex: none;
}
.explain-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-dim);
}

.explain-pop {
  position: fixed;
  z-index: 6000;                 /* above focus mode, which is 5000 */
  width: min(340px, calc(100vw - 16px));
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-2);
  padding: 13px 15px;
  animation: rise .14s var(--ease);
}
.explain-pop h5 {
  font-size: 13px; font-weight: 650; color: var(--text);
  margin-bottom: 6px; letter-spacing: 0;
}
.explain-pop p {
  font-size: 12px; line-height: 1.5; color: var(--muted);
  text-transform: none; letter-spacing: 0;
}
.explain-pop p.why {
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--border);
  color: var(--faint);
}

/* Headings and tile labels host a button, so they need to lay out as a row. */
.pg-section h4, #summary-laps h4 { display: flex; align-items: center; }
.pg-tile span, #summary-stats .tile span, .metric-label, #ride-stats label {
  display: flex; align-items: center; justify-content: center;
}

/* ---- route library ---- */
#lib-card { max-height: 88vh; overflow-y: auto; padding-top: 0; }

.lib-tabs { display: flex; gap: 6px; margin: 10px 0 14px; }
.lib-tab {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 8px;
  padding: 7px 16px;
  font-size: 12.5px;
  cursor: pointer;
}
.lib-tab:hover { color: var(--text); border-color: var(--muted); }
.lib-tab.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }

.lib-controls { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; }
.lib-controls input[type="search"], .lib-controls input[type="text"] {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  padding: 9px 12px;
  font-size: 13px;
  font-family: inherit;
}
.lib-controls input:focus { outline: none; border-color: var(--accent); }
.lib-controls select {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  padding: 9px 10px;
  font-size: 12.5px;
  font-family: inherit;
  cursor: pointer;
}

.lib-facets { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.lib-chip {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 20px;
  padding: 4px 12px;
  font-size: 11.5px;
  cursor: pointer;
}
.lib-chip:hover { color: var(--text); border-color: var(--muted); }
.lib-chip.on { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
.lib-chip b { font-weight: 600; opacity: 0.6; margin-left: 5px; }

.lib-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 8px;
}
.lib-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 13px;
  cursor: pointer;
  text-align: left;
  color: inherit;
  font: inherit;
  display: block;
  width: 100%;
}
.lib-card:hover { border-color: var(--accent); background: var(--surface-3); }
.lib-card h5 {
  font-size: 13px; font-weight: 600; color: var(--text);
  margin-bottom: 5px; letter-spacing: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lib-meta {
  display: flex; flex-wrap: wrap; gap: 4px 10px;
  font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.lib-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 7px; }
.lib-tag {
  font-size: 10px; letter-spacing: .4px;
  border: 1px solid var(--border); border-radius: 4px;
  padding: 2px 6px; color: var(--faint);
}
.lib-tag.place { color: var(--accent-2); border-color: var(--accent); }
.lib-tag.net { color: var(--blue); border-color: var(--blue); }

.lib-status {
  font-size: 12px; color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 10px;
}
.lib-status.err { color: var(--red); border-color: var(--red); }
.lib-attrib { font-size: 10.5px; color: var(--faint); margin-top: 14px; }
.lib-empty { grid-column: 1/-1; text-align: center; color: var(--muted); padding: 34px 0; font-size: 13px; }

/* The waypoint markers the builder drops on the map. */
.build-pin {
  background: var(--accent);
  border: 2px solid #fff;
  border-radius: 50%;
  width: 13px; height: 13px;
}

/* ---- heart-rate zones in settings ---- */
.set-head {
  display: flex; align-items: center;
  font-size: 12px; font-weight: 600; color: var(--text);
  margin: 18px 0 2px; padding-top: 14px;
  border-top: 1px solid var(--border);
}
.hr-custom { margin-top: 8px; }
.hr-row { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.hr-row label { flex: 1; font-size: 12px; color: var(--muted); }
.hr-row input {
  width: 54px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
  color: var(--text); padding: 5px 7px; font-size: 12px; text-align: right;
}
.hr-row .dash { color: var(--faint); font-size: 12px; }
.hr-custom-actions { display: flex; gap: 8px; margin-top: 12px; }

.hr-preview { display: flex; flex-direction: column; gap: 3px; margin-top: 10px; }
.hr-pv { display: flex; align-items: center; gap: 8px; font-size: 11.5px; }
.hr-pv i { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.hr-pv b { font-weight: 500; color: var(--text); width: 92px; }
.hr-pv span { color: var(--muted); font-variant-numeric: tabular-nums; }

.pg-scale {
  display: flex; align-items: center; gap: 8px;
  margin-top: 10px; flex-wrap: wrap;
}
.pg-scale-cap { font-size: 10px; letter-spacing: .6px; color: var(--faint); }
.pg-scale-step { display: flex; align-items: center; gap: 5px; }
.pg-scale-step i {
  width: 22px; height: 10px; border-radius: 3px;
  border: 1px solid var(--accent-2);
}
.pg-scale-step em { font-style: normal; font-size: 10.5px; color: var(--muted); }

/* ---- route builder, on the map ---- */
/* Everything the builder needs lives here, over the map, for as long as the
   rider is drawing. The first version put these controls in a modal, which
   meant closing it to click, reopening it to save, and never seeing the
   distance while you drew. */
#build-panel {
  position: absolute;
  top: 14px; left: 14px;
  z-index: 1200;                  /* over Leaflet's panes and controls */
  width: 268px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-2);
  padding: 12px 13px 13px;
  animation: rise .16s var(--ease);
}
.bp-head { display: flex; align-items: center; justify-content: space-between; }
.bp-head b { font-size: 13px; font-weight: 650; }
.bp-head .modal-x { font-size: 22px; width: 26px; height: 26px; }

.bp-stats { display: flex; gap: 14px; margin: 8px 0 9px; }
.bp-stats span { display: flex; align-items: baseline; gap: 4px; }
.bp-stats b {
  font-family: 'Barlow Condensed', 'Inter', sans-serif;
  font-variant-numeric: tabular-nums;
  font-size: 25px; font-weight: 600; color: var(--text); line-height: 1;
}
.bp-stats i { font-style: normal; font-size: 10px; color: var(--muted); }

.bp-hint {
  font-size: 11.5px; color: var(--muted); line-height: 1.45;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 7px 9px;
  margin-bottom: 9px;
  /* Two lines are reserved whether one or two are used: a hint that changes
     height moves every control below it, and a rider spam-clicking Undo ends
     up pressing whatever slid under the pointer. */
  min-height: 49px;
}
.bp-hint.err { color: var(--red); border-color: var(--red); }
.bp-hint.busy { color: var(--accent-2); }

.bp-row { display: flex; gap: 6px; margin-top: 6px; }
.bp-row select, .bp-row input {
  flex: 1; min-width: 0;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text);
  padding: 7px 9px;
  font-size: 12px;
  font-family: inherit;
}
.bp-row input:focus, .bp-row select:focus { outline: none; border-color: var(--accent); }
.bp-row button { padding: 7px 11px; font-size: 12px; border-radius: 7px; flex: 1; }
/* A select sharing a row with buttons collapses to its chevron, because the
   buttons refuse to shrink and it is allowed to. It gets its own row. */
.bp-full { width: 100%; }

/* Waypoints: obviously grabbable, and obviously removable. */
.bp-pin { cursor: grab; }
.bp-pin:active { cursor: grabbing; }

/* ---- map credits ---- */
.map-attrib-btn {
  width: 22px; height: 22px;
  padding: 0;
  background: rgba(8, 11, 17, 0.72);
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--muted);
  font-family: 'Inter', serif;
  font-size: 12px; font-style: italic; font-weight: 600;
  line-height: 1;
  cursor: pointer;
  backdrop-filter: blur(4px);
}
.map-attrib-btn:hover { color: var(--text); border-color: var(--muted); }
.leaflet-control-container .leaflet-bottom.leaflet-right { margin: 0 8px 8px 0; }

/* ---- about & credits ---- */
.about h4 { font-size: 15px; font-weight: 650; margin-bottom: 8px; }
.about h5 { font-size: 12px; font-weight: 600; margin: 16px 0 5px; color: var(--text); }
.about p { font-size: 12.5px; line-height: 1.6; color: var(--muted); margin-bottom: 10px; }
.about a { color: var(--accent); text-decoration: none; }
.about a:hover { text-decoration: underline; }
.about-meta {
  font-size: 11px; color: var(--faint);
  border-top: 1px solid var(--border);
  padding-top: 12px; margin-top: 16px;
}

.credit { padding: 10px 0; border-bottom: 1px solid var(--border); }
.credit:last-child { border-bottom: none; }
.credit-head { display: flex; align-items: center; gap: 8px; }
.credit-head a { font-size: 13px; font-weight: 600; color: var(--accent); text-decoration: none; }
.credit-head a:hover { text-decoration: underline; }
.credit-req {
  font-size: 9px; letter-spacing: .8px; text-transform: uppercase;
  color: var(--accent-2); border: 1px solid var(--accent);
  border-radius: 4px; padding: 1px 5px;
}
.credit-detail { font-size: 11.5px; color: var(--muted); line-height: 1.5; margin: 0; }

#settings .modal-card { max-height: 82vh; overflow-y: auto; padding-top: 0; }

/* ---- GPX drop target ---- */
.gpx-drop {
  border: 1.5px dashed var(--border);
  border-radius: 10px;
  padding: 26px 16px;
  text-align: center;
  transition: border-color .15s var(--ease), background-color .15s var(--ease);
}
.gpx-drop.over { border-color: var(--accent); background: var(--accent-dim); }
.gpx-drop b { display: block; font-size: 13px; font-weight: 600; color: var(--text); }
.gpx-drop span { display: block; font-size: 12px; color: var(--muted); margin-top: 5px; }

/* ---- how to shift ---- */
#gear-keys, #fixed-keys {
  display: flex; align-items: center; justify-content: center; gap: 3px;
  margin-top: 6px;
}
.keycap {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px;
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 10px; line-height: 1;
}
#gear-keys em, #fixed-keys em {
  font-style: normal; font-size: 10px; color: var(--faint);
  margin-left: 3px; letter-spacing: .3px;
}

/* ---- ride history ---- */
#rides-card { max-height: 88vh; overflow-y: auto; padding-top: 0; }

.rides-summary {
  display: flex; gap: 18px; flex-wrap: wrap;
  font-size: 12px; color: var(--muted);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 10px 2px; margin-bottom: 4px;
}
.rides-summary b {
  color: var(--text); font-variant-numeric: tabular-nums;
  font-weight: 600; margin-right: 4px;
}

.rh-month { margin-top: 18px; }
.rh-month-head {
  display: flex; align-items: baseline; gap: 12px;
  padding-bottom: 7px; margin-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.rh-month-head h4 { font-size: 14px; font-weight: 650; }
.rh-month-head span {
  font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.rh-row {
  display: grid;
  grid-template-columns: minmax(0, 2.2fr) repeat(4, minmax(0, 1fr)) auto;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 10px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  color: inherit; font: inherit; text-align: left;
  cursor: pointer;
}
.rh-row:hover { background: var(--surface-2); border-color: var(--border); }
.rh-name { min-width: 0; }
.rh-name b {
  display: block; font-size: 13px; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rh-name span { font-size: 11px; color: var(--faint); }
.rh-stat {
  font-size: 12px; color: var(--muted);
  font-variant-numeric: tabular-nums; text-align: right;
}
.rh-stat i { font-style: normal; color: var(--faint); font-size: 10px; margin-left: 3px; }

.rh-badge {
  font-size: 10px; letter-spacing: .3px;
  border: 1px solid var(--border); border-radius: 20px;
  padding: 2px 8px; color: var(--muted); white-space: nowrap;
}
.rh-badge.repeat { color: var(--accent-2); border-color: var(--accent); }
.rh-badge.faster { color: var(--green); border-color: var(--green); }
.rh-badge.slower { color: var(--faint); }
.rh-badge.kind-workout { color: var(--blue); border-color: var(--blue); }
.rh-badge.kind-test { color: var(--red); border-color: var(--red); }
.rh-badges { display: flex; gap: 5px; justify-content: flex-end; flex-wrap: wrap; }


/* The map with no basemap file: routes still draw, the rider is told why the
   world behind them is dark instead of being left to wonder. */
.basemap-missing {
  position: absolute;
  top: 14px; left: 50%;
  transform: translateX(-50%);
  z-index: 1100;
  max-width: 380px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-2);
  padding: 12px 15px;
}
.basemap-missing b { display: block; font-size: 13px; color: var(--text); margin-bottom: 4px; }
.basemap-missing span { font-size: 11.5px; color: var(--muted); line-height: 1.5; }

/* ---- builder panel v2: collapsible, numbered points ---- */
.bp-head-btns { display: flex; gap: 2px; }
#build-panel.collapsed { width: auto; padding: 0; background: transparent; border: none; box-shadow: none; }
#build-panel.collapsed .bp-head, #build-panel.collapsed #bp-body { display: none; }
.bp-mini {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 20px;
  box-shadow: var(--shadow-2);
  color: var(--muted);
  padding: 8px 14px;
  font-size: 12px;
  cursor: pointer;
}
.bp-mini b { color: var(--text); font-variant-numeric: tabular-nums; }
.bp-mini:hover { border-color: var(--accent); color: var(--text); }

.bp-sel {
  display: flex; flex-direction: column; gap: 5px;
  background: var(--accent-dim);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 8px 10px;
  margin-bottom: 9px;
}
.bp-sel-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; min-height: 22px;
}
.bp-sel b { font-size: 12px; color: var(--accent-2); white-space: nowrap; }
.bp-sel-btns { display: flex; gap: 4px; align-items: center; }
.bp-sel-btns button {
  background: transparent; border: 1px solid var(--border);
  color: var(--muted); border-radius: 6px;
  padding: 4px 8px; font-size: 11px; cursor: pointer;
}
.bp-sel-btns button:hover:not(:disabled) { color: var(--text); border-color: var(--muted); }
.bp-sel-btns button:disabled { opacity: .35; cursor: default; }

/* Icon-only delete: reads as an action, warns on hover like one. */
.bp-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 24px; padding: 0 !important;
}
.bp-icon-btn:hover { color: var(--red) !important; border-color: var(--red) !important; }

/* The order stepper: the OS number-spinner in the app's own clothes. Native
   spin buttons render in system chrome and ignore the theme entirely, so
   they are hidden and replaced with the icon set's chevrons. */
.bp-order {
  display: flex; align-items: stretch;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 7px;
  overflow: hidden;
}
.bp-order:focus-within { border-color: var(--accent); }
.bp-order input {
  width: 34px; border: none; background: transparent;
  color: var(--text); font-size: 13px; font-weight: 600;
  text-align: center; font-variant-numeric: tabular-nums;
  -moz-appearance: textfield; appearance: textfield;
}
.bp-order input:focus { outline: none; }
.bp-order input::-webkit-inner-spin-button,
.bp-order input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.bp-order-btns {
  display: flex; flex-direction: column;
  border-left: 1px solid var(--border);
}
.bp-order-btns button {
  flex: 1; display: flex; align-items: center; justify-content: center;
  width: 20px; padding: 0;
  background: transparent; border: none;
  color: var(--muted); cursor: pointer;
}
.bp-order-btns button:first-child { border-bottom: 1px solid var(--border); }
.bp-order-btns button:hover { color: var(--accent); background: var(--surface-2); }

/* Numbered waypoints. The number IS the order — what goes first, second,
   third is readable off the map itself. */
.bp-pin-n {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  background: var(--accent);
  border: 2px solid #fff;
  border-radius: 50%;
  color: #fff; font-size: 11px; font-weight: 700;
  font-family: 'Inter', sans-serif;
  box-shadow: 0 1px 4px rgba(0,0,0,.5);
  cursor: grab;
}
.bp-pin-n.start { background: var(--green); }
.bp-pin-n.selected { outline: 3px solid var(--accent-2); outline-offset: 1px; }

/* The route editor is a headline feature, not a footnote — it dresses like
   the Start Ride button, not like a settings link. */
.banner-btn {
  background: var(--accent);
  border: none;
  color: #fff;
  border-radius: 8px;
  padding: 6px 14px;
  font-size: 12.5px;
  font-weight: 650;
  cursor: pointer;
  margin-left: 10px;
}
.banner-btn:hover { background: var(--accent-2); }

/* ---- reordering: the number stepper and the chip strip ---- */
.bp-sel-num {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11px; color: var(--muted);
}
.bp-sel-num input {
  width: 40px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
  color: var(--text); padding: 3px 5px; font-size: 12px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.bp-sel-num input:focus { outline: none; border-color: var(--accent); }

/* One chip per point, in riding order. Drag a chip to a new slot and the
   whole route redraws through the new sequence. */
.bp-chips {
  display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 9px;
  /* One chip row is always reserved, so chips appearing does not shove the
     rows below. Growth past one row still moves things — but the controls
     that get spammed all live ABOVE this now. */
  min-height: 26px;
}
.bp-chip {
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--text); font-size: 11.5px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  cursor: grab; user-select: none;
}
.bp-chip.start { border-color: var(--green); color: var(--green); }
.bp-chip.selected { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
.bp-chip.drop-target { border-color: var(--accent-2); transform: scale(1.15); }
.bp-chip:active { cursor: grabbing; }

/* Pin colour carries the leg's direction: warm going up, blue coming down.
   On an out-and-back over the same road, this is what separates the two
   passes where the line overlaps itself. */
.bp-pin-n.up { background: #E0562B; }
.bp-pin-n.down { background: var(--blue); }

/* Direction arrows on the drawn route. Deliberately quiet — they answer
   "which way", they do not compete with the pins. */
.bp-chevron {
  width: 14px; height: 14px;
  display: flex; align-items: center; justify-content: center;
  color: #fff;
  font-size: 10px;
  text-shadow: 0 0 3px rgba(0,0,0,.9);
  opacity: .85;
  pointer-events: none;
}
.bp-sel > span { display: flex; flex-direction: column; min-width: 0; }
.bp-sel i {
  font-style: normal; font-size: 10.5px; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* The selection row never collapses — it idles. Height is constant whether a
   point is selected or not; only the content and emphasis change. The
   buttons keep their space via visibility, not display, for the same reason. */
.bp-sel.idle { background: var(--surface-2); border-color: var(--border); }
.bp-sel.idle b { color: var(--faint); }
.bp-sel.idle .bp-sel-btns, .bp-sel.idle .bp-order { visibility: hidden; }

/* ---- the sign-in gate (config.requireSignIn) ---- */
#signin-gate {
  position: fixed; inset: 0; z-index: 4000;
  background: rgba(8, 11, 17, 0.92);
  backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
}
.gate-card {
  width: min(360px, 90vw);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-2);
  padding: 28px;
  text-align: center;
}
.gate-card h2 { font-size: 19px; font-weight: 700; margin-bottom: 10px; }
.gate-card p { font-size: 13px; color: var(--muted); line-height: 1.55; margin-bottom: 18px; }
.gate-card button { width: 100%; }

.gate-card .secondary-btn { width: 100%; margin-top: 8px; }
.gate-note { font-size: 11.5px; color: var(--faint); margin-top: 12px; }

/* ---- Place finder: country dropdown, then a city — both typeable ---- */
#place-finder {
  position: absolute; top: 12px; right: 12px; z-index: 1000;
  width: 250px; font-size: 13px;
  display: flex; flex-direction: column; gap: 6px;
}
.pf-field { position: relative; }
.pf-field .pf-icon {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; color: var(--accent); pointer-events: none;
}
.pf-field .pf-icon svg { width: 100%; height: 100%; display: block; }
.pf-chevron {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  width: 14px; height: 14px; color: var(--faint); pointer-events: none;
  transition: transform 0.15s ease;
}
.pf-chevron svg { width: 100%; height: 100%; display: block; }
.pf-field:focus-within .pf-chevron { transform: translateY(-50%) rotate(180deg); color: var(--accent); }
/* Contenteditable divs playing the part of inputs — see mapview.js for why
   (Chrome autofill cannot touch them). The placeholder is painted from
   data-ph when the field is empty. */
.pf-input {
  width: 100%; box-sizing: border-box; padding: 8px 30px 8px 32px;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 10px;
  font: inherit; outline: none; cursor: text;
  white-space: nowrap; overflow: hidden;
}
#pf-spot { padding-right: 12px; }
.pf-input:focus { border-color: var(--accent); }
.pf-input:empty::before { content: attr(data-ph); color: var(--faint); }
#pf-results {
  background: var(--panel);
  border: 1px solid var(--border); border-radius: 10px;
  overflow-y: auto; max-height: 288px; box-shadow: var(--shadow-2);
}
.pf-item {
  display: flex; align-items: center; gap: 8px;
  width: 100%; text-align: left; padding: 8px 12px;
  background: none; border: none; color: var(--text);
  font: inherit; cursor: pointer;
}
.pf-item .pf-icon { width: 13px; height: 13px; color: var(--accent); flex: none; }
.pf-item .pf-icon svg { width: 100%; height: 100%; display: block; }
.pf-item .pf-label {
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.pf-item .pf-sub {
  margin-left: auto; color: var(--faint); font-size: 11px; flex: none;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis; max-width: 40%;
}
.pf-item:hover, .pf-item.sel { background: var(--accent-dim); }

/* ---- Language toggle: one small always-there button ---- */
#lang-btn {
  background: none; border: 1px solid var(--border); color: var(--muted);
  border-radius: 8px; padding: 5px 10px; font: inherit; font-size: 12px;
  cursor: pointer; margin-right: 8px; letter-spacing: 0.06em;
}
#lang-btn:hover { border-color: var(--accent); color: var(--text); }

/* Focus mode: the gear gets its own full-width row — shifting works in
   focus (window-level keys + BLE shifter), so it must be visible there. */
.focus-gearrow { grid-column: 1 / -1; margin-top: 6px; }
.focus-gearrow b { color: var(--green); font-size: clamp(44px, 6vw, 84px); }
.focus-gear-sub {
  display: block; color: var(--faint); font-size: 13px;
  letter-spacing: 2px; margin-top: 2px;
}

/* ---- Language-stable widths ----
   Switching EN↔ES must not move anything: every recurring button is pinned
   to the wider of its two labels (measured 2026-08-09, both languages).
   New buttons with translated labels should get the same treatment. */
#btn-trainer, #btn-hr, #btn-cadence, #btn-click {
  min-width: 112px; justify-content: center;
}
#profile { min-width: 74px; }
#lang-btn { min-width: 42px; text-align: center; }
/* Same pin in BOTH languages (that is the invariant), but slim enough that
   the row fits a narrow window — and it wraps rather than clips if not. */
#btn-start { min-width: 118px; }
#btn-pause, #btn-lap { min-width: 78px; }
#btn-finish { min-width: 138px; }
#btn-start, #btn-pause, #btn-lap, #btn-finish { padding-left: 10px; padding-right: 10px; }
.ctrl-row { flex-wrap: wrap; }
.lib-tab { min-width: 100px; }
#tab-find { min-width: 126px; }   /* Rutas del mundo */

/* ---- Builder: two cards, visibly two things ---- */
.build-card {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 12px; padding: 14px 16px; margin-bottom: 14px;
}
.build-card .lib-h { margin-top: 0; }
.sp-or { color: var(--faint); font-size: 12px; padding: 0 2px; }
.sp-check {
  display: flex; align-items: center; gap: 8px; color: var(--muted);
  font-size: 13px; cursor: pointer;
}
.sp-check input { accent-color: var(--accent); }
#sp-pin { width: auto; flex: 0 1 auto; }
.sp-row { display: flex; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; align-items: center; }
.sp-field { display: flex; flex-direction: column; gap: 4px; color: var(--muted); font-size: 12px; }
.sp-field input {
  width: 72px; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px; font: inherit;
}
.sp-field span { display: flex; align-items: center; gap: 6px; color: var(--faint); }
.sp-field select#sp-climb-band { padding: 6px 8px; max-width: 150px; }
#sp-country, #sp-city, #sp-pin, #sp-trip, #sp-climb-band {
  background: var(--surface-2); color: var(--text); border: 1px solid var(--border);
  border-radius: 8px; padding: 8px 12px; max-width: 240px;
  font-family: inherit; font-size: 13px; line-height: 1.2;
}
#sp-pin.armed { border-color: var(--accent); color: var(--accent); }
#sp-trip { cursor: pointer; }
#sp-trip:hover { border-color: var(--accent); color: var(--accent); }

/* The dropped start pin */
.sp-pin-icon { font-size: 24px; text-shadow: 0 2px 6px rgba(0,0,0,0.6); }

/* ---- Facet dropdowns: three questions, not thirty chips ---- */
.lib-selects { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.lib-selects select {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px;
  padding: 7px 10px; font: inherit; max-width: 240px;
}
.lib-selects select.on { border-color: var(--accent); }

/* ---- Checkbox dropdowns ---- */
.msel { position: relative; }
.msel-btn {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px;
  padding: 7px 12px; font: inherit; cursor: pointer;
}
.msel-btn.on { border-color: var(--accent); color: var(--accent); }
.msel-pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  min-width: 210px; max-height: 280px; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow-2); padding: 6px;
}
.msel-row {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 8px; border-radius: 6px; cursor: pointer;
  color: var(--text); font-size: 13px;
}
.msel-row:hover { background: var(--accent-dim); }
.msel-row input { accent-color: var(--accent); }
.msel-clear {
  width: 100%; margin-top: 4px; padding: 6px;
  background: none; border: 1px solid var(--border); border-radius: 6px;
  color: var(--muted); font: inherit; cursor: pointer;
}
.msel-clear:hover { border-color: var(--accent); color: var(--text); }

/* Builder rows: controls stand level, the lap number sits inside its sentence */
.build-card .lib-controls { display: flex; align-items: stretch; gap: 10px; }
.build-card .lib-controls select { padding: 0 12px; }
.build-card .lib-controls button { margin: 0; }
.sp-minlap-field {
  display: inline-flex; align-items: center; gap: 6px; color: var(--faint);
  font-size: 13px;
}
.sp-minlap-field input {
  width: 58px; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px; font: inherit;
}

/* Per-route GPX download, tucked in the card's corner */
.lib-card { position: relative; }
.lib-dl {
  position: absolute; top: 10px; right: 10px;
  font-size: 11px; letter-spacing: 0.04em; color: var(--faint);
  border: 1px solid var(--border); border-radius: 6px; padding: 3px 7px;
  cursor: pointer;
}
.lib-dl:hover { color: var(--accent); border-color: var(--accent); }

.sp-ridefrom { color: var(--muted); font-size: 13px; }

/* ---- Welcome gate: the world behind the door ---- */
#gate-world { position: absolute; inset: 0; overflow: hidden; opacity: 0.85; }
#gate-world svg { width: 100%; height: 100%; display: block; }
#gate-world path {
  fill: var(--surface-3); stroke: var(--accent);
  stroke-width: 0.5; stroke-opacity: 0.35; fill-opacity: 0.55;
}
#signin-gate .gate-card { position: relative; z-index: 1; }
.gate-cta { font-size: 16px; padding: 12px 26px; }

/* ---- the front door (start overlay) ---- */
#so-card { width: min(880px, 94vw); }
.so-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 14px 0 4px; }
@media (max-width: 720px) { .so-cards { grid-template-columns: 1fr; } }
.so-mode, .so-src {
  font: inherit; text-align: left; color: var(--text);
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px; min-height: 108px; cursor: pointer;
  display: flex; flex-direction: column; gap: 5px; position: relative;
  transition: border-color .12s var(--ease), transform .12s var(--ease);
}
.so-mode:hover, .so-src:hover { border-color: var(--accent); transform: translateY(-1px); }
.so-mode b { font-family: 'Barlow Condensed', 'Inter', sans-serif; font-size: 19px;
  font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.so-src b { font-size: 14px; }
.so-mode span, .so-src span { font-size: 12px; color: var(--muted); line-height: 1.5; }
.so-src.locked { cursor: default; opacity: .85; }
.so-src.locked:hover { border-color: var(--border); transform: none; }
.so-lock { position: absolute; top: 10px; right: 12px; font-style: normal; font-size: 10px;
  letter-spacing: .1em; text-transform: uppercase; font-weight: 700; color: var(--accent-2);
  background: var(--accent-dim); border: 1px solid rgba(255, 122, 24, .35);
  border-radius: 999px; padding: 2px 8px; }
.so-footrow { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.so-banner {
  font: inherit; flex: 1 1 240px; text-align: left; color: var(--text); cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 13px; font-size: 12.5px; transition: border-color .12s var(--ease);
}
.so-banner:hover { border-color: var(--accent); }
#so-ftp.guest-hot { border-color: var(--accent);
  background: linear-gradient(90deg, var(--accent-dim), var(--surface-2) 70%); }
.so-skip { display: flex; align-items: center; gap: 7px; margin-top: 12px;
  font-size: 12px; color: var(--muted); cursor: pointer; }
.guest-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: linear-gradient(90deg, var(--accent-dim), transparent 75%);
  border: 1px solid rgba(255, 122, 24, .3); border-radius: 8px;
  padding: 8px 12px; margin-top: 8px; font-size: 12.5px; color: var(--muted); }
.guest-bar .primary-btn { margin-left: auto; }
#guest-chip { background: var(--accent-dim); color: var(--accent-2);
  border: 1px solid rgba(255, 122, 24, .35); font-size: 11px; }
.guest-note { color: var(--accent-2); }

/* ---- bluetooth check ---- */
.bt-row { display: grid; grid-template-columns: 1fr 130px 74px; gap: 10px;
  align-items: center; padding: 11px 2px; border-bottom: 1px solid var(--border); }
.bt-row:last-of-type { border-bottom: 0; }
.bt-row b { display: block; font-size: 13.5px; }
.bt-sub { font-size: 11px; color: var(--muted); }
.bt-status { font-size: 12px; color: var(--faint); text-align: right; }
.bt-status.ok { color: var(--green); }
.bt-status.fail { color: var(--red); }
.bt-status.testing { color: var(--accent-2); }
.bt-nosupport { background: rgba(255, 90, 90, .12); border: 1px solid rgba(255, 90, 90, .3);
  border-radius: 8px; padding: 9px 12px; font-size: 12.5px; color: var(--text); }
.gate-guest { display: block; margin: 10px auto 0; font-size: 13px; }

/* Small, in the title row, out of the reading path: language is a setting,
   not a decision the overlay is asking. margin-left:auto parks it against
   the close button; the title keeps the row's weight. */
.so-lang {
  margin-left: auto; flex: 0 0 auto;
  font: inherit; font-size: 11.5px; color: var(--muted); cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 6px; padding: 3px 10px;
}
.so-lang:hover { color: var(--text); border-color: var(--muted); }

/* ---- coach panel, consent, sharing ---- */
.coach-row { display: flex; gap: 8px; align-items: center; margin: 10px 0; flex-wrap: wrap; }
.coach-row select, .coach-row input[type="text"], .coach-row input[type="email"], .coach-row input[type="date"] {
  flex: 1 1 150px; background: var(--bg); border: 1px solid var(--border);
  color: var(--text); border-radius: 7px; padding: 8px 10px; font: inherit; font-size: 13px; }
.coach-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 760px) { .coach-cols { grid-template-columns: 1fr; } }
.coach-h { font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); margin: 14px 0 8px; font-weight: 600; }
.coach-list { display: flex; flex-direction: column; gap: 6px; }
.coach-item { background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 9px 12px; font-size: 13px;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.coach-item .sub { color: var(--muted); font-size: 11.5px; }
.coach-item .spacer { margin-left: auto; }
.coach-item .score-ok { color: var(--green); }
.coach-item .score-warn { color: var(--accent-2); }
.consent-block b { display: block; font-size: 13px; margin: 12px 0 2px; }
.consent-block p { font-size: 13px; color: var(--muted); margin: 0; line-height: 1.55; }
#sharing-chip { background: rgba(76,154,255,.12); color: #8FBEFF;
  border: 1px solid rgba(76,154,255,.35); font-size: 11px; }
.so-today { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  border: 1px solid var(--green); border-radius: 8px; padding: 10px 14px;
  margin-bottom: 12px;
  background: linear-gradient(90deg, rgba(53,208,127,.12), var(--surface-2) 70%); }
.so-today b { font-size: 14px; display: block; }
.so-today .sub { font-size: 11.5px; color: var(--muted); }
.so-today .primary-btn { margin-left: auto; }

/* ---- coach panel notebook ---- */
.coach-current { font-size: 12px; color: var(--accent-2); margin-left: auto; margin-right: 10px; }
.nb-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin: 2px 0 14px; }
.nb-tabs button {
  font: inherit; font-size: 12.5px; cursor: pointer; color: var(--muted);
  background: var(--surface-2); border: 1px solid var(--border); border-bottom: none;
  border-radius: 8px 8px 0 0; padding: 8px 16px; position: relative; top: 1px;
}
.nb-tabs button.active {
  color: var(--accent); font-weight: 600; background: var(--panel);
  border-color: var(--border); border-bottom: 1px solid var(--panel);
}
.nb-pane { min-height: 220px; }
.coach-item.sel { border-color: var(--accent); background: var(--accent-dim); }
.coach-item .tierpill { font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); border: 1px solid var(--border); border-radius: 999px; padding: 1px 8px; }

/* ---- social badge + inbox ---- */
.social-badge { display: inline-grid; place-items: center; min-width: 16px; height: 16px;
  margin-left: 6px; padding: 0 4px; border-radius: 999px; background: var(--accent);
  color: #12060a; font-size: 10px; font-weight: 800; vertical-align: 1px; }
#social-inbox { margin-bottom: 14px; }

/* invite + prescribe polish (2026-08-19 review: the email box rendered at
   browser-default width and the buttons stretched — the row reads as one
   sentence now: address, primary act, quiet alternative) */
.coach-row input[type="email"] { flex: 2 1 220px; }
.coach-row .primary-btn, .coach-row .secondary-btn { flex: 0 0 auto; }
#coach-invite-out { background: var(--surface-2); border: 1px solid var(--border);
  border-left: 2px solid var(--accent); border-radius: 0 8px 8px 0;
  padding: 9px 12px; word-break: break-all; }
.coach-picker { width: 100%; }
.coach-picker option { padding: 5px 8px; }
.coach-picker optgroup { color: var(--accent-2); font-style: normal;
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em; }

/* ---- coach depth: drill-down, calendar, rpe, attention ---- */
.cd-trace { background: var(--bg); border: 1px solid var(--border); border-radius: 9px;
  padding: 6px; margin-bottom: 10px; }
.tiles-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 8px; margin-bottom: 14px; }
.tiles-row .tile { background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 9px 11px; }
.tiles-row .tile b { font-family: 'Barlow Condensed', sans-serif; font-size: 24px;
  display: block; line-height: 1; font-variant-numeric: tabular-nums; }
.tiles-row .tile span { font-size: 10.5px; color: var(--muted); }
.coach-cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; margin: 8px 0 16px; }
.coach-cal .day { background: var(--bg); border: 1px solid var(--border); border-radius: 7px;
  min-height: 84px; padding: 5px 6px; }
.coach-cal .day.today { border-color: var(--accent); }
.coach-cal .dh { font-size: 10px; color: var(--faint); letter-spacing: .08em;
  text-transform: uppercase; display: flex; justify-content: space-between; margin-bottom: 4px; }
.coach-cal .chip { display: block; font-size: 10.5px; line-height: 1.3; margin-bottom: 3px;
  border-left: 2px solid var(--z4); padding: 2px 5px; background: var(--surface-2);
  border-radius: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rpe-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 10px 0; }
.rpe-label { font-size: 13px; color: var(--muted); }
.rpe-chips { display: flex; gap: 4px; }
.rpe-chips button { font: inherit; font-size: 12px; width: 28px; height: 28px;
  border-radius: 6px; background: var(--surface-2); border: 1px solid var(--border);
  color: var(--muted); cursor: pointer; }
.rpe-chips button.on { background: var(--accent); border-color: var(--accent);
  color: #12060a; font-weight: 700; }
.coach-item.attn { border-left: 2px solid var(--red); }
.coach-item.rowbtn { cursor: pointer; }
.coach-item.rowbtn:hover { border-color: var(--accent); }
