/* Hover widget — Needle Inspector dark theme + Midscene-style info hierarchy.
 *
 * Color contract:
 *   --bg          near-black panel background (#1a1a1a)
 *   --bg-2        slightly raised surface for cards / hover (#222224)
 *   --bg-3        deeper inset (input, code blocks) (#141414)
 *   --line        subtle separator (#2a2a2c)
 *   --text        primary foreground (#e5e7eb)
 *   --text-mute   secondary labels (#9ca3af)
 *   --text-dim    tertiary / placeholder (#6b7280)
 *   --accent      mint/lime accent — running, current, success (#7CFFA8)
 *   --accent-dim  same hue at lower opacity for backgrounds
 *   --error       error red, used sparingly (#f87171)
 *   --warn        amber warning, for soft-sandbox + recording (#fbbf24)
 *   --link        cool blue for links / "click me" affordances (#7dd3fc)
 *
 * The launcher button and the user's page are NOT touched by the dark
 * scheme — only the panel itself. Per design decision in the v0.2.x UI
 * refresh discussion.
 */

:host, * { box-sizing: border-box; }

/* Catch-all hidden rule.
 *
 * Browsers' UA stylesheet applies `display: none` to `[hidden]`, but that
 * has the lowest possible specificity — any author rule with an explicit
 * display (e.g. `.fix-btn { display: inline-flex }`) wins, leaving
 * `el.hidden = true` visually no-op until the author rule also covers
 * `[hidden]`. Several existing rules add `.foo[hidden] { display: none }`
 * one-by-one (.cost, .modebar, .save-menu, .iconbtn.assertbtn, …) —
 * fragile and easy to forget. This generic rule covers every widget
 * element (including plugin-contributed DOM via host.applyDomMutations),
 * with `!important` to defeat any author display declaration. */
[hidden] { display: none !important; }

/* ───────────────────────── scrollbars ─────────────────────────
 *
 * The OS default scrollbar (especially on macOS when "Show scroll bars"
 * is set to "Always") is a bright gray slab on a white track — visually
 * jarring against the dark mint palette. We theme every scrollable region
 * inside the widget so the chrome blends in.
 *
 * Two declarations because Firefox and WebKit have different APIs:
 *   - WebKit/Blink: `::-webkit-scrollbar*` pseudo-elements
 *   - Firefox: `scrollbar-width` (thin/auto) + `scrollbar-color`
 *
 * Applied broadly within the shadow root via `*` so we don't have to
 * remember to add it on every new scrollable container.
 */
:host *::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
:host *::-webkit-scrollbar-track {
  background: transparent;
}
:host *::-webkit-scrollbar-thumb {
  background: #2a2a2c;
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
  transition: background 0.15s ease;
}
:host *::-webkit-scrollbar-thumb:hover {
  background: #3a3a3c;
  background-clip: padding-box;
}
:host *::-webkit-scrollbar-thumb:active {
  background: rgba(124, 255, 168, 0.45);
  background-clip: padding-box;
}
:host *::-webkit-scrollbar-corner {
  background: transparent;
}
/* Firefox */
:host * {
  scrollbar-width: thin;
  scrollbar-color: #2a2a2c transparent;
}

/* ───────────────────────── focus-visible (a11y) ─────────────────────────
 *
 * Every interactive element strips the OS default outline (which collides
 * with our dark theme) but adds a mint ring on keyboard focus so Tab
 * navigation remains visible. `:focus-visible` (not `:focus`) means the
 * ring only appears for keyboard nav, never on mouse click — matches
 * platform conventions.
 */
:host button:focus-visible,
:host textarea:focus-visible,
:host input:focus-visible,
:host [tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  /* Override any element-specific `outline: none` left over from older
   * polish passes. */
  outline-style: solid;
}
/* Inputs / textareas already get a border+shadow treatment on :focus
 * (see .modal-field input:focus / textarea:focus). We don't want a
 * doubled-up outline for those, so suppress the generic ring when the
 * element-specific focus style is in play. */
:host textarea:focus-visible,
:host .modal-field input:focus-visible {
  outline: none;
}

:host {
  --bg: #1a1a1a;
  --bg-2: #222224;
  --bg-3: #141414;
  --line: #2a2a2c;
  --text: #e5e7eb;
  --text-mute: #9ca3af;
  --text-dim: #6b7280;
  --accent: #7CFFA8;
  --accent-dim: rgba(124, 255, 168, 0.16);
  --error: #f87171;
  --error-dim: rgba(248, 113, 113, 0.18);
  --warn: #fbbf24;
  --link: #7dd3fc;
}

/* When a plugin mode is engaged, re-point --accent at the mode's colour
 * (--mode-accent, set by the plugin; falls back to security orange) on the
 * SHADOW HOST. Defining it here rather than on .panel means it cascades to
 * every element in the shadow tree — including the floating tooltip and the
 * launcher, which are siblings of .panel and wouldn't see a .panel-scoped
 * override. Default mode (currentMode === null) never gets .mode-engaged, so
 * it stays mint. */
:host(.mode-engaged) {
  /* The single knob. The widget JS sets this inline from the active mode's
   * `accent` (plugin-api HoverPluginMode.accent); when no plugin sets one this
   * literal applies = security orange. Everything below is derived from it via
   * color-mix so a plugin retints the whole engaged chrome with one colour. */
  --mode-accent: #fb923c;
  --accent: var(--mode-accent);
  --accent-dim: color-mix(in srgb, var(--mode-accent) 16%, transparent);
  --accent-hover: color-mix(in srgb, var(--mode-accent) 86%, white);
  --accent-ink: color-mix(in srgb, var(--mode-accent) 20%, black);
  /* soft light tint for engaged mode-bar text (the old #fed7aa for orange). */
  --mode-tint: color-mix(in srgb, var(--mode-accent) 38%, white);
}

/* ───────────────────────── launcher (unchanged colour) ───────────────────────── */

/* Launcher: dark ball matching the panel theme. Same colour vocabulary as
 * the rest of the widget (panel bg + mint accent), so the floating button
 * feels like it belongs to Hover rather than to the host page's chrome.
 * Slightly smaller (44px) so it pulls focus less when the user isn't
 * actively using Hover. */
.launcher {
  position: fixed; bottom: 24px; right: 24px;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(124, 255, 168, 0.5);
  cursor: pointer;
  background: #1a1a1a;
  color: #7CFFA8;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
  display: flex; align-items: center; justify-content: center;
  font-size: 18px;
  padding: 0;
  font-family: -apple-system, system-ui, "Segoe UI", sans-serif;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
  z-index: 2147483647;
}
.launcher:hover {
  transform: scale(1.06);
  border-color: rgba(124, 255, 168, 0.9);
  box-shadow: 0 4px 18px rgba(124, 255, 168, 0.28), 0 4px 16px rgba(0, 0, 0, 0.4);
}
.launcher.open {
  /* Subtle inversion so the user sees the click registered; no rotation
   * because the icon now reads top-down (rotation tilts it into nonsense). */
  background: var(--accent-dim, rgba(124, 255, 168, 0.16));
  border-color: var(--accent, #7CFFA8);
}

/* CDP state variants — keep the established colour code (gray = wrong
 * window, amber = no CDP) so users who learned the v1 palette aren't
 * disoriented, but tone everything down to match the new dark scheme. */
.launcher.cdp-wrong-window {
  border-color: rgba(156, 163, 175, 0.55);
  color: #9ca3af;
}
.launcher.cdp-wrong-window:hover {
  border-color: rgba(156, 163, 175, 0.9);
  box-shadow: 0 4px 18px rgba(156, 163, 175, 0.2), 0 4px 16px rgba(0, 0, 0, 0.4);
}
.launcher.cdp-no-cdp {
  border-color: rgba(251, 191, 36, 0.6);
  color: #fbbf24;
}
.launcher.cdp-no-cdp:hover {
  border-color: rgba(251, 191, 36, 0.95);
  box-shadow: 0 4px 18px rgba(251, 191, 36, 0.25), 0 4px 16px rgba(0, 0, 0, 0.4);
}
.launcher.cdp-launching {
  animation: hover-launching-pulse 1.4s ease-in-out infinite;
}
@keyframes hover-launching-pulse {
  0%, 100% { box-shadow: 0 4px 14px rgba(124, 255, 168, 0.25), 0 4px 16px rgba(0, 0, 0, 0.4); }
  50%      { box-shadow: 0 4px 22px rgba(124, 255, 168, 0.6),  0 4px 16px rgba(0, 0, 0, 0.4); }
}

/* The icon glyph inside the launcher button. We swap the ✨ HTML entity to
 * an inline SVG (defined in template.html) so it doesn't get rendered with
 * the system's colour emoji font, which would defeat the dark/mint look. */
.launcher svg { width: 20px; height: 20px; display: block; pointer-events: none; }

/* ───────────────────────── panel chrome (dark) ───────────────────────── */

.panel {
  position: fixed; bottom: 88px; right: 24px;
  width: 460px; height: 640px;
  max-height: calc(100vh - 120px);
  background: var(--bg);
  border: 1px solid var(--line);
  /* 16px corner radius matches the Save-as menu / modals; reads as a
   * deliberate device chrome rather than "generic box". */
  border-radius: 16px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.55);
  display: flex; flex-direction: column; overflow: hidden;
  font-family: -apple-system, system-ui, "Segoe UI", sans-serif;
  color: var(--text);
  opacity: 0; pointer-events: none; transform: translateY(8px);
  transition: opacity 0.15s ease, transform 0.15s ease;
  z-index: 2147483647;
  font-size: 13px;
}
.panel.open { opacity: 1; pointer-events: auto; transform: translateY(0); }

header {
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 6px;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.02), transparent);
}
/* Status pill — same hook the JS toggles between connected / disconnected / running */
/* Connection status — a single coloured dot + a short word, no pill/chip.
 * Cleaner than the old background tag; the dot carries the colour signal so
 * the text can stay a quiet secondary grey. The dot is a ::before so no extra
 * DOM. Colour follows the state class. */
.status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
  flex-shrink: 0;
  letter-spacing: 0.01em;
  text-transform: lowercase;
  color: var(--text-mute);
  margin-left: auto;
}
.status::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--text-dim);
}
.status.connected::before  { background: var(--accent); }
.status.disconnected::before { background: var(--text-dim); }
.status.running::before    { background: var(--accent); }

/* Header live-cost chip. Starts opacity 0; the `.visible` class added by
 * JS triggers a fade-in. `[hidden]` still removes from layout when the
 * fade-out completes (set by JS after a 220ms delay). */
.cost {
  font-size: 11px; padding: 2px 7px;
  border-radius: 999px;
  background: var(--bg-3);
  color: var(--text-mute);
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  white-space: nowrap;
  flex-shrink: 0;
  opacity: 0;
  transform: scale(0.92);
  transition: opacity 0.18s ease, transform 0.18s ease, background 0.2s ease, color 0.2s ease;
}
.cost[hidden] { display: none; }
.cost.visible {
  opacity: 1;
  transform: scale(1);
}
.cost.live {
  background: var(--accent-dim);
  color: var(--accent);
}

/* ───── icon buttons in header ─────
 * Square, 24px. Icons inside are inline SVGs that inherit currentColor
 * (NOT emoji), so the colour palette stays single-source and the buttons
 * read correctly on the dark panel. */
.iconbtn {
  border: 1px solid var(--line);
  background: var(--bg-2);
  border-radius: 6px;
  width: 24px; height: 24px;
  font-size: 12px; line-height: 1;
  color: var(--text-mute);
  cursor: pointer; padding: 0;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.iconbtn svg { width: 14px; height: 14px; display: block; pointer-events: none; }
/* Native `title` tooltips only fire on hover targets that *have* a title.
 * When a child element (SVG, span, etc.) is the actual hover target and it
 * has no title of its own, the tooltip silently doesn't appear. Forcing
 * children to be pointer-event transparent guarantees the button itself is
 * always the hover target, so its title attribute resolves. Same pattern is
 * applied to .agentbtn, .launcher, .save-trigger below. */
.iconbtn > * { pointer-events: none; }
.iconbtn:not(:disabled):hover {
  background: var(--bg-3);
  color: var(--text);
  border-color: #3a3a3c;
}
.iconbtn:disabled { opacity: 0.4; cursor: not-allowed; }
.iconbtn.active {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
}
.iconbtn.starbtn:not(:disabled):hover {
  color: #ffd700;
  border-color: rgba(255, 215, 0, 0.45);
  background: rgba(255, 215, 0, 0.08);
}
.iconbtn.starbtn:not(:disabled):hover svg { fill: rgba(255, 215, 0, 0.18); }
.iconbtn.assertbtn[hidden] { display: none; }
.iconbtn.assertbtn {
  width: auto; padding: 0 8px;
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
  gap: 4px; font-size: 11px; font-weight: 600;
}
.iconbtn.assertbtn:not(:disabled):hover { background: rgba(124, 255, 168, 0.24); }
/* Glyph + count share the same font-size so they sit on a common baseline.
 * (Was 12 vs 11 — visibly misaligned when the count is 1-digit.) */
.iconbtn.assertbtn .assert-glyph { font-size: 11px; }
.iconbtn.assertbtn .assert-count { font-size: 11px; font-variant-numeric: tabular-nums; }

/* ───── agent picker pill ───── */
.agentbtn {
  height: 22px;
  padding: 0 6px 0 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-2);
  color: var(--text);
  font-family: inherit;
  font-size: 11px;
  line-height: 1;
  font-weight: 500;
  display: inline-flex; align-items: center; gap: 4px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.agentbtn:not(:disabled):hover { background: var(--bg-3); border-color: #3a3a3c; }
.agentbtn:disabled { opacity: 0.5; cursor: not-allowed; }
.agentbtn.active {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
}
.agentbtn .agent-label {
  font-variant-numeric: tabular-nums;
  /* Header is dense — never wrap, otherwise the whole pill grows tall and
   * shoves the trailing icons + status pill into a second row. */
  white-space: nowrap;
}
.agentbtn .agent-warn[hidden] { display: none; }
.agentbtn .agent-warn { color: var(--warn); font-size: 11px; }
.agentbtn .agent-caret {
  color: var(--text-dim);
  font-size: 9px;
  transition: color 0.12s ease;
}
/* When the rest of the button text/border brightens on hover or focus,
 * the caret follows so the whole pill brightens as a unit. */
.agentbtn:not(:disabled):hover .agent-caret,
.agentbtn:focus-visible .agent-caret {
  color: var(--text);
}
/* Same hover-target rule as .iconbtn — the agent-warn child has its own
 * `title` which would otherwise shadow the parent's, AND the SVG/text bits
 * would intercept hover and prevent the parent title from firing. */
.agentbtn > * { pointer-events: none; }

/* ───────────────────────── skills overlay (kept light by exception) ───────────────────────── */

.skills-overlay {
  position: absolute; top: 40px; left: 0; right: 0; bottom: 0;
  background: var(--bg);
  display: none;
  flex-direction: column;
  z-index: 5;
}
.skills-overlay.open { display: flex; }
.skills-overlay .skills-header {
  padding: 10px 14px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-mute);
}
.skills-overlay .skills-header .count { font-weight: 600; color: var(--text); }
.skills-overlay .skills-list-items { flex: 1; overflow-y: auto; padding: 8px; }
.skills-overlay .skills-empty {
  padding: 20px 16px; text-align: center;
  color: var(--text-dim); font-size: 12px; line-height: 1.5;
}

.skill-row {
  padding: 10px 12px; border-radius: 6px;
  cursor: pointer; margin-bottom: 4px;
  border: 1px solid transparent;
}
.skill-row:hover { background: var(--bg-2); border-color: var(--line); }
.skill-row .skill-name { font-weight: 600; color: var(--text); font-size: 13px; }
.skill-row .skill-desc {
  font-size: 12px; color: var(--text-mute); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.skill-row .skill-slug {
  font-size: 11px; color: var(--text-dim); margin-top: 2px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}

/* ─── Saved-sessions tabbed header + panes (v0.11) ───────────────── */

.sessions-overlay .sessions-header {
  padding: 8px 12px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 12px;
  font-size: 12px; color: var(--text-mute);
}
.sessions-overlay .sessions-title {
  font-weight: 600; color: var(--text); margin-right: 4px;
}
.sessions-overlay .sessions-tabs {
  display: flex; gap: 2px;
}
.sessions-overlay .sessions-tab {
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--text-mute);
  font: inherit; font-size: 12px;
  padding: 4px 10px;
  cursor: pointer;
  border-radius: 4px 4px 0 0;
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}
.sessions-overlay .sessions-tab:hover {
  color: var(--text);
  background: var(--bg-2);
}
.sessions-overlay .sessions-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.sessions-overlay .sessions-tab-count {
  display: inline-block;
  min-width: 18px; padding: 0 5px;
  font-size: 10px; line-height: 16px;
  background: var(--bg-3);
  border-radius: 8px;
  margin-left: 4px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.sessions-overlay .sessions-tab.active .sessions-tab-count {
  background: var(--accent-dim);
  color: var(--accent);
}
.sessions-overlay .sessions-pane {
  flex: 1;
  overflow-y: auto;
  display: flex; flex-direction: column;
}
.sessions-overlay .sessions-pane[hidden] { display: none; }
.sessions-overlay .sessions-pane-hint {
  margin: 0; padding: 8px 14px;
  font-size: 11px; color: var(--text-dim);
  line-height: 1.5;
  background: var(--bg-3);
  border-bottom: 1px solid var(--line);
}
.sessions-overlay .sessions-pane-hint code,
.sessions-overlay .sessions-pane-hint strong,
.sessions-overlay .sessions-pane-hint em {
  color: var(--text-mute);
}
.sessions-overlay .sessions-pane-hint code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 10px;
  background: var(--bg);
  padding: 1px 4px;
  border-radius: 3px;
}
.sessions-overlay .skills-list-items,
.sessions-overlay .specs-list-items {
  flex: 1; overflow-y: auto; padding: 8px;
}

/* Spec-row variant — same shape as skill-row but with a right-edge
 * Re-record button. */
.skill-row.spec-row {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto auto auto;
  column-gap: 10px;
  align-items: start;
}
.skill-row.spec-row .skill-name { grid-column: 1; grid-row: 1; }
.skill-row.spec-row .skill-desc { grid-column: 1; grid-row: 2; }
.skill-row.spec-row .skill-slug { grid-column: 1; grid-row: 3; }
.skill-row.spec-row .spec-rerecord-btn {
  grid-column: 2; grid-row: 1 / 4;
  align-self: center;
  appearance: none;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 5px;
  color: var(--text-mute);
  font: inherit; font-size: 11px;
  padding: 5px 9px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.skill-row.spec-row .spec-rerecord-btn:not(:disabled):hover {
  background: var(--accent-dim);
  color: var(--accent);
  border-color: var(--accent);
}
.skill-row.spec-row .spec-rerecord-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ───────────────────────── agents overlay ───────────────────────── */

.agents-overlay {
  position: absolute; top: 40px; left: 0; right: 0; bottom: 0;
  background: var(--bg);
  display: none;
  flex-direction: column;
  z-index: 5;
}
.agents-overlay.open { display: flex; }
.agents-overlay .agents-header {
  padding: 10px 14px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-mute);
}
.agents-overlay .agents-header .count { font-weight: 600; color: var(--text); }
.agents-overlay .agents-list-items { flex: 1; overflow-y: auto; padding: 8px; }
.agent-row {
  padding: 10px 12px; border-radius: 6px;
  margin-bottom: 4px;
  border: 1px solid transparent;
  cursor: pointer;
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--bg-2);
}
.agent-row:hover { background: var(--bg-3); border-color: var(--line); }
.agent-row.current {
  background: var(--accent-dim);
  border-color: var(--accent);
  cursor: default;
}
.agent-row.uninstalled { cursor: default; opacity: 0.55; background: transparent; }
.agent-row.uninstalled:hover { background: transparent; border-color: transparent; }
.agent-row .agent-main { flex: 1; min-width: 0; }
.agent-row .agent-rowlabel {
  font-weight: 600; color: var(--text); font-size: 13px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.agent-row .agent-rowtag {
  font-size: 12px; color: var(--text-mute); margin-top: 2px;
  line-height: 1.4;
}
.agent-row .agent-hint {
  font-size: 11px; color: var(--text); margin-top: 6px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: var(--bg-3); padding: 4px 6px; border-radius: 4px;
  word-break: break-all;
}
.agent-row .agent-badge {
  font-size: 10px; font-weight: 600; letter-spacing: 0.02em;
  padding: 2px 6px; border-radius: 999px;
  text-transform: uppercase;
}
.agent-row .agent-badge.installed { background: var(--accent-dim); color: var(--accent); }
.agent-row .agent-badge.missing   { background: var(--bg-3); color: var(--text-dim); }
.agent-row .agent-badge.soft      { background: rgba(251, 191, 36, 0.16); color: var(--warn); }
.agent-row .agent-badge.hard      { background: rgba(125, 211, 252, 0.16); color: var(--link); }
.agent-row .agent-rowcheck {
  width: 16px; flex-shrink: 0; color: var(--accent); font-weight: 700; text-align: center;
}

/* ───────────────────────── mode bar (above panel header) ───────────────────────── */

/* Sits as the topmost row of .panel, full-width, ~28px tall. Hidden when
 * no plugins are loaded. Tints orange-red when a non-default mode is
 * active so the user can never forget they're in "altered" mode —
 * matches the panel border + launcher ring treatment below. */
.modebar {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 28px;
  padding: 0 12px;
  border: none;
  border-bottom: 1px solid var(--line);
  border-radius: 16px 16px 0 0;
  background: var(--bg-2);
  color: var(--text-mute);
  font: 500 11px/1 inherit;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.modebar[hidden] { display: none; }
.modebar:hover { background: var(--bg-3); color: var(--text); }
.modebar:focus-visible { outline: none; background: var(--bg-3); color: var(--text); }
.modebar > * { pointer-events: none; }
.modebar .modebar-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--text-dim);
  flex-shrink: 0;
}
.modebar .modebar-label {
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.modebar .modebar-caret {
  color: var(--text-dim);
  font-size: 9px;
  flex-shrink: 0;
}
/* margin-left: auto pushes the hint to the right edge while keeping the
 * primary identity group (dot · label · caret) left-aligned. min-width:0
 * + overflow rules let the hint truncate gracefully if it's long. */
.modebar .modebar-hint {
  margin-left: auto;
  color: var(--text-mute);
  font-size: 11.5px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.modebar.engaged .modebar-hint { font-weight: 600; }

/* Engaged state — non-default mode is active. A persistent toolbar tint in
 * the mode's accent (security orange by default; pentest red) so it reads as
 * "you're in altered state, be aware" — pattern borrowed from Burp's
 * "intercept on" banner. All shades derive from --mode-accent so the bar
 * retints with the mode. */
.modebar.engaged {
  background: linear-gradient(180deg, color-mix(in srgb, var(--mode-accent) 18%, transparent), color-mix(in srgb, var(--mode-accent) 8%, transparent));
  border-bottom-color: color-mix(in srgb, var(--mode-accent) 55%, transparent);
  color: var(--mode-tint);
}
.modebar.engaged .modebar-dot {
  background: var(--mode-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--mode-accent) 18%, transparent);
}
.modebar.engaged .modebar-label { color: var(--mode-tint); }
.modebar.engaged .modebar-hint  { color: color-mix(in srgb, var(--mode-tint) 85%, transparent); }
.modebar.engaged .modebar-caret { color: color-mix(in srgb, var(--mode-tint) 70%, transparent); }
.modebar.engaged:hover { background: linear-gradient(180deg, color-mix(in srgb, var(--mode-accent) 26%, transparent), color-mix(in srgb, var(--mode-accent) 14%, transparent)); }

/* Panel + launcher mirror the engaged tint so the user spots it from
 * across the page. We hook the state via a class on .panel set by the
 * widget JS — that's the same element that holds the existing
 * .open class, so no extra layout. */
/* Engaged panel chrome. The --accent retint that drives the tinting lives on
 * :host(.mode-engaged) (top of file) so it reaches the tooltip + launcher
 * too; here we only set the panel's own border/shadow. */
.panel.mode-engaged {
  border-color: color-mix(in srgb, var(--mode-accent) 70%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--mode-accent) 35%, transparent), 0 20px 60px rgba(0, 0, 0, 0.55);
}

/* When the modebar is present, every overlay that anchored its top at
 * 40px (header height) needs another 28px clearance so it doesn't peek
 * out underneath the bar. Listing them by class beats touching each
 * overlay block individually. */
.panel.has-modebar .skills-overlay,
.panel.has-modebar .agents-overlay,
.panel.has-modebar .modes-overlay,
.panel.has-modebar .plugin-overlay,
.panel.has-modebar .settings-overlay,
.panel.has-modebar .cdp-overlay,
.panel.has-modebar .fix-popover {
  top: 68px;
}
.launcher.mode-engaged {
  border-color: color-mix(in srgb, var(--mode-accent) 70%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--mode-accent) 18%, transparent), 0 6px 22px rgba(0, 0, 0, 0.5);
  color: var(--mode-accent);
}

.modes-overlay {
  position: absolute; top: 40px; left: 0; right: 0; bottom: 0;
  background: var(--bg);
  display: none;
  flex-direction: column;
  z-index: 5;
}
.modes-overlay.open { display: flex; }
.modes-overlay .modes-header {
  padding: 10px 14px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-mute);
}
.modes-overlay .modes-header .count { font-weight: 600; color: var(--text); }
.modes-overlay .modes-list-items { flex: 1; overflow-y: auto; padding: 8px; }
.mode-row {
  padding: 10px 12px; border-radius: 6px;
  margin-bottom: 4px;
  border: 1px solid transparent;
  cursor: pointer;
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--bg-2);
}
.mode-row:hover { background: var(--bg-3); border-color: var(--line); }
.mode-row.current {
  background: var(--accent-dim);
  border-color: var(--accent);
  cursor: default;
}
.mode-row .mode-main { flex: 1; min-width: 0; }
.mode-row .mode-rowlabel {
  font-weight: 600; color: var(--text); font-size: 13px;
}
.mode-row .mode-rowtag {
  font-size: 12px; color: var(--text-mute); margin-top: 2px;
  line-height: 1.4;
}
.mode-row .mode-pluginname {
  font-size: 11px; color: var(--text-dim); margin-top: 4px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.mode-row .mode-rowcheck {
  width: 16px; flex-shrink: 0; color: var(--accent); font-weight: 700; text-align: center;
}

/* ───────────────────────── plugin overlays (shared shell) ─────────────────────────
 * Generic overlay shell used by plugin-contributed overlays (network panel,
 * future plugin UIs). Plugins layout their inner rows via plugin-supplied CSS
 * scoped to [data-plugin-active="<name>"] — see widget host's namespaceCss. */
.plugin-overlay {
  position: absolute; top: 40px; left: 0; right: 0; bottom: 0;
  background: var(--bg);
  display: none;
  flex-direction: column;
  z-index: 5;
}
.plugin-overlay.open { display: flex; }
.plugin-overlay .plugin-overlay-header {
  padding: 10px 14px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-mute);
}
.plugin-overlay .plugin-overlay-body { flex: 1; overflow-y: auto; padding: 4px; }

/* ───────────────────────── CDP overlay (dark) ───────────────────────── */

.cdp-overlay {
  position: absolute; top: 40px; left: 0; right: 0; bottom: 0;
  background: var(--bg);
  display: none;
  align-items: center; justify-content: center;
  z-index: 6;
  padding: 24px;
}
.cdp-overlay.open { display: flex; }
.cdp-card {
  max-width: 320px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.cdp-icon { font-size: 36px; line-height: 1; }
.cdp-title { font-weight: 600; font-size: 14px; color: var(--text); }
.cdp-body  { font-size: 12px; color: var(--text-mute); line-height: 1.5; }
.cdp-action {
  margin-top: 6px;
  padding: 8px 14px; border-radius: 8px; border: none; cursor: pointer;
  font-size: 13px; font-weight: 600;
  background: var(--accent); color: #0a3a18;
  font-family: inherit;
}
.cdp-action:hover { filter: brightness(0.95); }
.cdp-action:disabled { opacity: 0.55; cursor: default; }
.cdp-action[hidden] { display: none; }
.cdp-overlay.cdp-launching .cdp-icon {
  animation: hover-cdp-spin 1.4s linear infinite;
}
@keyframes hover-cdp-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* ───────────────────────── body / conversation ───────────────────────── */

.body {
  flex: 1; padding: 14px 14px 18px;
  overflow-y: auto;
  font-size: 12.5px; color: var(--text); line-height: 1.45;
  background: var(--bg);
}

/* Fade-in animation for newly-appended conversation items. Because
 * renderAll() rebuilds the body on every state change, we can't just
 * animate `.body > *` (everything would re-animate on every tick).
 * Instead JS marks brand-new elements with `data-fresh="1"` for the
 * first paint after they appeared, and clears it after the animation.
 * That way only truly new items fade in. */
.body > [data-fresh="1"] {
  animation: msg-enter 0.22s ease-out both;
}
@keyframes msg-enter {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .body > [data-fresh="1"] { animation: none; }
}
.body:empty::before {
  content: "Describe what you want to verify, e.g. \"test the login flow\".";
  display: block;
  padding: 32px 16px;
  color: var(--text-mute);
  font-style: normal;
  font-size: 12.5px;
  line-height: 1.55;
  text-align: center;
  max-width: 280px;
  margin: 8px auto 0;
}

/* ───── user prompt — pill, right-aligned ─────
 * Larger padding + radius + a more pronounced gap from surrounding step
 * rows so the user's words feel like their own utterance, not just
 * another row in the timeline. Matches the ChatGPT Image 2 reference. */
.msg.user {
  display: flex; justify-content: flex-end;
  margin: 4px 2px 12px;
}
.msg.user + .group,
.msg.user + .msg.system,
.msg.user + .msg.ai { margin-top: 4px; }
.msg.user .bubble {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 9px 14px;
  border-radius: 14px 14px 4px 14px;
  font-size: 13px;
  line-height: 1.45;
  max-width: 86%;
  word-wrap: break-word;
}

/* ───── ai bubble (standalone — only for terminal summaries) ───── */
.msg.ai {
  margin: 4px 4px 6px;
}
.msg.ai .bubble {
  background: transparent;
  color: var(--text);
  padding: 4px 10px 4px 14px;
  border-left: 2px solid var(--accent);
  font-size: 12.5px;
  display: inline-block;
  max-width: 100%;
  word-wrap: break-word;
  white-space: pre-wrap;
  line-height: 1.5;
}
.msg.ai .bubble strong { font-weight: 600; color: var(--text); }
.msg.ai .bubble em { font-style: italic; color: var(--text-mute); }
.msg.ai .bubble code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 11px; background: var(--bg-3);
  padding: 1px 4px; border-radius: 3px;
  color: var(--accent);
}

.msg.system {
  font-size: 11px;
  color: var(--text-dim);
  padding: 2px 8px;
  margin: 4px 0;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}

/* ───────────────────────── grouped step row (Midscene-style) ─────────────────────────
 * One row per natural-language intent. Click the chevron to expand the
 * underlying tool calls. The "running" step gets the accent ring + spinner;
 * the closed group inherits status colours (ok / error).
 */

.group {
  margin: 0;
  border-radius: 10px;
  border: 1px solid transparent;
  /* Step rows default to a visible elevated surface so they read as
   * "actionable rows" at a glance. Matches the look of the ChatGPT
   * Image 2 reference where every step is clearly a card. */
  background: var(--bg-2);
  transition: background 0.12s, border-color 0.12s;
  position: relative;       /* anchor for the running-step left bar */
  overflow: hidden;
}
.group + .group { margin-top: 8px; }
.group:hover { background: #2a2a2c; }

/* Running step: left mint bar + a faint moving shimmer to telegraph
 * "this is the active row". The shimmer is a slow horizontal gradient
 * sweep at low opacity — visible enough to be noticed, subtle enough
 * not to feel like a UI bug. */
.group.running {
  background: var(--bg-2);
  border-color: transparent;
  box-shadow: none;
  padding-left: 4px;
  position: relative;
  overflow: hidden;
}
.group.running::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--accent);
  z-index: 1;
}
.group.running::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(124, 255, 168, 0.04) 30%,
    rgba(124, 255, 168, 0.10) 50%,
    rgba(124, 255, 168, 0.04) 70%,
    transparent 100%
  );
  background-size: 200% 100%;
  animation: gr-shimmer 2.2s ease-in-out infinite;
}
@keyframes gr-shimmer {
  0%   { background-position: 200% 50%; }
  100% { background-position: -100% 50%; }
}
/* Children need explicit z-index so the shimmer overlay sits BEHIND
 * them rather than over the text. */
.group.running .group-row,
.group.running .group-tools { position: relative; z-index: 2; }

.group.error {
  border-color: rgba(248, 113, 113, 0.35);
}
.group.error::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--error);
}

/* Cancelled (user pressed Stop). Visually neutral — no left bar, no
 * red/green tint — so the user sees "this was your choice, not a
 * failure". Border + icon use --text-mute. */
.group.cancelled {
  border-color: rgba(255, 255, 255, 0.10);
}

.group-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  cursor: pointer;
  user-select: none;
}
.group-row .gr-chevron {
  width: 12px; flex-shrink: 0;
  color: var(--text-dim); font-size: 10px;
  /* Animate both rotation AND colour so the open transition reads as one
   * coherent motion instead of "rotate + colour pop". */
  transition: transform 0.12s ease, color 0.12s ease;
  text-align: center;
}
.group.open .group-row .gr-chevron { transform: rotate(90deg); color: var(--text-mute); }

.group-row .gr-icon {
  /* Slightly larger hit-target than just a glyph, with a faint tinted
   * background so the status reads at a glance, like a status pill. */
  width: 16px; height: 16px;
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; line-height: 1;
  border-radius: 50%;
  font-weight: 700;
}
.group.ok        .gr-icon { color: var(--accent);   background: rgba(124, 255, 168, 0.12); }
.group.error     .gr-icon { color: var(--error);    background: rgba(248, 113, 113, 0.14); }
.group.cancelled .gr-icon { color: var(--text-mute); background: rgba(255, 255, 255, 0.06); }
.group.running   .gr-icon { color: var(--accent);   background: transparent; }

.group-row .gr-title {
  flex: 1; min-width: 0;
  font-size: 13px; color: var(--text);
  font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.group.running   .gr-title { color: var(--accent); font-weight: 500; }
.group.error     .gr-title { color: var(--error); }
.group.cancelled .gr-title { color: var(--text-mute); }
/* Spinner: open-top ring rotating at 0.9s/turn. Conveys "actively doing
 * something" — paired with a faint mint shimmer on the row background
 * (see .group.running below) to anchor activity. */
.group-row .gr-icon.gr-ring {
  width: 12px; height: 12px;
  border: 1.5px solid var(--accent);
  border-top-color: transparent;
  border-radius: 50%;
  background: transparent;
  animation: gr-spin 0.9s linear infinite;
  font-size: 0;
}
@keyframes gr-spin {
  to { transform: rotate(360deg); }
}

.group-row .gr-meta {
  flex-shrink: 0;
  font-size: 10.5px; color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.group-row .gr-meta .gr-cost { color: var(--accent); }
.group.error .gr-meta .gr-cost { color: var(--error); }

/* tools list — hidden by default, shown when group has .open */
.group-tools {
  display: none;
  padding: 0 10px 8px 34px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 11px;
  color: var(--text-mute);
}
.group.open .group-tools { display: block; }
.group-tool {
  display: flex; gap: 6px;
  padding: 2px 0;
  /* No word-break on the row itself — that would chop tool *names* like
   * "browser_take_screenshot" into "Sk\nil\nl" because their underscores
   * are valid break points. We want a tight column: the name stays whole
   * and the args (which are arbitrary JSON, often long) get the break. */
  align-items: flex-start;
}
.group-tool .gt-dot {
  color: var(--text-dim);
  flex-shrink: 0;
}
.group-tool .gt-name {
  color: var(--link);
  flex-shrink: 0;
  white-space: nowrap;
}
.group-tool.error .gt-name { color: var(--error); }
.group-tool .gt-args {
  color: var(--text-dim);
  min-width: 0;       /* allow flex child to actually shrink */
  word-break: break-all;
  overflow-wrap: anywhere;
}

/* ───────────────────────── report card ─────────────────────────
 *
 * Rendered AFTER the last group of a session when the agent emitted a
 * verification narrative. Holds:
 *   - status header (✓ Result / ✗ Failed) + turns + cost meta
 *   - plain-text body (the agent's report, markdown-stripped)
 *   - Save-as dropdown — primary action after a successful run
 *
 * Visually adjacent to but distinct from group rows: more weight, mint
 * left border on success, red on error. Sits between the groups and the
 * (optional) findings card.
 */
.report {
  margin: 16px 0 4px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  /* Intentionally NO overflow:hidden — would clip the Save-as menu that
   * pops upward out of .report-actions. Round corners stay clean because
   * .report-header carries its own top corner radius and .report-body /
   * .report-actions sit flush inside the inner padding. */
}
.report.ok        { border-left: 3px solid var(--accent); }
.report.error     { border-left: 3px solid var(--error); }
.report.cancelled { border-left: 3px solid var(--text-mute); }

.report-header {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  border-radius: 10px 10px 0 0;
}
.report.ok        .report-header { background: rgba(124, 255, 168, 0.06); }
.report.error     .report-header { background: rgba(248, 113, 113, 0.06); }
.report.cancelled .report-header { background: rgba(255, 255, 255, 0.03); }

.report-header-icon {
  width: 18px; height: 18px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
  flex-shrink: 0;
}
.report.ok        .report-header-icon { background: rgba(124, 255, 168, 0.18); color: var(--accent); }
.report.error     .report-header-icon { background: rgba(248, 113, 113, 0.18); color: var(--error); }
.report.cancelled .report-header-icon { background: rgba(255, 255, 255, 0.10); color: var(--text-mute); }

.report-header-label {
  font-weight: 600; font-size: 12px;
  color: var(--text);
  letter-spacing: 0.02em;
}
.report-header-meta {
  margin-left: auto;
  font-size: 10.5px; color: var(--text-mute);
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}

.report-body {
  padding: 10px 14px 12px;
  font-size: 12.5px;
  color: var(--text);
  line-height: 1.55;
  /* Preserve agent's newlines but allow long lines to wrap. */
  white-space: pre-wrap;
  word-wrap: break-word;
  /* Cap height so a very long report doesn't blow up the panel — user
   * can scroll inside if it overflows. */
  max-height: 260px;
  overflow-y: auto;
}
.report-actions {
  padding: 8px 12px 10px;
  display: flex; gap: 8px;
}

/* ───────────────────────── findings card ─────────────────────────
 *
 * Rendered AFTER a done group when the agent's final summary contains a
 * `## Findings` block. Lives outside the conversation timeline visually —
 * different background, prominent header, severity-coloured rows — so the
 * user's eye is drawn to "what bugs did we find?" rather than to the
 * step-by-step process.
 */
.findings {
  margin: 16px 0 4px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--warn);
  border-radius: 10px;
  overflow: hidden;
}
.findings-header {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  background: rgba(251, 191, 36, 0.06);
  border-bottom: 1px solid var(--line);
}
.findings-header-icon {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: rgba(251, 191, 36, 0.18);
  color: var(--warn);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
  flex-shrink: 0;
}
.findings-header-label {
  font-weight: 600; font-size: 12px;
  color: var(--text);
  letter-spacing: 0.02em;
}
.findings-header-count {
  margin-left: auto;
  font-size: 10.5px; color: var(--text-mute);
  font-variant-numeric: tabular-nums;
  background: var(--bg-3);
  border-radius: 999px;
  padding: 2px 7px;
  min-width: 18px; text-align: center;
}
.findings-list { padding: 6px; }
.finding-row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 7px 8px;
  border-radius: 6px;
  margin-bottom: 2px;
  font-size: 12px; line-height: 1.5;
  color: var(--text);
}
.finding-row:hover { background: var(--bg-3); }
.finding-severity {
  flex-shrink: 0;
  font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em;
  padding: 2px 7px;
  border-radius: 4px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  white-space: nowrap;
}
.finding-text {
  flex: 1; min-width: 0;
  word-wrap: break-word;
}
.finding-text strong { color: var(--text); font-weight: 600; }
.finding-text em { color: var(--text-mute); font-style: italic; }
.finding-text code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 11px;
  background: var(--bg-3);
  padding: 1px 4px; border-radius: 3px;
  color: var(--accent);
}

.finding-bug .finding-severity { background: rgba(248, 113, 113, 0.16); color: var(--error); }
.finding-minor .finding-severity { background: rgba(251, 191, 36, 0.16); color: var(--warn); }
.finding-info .finding-severity { background: var(--bg-3); color: var(--text-mute); }

/* ───────────────────────── Save-as dropdown (re-themed dark) ───────────────────────── */

.save-wrap { position: relative; display: inline-block; }
.save-trigger {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 8px 5px 10px;
  border-radius: 6px;
  border: 1px solid var(--accent);
  background: var(--accent-dim);
  color: var(--accent);
  font-size: 11px; font-weight: 600;
  cursor: pointer; font-family: inherit;
  transition: background 0.12s, transform 0.06s, color 0.12s, border-color 0.12s;
}
.save-trigger .trigger-icon,
.save-trigger .caret {
  display: inline-flex; align-items: center;
}
.save-trigger .trigger-icon svg { width: 12px; height: 12px; display: block; }
.save-trigger .caret svg { width: 10px; height: 10px; display: block; }
.save-trigger:hover:not(:disabled) { background: rgba(124, 255, 168, 0.24); }
.save-trigger:active:not(:disabled) { transform: translateY(1px); }
.save-trigger:disabled { opacity: 0.55; cursor: not-allowed; }
.save-trigger[aria-expanded="true"] .caret {
  transform: rotate(180deg);
}
.save-trigger .caret { transition: transform 0.15s ease; }
.save-trigger > * { pointer-events: none; }

.save-menu {
  position: absolute;
  bottom: calc(100% + 6px); left: 0;
  min-width: 280px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
  padding: 4px;
  z-index: 15;
  display: flex; flex-direction: column;
  animation: save-menu-in 0.14s cubic-bezier(0.16, 1, 0.3, 1);
}
.save-menu[hidden] { display: none; }
@keyframes save-menu-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.save-menu-item {
  display: flex; align-items: flex-start; gap: 10px;
  width: 100%;
  padding: 8px 10px;
  background: transparent;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  color: var(--text);
  transition: background 0.1s;
}
.save-menu-item:hover { background: var(--bg-3); }
.save-menu-item .i-icon {
  flex-shrink: 0;
  width: 18px; height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  margin-top: 1px;
}
.save-menu-item .i-icon svg { width: 16px; height: 16px; display: block; }
.save-menu-item.item-spec .i-icon  { color: var(--accent); }
.save-menu-item.item-case .i-icon  { color: var(--warn); }
.save-menu-item .i-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.save-menu-item .i-label { font-weight: 600; font-size: 12.5px; color: var(--text); }
.save-menu-item .i-sub {
  font-size: 10.5px; color: var(--text-dim);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  word-break: break-all;
}
.save-menu-item.item-spec .i-label  { color: var(--accent); }
.save-menu-item.item-case .i-label  { color: var(--warn); }

/* ───────────────────────── footer (input area) ───────────────────────── */

footer {
  border-top: 1px solid var(--line);
  padding: 10px;
  display: flex; flex-direction: column; gap: 8px;
  background: var(--bg);
}
textarea {
  width: 100%; resize: none;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 8px 10px;
  font-family: inherit; font-size: 12.5px;
  outline: none;
  background: var(--bg-3);
  color: var(--text);
}
textarea::placeholder { color: var(--text-dim); }
textarea:focus { border-color: var(--accent); }
textarea:disabled { background: var(--bg-2); color: var(--text-dim); cursor: not-allowed; }

.footer-actions {
  display: flex; align-items: center; gap: 8px;
}
.footer-actions .hint {
  flex: 1;
  font-size: 11px; color: var(--text-dim);
  text-align: right;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.send {
  /* margin-left: auto pushes Send to the flex container's far right.
   * Previously a flex:1 .hint span did this; that span was removed
   * in the v0.5 sub-toolbar work, so Send is now the right-pusher. */
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px 5px 12px;
  border-radius: 7px; border: 1px solid var(--accent);
  /* --accent-ink is the readable foreground on the accent fill: a near-black
   * tint of the accent hue. Default (mint) keeps the original deep green;
   * .panel.mode-engaged overrides it so the Send glyph stays legible on the
   * mode colour (e.g. dark-brown on orange). */
  background: var(--accent); color: var(--accent-ink, #0a3a18);
  font-size: 12px; font-weight: 700;
  cursor: pointer; font-family: inherit;
  transition: background 0.12s, transform 0.06s, color 0.12s;
}
.send:hover:not(:disabled) { background: var(--accent-hover, #5cf094); }
.send:disabled { background: var(--bg-2); color: var(--text-dim); border-color: var(--line); cursor: not-allowed; }
.send:active:not(:disabled) { transform: translateY(1px); }
.send.stop { background: var(--error); color: #2a0606; border-color: var(--error); }
.send.stop:hover:not(:disabled) { background: #fa9494; }
.send.stop:disabled { background: var(--bg-2); color: var(--text-dim); border-color: var(--line); cursor: not-allowed; }
.send .chord {
  font-size: 10px; opacity: 0.75;
  padding: 1px 5px;
  background: rgba(10, 58, 24, 0.22);
  border-radius: 4px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.send.stop .chord { display: none; }
.send > * { pointer-events: none; }

.record-btn {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 5px 9px;
  font-size: 11px;
  color: var(--text-mute);
  cursor: pointer;
  font-family: inherit;
  display: inline-flex; align-items: center; gap: 5px;
  /* Slightly longer transition so the flip into .recording reads as a
   * smooth state change instead of a flash. */
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.record-btn > * { pointer-events: none; }
.record-btn:not(:disabled):hover {
  color: var(--error);
  border-color: rgba(248, 113, 113, 0.5);
  background: rgba(248, 113, 113, 0.08);
}
.record-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.record-btn .rec-dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--error);
}
.record-btn.recording {
  background: rgba(248, 113, 113, 0.15);
  color: var(--error);
  border-color: rgba(248, 113, 113, 0.5);
  font-weight: 600;
}
.record-btn.recording .rec-dot { animation: rec-pulse 1.2s ease-in-out infinite; }
@keyframes rec-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.4; transform: scale(0.7); }
}

/*
 * Voice mode (push-to-talk). Round affordance sitting to the right of Send,
 * to read as an input-mode toggle ("speak instead of type") rather than
 * another text-side action button. Uses the mint accent on listening.
 */
.mic-btn {
  width: 32px; height: 32px;
  flex: 0 0 32px;
  border-radius: 50%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text-mute);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease, transform 0.12s ease, box-shadow 0.18s ease;
  user-select: none;
  -webkit-user-select: none;
  margin-left: 2px;
}
.mic-btn { position: relative; }
.mic-btn > * { pointer-events: none; }
.mic-btn .mic-glyph { width: 16px; height: 16px; }
/* Timer overlay — same slot as the icon, swapped via display rules below.
 * Tabular-nums keeps "9 → 10" from jumping width. */
.mic-btn .mic-timer {
  position: absolute; inset: 0;
  display: none;
  align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-family: inherit;
  line-height: 1;
}
.mic-btn.listening .mic-glyph { display: none; }
.mic-btn.listening .mic-timer { display: inline-flex; }
.mic-btn:not(:disabled):hover {
  color: var(--accent);
  border-color: rgba(124, 255, 168, 0.5);
  background: var(--accent-dim);
}
.mic-btn:not(:disabled):active { transform: scale(0.94); }
.mic-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.mic-btn.listening {
  background: var(--accent-dim);
  color: var(--accent);
  border-color: rgba(124, 255, 168, 0.6);
  /* Glow pulses to signal "still recording" — replaces the icon pulse
   * since the icon is hidden behind the timer while listening. */
  animation: mic-glow 1.3s ease-in-out infinite;
}
@keyframes mic-glow {
  0%, 100% { box-shadow: 0 0 0 2px rgba(124, 255, 168, 0.10); }
  50%      { box-shadow: 0 0 0 5px rgba(124, 255, 168, 0.22); }
}

/*
 * Settings overlay — mirrors .agents-overlay / .skills-overlay shape so the
 * three header panels feel consistent. One block of rows for now (just the
 * TTS toggle); future settings drop into .settings-list as more
 * .settings-row labels.
 */
.settings-overlay {
  position: absolute; top: 40px; left: 0; right: 0; bottom: 0;
  background: var(--bg);
  display: none;
  flex-direction: column;
  z-index: 5;
}
.settings-overlay.open { display: flex; }
.settings-overlay .settings-header {
  padding: 10px 14px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-mute);
}
.settings-list { flex: 1; overflow-y: auto; padding: 8px; }
.settings-row {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px;
  border-radius: 6px;
  border: 1px solid var(--line);
  margin-bottom: 6px;
  cursor: pointer;
  background: var(--bg-2);
}
.settings-row:hover { border-color: rgba(124, 255, 168, 0.35); }
.settings-row-label { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.settings-row-title { font-size: 13px; color: var(--text); font-weight: 500; }
.settings-row-hint { font-size: 11px; color: var(--text-mute); line-height: 1.4; }
.settings-row input[type="checkbox"] {
  margin-top: 2px;
  appearance: none;
  -webkit-appearance: none;
  width: 32px; height: 18px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 10px;
  position: relative;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease;
  flex: 0 0 auto;
}
.settings-row input[type="checkbox"]::before {
  content: '';
  position: absolute; top: 1px; left: 1px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--text-mute);
  transition: transform 0.18s ease, background 0.18s ease;
}
.settings-row input[type="checkbox"]:checked {
  background: var(--accent-dim);
  border-color: rgba(124, 255, 168, 0.5);
}
.settings-row input[type="checkbox"]:checked::before {
  transform: translateX(14px);
  background: var(--accent);
}

/* ───────────────────────── modal (dark) ───────────────────────── */

.modal {
  position: absolute; inset: 0;
  display: none; align-items: center; justify-content: center;
  z-index: 20;
}
.modal.open { display: flex; }
.modal-backdrop {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  animation: modal-fade-in 0.16s ease;
}
@keyframes modal-fade-in { from { opacity: 0; } to { opacity: 1; } }
.modal-card {
  position: relative;
  width: calc(100% - 28px);
  max-width: 360px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
  display: flex; flex-direction: column;
  overflow: hidden;
  animation: modal-card-in 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes modal-card-in {
  from { transform: translateY(10px) scale(0.96); opacity: 0; }
  to   { transform: translateY(0) scale(1); opacity: 1; }
}
.modal-head {
  display: flex; align-items: center; gap: 8px;
  padding: 14px 14px 4px;
}
.modal-title {
  flex: 1; font-weight: 600; font-size: 13.5px; color: var(--text);
}
.modal-close {
  border: none; background: transparent;
  font-size: 18px; line-height: 1; color: var(--text-dim);
  cursor: pointer; padding: 0;
  width: 24px; height: 24px; border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
}
.modal-close:hover { background: var(--bg-3); color: var(--text); }
.modal-body {
  padding: 8px 14px 4px;
  display: flex; flex-direction: column; gap: 12px;
  color: var(--text); font-size: 12.5px; line-height: 1.5;
}
.modal-field { display: flex; flex-direction: column; gap: 5px; }
.modal-field label {
  font-size: 10px; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: 0.04em;
  font-weight: 600;
}
.modal-field input {
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 8px 10px;
  font-size: 12.5px; color: var(--text);
  font-family: inherit;
  outline: none;
  transition: border-color 0.12s, box-shadow 0.12s;
  background: var(--bg-3);
}
.modal-field input::placeholder { color: var(--text-dim); }
.modal-field input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
.modal-field input.error {
  border-color: var(--error);
  box-shadow: 0 0 0 3px var(--error-dim);
  animation: modal-shake 0.22s;
}
@keyframes modal-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}
.modal-context {
  font-size: 11.5px; color: var(--text-mute);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px 8px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  word-break: break-all;
}
.modal-actions {
  padding: 12px 14px 14px;
  display: flex; gap: 8px; justify-content: flex-end;
}
.modal-actions button {
  font-size: 12px; font-weight: 600;
  padding: 6px 12px;
  border-radius: 6px;
  cursor: pointer;
  font-family: inherit;
  border: 1px solid transparent;
  transition: background 0.12s, border-color 0.12s, transform 0.06s;
}
.modal-actions button:active:not(:disabled) { transform: translateY(1px); }
.modal-actions .m-ghost {
  background: var(--bg-3); color: var(--text);
  border-color: var(--line);
}
.modal-actions .m-ghost:hover { background: var(--bg); border-color: #3a3a3c; }
.modal-actions .m-primary {
  background: var(--accent); color: #0a3a18;
}
.modal-actions .m-primary:hover { background: #5cf094; }
.modal-actions .m-danger {
  background: var(--error); color: #2a0606;
}
.modal-actions .m-danger:hover { background: #fa9494; }

/* ───────────────────────── custom tooltip ─────────────────────────
 * One floating bubble shared by every [data-tooltip] target. The script
 * positions it absolutely relative to the host (NOT relative to the panel)
 * so it can label the launcher as well as in-panel buttons.
 *
 * Why we don't use native `title=`: inside a Shadow DOM the system tooltip
 * still appears, but with the OS default delay (~500ms-1s) and light theme.
 * It clashes with the dark panel and feels laggy. This custom one shows in
 * ~120ms and matches the mint/dark palette.
 */
.hover-tip {
  position: fixed;
  z-index: 2147483647;
  background: #0e0e0e;
  color: var(--text);
  border: 1px solid var(--accent);
  border-radius: 5px;
  padding: 4px 8px;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 0.1s ease, transform 0.1s ease;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
  font-family: inherit;
  max-width: 280px;
}
.hover-tip.visible {
  opacity: 1;
  transform: translateY(0);
}
.hover-tip-text {
  display: inline-block;
  white-space: normal;
  line-height: 1.35;
}
/* Arrow — a small square rotated 45°, half buried under the bubble. The
 * script flips its `data-side` to position it on the right side or below.
 */
.hover-tip-arrow {
  position: absolute;
  width: 6px; height: 6px;
  background: #0e0e0e;
  border-right: 1px solid var(--accent);
  border-bottom: 1px solid var(--accent);
  transform: rotate(45deg);
}
.hover-tip[data-side="above"] .hover-tip-arrow {
  bottom: -4px; left: 50%; margin-left: -3px;
}
.hover-tip[data-side="below"] .hover-tip-arrow {
  top: -4px; left: 50%; margin-left: -3px;
  border-right: none; border-bottom: none;
  border-left: 1px solid var(--accent);
  border-top: 1px solid var(--accent);
}
.hover-tip[data-side="left"] .hover-tip-arrow {
  right: -4px; top: 50%; margin-top: -3px;
  border-right: 1px solid var(--accent); border-bottom: none;
  border-top: 1px solid var(--accent); border-left: none;
}
.hover-tip[data-side="right"] .hover-tip-arrow {
  left: -4px; top: 50%; margin-top: -3px;
  border-right: none; border-bottom: 1px solid var(--accent);
  border-top: none; border-left: 1px solid var(--accent);
}

/* ───────────────────────── picker overlay ─────────────────────────
 *
 * Three pieces, all gated on .picker-active being set on :host (script
 * toggles it when entering Fix mode or a Record assert sub-mode):
 *
 *   .picker-overlay   the per-element outline that follows the cursor
 *   .picker-badge     small chip on the overlay corner — names current mode
 *   .picker-tag       monospace tag-name label under the badge
 *   .picker-toast     post-action confirmation strip
 *
 * pointer-events:none everywhere — the overlay must never intercept the
 * click; user is clicking the real element under the cursor.
 */

:host(.picker-active) { cursor: crosshair !important; }

.picker-overlay {
  position: fixed;
  top: 0; left: 0; width: 0; height: 0;
  border: 2px solid var(--accent);
  border-radius: 2px;
  background: var(--accent-dim);
  pointer-events: none;
  z-index: 2147483646;
  display: none;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.4);
  transition: top 60ms linear, left 60ms linear, width 60ms linear, height 60ms linear;
}
:host(.picker-active) .picker-overlay.visible {
  display: block;
}
.picker-badge {
  position: absolute;
  top: -22px;
  right: -2px;
  background: var(--accent);
  color: #0e0e0e;
  font: 600 10px/1 ui-sans-serif, system-ui, sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 4px 7px;
  border-radius: 3px;
  white-space: nowrap;
}
.picker-tag {
  position: absolute;
  bottom: -20px;
  left: -2px;
  background: #0e0e0e;
  color: var(--accent);
  font: 500 10px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  padding: 4px 6px;
  border-radius: 3px;
  white-space: nowrap;
  border: 1px solid var(--accent);
}

.picker-toast {
  position: fixed;
  top: 56px;
  left: 50%;
  transform: translate(-50%, -8px);
  background: #0e0e0e;
  color: var(--text);
  font: 500 13px/1.3 ui-sans-serif, system-ui, sans-serif;
  padding: 10px 16px;
  border-radius: 8px;
  border: 1px solid var(--accent);
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 160ms ease, transform 160ms ease;
  z-index: 2147483647;
  box-shadow: 0 8px 24px rgba(0,0,0,0.55), 0 0 0 1px rgba(124,255,168,0.18);
  max-width: 80vw;
}
.picker-toast.visible {
  opacity: 1;
  transform: translate(-50%, 0);
}
.picker-toast.error {
  border-color: var(--error);
  box-shadow: 0 8px 24px rgba(0,0,0,0.55), 0 0 0 1px rgba(248,113,113,0.2);
}
.picker-toast-icon {
  font-size: 14px;
  line-height: 1;
}

/* ───────────────────────── Fix button + popover ─────────────────────────
 *
 * Fix button sits next to Record in the footer. Visual matches Record but
 * uses the mint accent (Hover's brand colour) instead of red, since Fix
 * is a "select-and-tell" action rather than a destructive record one.
 */
.fix-btn {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 5px 9px;
  font-size: 11px;
  color: var(--text-mute);
  cursor: pointer;
  font-family: inherit;
  display: inline-flex; align-items: center; gap: 5px;
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.fix-btn > * { pointer-events: none; }
.fix-btn:not(:disabled):hover {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-dim);
}
.fix-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.fix-btn .fix-icon {
  font-size: 13px;
  line-height: 1;
}
.fix-btn.active {
  background: var(--accent-dim);
  color: var(--accent);
  border-color: var(--accent);
  font-weight: 600;
}

/* Popover — covers the panel's .body when visible. Lives in shadow root,
 * inside .panel, after .body and footer. Absolute-positioned so it can sit
 * over .body without affecting layout when hidden.
 */
.fix-popover {
  position: absolute;
  top: 48px; /* below the header */
  left: 0;
  right: 0;
  bottom: 0;  /* extends to footer */
  background: var(--bg);
  display: none;
  flex-direction: column;
  padding: 14px;
  gap: 10px;
  z-index: 5;
}
.fix-popover.visible {
  display: flex;
}
.fix-popover-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.fix-popover-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
}
.fix-popover-cancel {
  background: transparent;
  border: 0;
  color: var(--text-mute);
  font-size: 18px;
  cursor: pointer;
  width: 24px;
  height: 24px;
  border-radius: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.fix-popover-cancel:hover {
  color: var(--text);
  background: var(--bg-2);
}
.fix-popover-target {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 12px;
  line-height: 1.4;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.fix-popover-el-tag {
  font: 500 12px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--accent);
}
.fix-popover-el-text {
  color: var(--text);
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fix-popover-el-text:empty { display: none; }
.fix-popover-el-src {
  font: 500 11px/1.3 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--text-mute);
  background: transparent;
  padding: 0;
}
.fix-popover-input {
  flex: 1;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 10px;
  color: var(--text);
  font: 400 13px/1.5 ui-sans-serif, system-ui, sans-serif;
  resize: none;
  min-height: 80px;
}
.fix-popover-input:focus {
  outline: none;
  border-color: var(--accent);
}
.fix-popover-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.fix-popover-hint {
  font-size: 10px;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 4px;
}
.fix-popover-hint kbd {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 1px 4px;
  font: 500 10px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--text-mute);
}
.fix-popover-copy {
  background: var(--accent);
  color: #0e0e0e;
  border: 0;
  border-radius: 6px;
  padding: 7px 14px;
  font: 600 12px/1 ui-sans-serif, system-ui, sans-serif;
  cursor: pointer;
  transition: filter 0.15s ease;
}
.fix-popover-copy:hover { filter: brightness(1.1); }

/* ───────────────────────── Record sub-toolbar ─────────────────────────
 *
 * Sits above .footer, only visible when host has .recording class set.
 * Segmented control with four modes; active mode is the assertion type
 * the next host-page click will produce (or 'action' for a normal step).
 */
.record-toolbar {
  display: none;
  flex-direction: column;
  gap: 6px;
  padding: 8px 14px;
  border-top: 1px solid var(--line);
  background: var(--bg-2);
  animation: rec-toolbar-in 0.18s ease;
}
:host(.recording) .record-toolbar {
  display: flex;
}
@keyframes rec-toolbar-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.record-toolbar-hint {
  font: 400 11px/1.4 ui-sans-serif, system-ui, sans-serif;
  color: var(--text-mute);
  padding: 2px 0;
}
.record-toolbar-hint[hidden] { display: none; }
/* Paused state (Fix popover open mid-recording). The popover usually
 * covers the sub-toolbar entirely, so this is mostly defensive — but
 * if the popover ever resizes or stays narrow, the dim treatment
 * makes it visually obvious that capture is suspended. */
:host(.record-paused) .record-toolbar {
  opacity: 0.4;
  pointer-events: none;
}
:host(.record-paused) .record-toolbar-label::after {
  content: ' (paused while Fix is open)';
  color: var(--text-dim);
  font-weight: 400;
}
.record-toolbar-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.record-toolbar-label {
  font: 500 11px/1 ui-sans-serif, system-ui, sans-serif;
  color: var(--text-mute);
  letter-spacing: 0.04em;
}
.record-toolbar-modes {
  display: inline-flex;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 2px;
  gap: 1px;
}
.rec-mode {
  background: transparent;
  border: 0;
  border-radius: 4px;
  padding: 4px 9px;
  font: 500 11px/1.2 ui-sans-serif, system-ui, sans-serif;
  color: var(--text-mute);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  transition: background 0.12s ease, color 0.12s ease;
}
.rec-mode > * { pointer-events: none; }
.rec-mode-icon {
  font-size: 10px;
  opacity: 0.7;
}
.rec-mode:hover:not(.active) {
  color: var(--text);
  background: rgba(255, 255, 255, 0.04);
}
.rec-mode.active {
  background: var(--bg);
  color: var(--accent);
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(0,0,0,0.3);
}
.rec-mode.active .rec-mode-icon { opacity: 1; }
/* Action mode is the "neutral" default — use white, not mint, so the
 * assertion modes stand out when one is active. */
.rec-mode[data-mode="action"].active {
  color: var(--text);
}
