/* ──────────────────────────────────────────────────────────────────────
   PLATFORM GATES
   - body[data-platform]  set by core/shell.js  (phone|tablet|electron|web)
   - body[data-size]      set by core/shell.js  (sm|md|lg, viewport-driven)
   - [data-feature="id"]  gated by core/features.json; shell.js sets the
     `hidden` attribute on disallowed elements. The rule below forces it
     to win over flex/grid display on tabs and panels.
   ────────────────────────────────────────────────────────────────────── */
[data-feature][hidden] { display: none !important; }

/* ── Shared close/delete "X" buttons ─────────────────────────────────────
   .btn-close-x  — for non-destructive dismiss (panel/modal close, hide card).
                   Hover is neutral grey.
   .btn-delete-x — for destructive actions (delete row, remove item).
                   Hover is red — signals consequence.
   Both share default layout and subtle resting state. */
/* Doubled-class selectors bump specificity (0,0,2,0) so these beat
   broader per-feature rules like `.cal-modal-card button` (0,0,1,1). */
.btn-close-x.btn-close-x, .btn-delete-x.btn-delete-x {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  min-width: 0;
  padding: 0;
  background: transparent;
  color: var(--dim2);
  border: 0;
  border-radius: 4px;
  font-size: var(--fs-lg);
  line-height: 1;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.btn-close-x.btn-close-x:hover   { background: var(--bg3); color: var(--txt); }
.btn-delete-x.btn-delete-x:hover { background: var(--red); color: #fff; }

/* ── Controller layout overrides (no sidebar) ── */
#main     { flex-direction: column !important; }
#header   { gap: 10px; }
#tabs      { display: flex; flex-direction: row; gap: 2px; background: var(--bg3); border-radius: 6px; padding: 3px; margin: 0; flex-shrink: 0; }
#tabs .tab { flex: none; padding: 7px 13px; border-radius: 4px; display: flex; align-items: center; gap: 6px; font-size: var(--fs-micro); color: var(--txt); background: none; border: 1px solid transparent; cursor: pointer; letter-spacing: 1.5px; text-transform: uppercase; transition: all .15s; }
#tabs .tab:hover { color: var(--amber-ink); border-color: var(--amber-ink); }
#tabs .tab.active{ background: var(--amber); color: var(--on-amber); border-color: var(--amber); font-weight: 600; }
#tabs .tab.active:hover { color: var(--bg0); }
#statusbar { padding: 0; background: none; border: none; flex: 1; min-width: 0; font-size: var(--fs-sm); }
/* The arrow now carries the severity glyph (setStatus in core/app-state.js),
   so it can't stay at the .4 opacity style.css gives it — a dimmed ✕ is not a
   signal. Colour comes from the inline style setStatus writes. */
#statusbar #status-arrow { opacity: 1; font-weight: 700; }
/* min-width:0 is load-bearing, not decorative. As a flex item this span
   defaults to min-width:auto = min-content, and a message carrying one long
   unbroken token (a fetched route URL) then refuses to shrink — the ellipsis
   never engages and #bt-warning gets pushed out of the header instead. */
#statusbar #status-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tab-dots  { display: flex; gap: 3px; }
.tab-dot   { width: 6px; height: 6px; border-radius: 50%; background: var(--dim3); transition: all .3s; }
.tab-dot.connected { background: var(--green); box-shadow: 0 0 6px var(--green); }

/* ── FTP & threshold-HR history tab ── */
.th-history-page { display: flex; flex-direction: column; gap: 16px; max-width: 880px; }
.th-history-header h2 { margin: 0 0 6px 0; font-size: var(--fs-lg); letter-spacing: 1px; color: var(--txt); }
.th-history-intro { margin: 0; font-size: var(--fs-xs); color: var(--dim); line-height: 1.5; }

.th-history-add-card { background: var(--bg3); border: 1px solid var(--bdr); border-radius: 8px; padding: 12px 13px; }
.th-history-add-label { font-size: var(--fs-micro); letter-spacing: 2px; color: var(--dim); text-transform: uppercase; margin-bottom: 8px; }
.thresholds-history-add { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.th-add-field { display: flex; flex-direction: column; gap: 4px; }
.th-add-field span { font-size: var(--fs-micro); color: var(--dim2); text-transform: uppercase; letter-spacing: 1px; }

.th-input { background: var(--bg0); border: 1px solid var(--bdr2); border-radius: 4px; padding: 6px 8px; font-size: var(--fs-xs); font-family: var(--font-data); color: var(--txt); outline: none; }
.th-input::placeholder { color: var(--dim2); }
.th-input[type="date"]           { width: 140px; }
.th-input[type="datetime-local"] { width: 190px; }
.th-input[type="number"] { width: 90px; }

.th-btn { background: var(--bg0); border: 1px solid var(--bdr2); border-radius: 4px; padding: 6px 12px; font-size: var(--fs-xs); font-family: var(--font-text); color: var(--dim); cursor: pointer; white-space: nowrap; }
.th-btn:hover { color: var(--txt); border-color: var(--dim2); }
.th-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.th-btn-primary { color: var(--amber-ink); border-color: var(--amber-ink); }
.th-btn-primary:hover { background: var(--amber); color: var(--on-amber); }

/* History table — inherits .analysis-table layout from analysis.css for
   consistency with the ride-history view. Tweaks here are just for the
   row-action cell and the source pill. */
.th-history-table-wrap { /* uses .analysis-table-wrap for chrome */ }
.th-source-tag { display: inline-block; padding: 1px 8px; background: var(--bg0); border-radius: 3px; color: var(--dim2); font-size: var(--fs-xs); text-transform: capitalize; letter-spacing: 0.5px; }
.th-row-action { width: 78px; text-align: right; white-space: nowrap; }
.th-delete-btn, .th-edit-btn { background: none; border: 1px solid var(--bdr2); color: var(--dim2); border-radius: 3px; padding: 2px 7px; cursor: pointer; font-family: inherit; font-size: var(--fs-xs); }
.th-delete-btn:hover { color: var(--red); border-color: var(--red); }
.th-edit-btn:hover   { color: var(--amber-ink); border-color: var(--amber-ink); }

/* Inline row edit — inputs sit in the cells they replace so columns don't
   jump when a row flips into edit mode. */
.th-edit-row td { vertical-align: middle; }
.th-edit-row .th-input[type="datetime-local"] { width: 100%; min-width: 170px; }
.th-edit-row .th-input[type="number"] { width: 78px; }
.th-edit-actions { display: flex; gap: 5px; justify-content: flex-end; }
.th-save-btn   { background: none; border: 1px solid var(--amber-ink); color: var(--amber-ink); border-radius: 3px; padding: 2px 7px; cursor: pointer; font-family: inherit; font-size: var(--fs-xs); }
.th-save-btn:hover   { background: var(--amber); color: var(--on-amber); }
.th-cancel-btn { background: none; border: 1px solid var(--bdr2); color: var(--dim2); border-radius: 3px; padding: 2px 7px; cursor: pointer; font-family: inherit; font-size: var(--fs-xs); }
.th-cancel-btn:hover { color: var(--txt); border-color: var(--dim2); }
.th-edit-error { color: var(--red); font-size: var(--fs-sm); }
.th-history-loading,
.th-history-empty { color: var(--dim2); font-style: italic; text-align: center; padding: 16px !important; }

.thresholds-history-recompute { background: var(--bg3); border: 1px solid var(--bdr); border-radius: 8px; padding: 12px 13px; }

/* ── Device cards ── */
.device-card  { background: var(--bg3); border: 1px solid var(--bdr); border-radius: 8px; padding: 12px 13px; display: flex; flex-direction: column; gap: 9px; transition: all .3s; }
.device-card.connected { border-color: var(--green); background: linear-gradient(135deg, color-mix(in srgb, var(--green) 27%, transparent), var(--bg3)); box-shadow: 0 0 12px color-mix(in srgb, var(--green) 20%, transparent), inset 0 1px 0 color-mix(in srgb, var(--green) 13%, transparent); }
.device-top   { display: flex; align-items: center; gap: 8px; }
.device-icon  { font-size: var(--fs-md); opacity: 0.7; transition: opacity .3s; }
.device-card.connected .device-icon { opacity: 1; }
.device-info  { flex: 1; min-width: 0; }
.device-label { font-size: var(--fs-micro); letter-spacing: 2px; color: var(--dim); text-transform: uppercase; transition: color .3s; }
.device-card.connected .device-label { color: var(--green); }
.device-name  { font-size: var(--fs-sm); font-weight: 600; color: var(--dim2); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; transition: color .3s; }
.device-card.connected .device-name { color: var(--txt); }
.device-reading { font-size: var(--fs-base); font-weight: 800; color: var(--green); flex-shrink: 0; min-width: 50px; text-align: right; }
.device-reading:empty { display: none; }
.device-dot   { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; display: none; }
.device-card.connected .device-dot { display: block; background: var(--green); box-shadow: 0 0 8px var(--green); animation: pulse 2s infinite; }
.device-btn   { background: var(--bg2); border: 1px solid var(--bdr2); color: var(--dim); border-radius: 4px; padding: 7px 10px; font-size: var(--fs-xs); cursor: pointer; letter-spacing: 1.5px; text-transform: uppercase; transition: all .15s; }
.device-btn:hover { filter: brightness(1.3); }
.device-sublabel { font-size: var(--fs-xs); color: var(--dim2); letter-spacing: 0.5px; margin-top: 2px; }
.power-match-btn { width: 100%; margin-top: -4px; }
.power-match-btn.active { color: var(--amber-ink) !important; background: rgba(var(--amber-wash), 0.13) !important; border-color: rgba(var(--amber-wash), 0.27) !important; }
.power-match-desc { text-align: center; margin-top: 2px; margin-bottom: 4px; }

/* ── Shared drawer styles ── */
#drawer-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.45); z-index: 199; }
#drawer-overlay.visible { display: block; }
.drawer { position: fixed; top: 0; right: 0; bottom: 0; width: 340px; max-width: 90vw; background: var(--bg0); border-left: 1px solid var(--bdr); z-index: 200; display: flex; flex-direction: column; gap: 12px; overflow-y: auto; padding: 18px 16px; transform: translateX(100%); transition: transform .25s ease; }
.drawer.visible { transform: translateX(0); }
.drawer-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2px; }
.drawer-title { font-size: var(--fs-sm); letter-spacing: 3px; color: var(--dim); text-transform: uppercase; font-weight: 600; }
.devices-grid { display: flex; flex-direction: column; gap: 12px; }
.devices-grid .device-card { min-width: 0; }
.devices-grid .device-btn { align-self: stretch; }
/* Settings page sub-tabs — match analysis-tabs visual */
.settings-tabs {
  display: flex;
  gap: 2px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--bg3);
  padding-bottom: 0;
}
.settings-tab-btn {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--dim);
  font-family: inherit;
  font-size: var(--fs-base);
  font-weight: 500;
  padding: 8px 16px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
  text-transform: none;
  letter-spacing: 0;
}
.settings-tab-btn:hover { color: var(--txt); }
.settings-tab-btn:focus, .settings-tab-btn:focus-visible { outline: none; }
.settings-tab-btn.active { color: var(--txt-hi); border-bottom-color: var(--amber-ink); }
/* Settings page cards reuse device-card styling for the Devices drawer side. */
#settings-panel .device-card { gap: 6px; }
.settings-tab-content { display: flex; flex-direction: column; gap: 10px; }
#settings-panel .settings-row { margin-top: 4px; }
#settings-panel .settings-input { font-size: var(--fs-xl); width: 80px; padding: 6px 10px; }

/* ── Profile tab — sectioned grid layout ──────────────────────────────────
   Built specifically for the rider profile (numeric thresholds,
   demographics, display preferences). The previous design reused the BLE
   Devices card chrome — too heavy for plain numeric inputs, and stretched
   each row to the full width of the page. New approach: section headings
   group related settings; cards inside each section pack into a responsive
   2-column grid; inputs are right-aligned with a small unit suffix; the
   "Saved" indicator fades in and out instead of permanently squatting next
   to every value. */
/* Constrained-form wrapper — keeps Profile a single focused column instead of
   sprawling across the whole settings panel. ~720px reads as a "form" rather
   than a dashboard, and pairs naturally with the section/row stack below. */
.prof-form {
  max-width: 720px;
  width: 100%;
}
.prof-section { margin-bottom: 22px; }
.prof-section-title {
  font-size: var(--fs-sm);
  letter-spacing: 2px;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--amber-ink);
  margin: 4px 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--bdr);
}
/* A row inside the form. Default is full-width single field; .prof-row-2 and
   .prof-row-3 split the row into equal columns for naturally-paired fields
   (Age+Sex, the three HR thresholds). Adjacent rows get a small gap. */
.prof-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}
.prof-row-2 { grid-template-columns: 1fr 1fr; }
.prof-row-3 { grid-template-columns: 1fr 1fr 1fr; }
.prof-row + .prof-row { margin-top: 8px; }
.prof-row + .prof-hrr-card { margin-top: 8px; }
.prof-hrr-card + .prof-row { margin-top: 8px; }
@media (max-width: 580px) {
  .prof-row-2, .prof-row-3 { grid-template-columns: 1fr; }
}
/* Compact field card: label/description on the left, input on the right.
   The right column stacks the input above the dirty-state "Saved: …" line. */
.prof-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  background: var(--bg1);
  border: 1px solid var(--bdr);
  border-radius: 6px;
  padding: 12px 14px;
  min-height: 56px;
}
.prof-field:hover { border-color: var(--bdr2); }
/* Stacked variant — label/desc on top, input below, both left-aligned.
   Used for narrow 3-up cells (HR thresholds) where the side-by-side
   layout would crush the label. */
.prof-field-stack {
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 8px;
}
.prof-field-stack .prof-field-input {
  align-items: flex-start;
}
.prof-field-head { flex: 1; min-width: 0; }
.prof-field-label {
  font-size: var(--fs-sm);
  color: var(--txt);
  font-weight: 600;
  letter-spacing: 0.02em;
}
.prof-field-desc {
  font-size: var(--fs-xs);
  color: var(--dim2);
  margin-top: 2px;
  line-height: 1.4;
}
.prof-field-input {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  flex-shrink: 0;
}
.prof-field-input-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.prof-input {
  width: 80px;
  padding: 6px 10px;
  font-size: var(--fs-base);
  font-weight: 700;
  font-family: inherit;
  background: var(--bg0);
  color: var(--txt);
  border: 1px solid var(--bdr2);
  border-radius: 4px;
  text-align: right;
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.prof-input:focus {
  border-color: var(--amber-ink);
  box-shadow: 0 0 0 2px rgba(var(--amber-wash), 0.18);
}
/* When the input differs from the saved value, accent the border so it's
   clear there's an unsaved edit pending. */
.prof-field.is-dirty .prof-input {
  border-color: var(--amber-ink);
}
.prof-input-select {
  width: auto;
  min-width: 88px;
  text-align: left;
  /* Matches .prof-input, deliberately. A select and a number input sit in the
     same row doing the same job — carrying the field's own value — and this
     one used to be 13px/600 against the input's 15px/700, so "83" read heavier
     than "Male" in the same column of the same form. (TKB-254) */
  font-weight: 700;
  font-size: var(--fs-base);
  padding-right: 22px;
}
/* Rendered support message bodies — output of renderMarkup() in
   features/settings/support.js. Mirrors .support-body in the admin panel's
   admin.css, but dark. Without these the default <p> margin blows the thread
   bubbles apart and code spans are indistinguishable from prose. */
.support-body p { margin: 0 0 8px; }
.support-body p:last-child { margin-bottom: 0; }
.support-body strong { color: var(--txt-hi); font-weight: 700; }
.support-body code {
  background: color-mix(in srgb, var(--dim) 18%, transparent);
  padding: 1px 5px;
  border-radius: 3px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-sm);
}
.support-body pre {
  background: color-mix(in srgb, var(--bg0) 65%, transparent);
  border: 1px solid color-mix(in srgb, var(--dim) 22%, transparent);
  border-radius: 5px;
  padding: 8px 10px;
  margin: 8px 0;
  overflow-x: auto;          /* long log lines scroll, never widen the panel */
}
.support-body pre code { background: none; padding: 0; }

/* Markdown toolbar above the ticket composers. */
.support-md-bar { display: flex; gap: 4px; margin-bottom: 6px; }
.support-md-btn {
  background: color-mix(in srgb, var(--dim) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--dim) 22%, transparent);
  color: var(--txt2);
  border-radius: 4px;
  padding: 3px 9px;
  font-size: var(--fs-sm);
  font-family: inherit;
  cursor: pointer;
  line-height: 1.4;
}
.support-md-btn:hover { background: color-mix(in srgb, var(--dim) 24%, transparent); color: var(--txt-hi); }
.support-md-btn code { font-family: ui-monospace, Menlo, Consolas, monospace; }

/* Free-text variant. The base .prof-input is tuned for the numeric profile
   fields — 80px wide, right-aligned, bold — which is exactly wrong for prose:
   a subject line renders as a few bold right-aligned characters. */
.prof-input-text {
  width: 100%;
  text-align: left;
  font-weight: 500;
  font-size: var(--fs-base);
  line-height: 1.5;
}
.prof-unit {
  font-size: var(--fs-xs);
  color: var(--dim2);
  min-width: 22px;
}
/* "Saved: 125 W" — only visible when the field is dirty (input differs from
   saved). Hidden by default to remove visual noise when nothing is changing. */
.prof-saved {
  font-size: var(--fs-micro);
  color: var(--dim2);
  letter-spacing: 1px;
  text-transform: uppercase;
  pointer-events: none;
  visibility: hidden;
  white-space: nowrap;
}
.prof-field.is-dirty .prof-saved { visibility: visible; }
.prof-saved:empty { visibility: hidden; }
/* The public name's status (TKF-460): always visible — a refusal has to stay on screen */
.prof-input-text { width: 16ch; text-align: left; }
.prof-name-status { font-size: var(--fs-micro); color: var(--dim2); letter-spacing: 0.5px; min-height: 1.2em; }
.prof-name-status.bad { color: var(--red, #e5484d); }

/* HR Reserve milestone card — visualises 50/70/85% HRR alongside the HR
   threshold inputs. Updates live as Max/Resting HR change. */
.prof-hrr-card {
  margin-top: 8px;
  background: var(--bg1);
  border: 1px solid var(--bdr);
  border-radius: 6px;
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}
.prof-hrr-card-label {
  font-size: var(--fs-micro);
  color: var(--dim2);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  flex-shrink: 0;
}
.prof-hrr-stops {
  display: flex;
  gap: 18px;
  flex: 1;
  flex-wrap: wrap;
}
.prof-hrr-stop {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.prof-hrr-pct {
  font-size: var(--fs-xs);
  color: var(--dim2);
  letter-spacing: 1px;
  font-weight: 600;
  min-width: 26px;
}
.prof-hrr-bpm {
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--amber-ink);
  font-family: var(--font-data);
  min-width: 28px;
  text-align: right;
}
.prof-hrr-unit {
  font-size: var(--fs-xs);
  color: var(--dim2);
}

/* Generic card used for non-field content (Stored Data). */
.prof-card {
  background: var(--bg1);
  border: 1px solid var(--bdr);
  border-radius: 6px;
  padding: 12px 14px;
}
/* Stacked cards within one section (e.g. Route Privacy: home + heatmap
   opt-in) get a small gap instead of sitting flush. */
.prof-card + .prof-card {
  margin-top: 12px;
}

/* Privacy & Data tab — lead-in line above the first section. */
.prof-privacy-intro {
  font-size: var(--fs-xs);
  color: var(--dim2);
  line-height: 1.5;
  margin: 0 0 18px;
  max-width: 60ch;
}
/* Transparency card: the "who processes your data" provider list. Each row
   is name · location · function, tight and scannable. Pure content, no JS. */
.prof-processor-list {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.prof-processor-list li {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--bdr);
}
.prof-processor-list li:last-child { border-bottom: 0; padding-bottom: 0; }
.prof-processor-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--txt);
}
.prof-processor-loc {
  font-size: var(--fs-xs);
  color: var(--amber-ink);
  text-align: right;
  white-space: nowrap;
  align-self: center;
}
.prof-processor-fn {
  grid-column: 1 / -1;
  font-size: var(--fs-xs);
  color: var(--dim2);
  line-height: 1.4;
}

/* Toggle (checkbox) pill for boolean settings — reads cleaner than a
   raw checkbox + label combo. */
.prof-toggle {
  position: relative;
  display: inline-block;
  width: 36px;
  height: 20px;
  flex-shrink: 0;
  cursor: pointer;
}
.prof-toggle input { opacity: 0; width: 0; height: 0; }
.prof-toggle-track {
  position: absolute;
  inset: 0;
  background: var(--bg0);
  border: 1px solid var(--bdr2);
  border-radius: 10px;
  transition: background .15s, border-color .15s;
}
.prof-toggle-track::before {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  background: var(--dim2);
  border-radius: 50%;
  transition: transform .15s, background .15s;
}
.prof-toggle input:checked + .prof-toggle-track {
  background: rgba(var(--amber-wash), 0.18);
  border-color: var(--amber-ink);
}
.prof-toggle input:checked + .prof-toggle-track::before {
  transform: translateX(16px);
  background: var(--amber);
}

/* Stored-data section — destructive actions, lead text on the left,
   buttons clustered on the right. Wraps to a stacked layout when narrow. */
.prof-card-stored {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 14px;
}
.prof-stored-text { min-width: 0; }
.prof-stored-lead {
  font-size: var(--fs-sm);
  color: var(--txt);
  font-weight: 600;
}
.prof-stored-fineprint {
  font-size: var(--fs-xs);
  color: var(--dim2);
  margin-top: 2px;
  line-height: 1.4;
}
/* PR email — per-category checkboxes, nested under the alerts toggle. Greyed
   and inert (.is-disabled) while the email opt-in above is off. */
.prof-emailcats { margin-top: 12px; }
.prof-emailcats.is-disabled { opacity: 0.45; pointer-events: none; }
.prof-emailcats-label {
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--dim2);
  margin-bottom: 4px;
}
.prof-check {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  font-size: var(--fs-sm);
  color: var(--txt);
  cursor: pointer;
}
.prof-check input { width: 14px; height: 14px; accent-color: var(--amber); margin: 0; flex: none; }
.prof-check-desc { color: var(--dim2); }
.prof-select {
  background: var(--bg2, var(--bg1));
  color: var(--txt);
  border: 1px solid var(--bdr, var(--bg3));
  border-radius: 5px;
  padding: 3px 8px;
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
}
.prof-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.prof-btn {
  background: var(--bg2);
  color: var(--txt);
  border: 1px solid var(--bdr2);
  border-radius: 4px;
  padding: 7px 12px;
  font-size: var(--fs-xs);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  font-family: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.prof-btn:hover { background: var(--bg3); border-color: var(--amber-ink); }
.prof-btn-danger {
  border-color: color-mix(in srgb, var(--red) 45%, transparent);
  color: var(--red);
}
.prof-btn-danger:hover {
  background: color-mix(in srgb, var(--red) 12%, transparent);
  border-color: var(--red);
  color: var(--red);
}

/* ── Plan & Billing (TKF-027) ──────────────────────────────────────────────
   The plan card reuses .prof-card-stored (lead + fineprint, actions right).
   Below it, the two price cards: a flat pair, the annual one lifted by a
   border in --amber-ink rather than a filled background, so the eyebrow's
   "save 28%" carries the emphasis and the card stays legible in both themes.
   The notice line above everything is the one-shot return-from-checkout
   message; its tone is a data attribute, decided by billing.js. */
.billing-notice {
  font-size: var(--fs-sm);
  margin-bottom: 14px;
  border-left: 0;
}
.billing-notice[data-tone="ok"]   { border-color: var(--green);     color: var(--txt); }
.billing-notice[data-tone="warn"] { border-color: var(--amber-ink); color: var(--txt); }
.billing-pro-list {
  margin: 0 0 12px;
  padding: 0 0 0 1.2em;
  font-size: var(--fs-sm);
  color: var(--txt);
  line-height: 1.5;
  max-width: 64ch;
}
.billing-pro-list li { margin: 2px 0; }
.billing-plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}
/* Sibling cards must not inherit .prof-card + .prof-card's stacking margin —
   they sit side by side in the grid. */
.billing-plans .prof-card + .prof-card { margin-top: 0; }
.billing-plan {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.billing-plan .tk-eyebrow { --kind: var(--dim2); }
.billing-plan-featured { border-color: var(--amber-ink); }
.billing-plan-featured .tk-eyebrow { --kind: var(--amber-ink); }
.billing-price {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.billing-amount {
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--txt);
  font-variant-numeric: tabular-nums;
}
.billing-per { font-size: var(--fs-xs); color: var(--dim2); }
.billing-plan .billing-choose { margin-top: auto; align-self: flex-start; }
.billing-plan .billing-choose:disabled { opacity: 0.45; cursor: default; }
.billing-legal { margin-top: 12px; max-width: 70ch; }
.billing-legal a { color: var(--dim2); text-decoration: underline; }
.prof-bt-list {
  grid-column: 1 / -1;
  margin-top: 4px;
  padding-top: 10px;
  border-top: 1px solid var(--bdr);
  font-size: var(--fs-xs);
  color: var(--dim2);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.prof-bt-list:empty { display: none; }

/* Route-privacy home-location picker */
.prof-home-map {
  width: 100%;
  height: 220px;
  margin-top: 10px;
  border-radius: 6px;
  border: 1px solid var(--bdr);
  overflow: hidden;
}
.prof-home-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 8px;
}
.prof-home-coords {
  font-size: var(--fs-sm);
  font-family: var(--font-data); font-variant-numeric: tabular-nums;
  color: var(--dim2);
}
.prof-home-search {
  display: flex;
  gap: 8px;
  align-items: stretch;
  margin-top: 10px;
}
.prof-home-search .prof-btn { white-space: nowrap; }
.prof-home-search-wrap { position: relative; flex: 1; }
.prof-home-search-wrap .prof-input { width: 100%; }
.prof-home-search-results {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  z-index: 1000;
  background: var(--bg1);
  border: 1px solid var(--bdr);
  border-radius: 6px;
  max-height: 180px;
  overflow-y: auto;
  box-shadow: 0 6px 18px rgba(0,0,0,0.35);
}
.prof-home-search-item {
  padding: 8px 10px;
  font-size: var(--fs-sm);
  color: var(--fg);
  cursor: pointer;
  border-bottom: 1px solid var(--bdr);
}
.prof-home-search-item:last-child { border-bottom: none; }
.prof-home-search-item:hover { background: var(--bg2); }
.prof-home-search-empty {
  padding: 8px 10px;
  font-size: var(--fs-sm);
  color: var(--dim2);
}
@media (max-width: 640px) {
  .prof-card-stored {
    grid-template-columns: 1fr;
  }
  .prof-actions { justify-content: flex-start; }
}

/* Scale-toggle reused inside the new compact field — tighten the visuals. */
.prof-field .scale-toggle { margin: 0; }

/* ── Integrations: card grid (Strava / Garmin / Wahoo / Hammerhead / Intervals.icu) ── */
.integration-section-title {
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--dim);
  margin: 6px 0 4px;
}
.integration-section-title + .integration-grid { margin-bottom: 8px; }
.integration-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 320px));
  gap: 14px;
  align-items: stretch;
  justify-content: start;
}
/* Force visible card order within either Supported grid regardless of HTML
   source order. Cards live in HTML as Strava→Garmin→Intervals; the user
   wants Intervals shown first across both Connected and Available rows. */
#intervals-settings-card { order: 1; }
#strava-settings-card    { order: 2; }
#garmin-settings-card    { order: 3; }
.integration-card {
  display: flex;
  flex-direction: column;
  background: var(--bg1);
  border: 1px solid var(--bdr);
  border-radius: 8px;
  padding: 16px 16px 14px;
  min-height: 200px;
}
.integration-card.is-placeholder { opacity: 0.55; }
.integration-prefs {
  margin: 10px 0;
  border: 1px solid var(--bdr);
  border-radius: 6px;
  background: var(--bg2);
  overflow: hidden;
}
.integration-prefs-summary {
  cursor: pointer;
  padding: 8px 10px;
  font-size: var(--fs-xs);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--dim);
  list-style: none;
  user-select: none;
  display: flex;
  align-items: center;
  gap: 6px;
}
.integration-prefs-summary::-webkit-details-marker { display: none; }
.integration-prefs-summary::before {
  content: '▸';
  font-size: var(--fs-sm);
  color: var(--dim2);
  transition: transform .15s;
}
.integration-prefs[open] > .integration-prefs-summary::before { transform: rotate(90deg); }
.integration-prefs-summary:hover { color: var(--txt); }
.integration-prefs-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 10px 10px;
  border-top: 1px solid var(--bdr);
}
.integration-pref-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.integration-pref-label {
  font-size: var(--fs-xs);
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--dim2);
}
.integration-header {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--bdr);
  padding-bottom: 12px;
}
/* Brand logos — text placeholder for partners without a supplied logo file;
   .integration-logo > img overrides for partners with a PNG/SVG. */
.integration-logo {
  font-size: var(--fs-md);
  font-weight: 800;
  letter-spacing: 3px;
  text-transform: uppercase;
  font-family: var(--font-data);
  /* Vertical centre alignment so an inline img sits on the same baseline
     as text-based sibling logos in the same row. */
  display: inline-flex;
  align-items: center;
  line-height: 1;
  min-height: 28px;
}
.integration-logo img {
  height: 28px;
  width: auto;
  display: block;
}
/* The Strava PNG has more transparent padding inside the canvas than Garmin's,
   so equal CSS height renders visually smaller. Bump it up so the wordmarks
   read at the same size. */
.integration-logo.strava-logo img { height: 30px; }
.integration-logo.strava-logo     { color: #fc4c02; }
.integration-logo.garmin-logo     { color: #007cc3; }
.integration-logo.wahoo-logo      { color: #00a2e1; }
.integration-logo.hammerhead-logo { color: #e63946; }
/* Intervals: SVG mark + "Intervals.icu" wordmark side-by-side. The SVG keeps
   its own colour (teal); the text uses a humanist sans-serif (NOT the
   JetBrains Mono inherited from .integration-logo) so the wordmark reads as
   a brand wordmark instead of a tracked-out monospaced caps label. Sized
   ~22px to visually match the 28px SVG mark height (fonts include
   ascender/descender slack so the visual cap-height lands a few px below
   the declared font-size).  */
.integration-logo.intervals-logo {
  color: var(--txt-hi);
  font-family: Arial, sans-serif;
  font-size: var(--fs-xxl);
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  gap: 8px;
}
.integration-desc {
  font-size: var(--fs-sm);
  color: var(--dim);
  line-height: 1.45;
  margin-bottom: 12px;
}
/* One-line purpose tagline above the data-flow caps. Says *why* the
   rider would connect this service — capabilities below say *what*. */
.integration-tagline {
  font-size: var(--fs-xs);
  color: var(--dim2);
  letter-spacing: 1px;
  text-transform: uppercase;
  margin-bottom: 10px;
}
/* Capabilities list — explicit IN/OUT pills + label so the rider knows
   exactly what each integration reads or writes. */
.integration-caps {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.integration-caps li {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-sm);
  color: var(--txt);
}
.cap-dir {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  padding: 1px 6px;
  border-radius: 3px;
  font-size: var(--fs-xs);
  letter-spacing: 1.2px;
  font-weight: 700;
  font-family: var(--font-data);
}
.cap-dir.in  { background: color-mix(in srgb, var(--blue) 18%, transparent); color: var(--blue, var(--blue)); }
.cap-dir.out { background: rgba(var(--amber-wash), 0.18); color: var(--amber-ink); }

/* Toggle-row variant of the capability list — rider opts in/out of each
   direction. The whole row is the click target via the wrapping <label>. */
.integration-caps-toggle .cap-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  cursor: pointer;
  user-select: none;
  padding: 4px 0;
  transition: opacity 120ms;
}
.integration-caps-toggle .cap-toggle.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.integration-caps-toggle .cap-switch {
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  margin: 0;
  cursor: pointer;
  accent-color: var(--amber);
}
.integration-caps-toggle .cap-switch:disabled { cursor: not-allowed; }
.integration-caps-toggle .cap-toggle:not(.is-disabled):hover { opacity: 0.85; }
.cap-soon {
  font-size: var(--fs-xs);
  color: var(--dim3);
  letter-spacing: 0.3px;
}
.integration-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: auto;
}
.integration-state {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-sm);
  color: var(--dim);
}
.integration-state-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--dim3);
}
.integration-state-dot.connected { background: var(--green); box-shadow: 0 0 8px color-mix(in srgb, var(--green) 50%, transparent); }
.integration-account { color: var(--dim2); font-size: var(--fs-xs); margin-left: 4px; }
.integration-input {
  width: 100%;
  background: var(--bg0);
  border: 1px solid var(--bdr);
  color: var(--txt);
  padding: 7px 10px;
  border-radius: 4px;
  font-family: inherit;
  font-size: var(--fs-sm);
  box-sizing: border-box;
}
.integration-input:focus {
  outline: none;
  border-color: var(--amber-ink);
  box-shadow: 0 0 0 2px rgba(var(--amber-wash), 0.25);
}
.integration-btn {
  background: var(--bg2);
  color: var(--txt);
  border: 1px solid var(--bdr2);
  border-radius: 4px;
  padding: 7px 14px;
  font-size: var(--fs-xs);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  font-family: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.integration-btn:hover:not(:disabled) { background: var(--bg3); border-color: var(--amber-ink); }
.integration-btn.primary {
  background: var(--amber);
  color: var(--on-amber);
  border-color: var(--amber);
}
.integration-btn.primary:hover:not(:disabled) { filter: brightness(1.1); border-color: var(--amber-ink); }
.integration-btn:disabled { cursor: not-allowed; opacity: 0.6; }
.integration-err {
  color: var(--red);
  font-size: var(--fs-xs);
  display: none;
}
.integration-err:not(:empty) { display: block; }
.integration-fineprint {
  font-size: var(--fs-xs);
  color: var(--dim2);
  line-height: 1.4;
  margin-top: 4px;
}
/* Right tab group (Settings + Devices) */
#tabs-right { margin-left: auto; display: flex; flex-direction: row; gap: 2px; background: var(--bg3); border-radius: 6px; padding: 3px; flex-shrink: 0; }
#tabs-right .tab { flex: none; padding: 6px 14px; border-radius: 4px; display: flex; align-items: center; gap: 6px; }
#tabs-right .tab.active { background: var(--amber); color: var(--on-amber); }
.tab-icon { flex: none; padding: 7px 13px; border-radius: 4px; display: flex; align-items: center; gap: 6px; background: none; border: 1px solid transparent; font-size: var(--fs-micro); color: var(--txt); cursor: pointer; letter-spacing: 1.5px; text-transform: uppercase; transition: all .15s; }
.tab-icon:hover { color: var(--amber-ink); border-color: var(--amber-ink); }
.tab-icon .tab-dots { display: flex; gap: 3px; }
.tab-icon .tab-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--dim3); transition: all .3s; }
.tab-icon .tab-dot.connected { background: var(--green); box-shadow: 0 0 6px var(--green); }

/* ── Icon sidebar navigation ── */
#nav-sidebar { display: none; position: fixed; left: 0; top: 0; bottom: 0; width: 52px; background: var(--bg1); border-right: 1px solid var(--bdr); flex-direction: column; z-index: 150; overflow: hidden; transition: width .2s ease; }
#nav-sidebar:hover { width: 180px; }
.nav-sb-top { display: flex; flex-direction: column; gap: 2px; padding: 8px 6px; }
/* Section header (Plan / Train / Tour). An inset border-top supplies the
   visual break in the collapsed sidebar (where the label text is invisible);
   the inner <span> fades in once the sidebar expands. min-height keeps the
   row height stable in both states. */
.nav-sb-section { margin: 6px 14px 0; padding: 6px 0 2px; border-top: 1px solid var(--bdr); min-height: 18px; font-size: var(--fs-micro); letter-spacing: 2px; text-transform: uppercase; color: var(--dim2); }
.nav-sb-section span { opacity: 0; transition: opacity .15s .05s; }
#nav-sidebar:hover .nav-sb-section span,
#nav-sidebar.pinned .nav-sb-section span { opacity: 1; }
/* Sits directly under .nav-sb-top (under Stages), not pinned to the sidebar
   foot. The separator is an inset pseudo-element line rather than a full-width
   border so it doesn't run edge-to-edge. */
.nav-sb-bottom { display: flex; flex-direction: column; gap: 2px; padding: 8px 6px; }
.nav-sb-bottom::before { content: ""; display: block; height: 1px; background: var(--bdr); margin: 2px 14px 8px; }
/* The border is 1px on every side and transparent at rest, so the active
   frame below adds no width and nothing shifts when the selection moves.
   Square corners on purpose: the active item reads as [ Calendar ], a boxed
   word, not a pill (TKF-310 follow-on — the 3px left rail this replaced was
   the last coloured left edge in the app). */
.nav-sb-btn { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 3px; background: none; border: 1px solid transparent; color: var(--dim); font-size: var(--fs-micro); letter-spacing: 1px; text-transform: uppercase; text-decoration: none; cursor: pointer; white-space: nowrap; transition: all .15s; }
.nav-sb-btn:hover { color: var(--on-amber-wash); background: var(--bg3); }
/* Frame and label answer to different rules (TKB-277). The frame is a SHAPE,
   so it takes --amber and is gold on both grounds; the label is a LETTER at
   --fs-micro, which needs 4.5:1, and no gold reaches that on paper — so it
   takes --on-amber-wash, which steps out of amber there and leaves the accent
   to the frame and the tint. The weight is the compensation for that, and
   lands on both grounds because weight cannot be themed without a second token. */
.nav-sb-btn.active { color: var(--on-amber-wash); font-weight: 600; border-color: var(--amber); background: rgba(var(--amber-wash), 0.07); }
.nav-sb-icon { width: 20px; height: 20px; flex-shrink: 0; }
.nav-sb-label { opacity: 0; transition: opacity .15s .05s; }
#nav-sidebar:hover .nav-sb-label { opacity: 1; }
.nav-sb-dots { margin-left: auto; }

/* Theme switch. The row offers the theme you would GET — sun while dark, moon
   while light. Both icons and both labels ship in the markup and the cascade
   picks between them, so no JS writes text and the label can never disagree
   with the applied theme. (TKF-226) */
/* Icon/label swap lives in assets/tokens.css — the app's sidebar row and the
   public pages' toggle share it. */
/* No `font: inherit` here — it is a shorthand, so it resets font-size to the
   inherited --fs-base, and, being an ID, outranks .nav-sb-btn's --fs-micro.
   The row then
   sits larger than every other item in the nav. Family already comes from the
   `button { font-family: inherit }` base rule. */
#nav-sb-theme { width: 100%; text-align: left; }


/* Unread badge on a sidebar icon (Support). Anchored to the ICON, not the row:
   the sidebar collapses to icons-only (.nav-sb-label is opacity:0 until hover),
   so a badge at the end of the row would be invisible exactly when it matters. */
.nav-sb-icowrap { position: relative; display: inline-flex; flex-shrink: 0; }
.nav-sb-badge {
  position: absolute;
  top: -5px;
  right: -6px;
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--sky);
  color: var(--bg0);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0;
  line-height: 15px;
  text-align: center;
  box-shadow: 0 0 0 2px var(--bg1, var(--bg0));   /* punch it out of the sidebar */
  display: block;
}
/* MUST come after the display:block above — an author rule beats the UA's
   [hidden] rule, so without this the badge would never hide. */
.nav-sb-badge[hidden] { display: none; }

/* Pin button — top-right of sidebar */
.nav-sb-pin { position: absolute; top: 10px; right: 8px; width: 32px; height: 32px; background: var(--bg3); border: 1px solid var(--bdr); border-radius: 6px; color: var(--dim2); cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; opacity: 0; transition: opacity .2s, color .15s, border-color .15s, background .15s, transform .15s; z-index: 2; }
.nav-sb-pin .nav-sb-icon { width: 16px; height: 16px; }
#nav-sidebar:hover .nav-sb-pin { opacity: 1; }
.nav-sb-pin:hover { color: var(--amber); border-color: var(--amber); background: var(--bg2); }
/* Glyph and border are both shapes, so both take --amber (TKB-277). Gold at
   2.00:1 on this ground is softer than the ink brown it replaces, but it is
   still more contrast than --bdr's 1.51:1 — the border every light-theme panel
   already draws. */
#nav-sidebar.pinned .nav-sb-pin { opacity: 1; color: var(--amber); border-color: var(--amber); background: rgba(var(--amber-wash), 0.13); transform: rotate(45deg); }

/* Pinned state — sidebar stays expanded */
#nav-sidebar.pinned { width: 180px; }
#nav-sidebar.pinned .nav-sb-label { opacity: 1; }
body[data-nav="sidebar"].sidebar-pinned #header { margin-left: 180px; }
body[data-nav="sidebar"].sidebar-pinned #main   { margin-left: 180px; }

/* Sidebar mode — activated via body[data-nav="sidebar"] */
body[data-nav="sidebar"] #nav-sidebar { display: flex; }
body[data-nav="sidebar"] #tabs,
body[data-nav="sidebar"] #tabs-right,
body[data-nav="sidebar"] #tabs-signout { display: none !important; }
body[data-nav="sidebar"] #header { margin-left: 52px; transition: margin-left .2s ease; }
body[data-nav="sidebar"] #main   { margin-left: 52px; transition: margin-left .2s ease; }
body[data-nav="sidebar"] #nav-sidebar:hover ~ #header { margin-left: 180px; }
body[data-nav="sidebar"] #nav-sidebar:hover ~ #main   { margin-left: 180px; }
/* Fixed panels must clear the sidebar */
body[data-nav="sidebar"] #analysis-panel,
body[data-nav="sidebar"] #calendar-panel,
body[data-nav="sidebar"] #route-planner-panel,
body[data-nav="sidebar"] #route-manager-panel,
body[data-nav="sidebar"] #dashboard-panel,
body[data-nav="sidebar"] #settings-panel,
body[data-nav="sidebar"] #iw-overlay { left: 52px !important; transition: left .2s ease; }
body[data-nav="sidebar"].sidebar-pinned #analysis-panel,
body[data-nav="sidebar"].sidebar-pinned #calendar-panel,
body[data-nav="sidebar"].sidebar-pinned #route-planner-panel,
body[data-nav="sidebar"].sidebar-pinned #route-manager-panel,
body[data-nav="sidebar"].sidebar-pinned #dashboard-panel,
body[data-nav="sidebar"].sidebar-pinned #settings-panel,
body[data-nav="sidebar"].sidebar-pinned #iw-overlay { left: 180px !important; }
/* Hover-expand: panels inside #main */
body[data-nav="sidebar"] #nav-sidebar:hover ~ #main #calendar-panel,
body[data-nav="sidebar"] #nav-sidebar:hover ~ #main #route-planner-panel,
body[data-nav="sidebar"] #nav-sidebar:hover ~ #main #dashboard-panel { left: 180px !important; }
/* Hover-expand: panels that are siblings of #nav-sidebar in #app */
body[data-nav="sidebar"] #nav-sidebar:hover ~ #analysis-panel,
body[data-nav="sidebar"] #nav-sidebar:hover ~ #route-manager-panel,
body[data-nav="sidebar"] #nav-sidebar:hover ~ #settings-panel,
body[data-nav="sidebar"] #nav-sidebar:hover ~ #iw-overlay { left: 180px !important; }

/* ── Settings (drawer) ── */
.settings-desc  { font-size: var(--fs-sm); color: var(--dim3); line-height: 1.5; }
.settings-row   { display: flex; align-items: center; gap: 8px; }
.settings-input { background: var(--bg0); border: 1px solid var(--bdr2); border-radius: 4px; padding: 6px 10px; font-size: var(--fs-xl); font-weight: 800; font-family: inherit; width: 80px; outline: none; }
.settings-unit  { color: var(--dim3); font-size: var(--fs-base); }
.settings-apply { background: var(--bg3); color: var(--dim); border-radius: 4px; padding: 8px 14px; font-size: var(--fs-xs); letter-spacing: 1.5px; cursor: pointer; border: 1px solid var(--bdr2); transition: all .15s; }
.settings-apply:hover { filter: brightness(1.3); }
.settings-saved { font-size: var(--fs-xs); }
#clear-btn, #reset-btn, #clear-bt-btn { background: color-mix(in srgb, var(--red) 8%, transparent); color: var(--dim); border: 1px solid var(--bdr2); border-radius: 4px; padding: 6px 12px; font-size: var(--fs-xs); letter-spacing: 1px; cursor: pointer; transition: all .15s; }
#clear-btn:hover, #reset-btn:hover, #clear-bt-btn:hover { filter: brightness(1.3); }

/* ── Debug Panel ── */
#debug-panel { display: none; position: fixed; bottom: 12px; right: 12px; width: 480px; max-height: 320px; background: var(--bg0); border: 1px solid var(--amber-ink); border-radius: 6px; font-size: var(--fs-xs); z-index: 1000; box-shadow: 0 4px 20px rgba(0,0,0,0.5); }
#debug-panel.visible { display: flex; flex-direction: column; }
#debug-panel.minimized { max-height: 36px; overflow: hidden; }
#debug-header { display: flex; align-items: center; padding: 8px 12px; background: var(--bg1); border-bottom: 1px solid var(--bdr); border-radius: 5px 5px 0 0; cursor: pointer; }
#debug-title { font-size: var(--fs-micro); letter-spacing: 2px; color: var(--amber-ink); text-transform: uppercase; flex: 1; }
.debug-header-btn { background: none; border: none; color: var(--dim2); font-size: var(--fs-base); cursor: pointer; padding: 2px 6px; transition: color .15s; }
.debug-header-btn:hover { color: var(--txt); }
#debug-log { flex: 1; overflow-y: auto; padding: 8px; font-family: var(--font-data); line-height: 1.6; }
.debug-entry { display: flex; gap: 8px; padding: 3px 0; border-bottom: 1px solid var(--bg2); }
.debug-time { color: var(--dim3); min-width: 80px; }
.debug-cat { min-width: 55px; font-weight: 600; }
.debug-cat.ftms { color: var(--green); }
.debug-cat.pwr { color: var(--sky); }
.debug-cat.hr { color: var(--red); }
.debug-cat.csc { color: var(--amber-ink); }
.debug-cat.servo { color: var(--blue); }
.debug-cat.state { color: var(--dim); }
.debug-msg { color: var(--txt); flex: 1; }
.debug-msg.error { color: var(--red); }
.debug-msg.success { color: var(--green); }
#debug-footer { display: flex; gap: 6px; padding: 6px 10px; background: var(--bg1); border-top: 1px solid var(--bdr); border-radius: 0 0 5px 5px; }
.debug-btn { background: var(--bg3); border: 1px solid var(--bdr); color: var(--dim); border-radius: 3px; padding: 4px 10px; font-size: var(--fs-xs); cursor: pointer; letter-spacing: 1px; transition: all .15s; }
.debug-btn:hover { filter: brightness(1.3); border-color: var(--amber-ink); color: var(--amber-ink); }

/* ── BLE Device Picker (Electron) ── */
#ble-picker-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.6); z-index: 2000; display: flex; align-items: center; justify-content: center; }
#ble-picker { background: var(--bg1); border: 1px solid var(--bdr); border-radius: 8px; width: 360px; max-height: 480px; display: flex; flex-direction: column; box-shadow: 0 8px 32px rgba(0,0,0,0.5); }
.ble-picker-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid var(--bdr); font-size: var(--fs-base); font-weight: 600; color: var(--amber-ink); letter-spacing: 1px; }
.ble-picker-header button { background: none; border: none; color: var(--dim); font-size: var(--fs-lg); cursor: pointer; padding: 0; line-height: 1; }
.ble-picker-header button:hover { color: var(--txt); }
#ble-picker-list { flex: 1; overflow-y: auto; padding: 8px; min-height: 100px; max-height: 320px; }
.ble-picker-scanning { text-align: center; color: var(--dim2); padding: 24px 0; font-size: var(--fs-sm); }
.ble-picker-item { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; border-radius: 6px; cursor: pointer; transition: all .15s; border: 1px solid transparent; }
.ble-picker-item:hover { background: var(--bg3); border-color: var(--amber-ink); }
.ble-picker-name { font-size: var(--fs-base); font-weight: 600; }
.ble-picker-rssi { font-size: var(--fs-xs); color: var(--dim3); }
.ble-picker-footer { padding: 8px 16px; border-top: 1px solid var(--bdr); display: flex; justify-content: flex-end; }
.ble-picker-footer button { background: var(--bg3); border: 1px solid var(--bdr2); color: var(--dim); border-radius: 4px; padding: 6px 16px; font-size: var(--fs-xs); cursor: pointer; letter-spacing: 1px; transition: all .15s; }
.ble-picker-footer button:hover { filter: brightness(1.3); }
