/* Light is the default palette. Dark is applied automatically when the OS
   is in dark mode (prefers-color-scheme), and can be forced either way with
   [data-theme] — set by js/theme.js from a saved choice, or synchronously
   by the inline script in <head> to avoid a flash on load. */
:root {
  --bg: #f4f5f7;
  --bg-card: #ffffff;
  --bg-elev: #eef0f3;
  --fg: #1b1e24;
  --fg-muted: #5b6472;
  --fg-dim: #8a93a3;
  --accent: #0969da;
  --accent-ink: #ffffff;
  --good: #1a8f4c;
  --bad: #d33a3a;
  --border: #d8dce2;
  --border-soft: #e7e9ed;
  --border-strong: #b9c0cb;
  --warn: #9a6700;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0e1014;
    --bg-card: #161a21;
    --bg-elev: #1d222b;
    --fg: #e6e9ef;
    --fg-muted: #8a93a3;
    --fg-dim: #5b6473;
    --accent: #7ec8ff;
    --accent-ink: #0b1018;
    --good: #5fd97a;
    --bad: #e85a5a;
    --border: #262c37;
    --border-soft: #1f242d;
    --border-strong: #3a4250;
    --warn: #e0a940;
  }
}

:root[data-theme="dark"] {
  --bg: #0e1014;
  --bg-card: #161a21;
  --bg-elev: #1d222b;
  --fg: #e6e9ef;
  --fg-muted: #8a93a3;
  --fg-dim: #5b6473;
  --accent: #7ec8ff;
  --accent-ink: #0b1018;
  --good: #5fd97a;
  --bad: #e85a5a;
  --border: #262c37;
  --border-soft: #1f242d;
  --border-strong: #3a4250;
  --warn: #e0a940;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font: 14px/1.5 -apple-system, "SF Pro Text", "Inter", system-ui, sans-serif;
}

header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 22px 28px 10px;
  border-bottom: 1px solid var(--border-soft);
}
header h1 { margin: 0; font-size: 18px; font-weight: 600; letter-spacing: 0.2px; }
header .sub { margin: 4px 0 0; color: var(--fg-muted); font-size: 13px; }

.theme-toggle {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--bg-elev);
  color: var(--fg-muted);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 10px;
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
.theme-toggle:hover { color: var(--fg); border-color: var(--border-strong); }

.card {
  margin: 20px 28px;
  padding: 18px 20px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.card h2 { margin: 0 0 10px; font-size: 14px; font-weight: 600; }
.card.loaded { padding: 14px 18px; }

/* The whole card is itself a <details> now, foldable down to "Data and
   lens selection" — its own summary sits outside the `#picker-card
   details summary` rule below (that one only matches a `details`
   *descendant* of #picker-card, and #picker-card being a details doesn't
   make it its own descendant), so it gets a matching look here instead. */
#picker-card > summary {
  cursor: pointer;
  font-size: 14px;
  font-weight: 700;
  padding: 4px 8px;
  margin: 0 -8px;
  border-radius: 6px;
  color: var(--fg);
  transition: background-color .12s ease;
}
#picker-card > summary:hover { background: var(--bg-elev); }
#picker-card > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
#picker-card > summary .muted { font-weight: 400; }
@media (prefers-reduced-motion: reduce) {
  #picker-card > summary { transition: none; }
}

/* Uniform vertical rhythm: one gap size between the picker card's top-level
   sections, a smaller one between a section's summary/body elements. Scoped
   with the #picker-card id so it wins over the plain-class rules below
   (which stay unscoped because .folder-pick/.hint/.manual-fallback are
   reused by lens rule-panels outside this card). */
#picker-card > * + * { margin-top: 16px; }
#picker-card > summary + * { margin-top: 10px; }
#picker-card details > * + * { margin-top: 10px; }
#picker-card .folder-pick,
#picker-card .hint,
#picker-card .lens-row { margin: 0; }
/* .manual-fallback keeps no override here: its only own rule is
   margin-top, which the alt-group rhythm rule below already outranks
   (id+2 classes beats a bare class) — adding it to this list would
   out-rank *that* rule instead and collapse the gap above it to 0. */
#picker-card .status:empty { margin: 0; min-height: 0; }

/* Group headers ("From a folder" / "Load one round directly") that split
   the six sections into the two ways of getting to a round. Pulled closer
   to the section right after them than the standard 16px rhythm, and
   given extra room from whatever came before — a label reads as
   belonging to the group below it, not floating between two groups. */
#picker-card > .section-group-label {
  margin-top: 28px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--fg-dim);
}
/* The very first group label used to be :first-child before #picker-card
   grew its own <summary> — that summary is the true first child now, so
   target "right after the summary" instead of "first child" to keep this
   label from inheriting the master toggle's spacing rhythm (10px) instead
   of its own 28px meant for separating it from a *previous section*. */
#picker-card > summary + .section-group-label { margin-top: 10px; }
#picker-card > .section-group-label + details,
#picker-card > .section-group-label + .alt-group { margin-top: 8px; }

/* A set of sections that are direct alternatives — same outcome, different
   path (Drive folder vs. Cache folder both build the same video/cache
   index) — gets bundled into one
   visible capsule instead of just a divider between otherwise-identical
   top-level cards. That's the actual point: at a glance, "these belong
   together as one choice" vs. "Video & lens is the next, unrelated step". */
/* No fill: --bg-elev is also what inputs/buttons use for their own
   surface, and filling the capsule with it flattened every field and
   button inside into the same gray as its background — nothing read as
   an actual control anymore. A border-only capsule still groups the
   alternatives at a glance without fighting its contents for contrast. */
#picker-card > .alt-group {
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  padding: 10px 12px;
}
#picker-card > .alt-group > * + * { margin-top: 10px; }

/* "or" divider between two alternatives inside a capsule. */
.or-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--fg-dim);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.or-divider::before,
.or-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

#picker-card details summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  padding: 4px 0;
  margin: 0 -8px;
  padding-left: 8px;
  padding-right: 8px;
  border-radius: 6px;
  color: var(--fg);
  transition: background-color .12s ease;
}
#picker-card details summary:hover { background: var(--bg-elev); }
#picker-card details summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
#picker-card details summary .muted { font-weight: 400; }
@media (prefers-reduced-motion: reduce) {
  #picker-card details summary { transition: none; }
}

.section-desc {
  color: var(--fg-muted);
  font-size: 12px;
}

.section-actions {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}

/* Shared button look for every picker-card action (and the handful of
   rule-panel buttons, e.g. #sps-refresh, that opt in) — one primary
   (filled accent) and one secondary (outlined) variant, instead of each
   section growing its own bespoke or entirely unstyled <button>. */
.btn {
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 14px;
  font: inherit;
  cursor: pointer;
  white-space: nowrap;
}
.btn:hover { border-color: var(--border-strong); }
.btn:disabled { opacity: 0.5; cursor: default; }
.btn:active:not(:disabled) { transform: scale(0.97); }
.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  font-weight: 600;
}
.btn-primary:hover { border-color: var(--accent); filter: brightness(1.08); }

/* Smooth, understated motion on every interactive control — state changes
   (hover, focus, disabled, a status turning green/red) read as a change
   instead of a jump cut. Kept short (Apple HIG: transitions communicate,
   they don't perform) and skipped for users who've asked for less motion. */
.btn,
input,
select,
input[type="file"]::file-selector-button {
  transition: border-color .15s ease, background-color .15s ease,
              color .15s ease, opacity .15s ease, transform .08s ease;
}
@media (prefers-reduced-motion: reduce) {
  .btn, input, select, input[type="file"]::file-selector-button,
  .btn:active:not(:disabled) { transition: none; transform: none; }
}
.btn:focus-visible,
input:focus-visible,
select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Live status text (drive/cache status lines, …) carries a `data-state`
   set from JS alongside its existing
   text, so the same line also reads as busy/success/error/warn at a
   glance — a spinner while a fetch is in flight, green once something is
   confirmed working, red on failure — instead of only ever sitting there
   as flat muted text no matter what's actually happening. */
[data-state] { transition: color .15s ease; }
[data-state="busy"] { color: var(--accent); }
[data-state="success"] { color: var(--good); }
[data-state="warn"] { color: var(--warn); }
[data-state="error"] { color: var(--bad); }
[data-state="busy"]::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 5px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  border-top-color: transparent;
  animation: spin .7s linear infinite;
  vertical-align: -1px;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  [data-state="busy"]::before { animation: none; }
}

/* Native file inputs only let us restyle the button part — leave the
   filename text ("No file chosen" etc.) as the browser renders it, but
   make that button match .btn so it doesn't look like a foreign control
   dropped into an otherwise-themed page. */
input[type="file"] {
  font: inherit;
  color: var(--fg-muted);
}
input[type="file"]::file-selector-button {
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 7px 12px;
  font: inherit;
  cursor: pointer;
  margin-right: 10px;
}
input[type="file"]::file-selector-button:hover { border-color: var(--border-strong); }

.picker-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.picker-row label,
.folder-pick {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  font-size: 12px;
  color: var(--fg-muted);
}
.folder-pick { margin-bottom: 14px; }
/* flex-direction:column defaults to align-items:stretch, which would
   otherwise blow up any <button> inside a .folder-pick (e.g. "Clear
   index") into a full-width bar. Everything else here (the file input,
   the descriptive <span>) still wants the full width. */
.folder-pick input[type="file"],
.folder-pick > span,
.picker-row label input,
.picker-row label select { align-self: stretch; }
.picker-row input,
.folder-pick input,
.section-actions input,
.picker-row select {
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font: inherit;
}
.picker-row select:disabled { opacity: 0.5; }

.lens-row { margin-bottom: 14px; }
.lens-row label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12px;
  color: var(--fg-muted);
}
.lens-row select {
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font: inherit;
}
#lens-pick-status { margin: 6px 0 0; }

.manual-fallback {
  margin-top: 14px;
  font-size: 12px;
  color: var(--fg-muted);
}
.manual-fallback summary { cursor: pointer; padding: 4px 0; }
.manual-fallback label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}
.manual-fallback input[type="file"] {
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font: inherit;
}

.hint {
  color: var(--fg-muted);
  font-size: 12px;
  margin: 12px 0 0;
}
.hint code {
  background: var(--bg-elev);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 11px;
}

.status {
  margin: 8px 0 0;
  color: var(--accent);
  font-size: 12px;
  min-height: 16px;
}

/* ── Viewer layout ──────────────────────────────────────────────────────── */
#viewer {
  padding: 4px 28px 32px;
}
.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 22px;
  align-items: start;
}

#stage {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
}

/* Video/round dropdowns pinned above the video so switching rounds
   doesn't need a scroll back up to the picker card. */
.stage-pick {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
  font-size: 12px;
  color: var(--fg-muted);
}
.stage-pick label {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.stage-pick label:first-child { flex: 1; min-width: 0; }
.stage-pick select {
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 10px;
  font: inherit;
  max-width: 100%;
}
.stage-pick label:first-child select { flex: 1; min-width: 0; }
.stage-pick select:disabled { opacity: 0.5; }
.stage-pick button {
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 10px;
  font: inherit;
  cursor: pointer;
  white-space: nowrap;
}
.stage-pick button:hover { border-color: var(--border-strong); }
.stage-pick button:disabled { opacity: 0.5; cursor: default; }

.video-wrap {
  position: relative;
  background: #000;
  border-radius: 6px;
  overflow: hidden;
  /* `--video-ratio` is set from JS once the video metadata loads
     (= videoWidth / videoHeight). Without it (e.g. before the first
     load) we fall back to 16:9 so the box still has a reasonable
     placeholder shape. The aspect-ratio + max-height combo caps
     portrait videos at 75vh while letting landscape videos fill the
     stage width as before. */
  aspect-ratio: var(--video-ratio, 16 / 9);
  max-height: 75vh;
  width: 100%;
  max-width: calc(75vh * var(--video-ratio, 16 / 9));
  margin: 0 auto;
}
.video-wrap video,
.video-wrap canvas {
  display: block;
  width: 100%;
  height: 100%;
}
.video-wrap canvas {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.controls {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}
.controls button,
.controls select {
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 12px;
  font: inherit;
  cursor: pointer;
}
.controls button:hover { border-color: var(--border-strong); }
.controls #scrubber {
  flex: 1;
  accent-color: var(--accent);
}

/* Hidden video used to grab thumbnails on scrubber hover. Position
   offscreen rather than `display: none` so the browser still decodes. */
#thumb-video {
  position: absolute;
  left: -9999px;
  top: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}

#thumb-tooltip {
  position: fixed;
  pointer-events: none;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px;
  z-index: 100;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
}
#thumb-canvas {
  display: block;
  background: #000;
  border-radius: 4px;
}
#thumb-label {
  text-align: center;
  margin-top: 4px;
  font-family: ui-monospace, "SF Mono", monospace;
  font-size: 11px;
}

#frame-label {
  margin-top: 8px;
  font-family: ui-monospace, "SF Mono", monospace;
  font-size: 12px;
}
.muted { color: var(--fg-muted); }
.small { font-size: 11px; }

/* ── Side panel ────────────────────────────────────────────────────────── */
#side {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 16px;
  position: sticky;
  top: 16px;
  max-height: calc(100vh - 32px);
  overflow-y: auto;
}

.video-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--border-soft);
}
.video-info .vi-label {
  color: var(--fg-muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.video-info .vi-name {
  font-size: 13px;
  font-weight: 600;
  word-break: break-word;
}
.video-info .vi-drive {
  color: var(--accent);
  font-size: 12px;
  text-decoration: none;
  width: fit-content;
}
.video-info .vi-drive:hover { text-decoration: underline; }

.rule-pick {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border-soft);
  margin-bottom: 12px;
}
.rule-pick span { color: var(--fg-muted); font-size: 12px; }
.rule-pick select {
  flex: 1;
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
  font: inherit;
}

#rule-panel h2 {
  font-size: 13px;
  font-weight: 600;
  margin: 0 0 6px;
}
#rule-panel h3 {
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin: 18px 0 8px;
}

.metric-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.metric {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
}
.metric-label {
  font-size: 11px;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.metric-val {
  font-family: ui-monospace, "SF Mono", monospace;
  font-size: 16px;
  margin-top: 2px;
}
.metric-sub {
  font-size: 11px;
  margin-top: 4px;
}
.good { color: var(--good); }
.bad  { color: var(--bad); }

#trace-canvas, #conf-canvas,
#sps-vel-canvas, #sps-ext-canvas {
  width: 100%;
  height: auto;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
}

/* step-punch-sync rule panel */
.sps-tbl {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  margin-bottom: 12px;
}
.sps-tbl th, .sps-tbl td {
  padding: 4px 6px;
  text-align: left;
  border-bottom: 1px solid var(--border-soft);
}
.sps-tbl th {
  color: var(--fg-muted);
  font-weight: 500;
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.4px;
}
.sps-tbl tr:hover { background: var(--bg-elev); }
.sps-tbl tr.unscored td { color: var(--fg-muted); font-style: italic; }
.role-lead {
  background: rgba(95,217,122,0.18);
  color: var(--good);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 11px;
}
.role-rear {
  background: rgba(245,185,69,0.18);
  color: #f5b945;
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 11px;
}

/* step detector banner */
.sd-banner {
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 14px;
  font-weight: 600;
  border-left: 4px solid var(--fg-muted);
  background: var(--bg-elev);
  color: var(--fg);
}
.sd-banner-idle {
  color: var(--fg-muted);
  font-weight: 400;
  font-style: italic;
}
.sd-banner-l {
  border-left-color: #7ec8ff;
  background: rgba(126,200,255,0.10);
  color: #7ec8ff;
}
.sd-banner-r {
  border-left-color: #ff8a5c;
  background: rgba(255,138,92,0.10);
  color: #ff8a5c;
}
.sd-banner-sub {
  margin-top: 4px;
  font-size: 12px;
  font-weight: 400;
  color: var(--fg);
  opacity: 0.85;
}
.sd-banner-sub i { color: var(--fg-muted); }

.slider {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 10px;
  font-size: 12px;
  color: var(--fg-muted);
}
.slider input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
}
.slider output {
  color: var(--fg);
  font-family: ui-monospace, "SF Mono", monospace;
}

.joint-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.joint-table th, .joint-table td {
  padding: 4px 6px;
  text-align: left;
  border-bottom: 1px solid var(--border-soft);
}
.joint-table th {
  color: var(--fg-muted);
  font-weight: 500;
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.4px;
}
.joint-table td.num {
  font-family: ui-monospace, "SF Mono", monospace;
  text-align: right;
}

.shortcuts {
  margin-top: 18px;
  font-size: 12px;
  color: var(--fg-muted);
}
.shortcuts summary { cursor: pointer; }
.shortcuts ul { padding-left: 18px; margin: 6px 0 0; }
.shortcuts kbd {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0 4px;
  font-family: ui-monospace, "SF Mono", monospace;
  font-size: 11px;
}

@media (max-width: 1100px) {
  .layout { grid-template-columns: 1fr; }
  #side { position: static; max-height: none; }
}

/* ── Export dialog ──────────────────────────────────────────────────────── */
#export-dialog {
  background: var(--bg-card);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0;
  width: min(420px, 92vw);
  box-shadow: 0 12px 40px rgba(0,0,0,.5);
}
#export-dialog::backdrop { background: rgba(0,0,0,.55); }
#export-dialog .export-form { padding: 18px 20px; margin: 0; }
#export-dialog h3 { margin: 0 0 14px; font-size: 16px; }
#export-dialog .opt {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border: 1px solid var(--border-soft); border-radius: 7px;
  margin-bottom: 8px; cursor: pointer;
}
#export-dialog .opt:has(input:checked) { border-color: var(--accent); background: var(--bg-elev); }
#export-dialog .opt .muted { color: var(--fg-muted); font-size: 13px; }
#export-dialog .export-range { padding: 4px 2px 0 30px; }
#export-dialog .export-range[hidden] { display: none; }
#export-dialog .rng-row { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
#export-dialog .rng-row label { width: 42px; color: var(--fg-muted); }
#export-dialog .rng-row input {
  flex: 1; background: var(--bg); color: var(--fg);
  border: 1px solid var(--border); border-radius: 6px; padding: 6px 9px; font: inherit;
}
#export-dialog .rng-row input:focus { outline: none; border-color: var(--accent); }
#export-dialog .rng-row button {
  background: var(--bg-elev); color: var(--fg-muted); border: 1px solid var(--border);
  border-radius: 6px; padding: 6px 10px; font: inherit; cursor: pointer; white-space: nowrap;
}
#export-dialog .rng-row button:hover { color: var(--fg); border-color: var(--border-strong); }
#export-dialog .hint { color: var(--fg-muted); font-size: 12px; margin: 6px 0 0; line-height: 1.5; }
#export-dialog .hint code {
  background: var(--bg); border: 1px solid var(--border-soft);
  border-radius: 4px; padding: 0 4px; color: var(--fg);
}
#export-dialog .export-err { color: var(--bad); font-size: 13px; min-height: 18px; margin: 10px 0 0; }
#export-dialog .export-actions { display: flex; justify-content: flex-end; gap: 8px; margin: 14px 0 0; padding: 0; }
#export-dialog .export-actions button {
  background: var(--bg-elev); color: var(--fg); border: 1px solid var(--border);
  border-radius: 6px; padding: 7px 16px; font: inherit; cursor: pointer;
}
#export-dialog .export-actions button:hover { border-color: var(--border-strong); }
#export-dialog .export-actions button.primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-weight: 600; }
