/* ════════════════════════════════════════════════════════════════════
   Zone F — Bottom Action Dock (DESIGN_INTERACTION_LAYER.md §3)
   ────────────────────────────────────────────────────────────────────
   Replaces the old always-on #hud key legend. Same bottom-center glass
   capsule; now holds context-aware high-frequency action buttons
   (content injected by ui/action-dock.js). Key hints live in tooltips.
   ════════════════════════════════════════════════════════════════════ */
.action-dock {
  position: absolute;
  bottom: 22px;   /* float just above the window's bottom edge */
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px 6px;
  /* Liquid glass (DESIGN.md §6.4) — floats over Canvas, tokenized + dark-correct. */
  background: var(--float-bg);
  border: 1px solid var(--line-1);
  border-radius: 999px;
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  color: var(--ink-2);
  /* DESIGN.md §9.1 bottom-center slot: above css2d chips (100), below
     floating panels (1000) so the Inspector can overlap it. */
  z-index: 200;
  box-shadow: var(--float-shadow), var(--float-edge);
  transition: left var(--dur-panel) var(--ease-out);
}
.action-dock:empty { display: none; }   /* before action-dock.js fills it */

.dock-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;            /* K6 — touch target ≥ 32×32 */
  height: 32px;
  padding: 0;
  /* 1px transparent at rest → border swap on hover = 0 layout shift */
  border: 1px solid transparent;
  border-radius: 999px;
  /* user 2026-07-04：撤回静止淡底座（难看背景阴影），hover 再 fill；dock 常驻玻璃胶囊
     本身已把这排钮与画布分开，钮不需各自底座。 */
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
.dock-btn:hover  { background: var(--hover-bg); color: var(--ink-1); border-color: var(--hover-border); }
.dock-btn:active { background: var(--active-bg); border-color: var(--active-border); }
/* v2 affordance：destructive 钮**静止**即着 --sig-error（§3.3 白名单：小图标着色），
   与普通钮一眼区分，不再靠 hover 才显危险语义。 */
.dock-btn.is-destructive { color: var(--sig-error); }
.dock-btn.is-destructive:hover { color: var(--bad); background: var(--bad-bg); }
/* toggled-on tool — solid reverse-ink pill, theme-aware (DESIGN.md §3.3) */
.dock-btn.is-on, .dock-btn.is-on:hover { background: var(--ink-1); color: var(--surface); }
/* 锁定态（DESIGN 锁定功能）：黄色挂锁 = 该件已锁、点击解锁（功能色仅小图标/淡底着色，DESIGN §3.3）。 */
.dock-btn.is-locked, .dock-btn.is-locked:hover { color: var(--sig-warn); background: var(--sig-warn-bg); }
.dock-btn svg { width: 16px; height: 16px; }

.dock-sep {
  width: 1px;
  height: 18px;
  margin: 0 3px;
  background: var(--line-hard);   /* v2 affordance：dock 分组分隔 = 唯一线索 → --line-hard(≥3:1)（U11）*/
  flex: 0 0 auto;
}
.dock-views { display: inline-flex; align-items: center; gap: 2px; }

/* Action dock flyout: compact upward menu attached to a dock grid button. */
.dock-flyout {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.dock-flyout-trigger {
  position: relative;
}

.dock-flyout-trigger.is-open,
.dock-flyout-trigger[aria-expanded="true"] {
  background: var(--hover-bg);
  color: var(--ink-1);
  border-color: var(--hover-border);
}

/* Flyout affordance (user 2026-07-10: 换成上部一个半透明小拉手): a short,
   semi-transparent grip bar centered on the trigger's TOP edge — a pull-tab
   pointing at the drawer that opens upward. The old bottom-right cyan square
   read as a notification dot; a top grabber reads as "pull here for more tools"
   and matches the topbar collapse handle's language. Monochrome (currentColor)
   so it tracks the button's ink — faint at rest, solid on hover / when open.
   action-dock.js (isFlyoutMarkerHit) opens the flyout from this same top band. */
.dock-flyout-trigger::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 50%;
  transform: translateX(-50%);
  width: 12px;
  height: 2.5px;
  border-radius: 2px;
  background: currentColor;
  opacity: 0.32;
  pointer-events: none;
  transition: opacity 120ms ease, width 120ms ease;
}

.dock-flyout-marker {
  display: none;
}

.dock-flyout-trigger:hover::after,
.dock-flyout-trigger.is-open::after,
.dock-flyout-trigger[aria-expanded="true"]::after {
  opacity: 0.85;
  width: 15px;
}

.dock-flyout-trigger.has-active::after {
  opacity: 0.85;
}

.dock-flyout-menu {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  z-index: 210;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 176px;
  max-width: min(280px, calc(100vw - 24px));
  padding: 5px;
  border: 1px solid var(--line-1);
  border-radius: 10px;
  background: var(--float-bg);
  color: var(--ink-2);
  box-shadow: var(--float-shadow), var(--float-edge);
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 8px) scale(0.98);
  transform-origin: 50% 100%;
  transition: opacity 140ms ease, transform 160ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.dock-flyout-menu[hidden] {
  display: none;
}

.dock-flyout-menu.is-open,
.dock-flyout-menu[data-open="true"] {
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, 0) scale(1);
}

.dock-flyout-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.dock-flyout-row {
  display: flex;
  align-items: center;
  min-width: 0;
}

.dock-flyout-tray {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
}

.dock-flyout-item {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  width: 100%;
  min-height: 28px;
  padding: 4px 8px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--ink-2);
  font: 500 11px/1.35 var(--font-mono, ui-monospace, monospace);
  text-align: left;
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}

.dock-flyout-tray .dock-flyout-item {
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  min-height: 32px;
  padding: 0;
  border-radius: 999px;
}

/* 禁用档（如笼系规格切换里库内无标注件的 16/60mm，2026-07-24）：半透明 + 禁用光标；
   点击在 dispatcher 按 aria-disabled 忽略，tooltip 给理由。 */
.dock-flyout-item.is-disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.dock-flyout-item.is-disabled:hover {
  background: transparent;
  color: var(--ink-2);
}

.dock-flyout-item:hover,
.dock-flyout-item:focus-visible {
  background: var(--hover-bg);
  color: var(--ink-1);
  border-color: var(--hover-border);
}

.dock-flyout-item:active {
  background: var(--active-bg);
  border-color: var(--active-border);
}

.dock-flyout-item.is-on,
.dock-flyout-item[aria-checked="true"],
.dock-flyout-item[aria-pressed="true"] {
  background: var(--ink-1);
  color: var(--surface);
  border-color: var(--ink-1);
}

.dock-flyout-item.is-on:hover,
.dock-flyout-item[aria-checked="true"]:hover,
.dock-flyout-item[aria-pressed="true"]:hover {
  background: var(--ink-1);
  color: var(--surface);
  border-color: var(--ink-1);
}

.dock-flyout-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dock-flyout-key {
  margin-left: auto;
  flex: 0 0 auto;
  color: var(--ink-4);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.dock-flyout-item.is-on .dock-flyout-key,
.dock-flyout-item[aria-checked="true"] .dock-flyout-key,
.dock-flyout-item[aria-pressed="true"] .dock-flyout-key {
  color: color-mix(in srgb, var(--surface) 70%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .dock-flyout-trigger::after,
  .dock-flyout-marker,
  .dock-flyout-menu,
  .dock-flyout-item {
    transition: none;
  }

  .dock-flyout-menu {
    transform: translate(-50%, 0) scale(1);
  }
}

/* ── BOM「清单」destination + spectral guide (2026-06-15, hover rays 追加) ──────
   The Bill-of-Materials button is anchored at the dock's far right (see
   action-dock.js) and wears a PERMANENT spectral guide (user 定常驻):
     · idle  — a thin rainbow RIM slowly orbits the circular pill (a refraction
       halo) over a soft, slow-breathing BLOOM;
     · hover — the pill refracts light into a fan of spectral RAYS that bloom
       outward while the rim energizes (faster + brighter) and the icon glows.
   All colour comes ONLY from the sanctioned laser-wavelength palette — violet ·
   cyan · green · amber · red, short→long wavelength (DESIGN.md §3.4), held in
   one --pn-spectral wheel — so the cue is on-brand, theme-aware, never an
   arbitrary "AI gradient". Kept quiet at rest (thin rim, slow 6s sweep,
   low-opacity bloom); the hover ray-burst is the livelier moment + retracts on
   leave. prefers-reduced-motion freezes all motion to a faint static rim. */
.dock-btn.dock-bom { position: relative; }
.dock-bom.is-guide {
  isolation: isolate;   /* contain the bloom/ray z-index above the glass */
  /* single source for the visible-spectrum sweep — start = end → seamless loop */
  --pn-spectral: conic-gradient(from 0deg,
    var(--wl-405), var(--sig-select), var(--wl-532),
    var(--sig-warn), var(--wl-1064), var(--wl-405));
}

/* idle: shared spectral wheel for rim + bloom */
.dock-bom.is-guide::before,
.dock-bom.is-guide::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  background: var(--pn-spectral);
  animation: dock-bom-spin 6s linear infinite;
}

/* crisp rim — gradient shown only in the 1.5px padding band (border-only trick) */
.dock-bom.is-guide::before {
  inset: -2px;
  padding: 1.5px;
  opacity: 0.85;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  transition: opacity 0.3s ease, filter 0.3s ease;
}

/* soft bloom behind the pill — breathes gently, slightly slower than the spin.
   z-index:-2 keeps it below the ray fan (-1), both still behind the icon. */
.dock-bom.is-guide::after {
  inset: -3px;
  z-index: -2;
  filter: blur(6px);
  animation: dock-bom-spin 6s linear infinite,
             dock-bom-breathe 3.6s ease-in-out infinite;
}

/* hover halo — soft spectral light that BLOOMS outward (散开) while its colours
   CIRCULATE (流转). Two overlapping waves (::before + a half-period-delayed
   ::after) each grow + rotate + fade, so a glow is always spreading. Blurred,
   radial-masked → a soft aura, no hard edges (replaces the earlier spoke fan). */
.dock-bom-rays {
  position: absolute;
  inset: -10px;
  z-index: -1;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s ease;
}
.dock-bom-rays::before,
.dock-bom-rays::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--pn-spectral);
  filter: blur(6px) saturate(1.15);
  /* soft halo band: glow in the outer ring, hollow centre + feathered edge */
  -webkit-mask: radial-gradient(closest-side, transparent 34%, #000 64%, transparent 100%);
          mask: radial-gradient(closest-side, transparent 34%, #000 64%, transparent 100%);
  animation: dock-bom-aura 4.4s ease-out infinite;
}
.dock-bom-rays::after { animation-delay: -2.2s; }   /* phase-offset → seamless waves */

/* hover = halo fades in; rim warms + icon gains a faint glow (gentle, no speed-up) */
.dock-bom.is-guide:hover .dock-bom-rays { opacity: 1; }
.dock-bom.is-guide:hover::before {
  opacity: 1;
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--sig-select) 55%, transparent));
}
.dock-bom.is-guide:hover svg {
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--wl-405) 55%, transparent));
}

@keyframes dock-bom-spin    { to { transform: rotate(360deg); } }
@keyframes dock-bom-breathe { 0%, 100% { opacity: 0.12; } 50% { opacity: 0.36; } }
/* one wave: grow out of the pill + rotate (flow) + fade as it spreads (散开 + 流转) */
@keyframes dock-bom-aura {
  0%   { transform: rotate(0deg)   scale(0.65); opacity: 0; }
  22%  { opacity: 0.75; }
  100% { transform: rotate(210deg) scale(1.5);  opacity: 0; }
}

/* Accessibility: no motion → static faint rim + a still soft halo on hover. */
@media (prefers-reduced-motion: reduce) {
  .dock-bom.is-guide::before { animation: none; opacity: 0.7; }
  .dock-bom.is-guide::after  { animation: none; opacity: 0.18; }
  .dock-bom-rays::before,
  .dock-bom-rays::after { animation: none; opacity: 0.4; transform: scale(1.1); }
}

/* ── "Lock all" master + hold-to-choose gesture (user 2026-07-02) ─────────────
   The dock button (action-dock.js lockAllButton) rests as a plain padlock —
   open when nothing's locked, yellow closed via .is-locked when something is
   (shares the --sig-warn lock skin with the per-selection btn).

   PRESS-AND-HOLD spins up a body-level overlay (#lock-gesture): a spectral
   charge RING fades in over the button and an "Unlock all" TARGET floats up
   above it with a context caption. Hold in place → the ring fills and LOCKS
   all; SLIDE UP onto the target → the ring GLIDES up to it and, on completion,
   UNLOCKS all. The ring is a tighter, quieter sibling of the BOM guide (same
   sanctioned laser-wavelength wheel, DESIGN §3.4). Motion follows ui-ux-pro-max
   §7: ease-out enter, transform/opacity only, spring-ish glide, exits faster
   than it enters, and freezes under prefers-reduced-motion.
   Hold duration is fed from JS (--pn-lock-ms = LOCK_HOLD_MS, single source). */

/* animatable sweep angle — lets the conic ring interpolate its fill in @keyframes */
@property --pn-lock-fill {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}
@keyframes dock-lock-fill {
  from { --pn-lock-fill: 0deg; }
  to   { --pn-lock-fill: 360deg; }
}

.lock-gesture {
  position: fixed;
  inset: 0;
  z-index: 250;                 /* above the dock (200), below floating panels (1000) */
  pointer-events: none;         /* finger is hit-tested by geometry, not by hitting these */
}
.lock-gesture[hidden] { display: none; }

/* shared charge ring — JS prepends translate(cx,cy); it glides on target switch */
.lg-ring {
  position: absolute;
  left: 0; top: 0;
  width: 38px; height: 38px;
  opacity: 0;
  transform: translate(-50%, -50%);
  transition: transform 240ms cubic-bezier(0.22, 1, 0.36, 1),   /* spring-ish glide (§7 spring-physics) */
              opacity 150ms ease-out;
  will-change: transform, opacity;
}
.lock-gesture.is-active .lg-ring { opacity: 1; }
.lg-fill {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  padding: 1.8px;
  /* spectral wheel compressed into the filled arc [0, --pn-lock-fill], then
     transparent — short→long wavelength, matching the BOM guide's palette. */
  background: conic-gradient(from -90deg,
    var(--wl-405), var(--sig-select), var(--wl-532), var(--sig-warn),
    var(--wl-1064) var(--pn-lock-fill), transparent var(--pn-lock-fill));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
}
.lg-ring.is-filling .lg-fill { animation: dock-lock-fill var(--pn-lock-ms, 1600ms) linear forwards; }
/* completion burst — a soft pulse, independent of the ring's inline transform */
.lg-ring::after {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--sig-warn) 55%, transparent), transparent 72%);
  opacity: 0;
  pointer-events: none;
}
.lock-gesture.is-done .lg-ring::after { animation: lg-burst 300ms ease-out; }
@keyframes lg-burst {
  0%   { opacity: 0.55; transform: scale(0.6); }
  100% { opacity: 0;    transform: scale(1.6); }
}

/* floating "Unlock all" target — a round glass button matching the dock size */
.lg-unlock {
  position: absolute;
  left: 0; top: 0;
  width: 32px; height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  color: var(--ink-2);
  background: var(--float-bg);
  border: 1px solid var(--line-1);
  box-shadow: var(--float-shadow), var(--float-edge);
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  opacity: 0;
  transform: translate(-50%, calc(-50% + 12px)) scale(0.9);   /* enters from below + smaller */
  transition: opacity 200ms ease-out,
              transform 240ms cubic-bezier(0.22, 1, 0.36, 1),
              color 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
  will-change: transform, opacity;
}
.lg-unlock svg { width: 16px; height: 16px; }
.lock-gesture.is-armed .lg-unlock { opacity: 0.6; transform: translate(-50%, -50%) scale(1); }
.lock-gesture.is-armed.is-unlock .lg-unlock {                 /* target is active (ring is on it) */
  opacity: 1;
  transform: translate(-50%, -50%) scale(1.08);
  color: var(--sig-warn);
  border-color: color-mix(in srgb, var(--sig-warn) 45%, var(--line-1));
  box-shadow: var(--float-shadow), 0 0 0 3px color-mix(in srgb, var(--sig-warn) 22%, transparent);
}

/* context caption — reads what completing will do (Lock all / Unlock all) */
.lg-cap {
  position: absolute;
  left: 0; top: 0;
  padding: 2px 9px;
  border-radius: 999px;
  font: 600 10px/1.4 var(--font-mono, ui-monospace, monospace);
  letter-spacing: 0.04em;
  white-space: nowrap;
  color: var(--ink-1);
  background: var(--float-bg);
  border: 1px solid var(--line-1);
  box-shadow: var(--float-shadow), var(--float-edge);
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  opacity: 0;
  transform: translate(-50%, calc(-50% + 10px));
  transition: opacity 200ms ease-out 40ms,
              transform 240ms cubic-bezier(0.22, 1, 0.36, 1) 40ms;
}
.lock-gesture.is-armed .lg-cap { opacity: 1; transform: translate(-50%, -50%); }

/* No motion → freeze the slides/glide; ring appears full, targets snap in (§7 reduced-motion). */
@media (prefers-reduced-motion: reduce) {
  .lg-ring { transition: opacity 120ms linear; }
  .lg-ring.is-filling .lg-fill { animation: none; --pn-lock-fill: 360deg; }
  .lock-gesture.is-done .lg-ring::after { animation: none; }
  .lock-gesture.is-armed .lg-unlock,
  .lock-gesture.is-armed.is-unlock .lg-unlock { transform: translate(-50%, -50%); transition: opacity 120ms linear; }
  .lock-gesture.is-armed .lg-cap { transform: translate(-50%, -50%); transition: opacity 120ms linear; }
}

/* ── Measure ruler label (融合 ③) — 玻璃 HUD 读数，浮在尺线中点上方 ─── */
.measure-label {
  position: absolute;
  z-index: 150;                  /* 在 css2d chips(100) 之上、floating panels(1000) 之下 */
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  font: 600 11px/1.4 var(--font-mono, ui-monospace, monospace);
  font-variant-numeric: tabular-nums;   /* 等宽数字，跟随时不抖 */
  letter-spacing: 0.02em;
  color: var(--ink-1);
  background: var(--float-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--float-radius);
  box-shadow: var(--float-shadow), var(--float-edge);
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  white-space: nowrap;
  user-select: none;
  pointer-events: none;
  transform: translate(-50%, calc(-50% - 16px));   /* 浮在中点上方，不压尺线 */
}
/* 琥珀点 —— 与 3D 尺线同色（--measure-accent），把读数和标尺视觉绑定 */
.measure-label::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--measure-accent);
  flex: 0 0 auto;
}

/* ── DRO (Digital Read-Out) — 两点/垂直测距读数，画布右上角 ──────────────
   Measure (M) / Vertical (V) 两工具共用。DESIGN.md 对齐（2026-07-02）：
     · 玻璃皮肤全走 token（--float-bg / --glass-border / --float-shadow +
       --float-edge），随主题翻（旧版硬编 rgba(7,9,11) 暗底 + 琥珀边，暗黑
       模式不跟手、亮色下是块黑砖）。
     · 单色（P2）：读数用 --ink-1，不再 42px 琥珀数字；琥珀只留一枚 live 圆点
       （--measure-accent）把读数与 3D 琥珀尺线绑定，同 .measure-label 手法。
     · 只留关键信息 + 紧凑：mode / live · 读数 · 一行上下文提示；删掉
       From / Cursor(x,y,z) / Snap 三行密网格。
   顶栏避让（U5）：top 落在 topbar + 右侧 tab strip 之下，绝不被顶栏盖住。
   z 在 chips/2D 刻度同层(150)、参数浮窗(1000) 之下；pointer-events:none 不挡 orbit。 */
.dro-panel {
  position: absolute;
  top: calc(var(--topbar-h) + var(--tabstrip-h) + 12px);
  right: 16px;
  z-index: 150;
  min-width: 156px;
  max-width: 260px;
  padding: 8px 12px 9px;
  background: var(--float-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--float-radius);
  box-shadow: var(--float-shadow), var(--float-edge);
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  font: 400 12px/1.4 var(--font-mono, ui-monospace, monospace);
  color: var(--ink-2);
  user-select: none;
  pointer-events: none;
}
.dro-panel[hidden] { display: none; }
.dro-panel .dro-tape {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 5px;
}
.dro-panel .dro-live {
  color: var(--ink-3);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.dro-panel .dro-live::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--measure-accent);   /* 琥珀 = 与 3D 尺线同色的 live 绑定点 */
  animation: dro-pulse 1.4s ease-in-out infinite;
}
@keyframes dro-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}
.dro-panel .dro-value-row {
  display: flex;
  align-items: baseline;
  gap: 5px;
  line-height: 1;
}
.dro-panel .dro-value {
  font-size: 28px;                     /* --text-2xl，紧凑（旧 42px 过大） */
  font-weight: 500;
  color: var(--ink-1);                 /* 单色（P2） */
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
}
.dro-panel .dro-unit {
  font-size: 13px;
  color: var(--ink-3);
  font-weight: 400;
}
.dro-panel .dro-hint {
  margin-top: 6px;
  font-size: 10px;
  color: var(--ink-3);
  white-space: nowrap;
}

/* ── Optical Path panel — 两点光程读数（P 工具），画布右上角 ─────────────
   DESIGN.md 对齐（2026-07-02）：旧版整块 inline 硬编暗底(rgba(24,24,27))+ 青字，
   不随主题翻、不入 token 系统。改走与 DRO 同一玻璃皮肤（token 化、主题感知、
   顶栏避让），只留关键信息（ΔOPL + 飞行时间 + 关系），删 GD 拆分 / 波长 / 交叉
   等细节行。青色仅一枚 header 圆点（--sig-select）把读数绑到 3D 青色光程管。
   与 DRO 同槽位（右上角），两工具互斥不会同现。 */
.optical-path-panel {
  position: absolute;
  top: calc(var(--topbar-h) + var(--tabstrip-h) + 12px);
  right: 16px;
  z-index: 150;
  width: 236px;
  padding: 9px 11px 10px;
  background: var(--float-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--float-radius);
  box-shadow: var(--float-shadow), var(--float-edge);
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  font: 400 12px/1.45 var(--font-mono, ui-monospace, monospace);
  color: var(--ink-2);
  user-select: none;
  pointer-events: none;
}
.optical-path-panel[hidden] { display: none; }
.optical-path-panel .opl-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 7px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.optical-path-panel .opl-dot {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--sig-select);       /* 青 = 与 3D 光程高亮管同色的绑定点 */
}
.optical-path-panel .opl-title { color: var(--ink-2); }
.optical-path-panel .opl-key { margin-left: auto; font-weight: 400; color: var(--ink-4); }
.optical-path-panel .opl-msg { color: var(--ink-3); line-height: 1.45; }
.optical-path-panel .opl-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 2px 0;
}
.optical-path-panel .opl-row .k { color: var(--ink-3); }
.optical-path-panel .opl-row .v {
  margin-left: auto;
  text-align: right;
  color: var(--ink-1);
  font-variant-numeric: tabular-nums;
  word-break: break-word;
}
.optical-path-panel .opl-row.is-primary .v { font-size: 14px; font-weight: 600; }
.optical-path-panel .opl-rel {
  margin-top: 5px;
  padding-top: 5px;
  border-top: 1px solid var(--line-1);
  font-size: 10px;
  color: var(--ink-3);
}

/* ── 点击记录簿（2026-08-04）：每条 = 色点 + P{id} + 距源光程 + 距源延时 ── */
.optical-path-panel .opl-cols {
  display: flex;
  gap: 6px;
  margin-bottom: 2px;
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
}
.optical-path-panel .opl-cols .c-dist { margin-left: auto; }
.optical-path-panel .opl-cols .c-delay { min-width: 64px; text-align: right; }
.optical-path-panel .opl-rec {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 2px 0;
}
.optical-path-panel .opl-rec-dot {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  align-self: center;
}
.optical-path-panel .opl-rec-id { color: var(--ink-3); min-width: 20px; }
.optical-path-panel .opl-rec-dist {
  margin-left: auto;
  color: var(--ink-1);
  font-variant-numeric: tabular-nums;
}
.optical-path-panel .opl-rec-delay {
  min-width: 64px;
  text-align: right;
  color: var(--ink-1);
  font-variant-numeric: tabular-nums;
}
.optical-path-panel .opl-rec.is-off .opl-rec-off { margin-left: auto; color: var(--ink-4); }
.optical-path-panel .opl-delta {
  margin-top: 5px;
  padding-top: 3px;
  border-top: 1px solid var(--line-1);
}
.optical-path-panel .opl-delta .opl-rel { border-top: 0; padding-top: 0; margin-top: 2px; }
.optical-path-panel .opl-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 7px;
}
.optical-path-panel .opl-note {
  font-size: 9px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-4);
}
/* Clear = 面板内唯一可点物：面板 pointer-events:none，仅按钮 auto（不挡角落 orbit）。
   静止透明 + hover 才填充（chrome 按钮无底座约定）。 */
.optical-path-panel .opl-clear {
  pointer-events: auto;
  margin-left: auto;
  padding: 3px 9px;
  font: 500 10px/1 var(--font-mono, ui-monospace, monospace);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  background: transparent;
  border: 1px solid var(--line-1);
  border-radius: 6px;
  cursor: pointer;
}
.optical-path-panel .opl-clear:hover {
  background: var(--surface-3);
  color: var(--ink-2);
  border-color: var(--line-2);
}

/* ════ 2D 立面光高刻度尺 + 波长色基准线 + 板边标注 + 探针 + 读数面板
   （DESIGN_INTERACTION_LAYER.md §4 · user 2026-06-15 重做 / 二轮调整）════
   仅 2D 立面模式显示（elevation-gauge.js 控 display）。光高 = 面包板顶面（世界 y=0）→ 光轴
   的垂直距离。① 左缘毫米刻度（0…200mm，两端渐隐 mask，left 钉到可视矩形左缘，不钻进 Library，
   刻度上不挂数值窗）；② 每束光水平基准线按波长上色、仅横跨面包板宽度（无文字）；③ 板边外侧的
   垂直光高标注（从 y=0 到光束，无文字，不侵占板内）；④ 强调色(cyan)探针 = 紧邻刻度的细把手 +
   水平游标；⑤ 右上读数面板把所有数值集中、字更大。除探针把手外 pointer-events:none，绝不挡
   orbit/pan/点选。定位逐帧由正交相机投影设定（left/width/top/height/right 全在 JS）。 */
.elev-gauge {
  position: absolute;
  inset: 0;
  z-index: 150;                  /* css2d chips(100) 之上、floating panels(1000) 之下 */
  pointer-events: none;
  font: 600 10px/1 var(--font-mono, ui-monospace, monospace);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  user-select: none;
}
.elev-ruler {                    /* 左缘刻度列（left 由 JS 设为可视矩形左缘）*/
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 52px;
  z-index: 1;
  /* 两端渐隐：刻度跑满视高，但顶/底各 ~7% 淡出，不硬切（user 2026-06-15）。mask 同时
     作用于刻度、标签与暗黑模式 scrim。 */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 7%, #000 90%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 7%, #000 90%, transparent 100%);
}
.elev-tick {                     /* 每 10mm 一短刻度（top 由 JS 逐帧投影设定）*/
  position: absolute;
  left: 10px;
  width: 7px;
  height: 0;
  border-top: 1px solid var(--ink-4);
  transform: translateY(-50%);
}
.elev-tick.is-major { width: 13px; border-top-color: var(--ink-2); }  /* 0/50/100 主刻度更长 */
.elev-tick-label {
  position: absolute;
  left: 17px; top: 50%;
  transform: translateY(-50%);
  color: var(--ink-2);
  white-space: nowrap;
}

/* ② 水平基准线：按波长上色（border-top-color 由 JS inline 设），仅横跨面包板屏幕宽度
   （left/width/top 由 JS）。无文字 —— 数值进读数面板 ⑤。drop-shadow 给在繁忙画布上成形。 */
.elev-datum {
  position: absolute;
  height: 0;
  border-top: 1.5px dashed currentColor;
  transform: translateY(-50%);
  z-index: 1;
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.35));
}

/* ③ 垂直光高标注：钉在面包板屏幕边缘外侧（left/top/height 由 JS）。纯视觉「从板边量光高」标记，
   两端短帽对齐 y=0 与光束高，无文字（数值进面板）。颜色（line/cap）按波长 inline 设。 */
.elev-oh {
  position: absolute;
  width: 0;
  z-index: 2;
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.35));
}
.elev-oh-line {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 1.5px;
  border-radius: 1px;
}
.elev-oh-cap {
  position: absolute;
  left: -4px;
  width: 9px;
  height: 1.5px;
  border-radius: 1px;
}
.elev-oh-cap.is-top { top: 0;    transform: translateY(-50%); }
.elev-oh-cap.is-bot { bottom: 0; transform: translateY(50%); }

/* ④ 探针：强调色(cyan) 水平游标 + 紧邻刻度右侧的细把手（slider thumb，不再是带数值的宽 pill →
   不挡刻度）。把手 pointer-events:auto + ns-resize；拖动用 pointer capture（不冒泡给 canvas →
   不触发 OrbitControls pan）。读数进面板 ⑤。位置以世界 Y 存。 */
.elev-probe {
  position: absolute;
  left: 0; right: 0;
  height: 0;
  transform: translateY(-50%);
  z-index: 3;
}
.elev-probe-line {
  position: absolute;
  height: 0;
  border-top: 1.5px dashed var(--sig-select);
  transform: translateY(-50%);
  opacity: 0.85;
}
.elev-probe-thumb {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 20px; height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  font-size: 11px;
  line-height: 1;
  color: var(--sig-select);
  background: var(--float-bg);
  border: 1.5px solid var(--sig-select);
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  pointer-events: auto;
  cursor: ns-resize;
  touch-action: none;            /* 触屏拖动不滚动页面 */
}
.elev-probe-thumb:focus-visible { outline: 2px solid var(--sig-select); outline-offset: 2px; }
.elev-probe[data-dragging] .elev-probe-thumb { box-shadow: 0 0 0 3px color-mix(in srgb, var(--sig-select) 35%, transparent); }
.elev-probe[data-dragging] .elev-probe-line { opacity: 1; }

/* ⑤ 读数面板：右上空白区（top/right 由 JS 按四边遮挡定位）。所有数值集中一处、字更大
   （user 2026-06-15：数值窗别挤刻度 / 字大一些）。每束光一行（色点对应基准线）+ 探针行实时。 */
.elev-readout {
  position: absolute;
  z-index: 4;
  /* 宽度按内容自适应（最长器件名决定）—— max-content 让 panel 收缩到最长行；
     min-width 兜住空态/短名；max-width 兜住极端长名不溢出可视区（仍可悬停看全 title）。
     user 2026-06-15：面板按器件名长度自动缩放。 */
  width: max-content;
  min-width: 132px;
  max-width: min(380px, 40vw);
  padding: 9px 11px;
  border-radius: var(--border-radius-lg, 12px);
  color: var(--ink-1);
  background: var(--float-bg);
  border: 1px solid var(--line-1);
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.16);
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  font: 500 12px/1.35 var(--font-mono, ui-monospace, monospace);
  font-variant-numeric: tabular-nums;
}
.elev-readout-title {
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 7px;
}
.elev-readout-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 3px 0;
}
.elev-readout-dot {
  flex: 0 0 auto;
  width: 10px; height: 10px;
  border-radius: 999px;
  background: var(--ink-3);
}
.elev-readout-dot.is-none { background: transparent; border: 1px dashed var(--ink-4); }
.elev-readout-row.is-probe .elev-readout-dot { background: var(--sig-select); }
.elev-readout-name {
  flex: 1 1 auto;
  min-width: 0;                  /* 允许行内省略号生效 */
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.elev-readout-val {
  flex: 0 0 auto;
  margin-left: auto;
  padding-left: 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-1);
}

/* ⑥ 字母编号牌：画布上每激光一枚（.elev-badge 绝对定位）+ 面板行首一枚（.elev-tag 行内）。
   玻璃底 + 波长色边框/字（color 由 JS inline 设波长色，border 取 currentColor）。 */
.elev-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  box-sizing: border-box;
  min-width: 17px;
  height: 17px;
  padding: 0 3px;
  border-radius: 5px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  background: var(--float-bg);
  border: 1.5px solid currentColor;
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
}
.elev-badge {                    /* 画布字母牌：挂在板边垂直光高线（.elev-oh）正下方 = 板面 y=0 端 */
  position: absolute;
  top: 100%;                     /* dim 容器底端 = 板面（surfaceY）*/
  left: 0;                       /* dim 主线 x */
  z-index: 3;
  transform: translate(-50%, 9px);   /* 水平居中于线、下移让出底端短帽 */
  pointer-events: none;
  filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.4));
}
.elev-readout-row.is-empty .elev-readout-name,
.elev-readout-row.is-empty .elev-readout-val { color: var(--ink-3); }
.elev-readout-sep {
  height: 1px;
  background: var(--line-1);
  margin: 6px 0;
  opacity: 0.7;
}

/* 暗黑模式 2D 立面尺可读性增强（user 2026-06-15）：① ruler scrim 托刻度/字；② 次/主刻度提权；
   ③ 波长线/标注本就有色，加深色描影使其在任意画布内容（含亮 bloom）上都成形。 */
[data-theme="dark"] .elev-ruler {
  background: linear-gradient(90deg,
    rgba(14, 14, 16, 0.72) 0%,
    rgba(14, 14, 16, 0.36) 62%,
    rgba(14, 14, 16, 0) 100%);
}
[data-theme="dark"] .elev-tick { border-top-color: var(--ink-3); }
[data-theme="dark"] .elev-tick.is-major { border-top-color: var(--ink-1); }
[data-theme="dark"] .elev-datum,
[data-theme="dark"] .elev-oh { filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.85)); }

/* ════ 3D 台面比例尺（scale-bar.js）════
   世界锚定的 SVG 尺身 + 端刻度 + 玻璃数值标，每帧按两端世界点投影重定位 ——
   随相机 orbit 旋转、随 dolly 等比缩放，越档自动换单位。仅 3D 透视态显示
   （2D 立面交给 elev-gauge）。单色 hairline（K1/K3），pointer-events:none。 */
.scalebar {
  position: absolute;
  inset: 0;
  z-index: 130;                  /* balloon(140) 之下、css2d chips(100) 之上 */
  pointer-events: none;
  user-select: none;
}
.scalebar-svg {
  position: absolute;
  inset: 0;
  overflow: visible;
}
.scalebar-svg .sb-bar {
  stroke: var(--ink-2);
  stroke-width: 1.5;
  stroke-linecap: round;
}
.scalebar-svg .sb-tick {
  stroke: var(--ink-2);
  stroke-width: 1.5;
  stroke-linecap: round;
}
.scalebar-label {
  position: absolute;
  transform: translate(-50%, -50%);
  padding: 1px 7px;
  border-radius: 999px;
  font: 600 10px/1 var(--font-mono, ui-monospace, monospace);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--ink-1);
  background: var(--float-bg);
  border: 1px solid var(--line-1);
  backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
  -webkit-backdrop-filter: blur(var(--float-blur)) saturate(var(--float-sat));
}

/* ── 气泡件号牌（CAD借鉴③）— DOM 圆牌，每帧投影定位在器件上方 ─── */
/* ── Overhead window stack（器件上方浮窗的统一承载层；DESIGN.md §8.4.B / §14）──
   overhead-stack.js 每个器件一个容器、每帧投影到屏幕一次。子窗「积木式」竖向堆叠：
   column-reverse 使 slot 0（读数 chip）落在最底贴器件，⚙ 行动药丸居中，件号气泡在顶。
   gap = 4px（DESIGN §5.1 基础单位）。容器 pointer-events:none，可交互子窗（chip / 药丸）
   各自开回 auto。z-index 140 = §8.4.A「Canvas 内浮标」带（css2d 100 之上、measure 150 之下）。*/
.overhead-stack {
  position: absolute;
  z-index: 140;
  display: flex;
  flex-direction: column-reverse;    /* order 小者在底（贴器件），大者在顶 */
  align-items: stretch;              /* 窗体等宽（user 2026-06-15「长度要一致」）= 撑到最宽窗 */
  gap: 4px;
  pointer-events: none;              /* 容器不挡画布；交互子窗各自 pointer-events:auto */
  transform: translate(-50%, -100%); /* 底边中心钉在投影锚点，向上长 = 积木堆叠 */
}

/* 玻璃窗体（读数 chip + ⚙ 行动药丸）共用皮肤(见 .overhead-chip)，被 stretch 撑等宽时
   内容居中；件号气泡是 CAD 数字徽章(圆)，退出 stretch、保持原圆居中堆顶。 */
.overhead-stack > .balloon-badge { align-self: center; }

.balloon-badge {
  /* 定位/层级/锚点交给 .overhead-stack 容器（BALLOON 槽，堆叠最顶）。本规则只管皮肤。*/
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font: 600 11px/1 var(--font-mono, ui-monospace, monospace);
  color: var(--surface);
  background: var(--ink-1);
  border: 1.5px solid var(--surface);   /* 白环 = CAD balloon 既视感 */
  border-radius: 999px;
  box-shadow: var(--float-shadow);
  pointer-events: none;
  user-select: none;
}

/* ── Inspector readout row (.ins-aoi — 现仅 #ins-beam-y 光高读数行使用；
   旧 #ins-aoi AOI 读数行已于 v1.11.01 并入 #ctl-aoi 控件，类名保留沿用) ── */
.ins-aoi {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 8px;
  padding: 6px 10px;
  border: 1px solid var(--line-1);
  border-radius: 5px;
  background: var(--surface-2);
}
.ins-aoi[hidden] { display: none; }
.ins-aoi-key {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--ink-3);
}
.ins-aoi-val {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-1);
  font-variant-numeric: tabular-nums;
}
.ins-aoi-note {
  font-size: 11px;
  color: var(--ink-3);
  margin-left: auto;
  text-align: right;
}

/* ── Swap menu (Inspector, DESIGN_INTERACTION_LAYER.md §1.3) ────────────
   In-flow (not absolute) so the panel's overflow:hidden never clips it —
   it expands at the top of the inspector body, pushing content down. */
.ins-swap-menu {
  margin: 0 0 10px;
  padding: 4px;
  background: var(--surface-2);
  border: 1px solid var(--line-1);
  border-radius: 6px;
  max-height: 220px;
  overflow-y: auto;
}
.ins-swap-menu[hidden] { display: none; }
.ins-swap-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  min-height: 32px;       /* K6 */
  padding: 6px 8px;
  border: none;
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  text-align: left;
  transition: background-color 120ms ease;
}
.ins-swap-item:hover { background: var(--overlay-1); }
.ins-swap-item:disabled,
.ins-swap-item[aria-disabled="true"] {
  opacity: 0.42;
  cursor: not-allowed;
}
.ins-swap-item:disabled:hover,
.ins-swap-item[aria-disabled="true"]:hover { background: transparent; }
.ins-swap-item-sku {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-1);
}
.ins-swap-item-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-3);
  white-space: nowrap;
}
/* Swap 菜单分组标题（Recommended / Same type —— 约束推荐置顶，§13） */
.ins-swap-group {
  padding: 4px 8px 3px;
  font-family: var(--font-mono);
  font-size: 11px;               /* §4.7 R6 — 阶下限 11（Inspector swap 菜单组头） */
  letter-spacing: 0.08em;        /* §4.7 tracking：大写 0.08em */
  text-transform: uppercase;
  color: var(--ink-3);
  border-bottom: 1px solid var(--line-1);
  margin-bottom: 2px;
}
.ins-swap-group + .ins-swap-group,
.ins-swap-item + .ins-swap-group { margin-top: 6px; }

/* A-4 验收 2：拖镜入潜望镜镜站的 Lower/Upper 选择浮层（library-drag.js）。
   行复用 .ins-swap-item / -sku / -meta（与 Inspector swap 菜单同视觉）。 */
.station-chooser {
  position: fixed;
  z-index: 1000;
  min-width: 240px;
  padding: 6px;
  background: var(--surface-2);
  border: 1px solid var(--line-1);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
}
.station-chooser-title {
  padding: 4px 8px 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-3);
  border-bottom: 1px solid var(--line-1);
  margin-bottom: 4px;
  white-space: nowrap;
}
.station-chooser-hint {
  transform: translateX(-50%);
  padding: 8px 14px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-1);
  white-space: nowrap;
}

kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 16px;
  padding: 0 5px;
  background: var(--paper-soft);
  border: 1px solid var(--line-2);
  border-bottom-width: 2px;
  border-radius: 3px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 500;
  color: var(--ink);
  line-height: 1;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

