/* ------------------------------------------------------------------ *
 * Ballistics — mobile-first shell.
 *
 * The app is always rendered inside a fixed-width "device" column so the
 * desktop experience is just the mobile experience centered on screen.
 * ------------------------------------------------------------------ */

:root {
  --bg: #0d1117;
  --surface: #161b22;
  --surface-2: #1f2630;
  --border: #2d333b;
  --text: #e6edf3;
  --text-dim: #8b949e;
  --accent: #f0883e;        /* amber */
  --accent-2: #2ea043;      /* green = good */
  --danger: #f85149;
  --radius: 12px;
  --nav-h: 64px;
  --top-h: 32px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: #010409;
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  /* App-like UI: suppress long-press / drag text selection (and the iOS
     long-press callout) everywhere by default. Re-enabled below for fields and
     anything tagged .selectable. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
/* Keep typing, caret, and word/double-tap selection working in fields — and let
   specific displayed text opt back in with the .selectable class. */
input, textarea, [contenteditable], [contenteditable] *, .selectable, .selectable * {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden; /* the app scrolls inside .app-main; the page itself never scrolls */
}

/* The mobile device frame. */
.device {
  position: relative;
  width: 100%;
  max-width: 430px;
  height: 100dvh;
  max-height: 932px;       /* iPhone 15 Pro Max-ish */
  background: var(--bg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* When installed (standalone, viewport-fit=cover) the content runs under the
     status bar / notch — reserve the top safe area so the header stays visible.
     Zero in a normal browser tab, so it's a no-op there. */
  padding-top: env(safe-area-inset-top);
}

/* Give it a framed look only when there's room (desktop). */
@media (min-width: 480px) {
  .device {
    border: 1px solid var(--border);
    border-radius: 28px;
    box-shadow: 0 0 0 8px #02040a, 0 24px 60px rgba(0, 0, 0, 0.6);
    height: 92dvh;
  }
}

.topbar {
  height: var(--top-h);
  flex: 0 0 var(--top-h);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
/* Per-view action icons (e.g. the calculator's table/inputs shortcuts), sitting
   just left of the mute toggle. */
.topbar-actions { position: absolute; right: 30px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; gap: 12px; }
.topbar-actions .pred-tool svg { width: 18px; height: 18px; }

.app-main {
  flex: 1 1 auto;
  min-height: 0; /* let the flex item shrink so THIS pane scrolls (header + navbar stay pinned) */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
}

/* ---------------- Bottom navbar ---------------- */
.navbar {
  height: calc(var(--nav-h) + env(safe-area-inset-bottom));
  flex: 0 0 auto;
  display: flex;
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding-bottom: env(safe-area-inset-bottom);
}

.nav-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 10px;
  letter-spacing: 0.03em;
  cursor: pointer;
  padding: 6px 0;
  transition: color 0.15s;
}
.nav-btn svg { width: 24px; height: 24px; stroke: currentColor; }
/* The Calc tab showing the active profile's emoji instead of the crosshair. */
.nav-btn .nav-emoji { font-size: 21px; line-height: 24px; height: 24px; }
.nav-context-item.on { color: var(--accent); font-weight: 600; }
.nav-btn.active { color: var(--accent); }
.nav-btn { position: relative; }
/* Circle-check badge on the Stage tab when a range is active. */
.nav-range-badge { position: absolute; top: 4px; left: calc(50% + 5px); display: none; line-height: 0; }
.nav-range-badge svg { width: 12px; height: 12px; stroke: none; }
.nav-btn.match-active .nav-range-badge { display: block; }
.nav-btn.match-active { color: var(--accent-2); }
/* Flashed on/off (~0.75s in JS) while a stage run is in progress, to draw the eye
   to the Stage tab. The transition softens each toggle into a pulse. */
.nav-btn { transition: color 0.25s ease, filter 0.25s ease; }
.nav-btn.run-flashing { color: var(--accent); filter: drop-shadow(0 0 6px var(--accent)); }
/* Long-press context menu above the navbar. */
.nav-context-menu { position: absolute; transform: translateX(-50%); z-index: 60; background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; padding: 4px; box-shadow: 0 6px 20px rgba(0,0,0,0.5); }
.nav-context-item { display: block; width: 100%; white-space: nowrap; background: none; border: none; color: var(--text); font-size: 13px; padding: 9px 14px; border-radius: 7px; cursor: pointer; text-align: left; }
.nav-context-item:active { background: var(--surface); }
.nav-context-item.disabled { color: var(--text-dim); cursor: default; }
.nav-context-sep { height: 1px; background: var(--border); margin: 4px 8px; }

/* Centered overlay sheet (stage read-through / summary). The backdrop dims the
   app and the card scrolls when the text runs long. */
.sheet-overlay { position: absolute; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center; padding: 20px; background: rgba(0, 0, 0, 0.55); }
.sheet-card { width: 100%; max-width: 340px; max-height: 75vh; overflow-y: auto; background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; padding: 16px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6); }
.sheet-title { margin: 0 0 8px; font-size: 16px; }
.sheet-body { font-size: 14px; color: var(--text); }
.sheet-line { padding: 6px 0; border-bottom: 1px solid var(--border); }
.sheet-line:last-child { border-bottom: none; }

/* ---------------- Generic UI ---------------- */
h2.view-title { margin: 4px 0 16px; font-size: 20px; }
h3 { margin: 18px 0 8px; font-size: 15px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.05em; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  margin-bottom: 12px;
}
.card.tappable { cursor: pointer; }
.card.tappable:active { background: var(--surface-2); }

.field { margin-bottom: 12px; }
.field label {
  display: block;
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 5px;
}
.row { display: flex; gap: 10px; }
.row > .field { flex: 1; }

input, select {
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 8px;
  padding: 11px 10px;
  font-size: 15px;
}
input:focus, select:focus { outline: none; border-color: var(--accent); }

.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
}
.toggle-row label { font-size: 14px; color: var(--text); }

button.btn {
  width: 100%;
  background: var(--accent);
  color: #1a1206;
  border: none;
  border-radius: 10px;
  padding: 13px;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  margin-top: 4px;
}
button.btn.secondary { background: var(--surface-2); color: var(--text); border: 1px solid var(--border); }
button.btn.danger { background: transparent; color: var(--danger); border: 1px solid var(--danger); }
button.btn:active { filter: brightness(0.9); }

.btn-sm {
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 12px;
  cursor: pointer;
}
.btn-sm.danger { color: var(--danger); border-color: transparent; }
.btn-sm.accent { background: var(--accent); color: #1a1206; border-color: transparent; font-weight: 700; }

/* Segmented tab bar (e.g. the profiles view: Profiles / Rifles / Barrels / Scopes). */
.tabs { display: flex; gap: 6px; margin: 4px 0 14px; }
.tabs .tab {
  flex: 1;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: 8px;
  padding: 8px 6px;
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
}
.tabs .tab.active { background: var(--accent); color: var(--bg); border-color: var(--accent); font-weight: 600; }

.list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.list-item:last-child { border-bottom: none; }
.list-item.tappable { cursor: pointer; }
/* Hit-% WEZ config modal: a stack of labelled inputs. */
.prob-pct.tappable { cursor: pointer; text-decoration: underline dotted; text-underline-offset: 2px; }
.wez-modal .wez-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 8px; }
.wez-modal .wez-label { font-size: 13px; color: var(--text); }
.wez-modal .wez-input { width: 9em; max-width: 50%; box-sizing: border-box; }
.wez-modal .wez-hint { flex-basis: 100%; font-size: 11px; }
/* Environmentals popup: the capture controls sit under a divider, the location
   button full-width above the elevation→derive row. */
.env-capture { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.env-capture .btn-sm { width: 100%; margin-bottom: 8px; }
.env-capture .wez-row .btn-sm { width: auto; margin-bottom: 0; }
/* WEZ view (its own page): compact rows + a big live hit-% with a breakdown. */
.wez-pct { font-size: 40px; font-weight: 800; color: var(--accent); line-height: 1.1; }
.wez-breakdown { margin-top: 6px; }
.wez-bd-row { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; padding: 1px 0; }
.wez-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 8px; }
.wez-label { font-size: 13px; color: var(--text); }
.wez-input { width: 9em; max-width: 50%; box-sizing: border-box; }
/* Read-only mirror value (precision/target from profile/target): plain text,
   right-aligned like the inputs, on a tappable row that opens the source. */
.wez-row.tappable { cursor: pointer; }
.wez-input.wez-ro { display: flex; align-items: center; justify-content: flex-end; text-align: right; color: var(--accent); font-weight: 600; }
/* The profile-comparison dope table: a seamless black backing instead of a
   rounded gray card. The black is on the TABLE (so it covers the full width even
   when the table is wider than the viewport), and no overflow wrapper — so the
   thead keeps its page-level stickiness (scrolling in .app-main like the
   trajectory table). The sticky header is black too, to match. */
.dope-compare-card { margin-bottom: 16px; }
.dope-compare-card .dope-table { background: #000; }
.dope-compare-card .dope-table thead th { background: #000; }
.dope-head-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.list-item .meta { font-size: 12px; color: var(--text-dim); margin-top: 2px; }
.list-item .title { font-weight: 600; }

.muted { color: var(--text-dim); font-size: 13px; }
.empty { text-align: center; color: var(--text-dim); padding: 32px 12px; }

/* Solution / results */
.solution {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 14px;
}
.solution .stat {
  background: var(--surface-2);
  border-radius: 10px;
  padding: 12px;
  text-align: center;
}
/* The prediction content (stats, dope, dials, buttons) as a left column with the
   tall wind slider stretched down its right edge. */
.pred-main { display: flex; gap: 10px; align-items: stretch; }
.pred-left { flex: 1 1 auto; min-width: 0; }
.solution .stat .val { font-size: 24px; font-weight: 700; color: var(--accent); }
/* De-emphasised stats (Time of flight, Mach): value reads gray like its label. */
.solution .stat.dim-val .val { color: var(--text-dim); }
.solution .stat .lbl { font-size: 11px; color: var(--text-dim); margin-top: 2px; text-transform: uppercase; }
/* Wind-source picker: three stacked dots BETWEEN the elevation and windage cells,
   spanning their height. Wind 2 (blue) on top, average (white) middle, Wind 1
   (orange) bottom — the active one wears a ring. */
.solution.wind-pick-row { grid-template-columns: 1fr auto 1fr; align-items: stretch; }
.wind-pick { display: flex; flex-direction: column; justify-content: space-between; align-items: center; padding: 6px 4px; }
.wind-pick-dot {
  width: 18px; height: 18px; border-radius: 50%; border: none; padding: 0;
  cursor: pointer; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; line-height: 1; color: #0d1117; /* dark, reads on every dot colour */
}
.wind-pick-dot.w2 { background: #6cb6ff; }
.wind-pick-dot.avg { background: #fff; }
.wind-pick-dot.w1 { background: var(--accent); }
/* Active dot wears a ring in its own colour — set explicitly so it doesn't recolour
   (and hide) the dark 2/A/1 label. */
.wind-pick-dot.w2.active { box-shadow: 0 0 0 2px var(--surface-2), 0 0 0 4px #6cb6ff; }
.wind-pick-dot.avg.active { box-shadow: 0 0 0 2px var(--surface-2), 0 0 0 4px #fff; }
.wind-pick-dot.w1.active { box-shadow: 0 0 0 2px var(--surface-2), 0 0 0 4px var(--accent); }
/* Tint the windage value to match the picked wind-source dot. */
.solution .stat.wind-val-w2 .val { color: #6cb6ff; }
.solution .stat.wind-val-avg .val { color: #f0f6fc; }
.solution .stat.wind-val-w1 .val { color: var(--accent); }
/* Compact stat strip (trajectory table): many small read-only values. */
.solution.compact { grid-template-columns: repeat(4, 1fr); gap: 6px; }
.solution.compact .stat { padding: 7px 4px; }
.solution.compact .stat .val { font-size: 14px; }
.solution.compact .stat .lbl { font-size: 9px; letter-spacing: 0.02em; }
/* Long-pressable readout tiles (Calc): a faint dashed underline on the label
   hints they can be swapped; the cursor backs it up on pointer devices. */
.solution.compact .stat.tile-pick { cursor: pointer; -webkit-user-select: none; user-select: none; }
.solution.compact .stat.tile-pick .lbl { border-bottom: 1px dashed var(--border); display: inline-block; padding-bottom: 1px; }

/* Compact stats row (ToF / velocity / mach / energy) — small and de-emphasised. */
.solution.compact { grid-template-columns: repeat(4, 1fr); gap: 6px; margin-bottom: 10px; }
.solution.compact .stat { padding: 6px 3px; }
.solution.compact .stat .val { font-size: 13px; }
.solution.compact .stat .lbl { font-size: 8px; margin-top: 1px; }

/* Pinned mini-readout above the navbar (Calc): elev + [wind1, avg, wind2] + dir. */
.pred-pin {
  /* A flex band in the device column (between the scroll area and the navbar),
     so it reserves its own height instead of overlaying the content/scrollbar. */
  flex: 0 0 auto;
  display: none;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 5px 10px;
  background: rgba(13, 17, 23, 0.96);
  border-top: 1px solid var(--border);
  font-size: 13px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  z-index: 40;
  pointer-events: none;
}
.pred-pin.show { display: flex; }
.pred-pin .pin-elev, .pred-pin .pin-wind { display: inline-flex; align-items: center; gap: 3px; }
/* Fixed arrow slots flanking the wind triplet: the arrow swaps sides as the
   hold flips L/R, but both sides always reserve the same width. */
.pred-pin .pin-wind-slot { display: inline-flex; width: 1.1em; justify-content: center; }
/* Set the elevation hold apart from the windage bracket: a faint divider + extra
   space, so "6.17" and "[1.66, …]" never read as one cramped run of numbers. */
.pred-pin .pin-elev { font-weight: 700; color: var(--text); padding-right: 12px; border-right: 1px solid var(--border); }
.pred-pin .pin-wind { color: var(--text-dim); }
.pred-pin .pin-avg { font-weight: 700; color: var(--text); }
.pred-pin .pin-w1 { color: var(--accent); font-weight: 700; }
.pred-pin .pin-w2 { color: #6cb6ff; font-weight: 700; }
.pred-pin .pin-msg { color: var(--text-dim); font-weight: 400; }
.pred-pin .pin-winddir { display: inline-flex; align-items: center; gap: 3px; }
.pred-pin .pin-deg { color: #fff; font-weight: 700; } /* matches the white wind-dir arrow */
/* Mover lead in the wind-direction slot: the crossing hold, white on a red highlight. */
.pred-pin .pin-mover-lead { color: #221c00; background: #ffd60a; border-radius: 4px; padding: 1px 6px; font-weight: 700; font-variant-numeric: tabular-nums; }
/* Azimuth + incline pin items — amber, matching the Calc dials they miniaturize. */
.pred-pin .pin-az, .pred-pin .pin-inc { display: inline-flex; align-items: center; gap: 3px; }
.pred-pin .pin-az-deg { color: var(--accent); font-weight: 700; }
/* Fixed-width angle boxes (3 integers max): tabular digits, right-aligned so
   the ° stays anchored while dialing — no layout shift as values change. The
   whole pin uses tabular digits so substitutions never change width anywhere. */
.pred-pin { font-variant-numeric: tabular-nums; }
.pred-pin .pin-ang { display: inline-block; min-width: 3.8ch; text-align: right; }
/* Incline: left-aligned so the number hugs its dial, but in a FIXED box sized
   for the worst case (−90°) — the slack sits on the right, so dragging the
   incline dial through sign/digit changes never shifts the row. */
.pred-pin .pin-inc { gap: 1px; }
.pred-pin .pin-ang-inc { min-width: 3.5ch; text-align: left; }
/* Breadcrumb band stacked directly above the dope band (same dimensions). The
   crumb keeps the top border (separating the readout from the scroll content);
   when it's showing, the dope band below drops its own border so the two merge
   into a single taller pinned readout. */
.pred-crumb-pin { padding-bottom: 2px; }
.pred-crumb-pin.show + .pred-pin { border-top: none; padding-top: 2px; }
.pred-crumb-pin .pin-crumb { color: #6cb6ff; font-weight: 600; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
/* Keep the scrollable content clear of the pinned bar. */

table.traj {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
table.traj th, table.traj td {
  padding: 7px 4px;
  text-align: right;
  border-bottom: 1px solid var(--border);
}
/* z-index keeps the sticky header above the hold-arrow SVGs, whose rotate()
   transform forms a stacking context that would otherwise paint over it. */
table.traj th { color: var(--text-dim); font-weight: 600; position: sticky; top: 0; background: var(--bg); z-index: 2; }
table.traj td:first-child, table.traj th:first-child { text-align: left; }
/* The two hold columns (Elev = 8th, Wind = 9th) are the heart of the dope card,
   each with its own L/R/up-down arrow — divide them (and set them off from the
   ballistics columns) with vertical rules so the arrows never read as one blur. */
table.traj th:nth-child(8), table.traj td:nth-child(8),
table.traj th:nth-child(9), table.traj td:nth-child(9) { border-left: 1px solid var(--border); }
table.traj th:nth-child(8), table.traj td:nth-child(8) { padding-left: 8px; }
table.traj th:nth-child(9), table.traj td:nth-child(9) { padding-left: 8px; }

/* Compare-view dope table: a two-tier header that sticks to the top as the page
   scrolls (same page-level sticky as table.traj above). */
.dope-table thead th { position: sticky; background: var(--surface); z-index: 2; }
.dope-table thead tr:first-child th { top: 0; height: 24px; box-sizing: border-box; }
.dope-table thead tr:last-child th { top: 24px; }

.pill {
  display: inline-block;
  font-size: 10px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-dim);
  border: 1px solid var(--border);
}
.pill.lib { color: var(--accent-2); }

.toast {
  position: absolute;
  left: 50%;
  bottom: calc(var(--nav-h) + 16px);
  transform: translateX(-50%);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 10px 16px;
  border-radius: 10px;
  font-size: 13px;
  opacity: 0;
  transition: opacity 0.2s;
  pointer-events: none;
  z-index: 50;
}
.toast.show { opacity: 1; }
.toast.err { border-color: var(--danger); color: var(--danger); }

/* ---------------- Voice assistant ---------------- */
.voice-mic {
  position: absolute;
  right: 16px;
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + 16px);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--accent);
  color: #1a1206;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
  z-index: 60;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
}
.voice-mic:active { filter: brightness(0.92); }
/* The mic in the navbar's voice slot (replacing the floating button). */
.nav-voice-slot { cursor: default; }
.nav-voice-slot .nav-voice-host { display: flex; align-items: center; justify-content: center; height: 32px; }
.voice-mic.in-nav { position: static; width: 38px; height: 38px; box-shadow: none; }
.voice-mic.in-nav svg { width: 20px; height: 20px; }
/* Gray placeholder while voice is disabled — long-press it to enable. */
.voice-mic-placeholder { background: var(--surface-2); color: var(--text-dim); border: 1px solid var(--border); }
.nav-voice-slot.voice-on .voice-mic-placeholder { display: none; }
.voice-mic.listening {
  background: var(--danger);
  color: #fff;
  animation: voice-pulse 1.2s ease-out infinite;
}
/* Muted-speaker badge — shown only when spoken answers are muted. */
.voice-mic-mute {
  position: absolute;
  top: -1px;
  right: -1px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--bg, #0d1117);
  color: var(--danger);
  display: none;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--bg, #0d1117);
}
.voice-mic.muted .voice-mic-mute { display: flex; }
@keyframes voice-pulse {
  0% { box-shadow: 0 0 0 0 rgba(248, 81, 73, 0.55); }
  100% { box-shadow: 0 0 0 16px rgba(248, 81, 73, 0); }
}

.voice-panel {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + 84px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  z-index: 60;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity 0.18s, transform 0.18s;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
}
.voice-panel.open { opacity: 1; transform: translateY(0); pointer-events: auto; }

.voice-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.voice-panel-title {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}
.voice-close {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 16px;
  cursor: pointer;
  line-height: 1;
}

/* Active match › stage › target, shown whenever the voice panel is open. */
.voice-context {
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 8px;
  min-height: 15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.voice-context-sep { color: var(--text-dim); opacity: 0.6; }
.voice-context-target { color: #6cb6ff; font-weight: 600; } /* light blue: the active target stands out */
.voice-context-empty { color: var(--text-dim); font-style: italic; }
.voice-context-profile { color: var(--accent); font-weight: 600; overflow: hidden; text-overflow: ellipsis; } /* active profile, above the breadcrumb */
.voice-context-crumb { overflow: hidden; text-overflow: ellipsis; }

/* Small label used above the dials. */
.cond-lbl { font-size: 11px; color: var(--text-dim); }

/* Prediction-card bottom row: the azimuth dial beside the incline quarter-dial. */
.pred-bottom { display: flex; gap: 12px; margin-top: 12px; align-items: flex-start; }
.pred-bottom > * { flex: 1 1 0; min-width: 0; }
/* The combined az/wind dial is 40% larger than the incline dial: its cell grows
   1.4× and its box is capped 40% bigger so the circle ends up 40% wider. */
/* Nudge ONLY the combo dial left within the dial row — a visual-only transform, so
   the incline dial and all surrounding spacing stay exactly where they are. */
.pred-bottom > .dial-card-azwind { flex-grow: 1.4; transform: translateX(-16px); }
.dial-head { text-align: center; margin-bottom: 6px; }
/* Headerless dials (incline + combo): drop the header so the dial shifts up and the
   row shrinks, pulling the controls below it up too. */
.dial-no-head .dial-head { display: none; }
/* The numeric angle inside a dial label — larger + bold to stand out. */
.dial-head .dial-ang { font-size: 1.35em; font-weight: 700; color: var(--text); }
/* In the combo dial header, tint each angle to its needle's colour. */
.dial-head .dial-ang.az { color: #f0883e; }
.dial-head .dial-ang.wind { color: #6cb6ff; }
.dial-hint { text-align: center; font-size: 9px; color: var(--text-dim); margin-top: 3px; }
.dial-box { width: 100%; max-width: 132px; aspect-ratio: 1 / 1; margin: 4px auto 2px; touch-action: none; cursor: pointer; user-select: none; border-radius: 50%; }
/* The combined az/wind dial is 40% larger than the incline dial (132px → ~185px). */
.dial-box.dial-azwind { max-width: 185px; position: relative; }
/* Widen the grab target horizontally without moving anything: a transparent
   overlay extends the pointer-catching area past the left + right rim by 35% of
   the true-wind needle's length. The needle runs 14 viewBox units (tip→base) =
   14% of the box width, so 35% of it ≈ 4.9% of the box width on each side. The
   overlay sits below the snap/lock badges (z-index ≥ 5) and survives the SVG
   innerHTML re-render (pseudo-elements aren't touched by it). */
.dial-box.dial-azwind::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: -4.9%; right: -4.9%;
}
/* The blue wind needle's base sits just outside the outer ring — let it draw past
   the SVG viewport instead of being clipped. */
.dial-box.dial-azwind svg { overflow: visible; }
/* While a dial is grabbed, glow its needle/arrow (like the grabbed wind arrows). */
.dial-box.grabbing svg { filter: drop-shadow(0 0 4px var(--accent)) brightness(1.25); }
/* The four control buttons — wind, compass, camera, lock — in a row below the
   two dials, centred. */
.dial-button-row { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 10px; padding-bottom: 8px; }
/* Moving-target row, in the open space below the button row. */
.mover-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 4px; flex-wrap: wrap; }
.mover-speed { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; font-weight: 700; padding: 3px 8px; border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); cursor: pointer; font-variant-numeric: tabular-nums; }
.mover-angle { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; font-weight: 700; padding: 3px 8px; border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); cursor: pointer; font-variant-numeric: tabular-nums; }
/* While the target is moving the speed chip pulses a yellow highlight. */
.mover-speed.active { border-color: #ffd60a; animation: mover-speed-pulse 1.2s ease-in-out infinite; }
@keyframes mover-speed-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 214, 10, 0.6); background: var(--surface-2); }
  50% { box-shadow: 0 0 0 6px rgba(255, 214, 10, 0); background: rgba(255, 214, 10, 0.3); }
}
@media (prefers-reduced-motion: reduce) {
  .mover-speed.active { animation: none; background: rgba(255, 214, 10, 0.3); }
}
.mover-left { display: inline-flex; align-items: center; gap: 6px; }
.mover-timer-btn { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 15px; line-height: 1; border: 1px solid var(--border); background: var(--surface-2); cursor: pointer; }
.mover-run { font-size: 14px; }
.mover-cap { font-size: 11px; color: var(--muted); }
.mover-calc-out { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.dial-aim-btn {
  position: relative; /* anchors the corner lock badge */
  width: 48px; height: 48px; border-radius: 50%; font-size: 20px; line-height: 1;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
  cursor: pointer; touch-action: none; user-select: none;
  display: flex; align-items: center; justify-content: center;
}
.dial-aim-btn:active { background: var(--surface); }
.dial-aim-btn .aim-ico { display: inline-flex; line-height: 0; }
/* Motion sensors missing / permission denied — dim the angle glyph and strike it
   through (still tappable to re-prompt on iOS). */
.dial-aim-btn.sensor-off { opacity: 0.5; }
.dial-aim-btn.sensor-off::after {
  content: ''; position: absolute; left: 9px; right: 9px; top: 50%;
  height: 2px; background: var(--danger); transform: rotate(-45deg); border-radius: 2px;
}
.dial-wind-btn {
  position: relative; /* in-flow in the button row; anchors the rim marker + badge */
  width: 48px; height: 48px; border-radius: 50%; font-size: 20px; line-height: 1;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
  cursor: pointer; touch-action: none; user-select: none;
  display: flex; align-items: center; justify-content: center;
}
.dial-wind-btn:active { background: var(--surface); }
/* The true wind bearing printed in the button (blue, matching the dial's blue
   wind needle) in place of the old wind-face icon. */
.dial-wind-btn .wind-true-deg { font-size: 14px; font-weight: 700; color: #f0f6fc; font-variant-numeric: tabular-nums; }
/* "true" / "wind" captions pinned above + below the (still-centered) degrees. */
.dial-wind-btn .wind-true-top { position: absolute; left: 50%; top: 6px; transform: translateX(-50%); font-size: 7px; font-weight: 700; letter-spacing: 0.5px; color: #f0f6fc; pointer-events: none; }
.dial-wind-btn .wind-true-lbl { position: absolute; left: 50%; bottom: 6px; transform: translateX(-50%); font-size: 7px; font-weight: 700; letter-spacing: 0.5px; color: #f0f6fc; pointer-events: none; }
/* A small triangle riding the button's rim, spun (in JS) to the true wind
   azimuth — a passive INDICATOR only (not draggable / clickable). Apex on the rim
   pointing inward, like the dial's blue wind needle, just smaller. */
.dial-wind-btn .wind-az-marker { position: absolute; inset: 0; pointer-events: none; }
.dial-wind-btn .wind-az-tri {
  position: absolute; left: 50%; top: -7px; transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 7px solid #6cb6ff;
  pointer-events: none;
}
/* Camera "sight" button — in-flow, side by side with the compass (aim) button. */
.dial-cam-btn, .dial-clock-btn {
  position: relative; /* anchors the corner lock badge */
  width: 48px; height: 48px; border-radius: 50%; font-size: 20px; line-height: 1;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
  cursor: pointer; touch-action: none; user-select: none;
  display: flex; align-items: center; justify-content: center;
}
.dial-cam-btn:active, .dial-clock-btn:active { background: var(--surface); }
.dial-cam-btn .cam-ico { display: inline-flex; line-height: 0; }
/* Clock mode active, or while the combo dial is being manipulated → tint the toggle. */
.dial-clock-btn.dial-grab-hi { border-color: var(--accent); box-shadow: 0 0 6px 1px var(--accent); }
/* Grayscale the colourful finger emoji (compass mode) to suit the dark theme. */
.dial-clock-btn .clock-ico.emoji-gray { filter: grayscale(1); }
/* The mode-cycle button is 20% larger (48→58px). Equal NEGATIVE margins keep its
   layout box at 48px, so its centre — and every neighbouring button's centre —
   stays put and the row's total width is unchanged; the bigger button just eats a
   little into the gaps on either side. */
.dial-button-row .dial-clock-btn, .dial-button-row .dial-lock-btn { width: 58px; height: 58px; margin: -5px; font-size: 24px; }
/* Long-press locks the camera to a view-only AR (no capture). A small padlock
   badge in the corner shows the locked state; the rim tints to the accent. */
.dial-cam-btn .cam-lock-badge, .dial-aim-btn .cam-lock-badge, .dial-wind-btn .cam-lock-badge, .dial-clock-btn .cam-lock-badge {
  display: none; position: absolute; top: -3px; right: -3px;
  font-size: 12px; line-height: 1; filter: drop-shadow(0 0 2px #000);
}
.dials-locked .dial-cam-btn, .dials-locked .dial-aim-btn, .dials-locked .dial-wind-btn, .dials-locked .dial-clock-btn { border-color: var(--accent); }
.dials-locked .dial-cam-btn .cam-lock-badge, .dials-locked .dial-aim-btn .cam-lock-badge, .dials-locked .dial-wind-btn .cam-lock-badge, .dials-locked .dial-clock-btn .cam-lock-badge { display: block; }
/* Lock toggle — last in the button row below the dials. */
.dial-lock-btn {
  position: relative; /* in-flow in the button row */
  width: 48px; height: 48px; border-radius: 50%; font-size: 20px; line-height: 1;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
  cursor: pointer; touch-action: none; user-select: none;
  display: flex; align-items: center; justify-content: center;
}
.dial-lock-btn:active { background: var(--surface); }
.dial-lock-btn.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.dial-lock-btn .lock-ico { pointer-events: none; }
/* When locked, the azimuth/incline dials and the wind-angle arrow can't be dragged. */
.dials-locked .dial-box { cursor: not-allowed; }
.dials-locked .wsl-track { cursor: not-allowed; }
/* Little padlock in the upper-right of each locked control (az dial, incl dial,
   wind scrubber) — the same mini indicator as the camera/sensor buttons. */
.dial-card, .wind-slider { position: relative; }
.dial-lock-badge { display: none; position: absolute; top: 3px; right: 4px; font-size: 12px; line-height: 1; filter: drop-shadow(0 0 2px #000); pointer-events: none; z-index: 5; }
/* Long-press freeze indicator (gyro held) — top-right corner, right of the lock,
   which sits to its left on the combo dial. The head reserves a gutter for both. */
.dial-freeze-badge { position: absolute; top: 3px; right: 4px; font-size: 12px; line-height: 1; filter: drop-shadow(0 0 2px #000); pointer-events: none; z-index: 5; }
.dial-card-azwind .dial-lock-badge { right: 22px; }
.dial-card-azwind .dial-head { padding-right: 42px; }
.dials-locked .dial-lock-badge { display: block; }
/* Snap-to-5° "5 | x" button. Absolute (never shifts with the resizing header text,
   and adds nothing to the layout); parked low on the card, centred horizontally on
   the gap between the angle (aim) and camera buttons in the row below, and nudged up
   about half its own height. Hidden while locked (the corner shows the padlock
   instead). */
.dial-snap-btn {
  /* Anchored to the true-wind button (position:relative): centred on it and lifted
     above its top by ~3× its own height. Absolute, so it shifts nothing else. */
  position: absolute; left: 50%; bottom: 100%; transform: translate(-50%, -300%);
  z-index: 6; padding: 1px 2px;
  border: none; background: transparent; cursor: pointer; white-space: nowrap;
  user-select: none; touch-action: none;
  color: #fff; font-weight: 700; font-size: 13px; line-height: 1;
  font-family: 'Latin Modern Math', 'STIX Two Math', 'Cambria Math', serif;
}
.dial-snap-btn i { font-style: italic; }
.dial-snap-btn.snap-on { color: #ffd24a; } /* sticky auto-snap on → gold */
.dial-snap-btn:active { color: var(--accent); }
.dials-locked .dial-snap-btn { display: none; }
/* While "hold to aim" is active (a dial or the aim button), it reads the device live. */
.dial-aiming { box-shadow: 0 0 0 2px var(--accent), 0 0 12px var(--accent); animation: dial-aim-pulse 1s ease-in-out infinite; }
@keyframes dial-aim-pulse { 50% { box-shadow: 0 0 0 2px var(--accent), 0 0 4px var(--accent); } }

/* Main-photo banner at the top of a range/match/stage/target/gear view. */
.main-photo-banner:empty { display: none; }
.main-photo-banner { margin: 0 0 12px; }
.main-photo-img { display: block; width: 100%; max-height: 220px; object-fit: cover; border-radius: 10px; cursor: pointer; }
/* A small main-photo thumbnail in a list row (e.g. a target). */
.row-photo-thumb { width: 40px; height: 40px; flex: 0 0 auto; object-fit: cover; border-radius: 6px; cursor: pointer; }
.row-photo-thumb-wrap:empty { display: none; }
/* Group a row's thumbnail with its text so the buttons still sit at the far right. */
.list-item > .li-left { display: flex; align-items: center; gap: 10px; min-width: 0; }
.list-item > .li-left > div { min-width: 0; }
.gear-row-actions { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
/* A thumbnail-sized box that shows the main photo or an "Add Photo" placeholder. */
.photo-thumb-box { width: 48px; height: 48px; flex: 0 0 auto; padding: 0; overflow: hidden; border: 1px dashed var(--border); border-radius: 6px; background: var(--surface-2); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.photo-thumb-add { font-size: 9px; line-height: 1.1; color: var(--text-dim); text-align: center; }
.photo-thumb-img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Full-screen camera viewfinder for aiming azimuth + incline (no photo is taken). */
.cam-overlay { position: fixed; inset: 0; z-index: 1000; background: #000; overflow: hidden; }
.cam-video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Thin crosshair to aim at the target, with a small centre ring. */
.cam-cross { position: absolute; inset: 0; pointer-events: none; }
.cam-cross-v { position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; transform: translateX(-50%); background: rgba(255, 255, 255, 0.85); }
.cam-cross-h { position: absolute; top: 50%; left: 0; right: 0; height: 1px; transform: translateY(-50%); background: rgba(255, 255, 255, 0.85); }
.cam-cross::after { content: ''; position: absolute; left: 50%; top: 50%; width: 12px; height: 12px; border: 1px solid rgba(255, 255, 255, 0.9); border-radius: 50%; transform: translate(-50%, -50%); }
.cam-readout {
  position: absolute; top: calc(env(safe-area-inset-top) + 14px); left: 50%; transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.55); color: #fff; font-size: 15px; padding: 8px 14px; border-radius: 999px; white-space: nowrap;
}
.cam-readout b { color: var(--accent); font-variant-numeric: tabular-nums; }
.cam-capture {
  position: absolute; bottom: calc(env(safe-area-inset-bottom) + 28px); left: 50%; transform: translateX(-50%);
  width: 72px; height: 72px; border-radius: 50%; background: rgba(255, 255, 255, 0.9);
  border: 4px solid rgba(255, 255, 255, 0.5); cursor: pointer;
}
/* Horizontal zoom scrubber above the shutter; the thumb pill shows "2.3×". */
.cam-zoom {
  position: absolute; left: 36px; right: 36px;
  bottom: calc(env(safe-area-inset-bottom) + 124px);
  height: 44px; touch-action: none; cursor: ew-resize; user-select: none;
}
.cam-zoom-line { position: absolute; left: 0; right: 0; top: 50%; height: 2px; transform: translateY(-50%); background: rgba(255, 255, 255, 0.55); border-radius: 2px; }
.cam-zoom-thumb {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  min-width: 44px; text-align: center; padding: 6px 8px; border-radius: 999px;
  background: rgba(0, 0, 0, 0.55); color: #fff; font-size: 13px;
  pointer-events: none; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.cam-capture.cam-ready { box-shadow: 0 0 0 3px var(--accent); }
.cam-capture:active { background: #fff; }
.cam-close {
  position: absolute; top: calc(env(safe-area-inset-top) + 10px); right: 14px;
  width: 40px; height: 40px; border-radius: 50%; background: rgba(0, 0, 0, 0.5);
  color: #fff; border: none; font-size: 18px; line-height: 1; cursor: pointer;
}
/* --- Mover-tracking camera (the telescope button on the mover row) --- */
/* A bigger close target than the shared chassis default. */
.mover-cam .cam-close { width: 52px; height: 52px; font-size: 24px; background: rgba(0, 0, 0, 0.6); }
/* Bubble level pinned to the very top edge: a tube with a sliding dot, green when level. */
.mover-bubble { position: absolute; top: calc(env(safe-area-inset-top) + 6px); left: 50%; transform: translateX(-50%); width: min(62%, 320px); z-index: 6; pointer-events: none; }
.mover-bubble-tube { position: relative; height: 10px; border-radius: 6px; background: rgba(0, 0, 0, 0.45); border: 1px solid rgba(255, 255, 255, 0.5); }
.mover-bubble-tube::before { content: ''; position: absolute; left: 50%; top: -3px; bottom: -3px; width: 1px; background: rgba(255, 255, 255, 0.7); }
.mover-bubble-dot { position: absolute; top: 50%; left: 50%; width: 16px; height: 16px; border-radius: 50%; transform: translate(-50%, -50%); background: rgba(255, 230, 120, 0.95); box-shadow: 0 0 6px rgba(0, 0, 0, 0.6); }
.mover-bubble-dot.level { background: #57d977; }
/* Live roll angle, sitting just left of the tube (absolute → doesn't shift it). */
.mover-bubble-deg { position: absolute; right: 100%; top: 50%; transform: translateY(-50%); margin-right: 8px; font-size: 13px; font-weight: 700; color: rgba(255, 255, 255, 0.92); font-variant-numeric: tabular-nums; text-shadow: 0 1px 3px #000; white-space: nowrap; }
.mover-bubble-deg.level { color: #57d977; }
/* Big mover-adjusted dope across the top, under the bubble. */
.mover-dope-bar { position: absolute; top: calc(env(safe-area-inset-top) + 26px); left: 0; right: 0; z-index: 6; display: flex; justify-content: center; gap: 28px; pointer-events: none; }
.mover-dope-cell { display: flex; flex-direction: column; align-items: center; }
.mover-dope-lbl { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; color: rgba(255, 255, 255, 0.8); }
.mover-dope-v { font-size: 34px; font-weight: 800; line-height: 1.05; color: #fff; font-variant-numeric: tabular-nums; text-shadow: 0 0 4px #000, 0 1px 3px #000; }
.mover-dope-v svg { width: 0.8em; height: 0.8em; }
/* Mark button along the bottom; amber once armed (waiting for the end), green when a line is set. */
.mover-mark { position: absolute; left: 50%; bottom: calc(env(safe-area-inset-bottom) + 26px); transform: translateX(-50%); z-index: 6; min-width: 160px; padding: 14px 26px; border-radius: 30px; border: none; font-size: 17px; font-weight: 800; color: #fff; background: rgba(20, 20, 20, 0.7); border: 2px solid rgba(255, 255, 255, 0.7); cursor: pointer; }
/* Armed (between Mark start and end) = "recording": pulse the red button. */
.mover-mark.armed { background: #c1271f; border-color: #f2655c; animation: mover-mark-rec 1s ease-in-out infinite; }
@keyframes mover-mark-rec {
  0%, 100% { box-shadow: 0 0 0 0 rgba(241, 101, 92, 0.7); }
  50% { box-shadow: 0 0 0 10px rgba(241, 101, 92, 0); }
}
@media (prefers-reduced-motion: reduce) { .mover-mark.armed { animation: none; } }
/* After a capture: Reset (left) + Done (right) replace the single Mark button. */
.mover-mark-row { position: absolute; left: 0; right: 0; bottom: calc(env(safe-area-inset-bottom) + 26px); z-index: 6; display: flex; justify-content: center; gap: 36px; padding: 0 24px; }
.mover-mark-row button { min-width: 128px; padding: 14px 24px; border-radius: 30px; font-size: 17px; font-weight: 800; color: #fff; cursor: pointer; }
.mover-mark-reset { background: rgba(20, 20, 20, 0.7); border: 2px solid rgba(255, 255, 255, 0.7); }
.mover-mark-done { background: #2f7d46; border: 2px solid #57d977; }
.mover-cam-hint { position: absolute; left: 50%; bottom: calc(env(safe-area-inset-bottom) + 84px); transform: translateX(-50%); z-index: 6; max-width: 80%; text-align: center; font-size: 13px; color: rgba(255, 255, 255, 0.92); text-shadow: 0 1px 3px #000; pointer-events: none; }
/* Larger captured speed/angle, under the dope bar. */
.mover-cam-summary { position: absolute; top: calc(env(safe-area-inset-top) + 86px); left: 0; right: 0; z-index: 6; text-align: center; font-size: 22px; font-weight: 800; color: #fff; text-shadow: 0 0 4px #000, 0 1px 3px #000; pointer-events: none; }
/* No-compass warning, centred on the view. */
.mover-cam-warn { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 6; max-width: 78%; text-align: center; font-size: 14px; font-weight: 700; color: #fff; background: rgba(160, 30, 24, 0.82); border: 1px solid rgba(255, 120, 110, 0.8); border-radius: 10px; padding: 10px 14px; text-shadow: 0 1px 2px #000; pointer-events: none; }

/* ONE tall wind slider down the right edge of the prediction card, carrying both
   speed needles (Wind 1 lower, Wind 2 upper). Bottom of the rail is 0, top is the
   configured full-scale speed. The needles are big + fat for easy thumb grabbing;
   they read their value from W1's TOP edge / W2's BOTTOM edge so that at equal
   values W2's bottom abuts W1's top (stacked, never overlapping). */
.wind-col { position: relative; flex: 0 0 auto; width: 46px; align-self: stretch; display: flex; flex-direction: column; align-items: stretch; gap: 4px; }
.wind-col .wind-slider { width: auto; flex: 1 1 auto; }
/* Slider/segments mode switch — one full-width button, labelled with the active
   wind model (W × S vs Σ (Wᵢ × Sᵢ)). Positioned absolutely up onto the WEZ line
   (top set in JS) so it doesn't push the slider/segments down. */
.wind-mode-toggle { position: absolute; left: 0; right: 0; z-index: 3; width: 100%; padding: 11px 0; font-size: 10px; font-weight: 400; letter-spacing: -0.3px; line-height: 1; white-space: nowrap; border-radius: 5px; border: 1px solid var(--border); background: var(--surface-2); color: var(--muted); cursor: pointer; }
/* Segmented-wind panel: three stacked Near/Middle/Far input groups. The dope's
   2/A/1 wind-pick dots show the resulting low/avg/high holds, so no readout here. */
.wind-seg { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.ws-body { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: space-between; gap: 0; min-height: 0; }
.ws-grp { display: flex; flex-direction: column; gap: 1px; border: 1px solid rgba(255, 255, 255, 0.22); border-radius: 6px; padding: 2px; }
.ws-grp-title { color: #fff; padding: 1px 0; font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; text-align: center; }
.ws-grp-head { display: flex; align-items: center; gap: 2px; }
.ws-grp-lbl { font-size: 11px; font-weight: 800; color: var(--muted); }
/* One L/R toggle per group, full width, red. The letter aligns to the side it
   means — L on the left, R on the right — to reinforce the wind direction. */
/* L/R direction: green = wind from the Right, yellow = from the Left. The letter
   sits on the side it means. Used on the calc group header and in the popups. */
.ws-dir { width: 100%; font-size: 11px; font-weight: 800; height: 16px; line-height: 1; padding: 0 4px; border-radius: 4px; border: 1px solid var(--border); color: #0d1117; cursor: pointer; }
.ws-dir.ws-dir-l { text-align: left; background: #e3b341; border-color: #e3b341; }
.ws-dir.ws-dir-r { text-align: right; background: #3fb950; border-color: #3fb950; }
/* Orange / white / blue, matching the slider needles and the dope wind-pick:
   W1 (low) orange, average white, W2 (gust) blue. */
.ws-chip { font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums; padding: 1px 0; border-radius: 4px; border: 1px solid var(--border); cursor: pointer; }
.ws-chip.ws-w1 { background: var(--accent); color: #0d1117; border-color: var(--accent); }
.ws-chip.ws-avg { background: #fff; color: #0d1117; border-color: #fff; }
.ws-chip.ws-w2 { background: #6cb6ff; color: #08233f; border-color: #6cb6ff; }
.wind-slider { position: relative; flex: 0 0 auto; width: 46px; align-self: stretch; display: flex; flex-direction: column; align-items: center; }
.wsl-track {
  position: relative; width: 18px; flex: 1 1 auto; min-height: 120px;
  border-radius: 9px; background: var(--surface-2); border: 1px solid var(--border);
  touch-action: none; cursor: ns-resize; user-select: none;
}
/* Keyboard button under the rail — type exact Wind 1 / Wind 2 values. */
.wsl-kb {
  margin-top: 6px; width: 34px; height: 26px; border-radius: 7px; font-size: 14px; line-height: 1;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
  cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0;
}
.wsl-kb:active { background: var(--surface); }
.dials-locked .wsl-kb { cursor: not-allowed; opacity: 0.5; }
/* Tiny numeric-keypad dialog for typing Wind 1 / Wind 2 (so phones show the number
   keyboard, which a native prompt can't). */
.num-modal-overlay { position: fixed; inset: 0; z-index: 2000; background: rgba(0, 0, 0, 0.55); display: flex; align-items: center; justify-content: center; padding: 20px; }
/* Pin near the top so the on-screen keyboard (which expands from the bottom)
   doesn't cover the multi-field ELR group dialog. */
.num-modal-overlay.num-modal-top { align-items: flex-start; padding-top: 6vh; }
.num-modal { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 16px; width: 220px; max-width: 100%; box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5); }
.num-modal.env-modal { width: 308px; } /* environmentals popup — 40% wider than the base modal */
.num-modal-title { font-size: 15px; font-weight: 700; margin-bottom: 10px; }
.num-modal-row { display: flex; align-items: center; gap: 8px; }
.num-modal-input { flex: 1 1 auto; min-width: 0; font-size: 20px; text-align: right; padding: 8px 10px; }
.num-modal-unit { color: var(--text-dim); font-size: 13px; }
.num-modal-actions { display: flex; gap: 8px; margin-top: 14px; }
.seg-sync { display: flex; align-items: center; gap: 7px; margin-top: 8px; font-size: 13px; color: var(--text); cursor: pointer; }
.seg-sync input { width: 16px; height: 16px; flex: 0 0 auto; }
.seg-field { margin-top: 6px; }
.seg-flabel { flex: 0 0 58px; font-size: 13px; font-weight: 700; color: #fff; }
.seg-dir { height: 34px; font-size: 15px; padding: 0 10px; } /* taller for the dialog */
.calc-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.calc-ico { display: inline-flex; align-items: center; }
/* Full-screen mover stopwatch. Ready/running = one tap pane; stopped = split into
   Done (top) / Timer again (bottom), evenly down the long axis of the phone. */
.timer-overlay { position: fixed; inset: 0; z-index: 2100; display: flex; flex-direction: column; background: var(--bg, #0d1117); color: var(--text); user-select: none; -webkit-user-select: none; touch-action: manipulation; }
.timer-full, .timer-pane { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; cursor: pointer; }
.timer-running { background: #161b22; }
.timer-hint { font-size: 24px; font-weight: 800; color: var(--muted); }
.timer-time { font-size: 72px; font-weight: 800; font-variant-numeric: tabular-nums; }
.timer-time-sm { font-size: 30px; font-weight: 800; font-variant-numeric: tabular-nums; }
.timer-done { background: #15301f; }
.timer-redo { background: #1b2530; border-top: 2px solid var(--border); }
.timer-travel-input { height: 64px; font-size: 30px; } /* twice the normal input height */
/* Reticle calculator: all three inputs share one width so their left/right edges
   line up (the label column is already fixed-width). Speed is big + tall. */
.calc-modal { width: 290px; } /* wider so the bigger inputs + label + unit fit */
/* Friendly bullet picker (compare Tweak + new profile): diameter/maker filters + a
   tappable, scrollable list. */
.bp-modal { display: flex; flex-direction: column; width: 330px; max-width: 100%; max-height: 80vh; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 16px; box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5); }
.bp-filters { display: flex; gap: 8px; margin: 10px 0; }
.bp-flbl { flex: 1; display: flex; flex-direction: column; gap: 3px; font-size: 11px; color: var(--text-dim); }
.bp-flbl select { width: 100%; }
/* Compact weight-range + BC-threshold rows in the bullet picker. */
.bp-range { display: flex; align-items: center; gap: 4px; }
.bp-range select { flex: 0 0 auto; }
.bp-num { width: 100%; min-width: 0; box-sizing: border-box; }
.bp-dash { color: var(--text-dim); }
/* The BC filter fields only need to be a few characters wide (G7/G1, ≥/≤, BC),
   so pin their widths instead of letting them stretch across the row. */
.bp-range .bp-bcdrag { width: 3.6em; }
.bp-range .bp-bcop { width: 3em; }
.bp-range .bp-bcval { width: 5em; flex: 0 0 auto; min-width: 0; box-sizing: border-box; }
.bp-list { flex: 1 1 auto; min-height: 80px; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; }
.bp-mfr { font-size: 11px; font-weight: 700; color: var(--muted); padding: 7px 8px 2px; text-transform: uppercase; letter-spacing: 0.03em; }
.bp-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 9px 10px; cursor: pointer; border-top: 1px solid var(--border); }
.bp-row:active { background: var(--surface-2); }
.bp-row.sel { background: var(--surface-2); box-shadow: inset 3px 0 0 var(--accent); }
.bp-name { font-size: 14px; }
.bp-bc { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* ---- Shot groups: capture overlay + thumbnails ---- */
.gc-modal { width: 380px; max-width: 100%; }
.gc-row { display: flex; gap: 10px; margin: 8px 0; }
.gc-fld { flex: 1; display: flex; flex-direction: column; gap: 3px; font-size: 11px; color: var(--text-dim); }
.gc-fld select, .gc-fld input { width: 100%; box-sizing: border-box; }
.gc-dist { display: flex; align-items: center; gap: 4px; }
.gc-dist input { width: 5em; box-sizing: border-box; }
/* White plot box with a pale-red grid every tenth of the box. */
.gc-box { position: relative; width: 100%; aspect-ratio: 1; margin: 8px 0; background-color: #f4f4f4;
  background-image:
    linear-gradient(to right, rgba(200, 60, 60, 0.28) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(200, 60, 60, 0.28) 1px, transparent 1px);
  background-size: 10% 10%;
  border: 1px solid var(--border); border-radius: 6px; touch-action: none; cursor: crosshair; overflow: hidden; }
.gc-dots { position: absolute; inset: 0; }
.gc-dot { position: absolute; transform: translate(-50%, -50%); border-radius: 50%; background: #1a1a1a; border: 1px solid #555; box-sizing: border-box; }
.gc-stats { font-size: 12px; text-align: center; margin: 4px 0; }
.gc-actions { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.group-thumb { border-radius: 4px; flex: 0 0 auto; }
.group-thumb .gt-bg { fill: #f4f4f4; stroke: var(--border); }
.group-thumb .gt-dot { fill: #1a1a1a; }
.group-thumb-empty { width: 48px; height: 48px; flex: 0 0 auto; border: 1px dashed var(--border); border-radius: 4px; }
/* A little breathing room between a group's thumbnail and its details in the log. */
.list-item > .group-thumb, .list-item > .group-thumb-empty { margin-right: 10px; }
.group-form-thumb { display: flex; align-items: center; gap: 8px; }
/* Per-distance group summary table. */
.group-summary { width: 100%; border-collapse: collapse; font-size: 13px; }
.group-summary th { text-align: right; font-weight: 600; color: var(--text-dim); padding: 4px 6px; border-bottom: 1px solid var(--border); }
.group-summary th:first-child, .group-summary td:first-child { text-align: left; }
.group-summary td { text-align: right; padding: 4px 6px; border-bottom: 1px solid var(--border); }
.group-summary tr:last-child td { border-bottom: none; }
/* ES is the headline group figure — highlight that column. */
.group-summary th.gs-es, .group-summary td.gs-es { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
.group-summary td.gs-es { font-weight: 700; }
.list-item.tappable { cursor: pointer; }
.calc-inp { flex: 0 0 auto; width: 126px; text-align: center; padding: 4px; }
.calc-speed-input { height: 64px; font-size: 34px; font-weight: 800; }
.seg-flabel.seg-w1 { color: var(--accent); } /* orange */
.seg-flabel.seg-w2 { color: #6cb6ff; } /* blue */
.seg-flabel.seg-avg { color: #fff; } /* white */
.num-modal-actions .btn { flex: 1 1 0; }
.wsl-needle {
  position: absolute; left: 50%; transform: translateX(-50%);
  width: 42px; height: 45px; border-radius: 9px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  line-height: 1; pointer-events: none; border: 2px solid var(--bg);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.wsl-needle.w1 { background: var(--accent); color: #0d1117; } /* black text reads on the orange */
.wsl-needle.w2 { background: #6cb6ff; color: #08233f; }
.wsl-val { font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; }
.wsl-tag { font-size: 11px; font-weight: 700; opacity: 0.85; letter-spacing: 0.5px; }
/* Glow the grabbed needle (matching the dials' grab highlight). */
.wsl-needle.grabbing { box-shadow: 0 0 9px 3px currentColor; }
/* While the rest is locked, a long-press temporarily unlocks just this slider:
   accent the rail, restore the resize cursor + keyboard, and drop the padlock. */
.wind-slider.wsl-unlocked .wsl-track { cursor: ns-resize; border-color: var(--accent); }
.wind-slider.wsl-unlocked .dial-lock-badge { display: none; }
.wind-slider.wsl-unlocked .wsl-kb { cursor: pointer; opacity: 1; }
/* Setting-driven exemption: the global lock leaves this slider adjustable (no
   padlock, normal cursors) — without the temporary-unlock accent highlight. */
.wind-slider.wsl-exempt .wsl-track { cursor: ns-resize; }
.wind-slider.wsl-exempt .dial-lock-badge { display: none; }
.wind-slider.wsl-exempt .wsl-kb { cursor: pointer; opacity: 1; }
/* Value popped in the UPPER-LEFT of the prediction card while dragging a wind needle. */
.wind-drag-value {
  position: absolute; inset: 0; z-index: 50; pointer-events: none; opacity: 0;
  display: flex; align-items: flex-start; justify-content: flex-start; padding: 2px 6px;
  font-size: 140px; font-weight: 900; line-height: 1; font-variant-numeric: tabular-nums;
  text-shadow: 0 3px 24px rgba(0, 0, 0, 0.65);
}
.wind-drag-value.w1 { color: var(--accent); }
.wind-drag-value.w2 { color: #6cb6ff; }
/* Compact hit-probability on the line under the header: "<pct> (<MOA>)". */
/* The probability line: hit chance on the left, a quick wind-call confidence
   editor on the right, sharing one row. */
/* One continuous cell spanning the full row — the gun Hit% and the wind-call
   error flow together as inline text rather than separate grid-like cells. */
.prob-row { display: block; margin: 2px 0 4px; white-space: nowrap; overflow: hidden; }
.pred-prob, .prob-line, .prob-conf { display: inline; }
/* Reserve room for the widest value ("100%") and right-align, so the rest of the
   line doesn't shift as the percentage grows from 1 to 3 digits. */
.prob-pct { display: inline-block; min-width: 3.2em; text-align: right; font-variant-numeric: tabular-nums; font-size: 18px; font-weight: 700; color: var(--accent-2); }
.prob-conf .muted { white-space: nowrap; }
.prob-conf-input { width: 2.4em; padding: 2px 4px; font-size: 13px; text-align: right; vertical-align: middle; margin-left: 4px; }

/* Solution component parts (H/V Coriolis, spin drift) under a hold on the calc
   card — smaller and tinted, tappable to fold the effect in/out of the value. */
.comp-stat .comp-part {
  font-size: 11px; line-height: 1.5; cursor: pointer; user-select: none;
  border-radius: 4px; padding: 0 4px; margin: 2px auto 0;
  /* Always stack vertically — block-level so a wide screen can't pull the two
     components onto one line; fit-content + auto margins keeps each centred. */
  display: block; width: fit-content;
}
.comp-stat .comp-part.on { color: #6cb6ff; }                 /* folded into the solution */
.comp-stat .comp-part.off { color: var(--text-dim); opacity: 0.6; text-decoration: line-through; }
.comp-stat .comp-part.locked { cursor: default; } /* locked in Settings — display only */
/* Mover view of a dope cell: the three moving-target values in place of the parts,
   with the red glow used on the mover row. */
.comp-stat.comp-mover .comp-mover-v { display: flex; align-items: center; gap: 2px; font-size: 12px; line-height: 1.3; }
.comp-stat.comp-mover .mover-ind { display: inline-flex; align-items: center; line-height: 0; }
.comp-stat.comp-mover .mover-num { color: #fff; text-shadow: 0 0 5px #ffd60a, 0 0 11px #ffd60a; font-variant-numeric: tabular-nums; padding: 0 4px; }
.comp-stat.comp-mover .mover-num.mid { font-weight: 700; color: #221c00; background: #ffd60a; border-radius: 4px; text-shadow: none; }
/* Elevation: centred stack with a reserved arrow slot + right-aligned numbers, so the column lines up. */
.comp-stat.comp-mover .comp-mover-v.elev .mover-ind { width: 1em; justify-content: center; }
.comp-stat.comp-mover .comp-mover-v.elev .mover-num { min-width: 3.4ch; text-align: right; }
/* Windage: staggered top-left / centre / bottom-right. */
.comp-stat.comp-mover .comp-mover-v.l { align-self: flex-start; }
.comp-stat.comp-mover .comp-mover-v.r { align-self: flex-end; }
/* Reserve a constant height for the elev/windage cells (centred), so flipping a
   cell between its two component parts and the taller three-value mover view —
   or one cell moving while the other doesn't — never resizes the dope row. */
.solution.wind-pick-row .comp-stat { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; min-height: 104px; padding-top: 9px; }

.pred-dist { color: #6cb6ff; } /* the prediction distance, in the active-target blue */
/* the editable distance in the prediction header: looks like the blue distance,
   with a dashed underline hinting it can be typed into. */
/* Prediction (Calc) mode: the form fills the area above the navbar + pinned dope,
   and the single prediction card stretches to fill it (no surrounding margin). */
.calc-fill { min-height: 100%; display: flex; flex-direction: column; }
.calc-fill > .card { flex: 1 1 auto; margin-top: 0; display: flex; flex-direction: column; }
/* The calculator (prediction) page goes edge-to-edge: drop the app-main side/top
   padding and the card's border/radius so the surface-coloured panel fills the
   whole area, maximising room for the content. */
.app-main.calc-page { padding-top: 0; padding-left: 0; padding-right: 0; }
.calc-page .calc-fill > .card { border: none; border-radius: 0; margin: 0; padding: 6px 12px 10px; }
/* Sg footnote sticks to the bottom edge of the full-height card (the stretch fills
   above it), so it's always visible rather than floating after the content. */
.calc-fill > .card .pred-foot { margin-top: auto; padding-top: 10px; }

/* The prediction header with no "Prediction @" prefix — the distance sits
   centered on its row, large (the tools live in the topbar now). */
.pred-header { margin: 0 0 8px; font-size: 24px; text-transform: none; letter-spacing: 0; color: var(--text); display: grid; grid-template-columns: 1fr auto 1fr; align-items: start; gap: 8px; }
.pred-head-dist { display: inline-flex; align-items: baseline; gap: 0.25em; justify-content: center; line-height: 1; }
/* Prev/next-distance (or prev/next-target) steppers flanking the yardage —
   gray, and centered in their side columns so each sits equidistant between
   the yardage and the card edge. */
.pred-step { display: inline-flex; flex-direction: column; align-items: center; justify-content: flex-start; background: none; border: none; cursor: pointer; font: inherit; font-size: 15px; color: var(--text-dim); padding: 0 4px; line-height: 1.0; }
.pred-step:active { color: var(--text); }
.pred-step-prev, .pred-step-next { justify-self: center; }
/* Nudge the prev/next target links inward toward the centre distance. */
.pred-step-prev { transform: translateX(30px); }
.pred-step-next { transform: translateX(-30px); }
.pred-step-dist { white-space: nowrap; line-height: 1.0; }
.pred-step-prev .pred-step-dist::before { content: '‹ '; }
.pred-step-next .pred-step-dist::after { content: ' ›'; }
/* The target's name under the yardage on the prev/next steps — kept tight so the
   two stacked lines never grow taller than the large centre distance (the steps
   top-align with it, so the row height doesn't change). */
.pred-step-name { font-size: 10px; line-height: 1.05; color: var(--text-dim); max-width: 9ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pred-head-right { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.pred-tool { background: none; border: none; color: var(--text-dim); padding: 2px; line-height: 0; cursor: pointer; display: inline-flex; }
.pred-tool:active { color: var(--text); }
.pred-tool svg { width: 20px; height: 20px; stroke: currentColor; }
.pred-dist-input { background: transparent; border: none; border-bottom: 1px dashed rgba(108,182,255,0.5); font: inherit; color: #6cb6ff; width: 3em; padding: 0 2px; text-align: right; -moz-appearance: textfield; }
.pred-dist-input:focus { outline: none; border-bottom-color: #6cb6ff; }

/* Number inputs without the up/down spinner arrows. */
.no-spin { -moz-appearance: textfield; appearance: textfield; }
.no-spin::-webkit-outer-spin-button,
.no-spin::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* Gyroscopic stability, as small footnote text at the bottom of the prediction card. */
.pred-foot { margin-top: 10px; }
.pred-sg { font-weight: 400; font-size: 11px; color: #9aa0a6; }
/* Active match → stage → target breadcrumb in the prediction footer; tap to
   toggle. Struck through (and dimmed) while deactivated. */
.dope-crumb { font-size: 12px; font-weight: 600; color: #6cb6ff; cursor: pointer; margin-bottom: 3px; user-select: none; }
.dope-crumb:active { opacity: 0.7; }
.dope-crumb.off { color: var(--text-dim); font-weight: 400; text-decoration: line-through; }

/* Brief highlight when the settings screen scrolls to a voice-requested setting. */
.settings-flash { animation: settings-flash 1.8s ease-out; border-radius: 6px; }
@keyframes settings-flash { 0%, 40% { background: rgba(240, 136, 62, 0.28); } 100% { background: transparent; } }

.voice-status { font-size: 13px; color: var(--accent); min-height: 16px; }
.voice-transcript { font-size: 15px; color: var(--text); margin: 6px 0; min-height: 18px; }

.voice-answer:empty { display: none; }
.voice-answer.err .voice-answer-msg { color: var(--danger); font-size: 14px; }
.voice-answer-title { font-size: 12px; color: var(--text-dim); margin: 6px 0 4px; }
.voice-answer-line { font-size: 16px; font-weight: 600; color: var(--text); margin: 0 0 10px; }
.voice-holds { display: flex; gap: 10px; }
.voice-hold {
  flex: 1;
  background: var(--surface-2);
  border-radius: 10px;
  padding: 10px;
  text-align: center;
}
.voice-hold-val { font-size: 26px; font-weight: 700; color: var(--accent); line-height: 1.1; }
.voice-hold-unit { font-size: 12px; color: var(--text); margin-top: 2px; }
.voice-hold-lbl { font-size: 10px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.04em; margin-top: 4px; }
.voice-answer-sub { font-size: 12px; color: var(--text-dim); margin-top: 8px; }

/* Searchable combobox (bullet library diameter picker): a text input whose
   panel always opens with the full option list, narrowing only as you type. */
.combo { position: relative; }
.combo-panel { position: absolute; left: 0; right: 0; top: 100%; margin-top: 4px; z-index: 50; background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5); max-height: 45vh; overflow-y: auto; }
.combo-option { padding: 9px 12px; cursor: pointer; }
.combo-option:hover, .combo-option.active { background: rgba(255, 255, 255, 0.08); }
.combo-empty { padding: 9px 12px; color: var(--text-dim); }
/* Emoji picker panel (profile editor): themed groups of tappable emoji. */
.emoji-group-label { padding: 8px 12px 0; font-size: 11px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.05em; }
.emoji-grid { display: flex; flex-wrap: wrap; gap: 2px; padding: 6px 10px; }
.emoji-opt { font-size: 22px; line-height: 1.2; background: none; border: none; cursor: pointer; padding: 5px 6px; border-radius: 8px; }
.emoji-opt:hover, .emoji-opt:active { background: rgba(255, 255, 255, 0.08); }

/* --- AR target finder ------------------------------------------------------ */
.ar-layer { position: absolute; inset: 0; pointer-events: none; }
.ar-marker {
  position: absolute; transform: translate(-50%, -50%); pointer-events: auto;
  display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 4px; white-space: nowrap;
  background: rgba(13, 17, 23, 0.72); color: #cdd9e5; font-size: 12px; font-weight: 600;
  border: 1.5px solid #6cb6ff; border-radius: 14px; padding: 4px 9px; cursor: pointer;
}
.ar-marker.on { border-color: var(--accent); color: var(--accent); }
.ar-marker.edge { opacity: 0.92; border-style: dashed; }
.ar-marker .ar-chev { font-size: 14px; font-weight: 700; line-height: 1; }
.ar-marker.edge[data-edge='right'] { flex-direction: row-reverse; }
.ar-banner {
  /* Bottom-right corner (mirrors the Align button's left corner): clear of the
     top-center Az/Inc readout in aim mode, the centered shutter, and the zoom. */
  position: absolute; right: 14px; bottom: calc(30px + env(safe-area-inset-bottom));
  max-width: 35%; text-align: right; font-size: 12px; color: #cdd9e5;
  background: rgba(13, 17, 23, 0.72); border-radius: 10px; padding: 6px 10px;
}
.ar-banner.bad { color: #f85149; }
.ar-pills {
  position: absolute; left: 50%; transform: translateX(-50%);
  /* Above the zoom scrubber band (bottom 124px + 44px tall). */
  bottom: calc(178px + env(safe-area-inset-bottom)); display: flex; gap: 6px;
}
.ar-pill {
  background: rgba(13, 17, 23, 0.72); color: #cdd9e5; font-size: 12px;
  border: 1px solid var(--border); border-radius: 999px; padding: 6px 12px; cursor: pointer;
}
.ar-pill.on { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 600; }
.ar-align, .ar-enable {
  position: absolute; left: 14px; bottom: calc(30px + env(safe-area-inset-bottom));
  background: rgba(13, 17, 23, 0.72); color: #cdd9e5; font-size: 12px;
  border: 1px solid var(--border); border-radius: 10px; padding: 8px 12px; cursor: pointer;
}
.ar-enable { left: 50%; bottom: 50%; transform: translateX(-50%); font-size: 14px; }
/* Faint center mark shown ONLY during the align action. */
.ar-reticle {
  position: absolute; left: 50%; top: 50%; width: 26px; height: 26px;
  transform: translate(-50%, -50%); pointer-events: none;
  border: 1px solid rgba(255, 255, 255, 0.55); border-radius: 50%;
}
.ar-reticle::after {
  content: ''; position: absolute; left: 50%; top: 50%; width: 3px; height: 3px;
  transform: translate(-50%, -50%); border-radius: 50%; background: rgba(255, 255, 255, 0.7);
}


/* "Align" caption above the centred action button in the AR finder. */
.cam-action-label { position: absolute; left: 50%; bottom: calc(env(safe-area-inset-bottom) + 106px); transform: translateX(-50%); font-size: 12px; font-weight: 600; color: #fff; background: rgba(0, 0, 0, 0.6); padding: 3px 12px; border-radius: 999px; pointer-events: none; }

/* Stage list drag handle + the row being dragged. */
.drag-handle { cursor: grab; touch-action: none; color: var(--text-dim); font-size: 18px; line-height: 1; padding: 4px 2px; user-select: none; flex: 0 0 auto; }
.drag-handle:active { cursor: grabbing; }
/* The row being dragged: an accent ring + lift so it stands out from the rest. */
[data-stage-id].dragging { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent), 0 6px 16px rgba(0, 0, 0, 0.55); background: var(--surface-2); }
.stage-num { color: var(--accent); font-weight: 700; }

/* AR dope toggle (top-left) + the hold appended to each marker label. */
.ar-dope-btn { position: absolute; left: 14px; top: calc(14px + env(safe-area-inset-top)); background: rgba(13,17,23,0.72); color: #cdd9e5; font-size: 12px; border: 1px solid var(--border); border-radius: 999px; padding: 6px 12px; cursor: pointer; }
/* The hold sits on its OWN line under the name·distance, with room between the
   elevation and windage holds so they don't crowd each other. */
.ar-marker-dope { color: var(--accent); font-weight: 700; flex-basis: 100%; display: flex; align-items: center; justify-content: center; gap: 12px; margin-top: 2px; }
.ar-marker-dope:empty { display: none; }
