:root {
  color-scheme: dark;
  --bg: #040e1f;
  --bg-elevated: #071327;
  --surface: #0b1728;
  --surface-2: #142238;
  --surface-3: #1f2937;
  --line: #25324a;
  --line-strong: #34435f;
  --ink: #f9fafb;
  --ink-dim: #b5bdca;
  --ink-faint: #7d899b;
  --accent: #6366f1;
  --accent-hover: #7477f5;
  --accent-ink: #ffffff;
  --secondary: #06b6d4;
  --violet: #8b5cf6;
  --user-bubble: #4f46e5;
  --user-ink: #ffffff;
  --warn: #f59e0b;
  --bad: #ef4444;
  --ok: #10b981;
  /* Per-engine accent, one variable per real engine, all drawn from the
   * palette above rather than one-off hex values — every surface that
   * colors an engine (message accent bar, agent dot, council columns)
   * reads from THESE, so they can never drift out of sync with each other
   * or with the rest of the theme again. Overridable per-viewer from
   * Manage > Appearance (see the --engine-*-custom indirection below). */
  --engine-codex: var(--engine-codex-custom, var(--ok));
  --engine-claude: var(--engine-claude-custom, var(--warn));
  --engine-zen: var(--engine-zen-custom, var(--secondary));
  --engine-local: var(--engine-local-custom, var(--accent));
  --engine-local-agent: var(--engine-local-agent-custom, var(--violet));
  --engine-mock: var(--engine-mock-custom, var(--ink-faint));
  --engine-device: var(--engine-device-custom, var(--violet));
  /* chatgpt-web / claude-web (2026-09-13): every other engine's default
   * reuses an existing palette token, but codex/claude/zen/local/local-agent
   * had already claimed the five distinct hues this palette has — these two
   * literal hex values are deliberately new colors, not one-off drift, so
   * the web-chat buckets stay visually distinct from their premium-tier
   * counterparts (claude vs claude-web especially). Still fully overridable
   * per-viewer via the same -custom indirection as every other engine. */
  --engine-chatgpt-web: var(--engine-chatgpt-web-custom, #74aa9c);
  --engine-claude-web: var(--engine-claude-web-custom, #d97757);
  --engine-grok: var(--engine-grok-custom, #e63946);
  --engine-openrouter: var(--engine-openrouter-custom, #8ec07c);
  --shadow: 0 18px 50px rgba(0, 0, 0, 0.34);
  --glow: 0 0 32px rgba(99, 102, 241, 0.2);
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 24px;
  font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif;
  background: var(--bg);
  color: var(--ink);
}

:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f4f7fb;
  --bg-elevated: #edf2f9;
  --surface: #ffffff;
  --surface-2: #eef2ff;
  --surface-3: #e3e9f2;
  --line: #d5deeb;
  --line-strong: #b9c6d9;
  --ink: #101828;
  --ink-dim: #475467;
  --ink-faint: #667085;
  --accent: #4f46e5;
  --accent-hover: #4338ca;
  --secondary: #0891b2;
  --violet: #7c3aed;
  --user-bubble: #4f46e5;
  --shadow: 0 18px 44px rgba(29, 41, 57, 0.12);
  --glow: 0 0 26px rgba(79, 70, 229, 0.12);
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;
    --bg: #f4f7fb;
    --bg-elevated: #edf2f9;
    --surface: #ffffff;
    --surface-2: #eef2ff;
    --surface-3: #e3e9f2;
    --line: #d5deeb;
    --line-strong: #b9c6d9;
    --ink: #101828;
    --ink-dim: #475467;
    --ink-faint: #667085;
    --accent: #4f46e5;
    --accent-hover: #4338ca;
    --secondary: #0891b2;
    --violet: #7c3aed;
    --user-bubble: #4f46e5;
    --shadow: 0 18px 44px rgba(29, 41, 57, 0.12);
    --glow: 0 0 26px rgba(79, 70, 229, 0.12);
  }
}

* { box-sizing: border-box; }
html { height: 100%; overflow: hidden; overscroll-behavior: none; background: var(--bg); }
body {
  margin: 0;
  position: fixed;
  inset: 0;
  overflow: hidden;
  overscroll-behavior: none;
  background:
    radial-gradient(circle at 80% -10%, rgba(99, 102, 241, 0.14), transparent 34rem),
    var(--bg);
  color: var(--ink);
}
button, input, select, textarea { font: inherit; color: inherit; }
button, select { cursor: pointer; }
button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--secondary);
  outline-offset: 2px;
}
h1, h2, p { margin: 0; }
.muted { color: var(--ink-faint); font-size: 13px; }
.hidden, [hidden] { display: none !important; }

/* Brand */
.brand-img { flex: none; object-fit: contain; border-radius: 24%; filter: drop-shadow(0 6px 16px rgba(99, 102, 241, 0.3)); }
.brand-img-lg { width: 84px; height: 84px; margin-bottom: 6px; }
.brand-img-sm { width: 40px; height: 40px; border-radius: 22%; }
.topbar-logo { width: 28px; height: 28px; border-radius: 22%; flex: none; }
.brand-mark { position: relative; flex: none; filter: drop-shadow(0 0 12px rgba(99, 102, 241, 0.42)); }
.brand-mark-lg { width: 72px; height: 72px; margin-bottom: 4px; }
.brand-mark-sm { width: 38px; height: 38px; }
.brand-mark::before, .brand-mark::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 58%; height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--secondary), var(--accent), var(--violet));
  transform-origin: left center;
}
.brand-mark::before { transform: rotate(-42deg); }
.brand-mark::after { transform: rotate(42deg); }
.brand-core, .brand-node { position: absolute; display: block; border-radius: 50%; }
.brand-core {
  left: 31%; top: 31%; width: 38%; height: 38%; z-index: 2;
  background: linear-gradient(135deg, var(--secondary), var(--accent) 52%, var(--violet));
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.3);
}
.brand-node { width: 18%; height: 18%; z-index: 3; background: var(--surface); border: 2px solid var(--secondary); }
.brand-node.n1 { left: 4%; top: 41%; }
.brand-node.n2 { right: 3%; top: 8%; border-color: var(--violet); }
.brand-node.n3 { right: 3%; bottom: 8%; border-color: var(--accent); }

/* Pairing */
.pair {
  height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 24px; text-align: center;
}
.pair::before {
  content: ""; position: fixed; width: 420px; height: 420px; border-radius: 50%;
  background: radial-gradient(circle, rgba(99,102,241,.14), rgba(6,182,212,.04) 42%, transparent 70%);
  pointer-events: none;
}
.pair > * { position: relative; }
.brand-kicker { color: var(--secondary); font-size: 11px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; }
.pair h1 { font-size: 34px; letter-spacing: 0; }
.pair-copy { max-width: 360px; color: var(--ink-dim); font-size: 14px; line-height: 1.5; }
.pair-card {
  width: min(380px, calc(100vw - 32px)); margin-top: 18px; padding: 20px;
  display: grid; gap: 10px; text-align: left;
  border: 1px solid var(--line); border-radius: var(--radius-xl);
  background: color-mix(in srgb, var(--surface) 92%, transparent); box-shadow: var(--shadow), var(--glow);
  backdrop-filter: blur(18px);
}
.pair-card label { font-size: 14px; font-weight: 700; }
.pair input {
  width: 100%; text-align: center; letter-spacing: 0; font-size: 22px; padding: 13px;
  border-radius: var(--radius-md); border: 1px solid var(--line-strong); background: var(--bg-elevated);
}
.pair button {
  width: 100%; min-height: 48px; padding: 12px; border-radius: var(--radius-md); border: 0;
  background: linear-gradient(135deg, var(--accent), var(--violet)); color: var(--accent-ink); font-weight: 750;
  box-shadow: 0 10px 24px rgba(99,102,241,.24);
}

/* Shell */
#app { height: 100%; width: 100%; overflow: hidden; display: grid; grid-template-rows: auto 1fr; }
#app > * { min-width: 0; }
/* Mobile bottom tab bar (2026-09-17 redesign pass), referencing the
   mockups' own actual fixed-bottom-tab-bar screen (Chat/Projects/
   Connectors/Agents/More), not the separate Home-screen quick-action grid
   mockups which are a different concept (see Home dashboard, already
   shipped). A real 3rd grid row -- not position:fixed -- so main's own 1fr
   row shrinks to make room automatically; no overlap with the composer to
   get wrong, because there's nothing to overlap. */
.mobile-tab-bar { display: none; }
/* Owner's ask (Appearance toggle): !important because the mobile breakpoint
   below sets display:grid on the same element -- this class needs to win
   regardless of which loads/cascades in what order. A display:none grid
   child contributes nothing to its track's auto-sizing, so #app's 3rd grid
   row collapses to 0 height on its own; no separate grid-template-rows
   override needed here. */
html.hide-mobile-tabbar .mobile-tab-bar { display: none !important; }
.topbar {
  display: flex; align-items: center; gap: 8px; min-width: 0; min-height: 60px; padding: 8px 10px; overflow: hidden;
  border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(16px); z-index: 10;
}
/* 2026-09-26 (owner's ask): parity with hub-phone-agent's silent
 * check-on-open -- that app's update state is visible for free since
 * HomeScreen IS its front door; this app's front door is the chat page, so
 * an update found on launch needs its own strip here instead of staying
 * buried in System -> Updates until someone happens to open it. */
.app-update-banner {
  display: flex; align-items: center; gap: 10px; padding: 8px 14px;
  background: color-mix(in srgb, var(--accent) 14%, var(--bg));
  border-bottom: 1px solid var(--accent); font-size: 13px; color: var(--ink);
}
.app-update-banner span:first-child { flex: 1 1 auto; min-width: 0; }
.app-update-banner button.ghost { min-height: 30px; padding: 4px 10px; }
.app-update-banner button.icon { min-height: 30px; min-width: 30px; font-size: 16px; line-height: 1; }

/* F11 (2026-09-25 review): "search within a thread" -- the browser's own
   native find-in-page has nothing to attach to once this app runs
   installed/standalone (no browser chrome at all in that mode, which is
   the PWA's primary intended usage), so this is a real gap, not
   redundant with anything already there. */
.in-thread-search-bar {
  display: flex; align-items: center; gap: 8px; padding: 8px 14px;
  background: var(--surface-2); border-bottom: 1px solid var(--line-strong); font-size: 13px;
}
.in-thread-search-bar img { opacity: .6; flex-shrink: 0; }
.in-thread-search-bar input {
  flex: 1 1 auto; min-width: 0; background: transparent; border: 0; color: var(--ink);
  font-size: 13px; outline: none;
}
.in-thread-search-count { color: var(--ink-faint); font-size: 12px; white-space: nowrap; }
.in-thread-search-bar button.icon { min-height: 28px; min-width: 28px; font-size: 15px; line-height: 1; }
mark.in-thread-search-hit { background: color-mix(in srgb, var(--warn) 55%, transparent); color: inherit; border-radius: 2px; }
mark.in-thread-search-hit.current { background: var(--warn); color: #1a1200; }
.topbar-title { flex: 1 1 0; min-width: 0; text-align: center; }
.thread-title { min-width: 0; font-size: 15px; font-weight: 720; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar-subtitle { display: flex; align-items: center; justify-content: center; gap: 5px; margin-top: 2px; color: var(--ink-faint); font-size: 10px; min-width: 0; }
/* #sessionContext is "<project name> · local host" -- an arbitrary-length
 * project name (e.g. "Command Centers") was wrapping onto 2-3 lines on
 * narrow phones, which stretched the whole topbar row tall and made every
 * icon next to it (menu/bell/settings/refresh) look inconsistently placed
 * even though they were correctly centered against that row's own height --
 * the row's height was the actual bug. One line, ellipsized, like the title
 * above it already was. */
#sessionContext { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.status-pulse { width: 6px; height: 6px; border-radius: 50%; background: var(--ok); box-shadow: 0 0 8px color-mix(in srgb, var(--ok) 70%, transparent); }
.icon {
  display: grid; place-items: center; width: 44px; height: 44px; flex: none; border-radius: var(--radius-md);
  border: 0; background: transparent; color: var(--ink-dim); transition: background 150ms, color 150ms, transform 150ms;
}
.icon:hover { background: var(--surface-2); color: var(--ink); }
.icon:active { transform: scale(.96); }
.topbar-engine { flex: 0 1 104px; min-width: 72px; min-height: 34px; height: 34px; font-size: 12px; color: var(--ink); border-color: color-mix(in srgb, var(--accent) 50%, var(--line)); }
.notif-bell { position: relative; }
.notif-bell-badge {
  position: absolute; top: 4px; right: 4px; min-width: 16px; height: 16px; padding: 0 4px;
  display: grid; place-items: center; border-radius: 999px; background: var(--danger, #e5484d);
  color: #fff; font-size: 10px; font-weight: 700; line-height: 1; box-shadow: 0 0 0 2px var(--surface);
}
.session-settings-trigger { position: relative; background: var(--surface-2); border: 1px solid var(--line); color: var(--ink-dim); }
.session-settings-trigger.has-overrides, .drawer-settings-btn.has-overrides { color: var(--secondary); border-color: color-mix(in srgb, var(--secondary) 46%, var(--line)); }
.session-settings-trigger.has-overrides::after, .drawer-settings-btn.has-overrides::after { content: ""; position: absolute; top: 7px; right: 7px; width: 6px; height: 6px; border-radius: 50%; background: var(--secondary); box-shadow: 0 0 8px color-mix(in srgb, var(--secondary) 70%, transparent); }
.drawer-settings-btn { position: relative; }
/* Per-session settings: one compact topbar entry point, clear named choices. */
.session-settings-backdrop { position: fixed; inset: 0; z-index: 44; width: 100%; height: 100%; padding: 0; border: 0; background: rgba(1, 7, 18, .62); backdrop-filter: blur(3px); }
.session-settings-menu {
  position: fixed; top: 68px; right: 12px; z-index: 45; width: min(420px, calc(100vw - 24px));
  padding: 16px; border: 1px solid var(--line-strong); border-radius: var(--radius-lg);
  background: var(--surface); box-shadow: var(--shadow), var(--glow);
}
.session-settings-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.session-settings-head h2 { margin-top: 2px; font-size: 19px; letter-spacing: 0; }
.session-settings-head .icon { font-size: 27px; }
.session-settings-copy { margin: 8px 0 14px; color: var(--ink-faint); font-size: 12px; line-height: 1.45; }
.session-options { display: grid; gap: 8px; }
.session-option {
  width: 100%; min-height: 66px; padding: 10px; display: grid; grid-template-columns: 42px minmax(0, 1fr) auto;
  align-items: center; gap: 10px; text-align: left; border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--bg-elevated); color: var(--ink); transition: border-color 150ms, background 150ms;
}
.session-option:hover { background: var(--surface-2); border-color: var(--line-strong); }
.session-option.on { border-color: color-mix(in srgb, var(--accent) 58%, var(--line)); background: color-mix(in srgb, var(--accent) 9%, var(--surface)); }
.session-option-icon { width: 42px; height: 42px; display: grid; place-items: center; border-radius: 11px; background: var(--surface-2); }
.session-option-icon svg { width: 23px; height: 23px; }
.auto-icon { color: var(--violet); }
.full-icon { color: var(--warn); }
.local-icon { color: var(--secondary); }
.observe-icon { color: var(--ok); }
#observeBtn.on .session-option-state { background: var(--ok); color: #04210f; }
.session-option-copy { min-width: 0; }
.session-option-copy strong { display: block; font-size: 13px; }
.session-option-copy small { display: block; margin-top: 3px; color: var(--ink-faint); font-size: 10px; line-height: 1.35; }
.session-option-state { min-width: 34px; padding: 4px 7px; border-radius: 999px; background: var(--surface-2); color: var(--ink-faint); font-size: 10px; font-weight: 800; text-align: center; }
.session-option.on .session-option-state { background: var(--accent); color: white; }
#fullHostBtn.on .session-option-state { background: var(--warn); color: #211500; }
#privacyBtn.on .session-option-state { background: var(--secondary); color: #001a20; }
.session-settings-actions { margin-top: 12px; display: grid; grid-template-columns: 1fr; gap: 7px; }
.reset-session-button { min-height: 42px; padding: 9px 12px; border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-dim); font-weight: 700; }
.reset-session-button:hover { border-color: var(--line-strong); color: var(--ink); }
.reset-session-button:disabled { opacity: .55; }

/* Drawer */
#scrim { position: fixed; inset: 0; background: rgba(1, 7, 18, .68); opacity: 0; pointer-events: none; transition: opacity 220ms; z-index: 20; backdrop-filter: blur(2px); }
#app.drawer-open #scrim { opacity: 1; pointer-events: auto; }
#drawer {
  position: fixed; top: 0; left: 0; height: 100%; width: min(88vw, 340px); z-index: 21;
  display: flex; flex-direction: column; transform: translateX(-100%); transition: transform 220ms ease;
  background: var(--surface); border-right: 1px solid var(--line); box-shadow: var(--shadow);
}
#app.drawer-open #drawer { transform: translateX(0); }
#app.drawer-dragging #drawer, #app.drawer-dragging #scrim { transition: none; }
.drawer-brand { display: flex; align-items: center; gap: 10px; min-height: 64px; padding: 11px 12px; border-bottom: 1px solid var(--line); }
.drawer-brand > div:nth-child(2) { display: grid; gap: 2px; min-width: 0; }
.drawer-brand strong { font-size: 15px; letter-spacing: 0; }
.drawer-brand span { color: var(--ink-faint); font-size: 10px; }
.theme-button { margin-left: auto; font-size: 20px; }
.drawer-head { display: flex; gap: 8px; padding: 12px 12px 8px; align-items: stretch; }
.new-btn {
  flex: 1; min-width: 0; min-height: 46px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 10px 12px; text-align: left; border-radius: var(--radius-md); border: 1px solid color-mix(in srgb, var(--accent) 60%, var(--line));
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 22%, var(--surface)), color-mix(in srgb, var(--violet) 13%, var(--surface)));
  color: var(--ink); font-weight: 700;
}
.drawer-head-menu { position: relative; flex: none; }
.drawer-head-menu > .icon { width: 42px; height: 46px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-2); }
.popover-menu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 25; min-width: 180px;
  display: flex; flex-direction: column; padding: 6px; gap: 2px;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius-md); box-shadow: var(--shadow);
}
.popover-menu button {
  text-align: left; border: 0; background: transparent; color: var(--ink); font-size: 13px;
  padding: 9px 10px; border-radius: var(--radius-sm);
}
.popover-menu button:hover { background: var(--surface-2); }
.popover-menu button.danger { color: #ff9da3; }
/* 2026-09-16 (owner's ask, dictation mode switcher): the composer sits at
   the bottom of the screen, so this reuses .popover-menu's shape but opens
   UPWARD (bottom-anchored) instead of .popover-menu's own default
   top-anchored placement, which would push it off-screen here. */
.mic-wrap { position: relative; }
/* 2026-09-16: real bug, confirmed live -- .composer has overflow:hidden
   (needed for the mobile-overflow-prevention work earlier this session),
   and this menu opens ABOVE the mic button (bottom: calc(100% + 6px)),
   which pushes it outside .composer's own box -- silently clipped to
   invisible, "long-press does nothing" from the owner's side even though
   it was actually opening every time. Fixed with a portal: JS moves this
   element to a direct child of <body> and switches to position:fixed with
   coordinates computed from the mic button's own getBoundingClientRect(),
   so it's no longer a descendant of anything that can clip it. */
.mic-mode-menu { position: fixed; top: auto; bottom: auto; right: auto; min-width: 190px; }
.mic-mode-menu button.active { background: var(--surface-2); font-weight: 700; color: var(--accent); }
/* Attach menu (2026-09-17 redesign pass): same portal/fixed-position fix as
   the mic mode menu above, just wired to a different trigger (see
   openAttachMenu() in app.js) -- two-line items (name + short description),
   like the reference mockups' attachment menu. */
.attach-wrap { position: relative; }
#attachMenu { min-width: 220px; }
#attachMenu button small { display: block; margin-top: 1px; color: var(--ink-faint); font-size: 11px; }
.drawer-engine {
  margin: 0 12px 8px; width: calc(100% - 24px); min-height: 40px; border-radius: var(--radius-md);
  border: 1px solid var(--line); background: var(--surface-2); padding: 0 10px; font-weight: 600; font-size: 12px; color: var(--ink-dim);
}
.thread-search {
  display: flex; align-items: center; gap: 8px; margin: 0 12px 8px; padding: 0 10px;
  min-height: 40px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-elevated); color: var(--ink-faint);
}
.thread-search:focus-within { border-color: var(--accent); color: var(--ink-dim); }
.thread-search input { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--ink); font-size: 13px; padding: 8px 0; outline: none; }
.thread-search input::-webkit-search-cancel-button { -webkit-appearance: none; }
.thread-empty-search { padding: 20px 14px; text-align: center; color: var(--ink-faint); font-size: 12px; }
.drawer-tools { display: flex; align-items: center; gap: 6px; padding: 0 12px 8px; }
.drawer-tools .mini {
  min-height: 34px; padding: 6px 10px; font-size: 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-dim);
}
.drawer-tools .mini.danger { color: #ff9da3; border-color: color-mix(in srgb, var(--bad) 42%, var(--line)); }
.drawer-tools .mini.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.sel-count { flex: 1; font-size: 12px; color: var(--ink-dim); }
.thread-list { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 4px 8px 8px; }
.thread-wrap { position: relative; display: flex; align-items: center; overflow: hidden; border-radius: var(--radius-md); margin-bottom: 3px; }
.thread-action { position: absolute; top: 0; bottom: 0; display: flex; align-items: center; padding: 0 18px; font-size: 13px; font-weight: 700; color: #fff; opacity: 0; }
.thread-action.rename { left: 0; background: #2563a6; }
.thread-action.delete { right: 0; background: #a02d3d; }
.t-pin { margin-right: 3px; font-size: 10px; }
/* Rename/pin/delete/move (threads) and reorder (threads + project sections)
 * are both reached purely by long-press now -- see attachRowGestures() /
 * attachHeadingDrag() in app.js. No kebab or grip button is rendered at all
 * (owner's direct feedback: the always-visible pair looked cluttered).
 * .press-armed is the brief "about to do something" cue between the
 * long-press firing and either the menu opening or a drag actually starting;
 * .dragging is the floating row itself once a drag is underway. */
.press-armed { background: color-mix(in srgb, var(--surface-2) 80%, transparent); }
.dragging { cursor: grabbing; box-shadow: var(--shadow-lg, 0 8px 24px rgba(0,0,0,.35)); opacity: .95; }
.reorder-placeholder { border: 1px dashed var(--line); border-radius: var(--radius-md); margin-bottom: 3px; background: var(--surface-2); }
.thread {
  position: relative; display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; min-height: 48px;
  padding: 9px 10px; text-align: left; border: 0; border-radius: var(--radius-md); background: var(--surface); color: var(--ink);
  transform: translateX(0); transition: transform 200ms ease, background 150ms; touch-action: pan-y;
}
.thread:hover { background: color-mix(in srgb, var(--surface-2) 64%, transparent); }
/* The inset left-bar is the ONE cue for "this is the thread you're looking
 * at right now" — .has-job used to carry the identical bar (below), which
 * made every thread with a background job look exactly like the open one.
 * .has-job keeps its own distinct glow only; .active.has-job (the open
 * thread that ALSO happens to be running) gets both cues together. */
.thread.active { background: var(--surface-2); box-shadow: inset 3px 0 var(--accent); }
.thread.has-job {
  background: color-mix(in srgb, var(--surface-2) 60%, var(--accent) 8%);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 18%, transparent);
  animation: thread-glow 2s ease-in-out infinite alternate;
}
/* animation (not the static rule above) wins for the properties it
 * targets, so the open+running combo needs its OWN keyframes carrying the
 * inset bar through every frame rather than relying on the static rule. */
.thread.active.has-job { animation-name: thread-glow-active; }
@keyframes thread-glow {
  from { box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 15%, transparent); }
  to { box-shadow: 0 0 18px color-mix(in srgb, var(--accent) 28%, transparent); }
}
@keyframes thread-glow-active {
  from { box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 15%, transparent), inset 3px 0 var(--accent); }
  to { box-shadow: 0 0 18px color-mix(in srgb, var(--accent) 28%, transparent), inset 3px 0 var(--accent); }
}
.thread-dots {
  display: flex; align-items: center; gap: 3px; margin-left: auto; padding-left: 8px; flex: none;
}
.dot-bounce {
  width: 5px; height: 5px; border-radius: 50%; background: var(--secondary);
  animation: dotBounce 1.2s ease-in-out infinite;
}
.dot-bounce:nth-child(2) { animation-delay: 0.15s; }
.dot-bounce:nth-child(3) { animation-delay: 0.3s; }
@keyframes dotBounce {
  0%, 80%, 100% { opacity: 0.3; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-4px); }
}
.thread .t-main { flex: 1; min-width: 0; display: block; }
.thread .t-title { display: block; font-size: 13px; font-weight: 620; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.thread .t-sub { display: flex; align-items: center; gap: 6px; margin-top: 3px; color: var(--ink-faint); font-size: 10px; }
.thread .t-tag { padding: 2px 5px; border-radius: 999px; background: var(--surface-2); color: var(--ink-faint); font-size: 8px; line-height: 1; letter-spacing: 0; text-transform: uppercase; }
/* Replaces the old state-dot + agent-dot pair (owner's direct feedback: two
 * small colored blobs side by side wasn't beautiful). Engine identity is now
 * the real per-engine icon badge (.who-badge, same glyph the chat message
 * headers use); status is color on the engine name + "last used" time text
 * itself -- green = last turn completed, red = failed/interrupted, amber =
 * waiting on you (approval or a manual relay reply). Running/idle stay the
 * default muted color on purpose -- running already has its own bouncing-dot
 * indicator (.thread-dots), and idle just means nothing has happened yet. */
.thread .t-engine-name { font-weight: 700; }
.thread .st-ok { color: var(--ok); text-shadow: 0 0 6px color-mix(in srgb, var(--ok) 45%, transparent); }
.thread .st-bad { color: var(--bad); text-shadow: 0 0 6px color-mix(in srgb, var(--bad) 45%, transparent); }
.thread .st-wait { color: var(--warn); text-shadow: 0 0 6px color-mix(in srgb, var(--warn) 45%, transparent); }
.thread .t-check { width: 20px; height: 20px; border-radius: 6px; border: 2px solid var(--ink-faint); flex: none; display: none; place-items: center; }
#app.select-mode .thread .t-check { display: grid; }
#app.select-mode .thread { touch-action: pan-y; transform: none !important; }
.thread.sel .t-check { background: var(--accent); border-color: var(--accent); }
.thread.sel .t-check::after { content: "✓"; color: var(--accent-ink); font-size: 12px; }
.title-edit { flex: 1; min-width: 0; font-size: 15px; font-weight: 650; text-align: center; border: 1px solid var(--accent); border-radius: var(--radius-sm); background: var(--surface); padding: 5px 8px; }
.state-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-faint); display: inline-block; align-self: center; }
.state-dot.running { background: var(--secondary); box-shadow: 0 0 8px color-mix(in srgb, var(--secondary) 70%, transparent); }
.state-dot.completed { background: var(--ok); }
.state-dot.failed, .state-dot.interrupted { background: var(--bad); }
.state-dot.waiting_approval { background: var(--warn); }
.drawer-foot {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px max(10px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--line); font-size: 11px; color: var(--ink-faint);
}
.manage-open {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 42px;
  border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-2); color: var(--ink-dim); font-weight: 650; font-size: 12px;
}
.manage-open:hover { background: var(--surface-3); color: var(--ink); }
.drawer-foot-status { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.dot { width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--ink-faint); }
.dot.on { background: var(--ok); box-shadow: 0 0 8px color-mix(in srgb, var(--ok) 70%, transparent); }
.link { border: 0; background: transparent; color: var(--secondary); margin-left: auto; }

/* ---- Manage hub dashboard ---- */
.manage-home { width: min(100%, 980px); margin: 0 auto; gap: 14px !important; }
.manage-hero {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 16px; border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: linear-gradient(135deg, color-mix(in srgb, var(--surface-2) 74%, transparent), var(--surface));
}
.manage-kicker, .pview-head span {
  display: block; margin-bottom: 5px; color: var(--secondary); font-size: 10px; font-weight: 850;
  letter-spacing: 0; text-transform: uppercase;
}
.manage-hero h2, .pview-head h2 { font-size: 20px; line-height: 1.15; letter-spacing: 0; }
.manage-hero p, .pview-head p { margin-top: 6px; color: var(--ink-dim); font-size: 12px; line-height: 1.45; }
.manage-health {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  min-height: 30px; padding: 6px 9px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--bg-elevated); color: var(--ink-dim); font-size: 11px; font-weight: 700;
}
/* 2026-09-17 redesign pass: a personalized landing (greeting + do-something-
   now actions + recent chats) above the existing stats/nav grids, matching
   the reference mockups -- additive, the comprehensive Control/Capabilities
   grids below are unchanged and still the real navigation surface. */
.manage-greeting h2 { font-size: 19px; margin: 0; }
.manage-greeting p { margin-top: 4px; color: var(--ink-dim); font-size: 12px; }
/* .home-qa-card, NOT .quick-action -- that name is already taken (line ~532
   below) by the empty-chat-state's own unrelated quick-actions row, whose
   `display: flex` + bare `span`/`strong`/`small` child rules were silently
   winning over these on source order and mangling this layout until caught
   live via screenshot. */
.manage-quick-actions { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 9px; }
/* `.manage-home .home-qa-card`, not just `.home-qa-card` -- same
   `.pview button` specificity trap as .recent-chat-item below: without the
   extra ancestor class this rendered as a solid accent-colored CTA button,
   confirmed via getComputedStyle (backgroundColor was rgb(79,70,229),
   .pview button's --accent, not --surface) even though a screenshot glance
   made it look fine at first -- measured, not assumed, the second time. */
.manage-home .home-qa-card {
  display: grid; gap: 4px; text-align: left; padding: 13px 12px; min-height: 0; font-weight: 400;
  border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface); color: var(--ink);
  box-shadow: 0 8px 22px rgba(0,0,0,.06); transition: border-color 140ms, transform 140ms, background 140ms;
}
.home-qa-card:hover { border-color: color-mix(in srgb, var(--secondary) 44%, var(--line-strong)); background: color-mix(in srgb, var(--surface-2) 58%, var(--surface)); }
.home-qa-card:active { transform: scale(.985); }
.home-qa-card .qa-icon { font-size: 18px; line-height: 1; }
.home-qa-card .qa-name { font-size: 13px; font-weight: 750; }
.home-qa-card .qa-desc { font-size: 11px; color: var(--ink-dim); }
#qaNewChat .qa-icon { color: var(--secondary); }
#qaLaunchCouncil .qa-icon { color: var(--violet); }
#qaCreateProject .qa-icon { color: var(--ok); }
#qaAddConnector .qa-icon { color: var(--warn); }
.manage-home .manage-link { background: none; border: none; color: var(--secondary); font-size: 11px; font-weight: 700; padding: 0; min-height: 0; }
/* `.manage-home .recent-chat-item` (not just `.recent-chat-item`) deliberately
   -- `.pview button` (a blanket "every plain button in a Manage panel is a
   solid accent CTA" rule) otherwise wins on specificity and paints every
   recent-chat row like a submit button instead of a quiet list row. */
.manage-home .recent-chat-item {
  width: 100%; text-align: left; font: inherit; cursor: pointer; min-height: 0;
  background: var(--bg-elevated); color: var(--ink); font-weight: 400;
  transition: border-color 140ms, background 140ms;
}
.recent-chat-item:hover { border-color: color-mix(in srgb, var(--secondary) 44%, var(--line-strong)); }
.recent-chat-item .meta { align-items: center; }
@media (max-width: 640px) {
  .manage-quick-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.manage-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; }
.pview .manage-stat {
  min-height: 74px; display: grid; align-content: center; gap: 3px; text-align: left;
  padding: 12px; border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--surface); color: var(--ink); box-shadow: 0 8px 22px rgba(0,0,0,.06);
}
.manage-stat span { font-size: 21px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ink); }
.manage-stat small { color: var(--ink-faint); font-size: 10px; text-transform: uppercase; letter-spacing: 0; }
.manage-section { display: grid; gap: 8px; }
.manage-section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.manage-section-head h3 { margin: 0; font-size: 12px; color: var(--ink); }
.manage-section-head span { color: var(--ink-faint); font-size: 11px; }
.manage-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
.pview .manage-card {
  display: grid; grid-template-columns: auto 1fr auto; grid-template-rows: auto auto; column-gap: 10px; row-gap: 3px;
  align-content: start; text-align: left; padding: 13px; min-height: 84px;
  border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface); color: var(--ink);
  box-shadow: 0 8px 22px rgba(0,0,0,.06); transition: border-color 140ms, transform 140ms, background 140ms;
}
.pview .manage-card:hover, .pview .manage-stat:hover {
  border-color: color-mix(in srgb, var(--secondary) 44%, var(--line-strong));
  background: color-mix(in srgb, var(--surface-2) 58%, var(--surface));
}
.pview .manage-card:active, .pview .manage-stat:active { transform: scale(.985); }
.manage-card .mc-icon {
  grid-row: 1 / 3; width: 34px; height: 34px; display: grid; place-items: center; font-size: 17px;
  border-radius: 9px; background: color-mix(in srgb, var(--secondary) 12%, var(--surface-2)); color: var(--secondary);
}
.manage-card .mc-name { font-size: 13px; font-weight: 750; align-self: end; }
.manage-card .mc-desc { grid-column: 2; font-size: 11px; line-height: 1.35; color: var(--ink-dim); }
.manage-card .mc-badge {
  grid-column: 3; grid-row: 1 / 3; align-self: center; min-width: 30px; padding: 3px 7px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--bg-elevated);
  font-size: 10px; font-weight: 800; color: var(--ink-dim); text-align: center;
}
.manage-card .mc-badge:empty { display: none; }
.os-snapshot {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 8px;
}
.pview .os-cell {
  min-height: 88px; display: grid; align-content: space-between; justify-items: start; gap: 5px;
  padding: 11px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--bg-elevated) 72%, var(--surface));
  color: var(--ink); text-align: left; box-shadow: none;
}
.os-cell span { font-size: 10px; font-weight: 850; color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0; }
.os-cell strong { font-size: 20px; line-height: 1; font-variant-numeric: tabular-nums; }
.os-cell small { font-size: 11px; line-height: 1.3; color: var(--ink-dim); }
@media (max-width: 560px) {
  .manage-hero { flex-direction: column; }
  .manage-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .os-snapshot { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .manage-grid { grid-template-columns: 1fr; }
}

/* ---- discoverability intro line under a panel/card heading ---- */
.pview-intro { margin: -2px 0 2px; font-size: 11.5px; line-height: 1.5; color: var(--ink-faint); max-width: 62ch; }
.pv-card > .pview-intro { margin-top: -4px; }

/* Web Chat's fallback-engine explainer (2026-09-13, owner's ask: "step by
 * step like holding a baby's hand so they dont miss it") — plain numbered
 * steps for the two non-obvious fallback choices, Local agent and Zen. */
.webchat-explainer { display: grid; gap: 16px; margin-top: 4px; }
.webchat-explainer h3 { margin: 0; font-size: 13px; color: var(--ink); }
.webchat-explainer ol { margin: 6px 0 0; padding-left: 20px; display: grid; gap: 6px; }
.webchat-explainer li { font-size: 12.5px; line-height: 1.5; color: var(--ink-dim); }
.webchat-explainer li strong { color: var(--ink); }
@media (min-width: 640px) { .webchat-explainer { grid-template-columns: 1fr 1fr; } }

/* Chat */
#chat { width: 100%; min-height: 0; min-width: 0; overflow: hidden; display: grid; grid-template-rows: auto auto 1fr auto; }
#inThreadSearchBar { grid-row: 1; grid-column: 1; }
#reconnectBar { grid-row: 2; grid-column: 1; }
#messages { grid-row: 3; grid-column: 1; }
#composer { grid-row: 4; grid-column: 1; min-width: 0; }
.messages {
  min-height: 0; min-width: 0; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch; padding: 20px 14px 12px; display: flex; flex-direction: column; gap: 16px;
  scroll-padding-bottom: 20px;
}
.messages > * { width: min(100%, 820px); min-width: 0; margin-left: auto; margin-right: auto; }
.msg.assistant, .act, .act-body, .msg.user { word-break: break-word; }
.empty { margin: auto !important; color: var(--ink-faint); font-size: 14px; text-align: center; }
.empty-state { width: min(100%, 620px); display: grid; justify-items: center; gap: 9px; padding: 24px 0; }
.empty-state h2 { color: var(--ink); font-size: 28px; letter-spacing: 0; }
.empty-state > p { max-width: 440px; color: var(--ink-dim); line-height: 1.55; }
.quick-actions { width: 100%; margin-top: 16px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.quick-action {
  min-height: 54px; padding: 10px 12px; display: flex; align-items: center; gap: 10px; text-align: left;
  border-radius: var(--radius-md); border: 1px solid var(--line); background: color-mix(in srgb, var(--surface) 90%, transparent); color: var(--ink-dim);
  transition: border-color 150ms, background 150ms, transform 150ms;
}
.quick-action span { width: 30px; height: 30px; display: grid; place-items: center; flex: none; border-radius: 9px; background: var(--surface-2); color: var(--secondary); font-size: 15px; }
.quick-action strong { display: block; color: var(--ink); font-size: 13px; }
.quick-action small { display: block; margin-top: 2px; color: var(--ink-faint); font-size: 10px; }
.quick-action:hover { border-color: var(--accent); background: var(--surface-2); transform: translateY(-1px); }
.empty-message { padding: 20px; border: 1px dashed var(--line-strong); border-radius: var(--radius-lg); background: var(--surface); }
.msg { position: relative; max-width: 100%; color: var(--ink); font-size: 14px; line-height: 1.62; }
.msg.user {
  width: fit-content; max-width: min(82%, 680px); margin-right: max(0px, calc((100% - 820px) / 2)); margin-left: auto;
  padding: 11px 15px; white-space: pre-wrap; overflow-wrap: anywhere;
  border: 1px solid rgba(255,255,255,.1); border-radius: 18px 18px 5px 18px;
  background: linear-gradient(135deg, var(--user-bubble), color-mix(in srgb, var(--user-bubble) 68%, var(--violet)));
  color: var(--user-ink); box-shadow: 0 8px 22px rgba(50, 46, 160, .16);
}
/* 2026-09-16 (mid-task steering, owner's ask): a message sent while a turn
   is already running and this engine can't accept it mid-stream (no
   injectMessage support) gets queued client-side instead of failing --
   dimmed + a small caption so it visibly reads as "not sent yet", not lost. */
.msg.user.queued { opacity: .62; }
.queued-note { margin-top: 4px; display: flex; align-items: center; gap: 8px; font-size: 11px; font-style: italic; opacity: .85; }
.queued-note span { flex: 1 1 auto; min-width: 0; }
.queued-cancel {
  flex-shrink: 0; border: 1px solid color-mix(in srgb, var(--bad) 55%, transparent); border-radius: var(--radius-sm);
  padding: 2px 8px; font-size: 10px; font-style: normal; font-weight: 700; color: var(--bad);
  background: color-mix(in srgb, var(--bad) 10%, transparent);
}
.queued-cancel:hover, .queued-cancel:focus-visible { background: color-mix(in srgb, var(--bad) 20%, transparent); }
.msg-body { min-width: 0; }
.msg-body.restart-continuation { cursor: pointer; }
.msg-body.restart-continuation.collapsed { opacity: .65; font-style: italic; }
.msg.assistant {
  align-self: stretch; overflow-wrap: anywhere;
  --eng: var(--secondary);
  border: 1px solid var(--line); border-left: 3px solid color-mix(in srgb, var(--eng) 70%, var(--line));
  border-radius: var(--radius-lg); background: var(--surface);
  padding: 11px 14px 12px; box-shadow: 0 6px 18px rgba(0,0,0,.06);
}
.msg.assistant.exec-local { --eng: var(--engine-local); }
.msg.assistant.exec-local-agent { --eng: var(--engine-local-agent); }
.msg.assistant.exec-codex { --eng: var(--engine-codex); }
.msg.assistant.exec-claude { --eng: var(--engine-claude); }
.msg.assistant.exec-zen { --eng: var(--engine-zen); }
.msg.assistant.exec-chatgpt-web { --eng: var(--engine-chatgpt-web); }
.msg.assistant.exec-claude-web { --eng: var(--engine-claude-web); }
.msg.assistant.exec-grok { --eng: var(--engine-grok); }
.msg.assistant.exec-openrouter { --eng: var(--engine-openrouter); }
.msg.assistant.exec-device { --eng: var(--engine-device); }
.msg.assistant.exec-mock { --eng: var(--engine-mock); }
.msg.assistant .who {
  display: flex; align-items: center; gap: 6px; width: fit-content; margin-bottom: 8px;
  color: var(--eng); font-size: 10px; font-weight: 800; letter-spacing: 0; text-transform: uppercase;
}
/* Per-engine icon badge (2026-09-17, owner's ask: real icon art, not just a
   colored initial letter -- explicitly authorized to move past the earlier
   letter-fallback since this is a private, licensed, non-distributed tool).
   Original hand-drawn glyphs (ENGINE_ICON_SVGS in app.js), not copies of any
   provider's actual logo mark -- rendered as a real child <span> now rather
   than CSS ::before content, since a multi-path original SVG is far more
   maintainable as JS-built markup than a hand-escaped CSS data-URI. Kept to
   this one surface (every assistant reply's own header) -- the compact
   thread-list dots and Council picker chips stay plain color dots, already
   tuned this session as the right density for how small they render. */
.who-badge {
  width: 16px; height: 16px; border-radius: 50%; background: var(--eng); flex: none;
  display: grid; place-items: center;
  box-shadow: 0 0 8px color-mix(in srgb, var(--eng) 55%, transparent);
}
.msg-actions {
  display: flex; align-items: center; gap: 4px; min-width: 0; white-space: normal;
  opacity: 0; transition: opacity 140ms, transform 140ms;
}
.msg:hover .msg-actions, .msg:focus-within .msg-actions { opacity: 1; }
.msg-actions button {
  position: relative; width: 30px; height: 30px; min-height: 0; padding: 0; display: inline-grid; place-items: center;
  border: 1px solid var(--line); border-radius: 999px; background: color-mix(in srgb, var(--surface-2) 88%, transparent);
  color: var(--ink-dim); font-size: 10px; font-weight: 800; box-shadow: 0 5px 14px rgba(0,0,0,.08);
}
.msg-actions button:hover { border-color: var(--secondary); color: var(--ink); background: var(--surface-2); }
.msg-actions button[data-message-action="rewind"]:hover { border-color: var(--bad); color: color-mix(in srgb, var(--bad) 76%, white); }
.msg-actions button.done { border-color: var(--ok); color: var(--ok); }
.msg-actions button:disabled { opacity: .55; pointer-events: none; }
.msg-actions span { font-size: 14px; line-height: 1; }
.msg-actions small { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.msg-actions button::after {
  content: attr(aria-label); position: absolute; bottom: calc(100% + 7px); left: 50%; transform: translate(-50%, 4px);
  min-width: max-content; max-width: 180px; padding: 5px 7px; border: 1px solid var(--line);
  border-radius: 6px; background: var(--ink); color: var(--bg); font-size: 10px; font-weight: 800;
  box-shadow: 0 8px 22px rgba(0,0,0,.18); opacity: 0; pointer-events: none; transition: opacity 120ms, transform 120ms; z-index: 5;
}
.msg-actions button:hover::after, .msg-actions button:focus-visible::after { opacity: 1; transform: translate(-50%, 0); }
.msg-actions-top { display: none !important; }
.msg-actions-bottom {
  margin-top: 8px; padding-top: 7px; border-top: 1px solid color-mix(in srgb, var(--line) 68%, transparent);
  justify-content: flex-end; flex-wrap: wrap; opacity: 1;
}
.msg.user .msg-actions-bottom { border-top-color: rgba(255,255,255,.18); }
.msg.user .msg-actions button {
  border-color: rgba(255,255,255,.2); background: rgba(255,255,255,.12); color: color-mix(in srgb, var(--user-ink) 86%, transparent);
}
.msg.user .msg-actions button:hover { background: rgba(255,255,255,.2); color: var(--user-ink); }
@media (hover: none) { .msg-actions { opacity: 1; } }

.message-edit-modal {
  position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: 16px;
  background: rgba(0,0,0,.38); backdrop-filter: blur(8px);
}
.message-edit-card {
  width: min(100%, 620px); display: grid; gap: 10px; padding: 13px;
  border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); box-shadow: 0 24px 70px rgba(0,0,0,.26);
}
.message-edit-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.message-edit-head strong { font-size: 14px; color: var(--ink); }
.message-edit-head button {
  width: 30px; height: 30px; min-height: 0; padding: 0; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--bad) 58%, var(--line)); background: color-mix(in srgb, var(--bad) 16%, var(--surface));
  color: color-mix(in srgb, var(--bad) 72%, white); font-size: 18px; line-height: 1;
}
.message-edit-card textarea {
  width: 100%; min-height: 180px; resize: vertical; padding: 10px 11px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-elevated); color: var(--ink);
  font: 13px/1.5 inherit;
}
.message-edit-card p { margin: -2px 0 0; color: var(--ink-faint); font-size: 11px; line-height: 1.45; }
.message-edit-actions { display: flex; justify-content: flex-end; gap: 8px; }
.message-edit-actions .danger { color: #ff9da3; border-color: color-mix(in srgb, var(--bad) 42%, var(--line)); }

/* 2026-09-15 (transcript redesign §25): execution trace modal -- reuses the
 * edit-message modal shell (.message-edit-modal/.message-edit-card), adds
 * scroll since a real turn's full trace (deliberately uncapped, unlike the
 * live 8-line "Currently doing" view) can run long. */
.trace-card { max-height: min(80vh, 640px); overflow-y: auto; }
.trace-meta { font-size: 11px; color: var(--ink-faint); }
.trace-timeline { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.trace-card .live-activity { border: none; background: none; padding: 0; }
.trace-card .live-activity ul { padding: 0; }
.trace-card .file-change-summary { width: 100%; margin: 4px 0 0; }
.trace-timeline li.expandable { cursor: pointer; }
.trace-timeline li.expandable:hover { text-decoration: underline; text-underline-offset: 2px; }
.trace-detail {
  margin: 6px 0 2px 14px; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--surface); font-size: 11.5px;
}
.trace-detail-meta { display: flex; gap: 10px; align-items: center; margin-bottom: 6px; color: var(--ink-faint); }
.trace-detail-status.ok { color: var(--ok); font-weight: 650; }
.trace-detail-status.bad { color: var(--bad); font-weight: 650; }
.trace-detail-command, .trace-detail-output {
  margin: 0 0 6px; padding: 6px 8px; background: var(--bg-elevated); border: 1px solid var(--line);
  border-radius: var(--radius-sm); font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; line-height: 1.5; overflow-x: auto; white-space: pre; max-width: 100%;
}
.trace-detail-more { font-size: 10.5px; padding: 4px 9px; min-height: 0; }
.trace-ha-states { list-style: none; margin: 0; padding: 0; display: grid; gap: 3px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; }
.trace-ha-states li { padding: 3px 8px; background: var(--bg-elevated); border: 1px solid var(--line); border-radius: var(--radius-sm); }

/* markdown body */
.md { color: var(--ink); font-size: 14px; line-height: 1.62; }
.md > :first-child { margin-top: 0; }
.md > :last-child { margin-bottom: 0; }
.md p { margin: 0 0 10px; }
.md h1, .md h2, .md h3, .md h4 { margin: 15px 0 7px; font-weight: 750; line-height: 1.3; letter-spacing: 0; }
.md h1 { font-size: 18px; } .md h2 { font-size: 16px; } .md h3 { font-size: 14.5px; } .md h4 { font-size: 13px; color: var(--ink-dim); }
.md ul, .md ol { margin: 0 0 10px; padding-left: 20px; }
.md li { margin: 3px 0; }
.md li::marker { color: var(--ink-faint); }
.md a { color: var(--secondary); text-decoration: underline; text-underline-offset: 2px; }
.md img.md-img { display: block; max-width: min(100%, 720px); height: auto; margin: 8px 0 10px; border-radius: 12px; }
.md strong { font-weight: 700; }
.md em { font-style: italic; }
.md hr { border: 0; border-top: 1px solid var(--line); margin: 13px 0; }
.md blockquote { margin: 0 0 10px; padding: 2px 0 2px 11px; border-left: 3px solid var(--line-strong); color: var(--ink-dim); }
.md code {
  font: .87em/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--bg-elevated); border: 1px solid var(--line); border-radius: 5px; padding: 1px 5px; color: var(--secondary);
}
.md pre.md-code {
  position: relative; margin: 0 0 11px; padding: 12px 12px 12px; border: 1px solid var(--line);
  border-radius: var(--radius-md); background: var(--bg-elevated); overflow-x: auto;
}
.md pre.md-code code {
  display: block; background: none; border: 0; padding: 0; color: var(--ink);
  font: 12.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre;
}
.md .md-lang { position: absolute; top: 7px; right: 42px; font-size: 9px; letter-spacing: 0; text-transform: uppercase; color: var(--ink-faint); }
.md pre.md-code { padding-top: 34px; }
.md .md-copy {
  position: absolute; top: 6px; right: 6px; width: 30px; height: 30px; min-height: 0; padding: 0;
  display: grid; place-items: center; font-size: 0; line-height: 0;
  border: 1px solid var(--line-strong); border-radius: 6px; background: var(--surface-2); color: var(--ink-dim); opacity: 0; transition: opacity 140ms;
}
.md .md-copy::before { content: "⧉"; font-size: 16px; line-height: 1; }
.md .md-copy.done::before { content: "✓"; color: var(--ok); }
.md pre.md-code:hover .md-copy, .md .md-copy:focus { opacity: 1; }
@media (hover: none) { .md .md-copy { opacity: .8; } }
.md .download-card {
  display: flex; align-items: center; gap: 10px; margin: 0 0 10px; padding: 10px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-md);
}
.md .download-card-icon { font-size: 20px; flex: none; }
.md .download-card-meta { flex: 1; min-width: 0; }
.md .download-card-name { font-size: 13px; font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.md .download-card-sub { font-size: 11px; color: var(--ink-faint); }
.md .download-card-btn {
  flex: none; background: var(--accent); color: var(--accent-ink); border-radius: 8px;
  padding: 6px 12px; font-size: 12px; text-decoration: none; font-weight: 700;
}
.md .download-card-btn:hover { background: var(--accent-hover); }
.act { align-self: stretch; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface); overflow: hidden; font-size: 13px; }
.act .act-head { display: flex; align-items: center; gap: 8px; padding: 10px 12px; color: var(--ink-dim); }
.act .act-head .name { font-weight: 700; color: var(--ink); }
.act .act-body { padding: 0 12px 11px; color: var(--ink-dim); font: 12px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 40vh; overflow: auto; }
.act.ok .act-head { color: var(--ok); }
.act.bad .act-head { color: var(--bad); }
/* 2026-09-22, owner's ask (real screenshot): the flushed-history marker
   reused the plain .act look (built for compact tool-activity rows) and its
   "Load full history" button only had class="ghost" -- there is no global
   .ghost rule (the existing ones are scoped to .modal-actions/.pview), so
   it fell back to the bare browser-default button: a flat grey box that
   didn't match anything else in the transcript. Gives this one card its
   own accent-tinted, rounded-corner treatment (same --radius-lg/--secondary
   language as .msg.assistant's own left-accent card) and a real pill button
   matching .quick-action's hover lift instead of UA defaults. */
.live-voice-marker {
  flex-shrink: 0;
  align-self: center;
  padding: 6px 14px;
  border-radius: 999px;
  font-size: 0.85rem;
  color: var(--muted, inherit);
  background: color-mix(in srgb, var(--surface-2) 55%, var(--surface));
}
.flushed-marker {
  border-radius: var(--radius-lg);
  border-color: color-mix(in srgb, var(--secondary) 30%, var(--line));
  background: color-mix(in srgb, var(--surface-2) 55%, var(--surface));
  /* .messages is a flex column with a definite (grid-row) height, so when a
     thread's total content exceeds the viewport, flexbox's default
     flex-shrink:1 kicks in -- and .act's own overflow:hidden makes its
     "automatic minimum size" resolve to 0 in that calculation, so this card
     can get crushed toward 0px instead of just scrolling like everything
     else. Confirmed live (a real, pre-existing latent bug in every .act
     card, just not visibly triggered before this one got taller). */
  flex-shrink: 0;
}
.flushed-marker .act-head { flex-wrap: wrap; row-gap: 10px; padding: 12px 14px; }
.flushed-dot { color: var(--secondary); font-size: 16px; line-height: 1; }
.flushed-text { flex: 1 1 220px; min-width: 0; }
.flushed-marker .ghost.flushed-load {
  flex: none; min-height: 34px; padding: 7px 16px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface-2); color: var(--ink-dim); font-size: 12px; font-weight: 700; white-space: nowrap;
  transition: border-color 150ms, background 150ms, color 150ms, transform 150ms;
}
.flushed-marker .ghost.flushed-load:hover { border-color: var(--secondary); color: var(--ink); background: var(--surface); transform: translateY(-1px); }
.spinner { width: 13px; height: 13px; border: 2px solid var(--line-strong); border-top-color: var(--secondary); border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.icon.spinning svg { animation: spin .5s linear; }
/* flex-shrink:0 is load-bearing, not decorative (found live 2026-09-16 on a
 * 232-message thread): .messages is a flex column, and this card's own
 * overflow:hidden (needed for the rounded-corner list-collapse below) gives
 * it an automatic flex min-size of 0 per the flexbox spec, unlike sibling
 * .msg bubbles (overflow:visible, so their min-size is their content size
 * and they can't be shrunk). Once a thread's total message height exceeds
 * the scrollable .messages viewport, the shrink algorithm freezes every
 * other child at its full size and dumps 100% of the negative space onto
 * this one, crushing it to ~1px -- present in the DOM with real content,
 * completely invisible. Short/new threads never hit this since there's no
 * shrink pressure yet, which is why it looked fine in isolation. */
.live-activity {
  align-self: stretch; flex-shrink: 0; padding: 0; overflow: hidden; border: 1px solid var(--line);
  border-radius: var(--radius-md); background: color-mix(in srgb, var(--surface) 92%, var(--secondary) 8%);
  font-size: 12px; box-shadow: 0 8px 20px rgba(0,0,0,.08);
}
.live-activity-head {
  display: flex; align-items: center; gap: 8px; padding: 11px 12px; cursor: pointer; user-select: none;
  color: var(--ink); font-size: 12px; font-weight: 700; letter-spacing: 0; text-transform: none;
}
/* Verified live at 360/390px (2026-09-16): the headline text is a flex
   child with the browser default min-width:auto, so a long unbroken
   headline (e.g. "Running command · " + a 120-char shell command, per
   describeTool()'s own clip budget) sizes to its own max-content width
   instead of wrapping, silently overflowing past .live-activity's
   overflow:hidden with no ellipsis. Brief section 33 wants this row held to
   1-2 lines -- clamp it explicitly rather than rely on incidental clipping. */
.live-activity-head span:last-child {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-width: 0; overflow-wrap: anywhere;
}
.live-activity-head::after {
  content: "›"; margin-left: auto; font-size: 20px; line-height: 1; color: var(--ink-faint); transition: transform .16s;
}
.live-activity.expanded .live-activity-head::after { transform: rotate(90deg); }
.live-pulse {
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--secondary); box-shadow: 0 0 10px color-mix(in srgb, var(--secondary) 70%, transparent);
  animation: pulse 1.2s ease-in-out infinite;
}
.live-activity ul { list-style: none; margin: 0; padding: 0 12px 11px; display: none; gap: 6px; }
.live-activity.expanded ul { display: grid; }
.live-activity li {
  display: grid; grid-template-columns: 8px minmax(0, 1fr); gap: 7px; align-items: start;
  min-width: 0; padding: 6px 0; border-top: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  color: var(--ink-dim); line-height: 1.35; overflow-wrap: anywhere;
}
.live-activity li::before {
  content: ""; width: 5px; height: 5px; margin-top: 6px; border-radius: 50%;
  background: var(--ink-faint);
}
.live-activity li.live-run::before, .live-activity li.live-pending::before { background: var(--secondary); }
.live-activity li.live-output { color: var(--ink-faint); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; }
.live-activity li.live-ok::before { background: var(--ok); }
.live-activity li.live-warn::before { background: var(--warn); }
.live-activity li.live-bad::before { background: var(--bad); }
/* Session monitor card (2026-09-27, owner's ask): a visible marker for an
 * async "check back later" wait the agent scheduled (e.g. Claude Code's own
 * ScheduleWakeup) that the hub would otherwise have no state for at all. */
.session-monitor {
  align-self: stretch; flex-shrink: 0; padding: 11px 12px; border: 1px solid var(--line);
  border-radius: var(--radius-md); background: color-mix(in srgb, var(--surface) 92%, var(--secondary) 8%);
  font-size: 12px; box-shadow: 0 8px 20px rgba(0,0,0,.08);
}
.session-monitor-head { display: flex; align-items: center; gap: 8px; color: var(--ink); font-weight: 700; }
.session-monitor-meta { margin-top: 4px; color: var(--ink-faint); }
.session-monitor-note { margin-top: 6px; color: var(--ink-dim); overflow-wrap: anywhere; }
.working { align-self: flex-start; display: flex; align-items: center; gap: 4px; padding: 7px 4px; }
.working .work-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--secondary); animation: pulse 1.2s ease-in-out infinite; }
.working .work-dot:nth-child(2) { animation-delay: .2s; }
.working .work-dot:nth-child(3) { animation-delay: .4s; }
@keyframes pulse { 0%, 100% { opacity: .25; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-2px); } }
.job-timer { margin-left: 4px; font-size: 11px; font-variant-numeric: tabular-nums; color: var(--ink-faint); }
.working .job-timer { align-self: center; min-width: 3.2em; animation: timerPulse 1.2s ease-in-out infinite; }
@keyframes timerPulse { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
.job-timer-done { align-self: flex-start; padding: 2px 4px 9px; margin-left: 0; }
.job-timer-done.clickable { cursor: pointer; }
.job-timer-done.clickable:hover, .job-timer-done.clickable:focus-visible { color: var(--ink-dim); text-decoration: underline; text-underline-offset: 2px; }
.approval { align-self: stretch; border: 1px solid color-mix(in srgb, var(--warn) 65%, var(--line)); border-radius: var(--radius-md); background: color-mix(in srgb, var(--warn) 9%, var(--surface)); padding: 13px; }
.approval::before { content: "Approval required"; display: block; margin-bottom: 7px; color: var(--warn); font-size: 10px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; }
.approval .a-prompt { margin-bottom: 11px; color: var(--ink); font-size: 13px; overflow-wrap: anywhere; }
.approval .a-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.approval button { min-height: 42px; padding: 9px; border-radius: var(--radius-sm); border: 0; font-weight: 700; }
.approval .approve { background: var(--accent); color: var(--accent-ink); }
.approval .deny { background: color-mix(in srgb, var(--bad) 16%, var(--surface)); color: color-mix(in srgb, var(--bad) 62%, white); }

/* Manual chat-relay card (chatgpt-web / claude-web) — same "paused, needs
 * you" shape as .approval above, but for pasting a reply instead of
 * approve/deny: a scrollable prompt box + copy button, a reply textarea,
 * and Send / Skip actions. */
.manual-relay { align-self: stretch; border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--surface-2); padding: 13px; }
.manual-relay .mr-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; font-size: 13px; }
.manual-relay .mr-head .muted { color: var(--ink-faint); font-weight: 400; }
.manual-relay .mr-prompt pre { margin: 0; max-height: 160px; overflow-y: auto; white-space: pre-wrap; word-break: break-word; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11.5px; line-height: 1.5; color: var(--ink-dim); background: var(--bg-elevated); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px; }
.manual-relay .mr-prompt-actions { display: flex; justify-content: flex-end; margin: 7px 0 11px; }
.manual-relay .mr-quick-replies { display: flex; flex-wrap: wrap; gap: 8px; margin: 11px 0; }
.manual-relay .mr-quick-replies button { min-height: 36px; padding: 6px 14px; font-size: 13px; font-weight: 600; border-radius: 999px; border: 1px solid var(--line-strong); background: var(--bg-elevated); color: var(--ink); }
.manual-relay .mr-quick-replies button:hover { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.manual-relay .mr-copy { min-height: 34px; padding: 6px 12px; font-size: 12px; }
.manual-relay .mr-reply { width: 100%; box-sizing: border-box; resize: vertical; border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--bg-elevated); color: var(--ink); padding: 10px; font: inherit; margin-bottom: 11px; }
.manual-relay .mr-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.manual-relay button { min-height: 42px; padding: 9px; border-radius: var(--radius-sm); border: 0; font-weight: 700; }
.manual-relay .mr-send { background: var(--accent); color: var(--accent-ink); }
.manual-relay .mr-skip { background: transparent; color: var(--ink-dim); border: 1px solid var(--line-strong); }

/* Plan credit report (Auto-route) — a compact per-subtask bucket list plus
 * the overall estimated saving, shown once a plan run completes. */
.plan-credit { align-self: stretch; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-2); padding: 11px 13px; }
.plan-credit .pc-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; margin-bottom: 9px; font-size: 12.5px; }
.plan-credit .pc-saved { color: var(--ok); font-size: 11px; }
.plan-credit .pc-rows { display: grid; gap: 6px; }
.plan-credit .pc-row { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-dim); }
.plan-credit .pc-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plan-credit .pc-bucket { color: var(--ink-faint); font-size: 11px; }
.plan-credit .pc-real-cost { color: var(--ink-faint); font-size: 11px; font-variant-numeric: tabular-nums; }
.plan-credit .pc-cost { color: var(--ink-faint); font-size: 11px; font-variant-numeric: tabular-nums; margin-left: auto; }

/* Composer */
.composer { min-width: 0; overflow: hidden; border-top: 1px solid var(--line); background: color-mix(in srgb, var(--bg) 92%, transparent); padding: 9px 10px 11px; backdrop-filter: blur(16px); }
/* composer-top-row (2026-09-19, owner's ask): the paste chip used to live
 * inside .composer-row, the same fixed-width icon strip as attach/Council/
 * mic/send/stop -- none of those shrink, so the chip's extra ~128px pushed
 * Stop off the edge of narrow viewports. It's now its own row above the
 * message box, rightmost of the real attachment chips it sits next to, so
 * it can never compete with the send/stop controls for width again. */
.composer-top-row { width: min(100%, 840px); margin: 0 auto; display: flex; align-items: center; gap: 8px; }
.chips { width: auto; flex: 1 1 auto; margin: 0; display: flex; flex-wrap: wrap; gap: 6px; padding: 0 2px 7px; }
.chip { display: flex; align-items: center; gap: 6px; background: var(--surface-2); border: 1px solid var(--line); border-radius: 999px; padding: 5px 7px 5px 10px; font-size: 11px; color: var(--ink-dim); }
.chip:has(.chip-thumb) { padding-left: 3px; }
.chip-thumb { flex: none; width: 22px; height: 22px; border-radius: 50%; object-fit: cover; }
.chip-name { min-width: 0; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip button { border: 0; background: transparent; color: var(--ink-faint); padding: 0 2px; }
/* Owner's ask: pressing into the message box should surface whatever's on
 * the clipboard (screenshot, image, or text) as something tappable, instead
 * of relying on the OS's own long-press-to-paste gesture. Now sits in
 * .composer-top-row, rightmost, next to the real attachment chips (see
 * comment above) -- .clipboard-suggest-wrap is the fixed-size
 * overflow:hidden frame (matches .thread-wrap's own swipe-track pattern),
 * .clipboard-suggest is the actual button that gets dragged/dismissed by
 * attachClipboardGestures() in app.js. checkClipboardSuggestion() populates
 * it either from navigator.clipboard.read()/readText() (secure-context
 * browser path) or window.AndroidBridge.readClipboard() (the installed
 * app's native path, which a bare WebView needs since it has no
 * permission-dialog UI for the browser Clipboard API at all) or
 * RichContentWebView's own keyboard-commit bridge
 * (window.__nativeRichContent) for a screenshot offered directly by the
 * keyboard without ever touching the clipboard. */
.clipboard-suggest-wrap {
  flex: none; position: relative; width: 128px; height: 40px; border-radius: 14px;
  overflow: hidden; animation: clipboard-suggest-in 180ms ease-out; margin-bottom: 7px;
}
.clipboard-suggest {
  position: absolute; inset: 0; width: 100%; display: flex; align-items: center; gap: 6px;
  padding: 0 8px; border-radius: 14px; border: 1px solid rgba(20,156,255,.55);
  background: linear-gradient(180deg, var(--surface-2), var(--bg-elevated)); color: var(--ink); text-align: left;
  box-shadow: 0 0 0 1px rgba(25,120,255,.16), 0 0 10px rgba(0,216,255,.14);
  transform: translateX(0); transition: transform 200ms ease, box-shadow 150ms, border-color 150ms;
}
.clipboard-suggest:hover { border-color: var(--secondary); box-shadow: 0 0 0 1px rgba(0,216,255,.3), 0 0 14px rgba(0,216,255,.22); }
.clipboard-suggest-thumb { flex: none; width: 24px; height: 24px; border-radius: 8px; overflow: hidden; display: grid; place-items: center; font-size: 13px; background: var(--surface-3); }
.clipboard-suggest-thumb img { width: 100%; height: 100%; object-fit: cover; }
.clipboard-suggest-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0; }
.clipboard-suggest-body strong { font-size: 11px; line-height: 1.2; color: var(--secondary); }
.clipboard-suggest-body small { font-size: 9px; color: var(--ink-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }
@keyframes clipboard-suggest-in { from { opacity: 0; transform: scale(.9); } to { opacity: 1; transform: scale(1); } }
@media (max-width: 480px) { .clipboard-suggest-wrap { width: 108px; } }
/* Owner's ask: long-press the chip to choose from recently pasted items,
 * not just whatever's currently on the clipboard. Real Android clipboard
 * HISTORY isn't something any third-party app can read (the OS only ever
 * exposes the single current clip via ClipboardManager) -- this is our own
 * in-app history of items already successfully pasted through this
 * feature (pushClipboardHistory in app.js), session-only by design (not
 * persisted to localStorage: an image entry's own object URL wouldn't
 * survive a reload anyway, and a reload is rare in this long-lived WebView
 * app). position:fixed + portalled to <body>, same convention as
 * threadRowMenu/threadMoveMenu. */
.clipboard-history-menu { position: fixed; top: auto; bottom: auto; right: auto; left: auto; min-width: 220px; max-width: 280px; max-height: 320px; overflow-y: auto; }
.clipboard-history-menu button { display: flex; align-items: center; gap: 8px; width: 100%; }
.clipboard-history-item-thumb { flex: none; width: 28px; height: 28px; border-radius: var(--radius-sm); overflow: hidden; display: grid; place-items: center; font-size: 14px; background: var(--surface-2); }
.clipboard-history-item-thumb img { width: 100%; height: 100%; object-fit: cover; }
.clipboard-history-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clipboard-history-empty { padding: 9px 10px; font-size: 12px; color: var(--ink-faint); }
.council-composer-panel {
  width: min(100%, 840px); margin: 0 auto 8px; display: grid; gap: 8px;
  border: 1px solid color-mix(in srgb, var(--secondary) 45%, var(--line));
  border-radius: var(--radius-lg); background: color-mix(in srgb, var(--surface-2) 82%, var(--secondary) 6%);
  padding: 10px; box-shadow: 0 10px 26px rgba(0,0,0,.12);
}
.council-composer-head { display: grid; grid-template-columns: 34px minmax(0, 1fr) 34px; align-items: center; gap: 8px; }
.council-composer-icon {
  width: 34px; height: 34px; display: grid; place-items: center; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--secondary) 18%, var(--surface)); color: var(--secondary); font-weight: 800;
}
.council-composer-head strong { display: block; font-size: 13px; color: var(--ink); }
.council-composer-head small { display: block; margin-top: 2px; font-size: 10.5px; color: var(--ink-faint); }
.council-composer-close {
  width: 34px; height: 34px; display: grid; place-items: center; border: 1px solid color-mix(in srgb, var(--bad) 55%, var(--line));
  border-radius: 50%; background: color-mix(in srgb, var(--bad) 14%, var(--surface)); color: #ff9da3; font-weight: 900;
}
.council-mode-tabs {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px;
  padding: 4px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface);
}
.council-mode-tabs button {
  min-width: 0; min-height: 32px; border: 0; border-radius: var(--radius-sm); background: transparent;
  color: var(--ink-dim); font-size: 12px; font-weight: 800;
}
.council-mode-tabs button.on {
  background: color-mix(in srgb, var(--secondary) 16%, var(--surface-2));
  color: var(--ink); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--secondary) 42%, transparent);
}
.council-agent-picker { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.council-agent {
  min-width: 0; min-height: 36px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink-dim); font-size: 12px; font-weight: 750; padding: 7px 8px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.council-agent.council-engine {
  display: grid; grid-template-columns: 12px minmax(0, 1fr); align-items: center; gap: 7px; text-align: left;
}
.council-agent.council-engine span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.council-agent.on { border-color: color-mix(in srgb, var(--secondary) 62%, var(--line)); background: color-mix(in srgb, var(--secondary) 14%, var(--surface)); color: var(--ink); }
.council-composer-options { display: grid; grid-template-columns: minmax(0, 1fr); gap: 7px; }
.council-composer-options label { display: grid; gap: 5px; color: var(--ink-dim); font-size: 11.5px; min-width: 0; }
.council-composer-options input[type="number"], .council-composer-options select {
  width: 100%; min-height: 36px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg-elevated); color: var(--ink); padding: 7px 9px;
}
.council-composer-panel .muted { min-height: 14px; font-size: 11px; }
/* .checkline's own `display: flex !important` (below) ties in specificity
 * with the site-wide `[hidden] { display: none !important }` reset and,
 * being later in the file, wins the tie — so a `.checkline` element (like
 * the custom-roles checkbox below) needs its OWN higher-specificity hidden
 * override, or `hidden` silently does nothing on it. */
#councilCustomRolesWrap[hidden], #councilZenModelWrap[hidden] { display: none !important; }
#councilZenModelWrap select { min-height: 32px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-elevated); color: var(--ink); padding: 4px 8px; }
/* Local council's "Compare the following" — owner's ask: no fixed lens
 * list, a dynamic free-text list instead. These are appended straight into
 * .council-agent-picker (a 2-column grid shared with the online engine
 * picker), so each top-level piece needs to span both columns itself. */
.council-compare-toggle { grid-column: 1 / -1; }
.council-compare-list { grid-column: 1 / -1; display: grid; gap: 6px; }
.council-compare-row { display: grid; grid-template-columns: minmax(0, 1fr) 30px; gap: 6px; }
.council-compare-row input[type="text"] {
  min-width: 0; min-height: 34px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg-elevated); color: var(--ink); padding: 6px 9px; font-size: 12.5px;
}
.council-compare-remove {
  min-width: 0; min-height: 34px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink-faint); font-size: 15px; font-weight: 800;
}
.council-compare-remove:disabled { opacity: .35; }
.council-compare-add {
  grid-column: 1 / -1; min-height: 34px; border: 1px dashed var(--line-strong); border-radius: var(--radius-sm);
  background: transparent; color: var(--ink-dim); font-size: 12px; font-weight: 750;
}
.council-compare-add:disabled { opacity: .4; }
.council-role-picker { display: grid; gap: 6px; }
.council-role-row { display: grid; grid-template-columns: minmax(0, 110px) minmax(0, 1fr); align-items: center; gap: 7px; }
.council-role-row .agent-dot { flex: none; }
.council-role-engine { font-size: 11.5px; color: var(--ink-dim); font-weight: 750; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.council-role-row input[type="text"] {
  min-width: 0; min-height: 32px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg-elevated); color: var(--ink); padding: 6px 9px; font-size: 12px;
}

/* Council panel: the member/chairman breakdown rendered inline in the
 * thread, right above the chairman's synthesis message it belongs to
 * (see councilPanelsByMessageId in app.js) — columns instead of a thread
 * per member. */
.council-panel {
  width: min(100%, 840px); margin: 10px auto 4px; display: grid; gap: 8px;
  border: 1px solid color-mix(in srgb, var(--secondary) 38%, var(--line));
  border-radius: var(--radius-lg); background: color-mix(in srgb, var(--surface-2) 78%, var(--secondary) 5%);
  padding: 10px;
}
.council-panel-head { display: flex; align-items: baseline; gap: 8px; }
.council-panel-icon { color: var(--secondary); font-weight: 800; }
.council-panel-head strong { font-size: 12.5px; color: var(--ink); }
.council-panel-chair { margin-left: auto; font-size: 10.5px; color: var(--ink-faint); }
.council-panel-grid {
  display: grid; gap: 8px;
  grid-template-columns: repeat(var(--council-cols, 2), minmax(0, 1fr));
}
.council-panel-col {
  min-width: 0; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface);
  padding: 8px; font-size: 12px; color: var(--ink-dim);
}
.council-panel-col.failed { border-color: color-mix(in srgb, var(--bad) 45%, var(--line)); }
.council-panel-col.skipped { opacity: .6; }
.council-panel-colhead {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  font-size: 11px; font-weight: 800; color: var(--ink); margin-bottom: 5px;
}
.council-panel-coltext { font-size: 12px; line-height: 1.42; }
.council-panel-coltext p { margin: 0 0 6px; }
.council-conf { padding: 1px 6px; border-radius: 999px; font-size: 9px; text-transform: uppercase; background: var(--surface-2); color: var(--ink-faint); }
.council-conf.conf-high { color: color-mix(in srgb, var(--accent) 70%, var(--ink)); }
.council-conf.conf-low { color: color-mix(in srgb, var(--bad) 65%, var(--ink)); }
@media (max-width: 640px) {
  .council-panel-grid { grid-template-columns: repeat(1, minmax(0, 1fr)) !important; }
}

/* 2026-09-15 (transcript redesign §12): file-change-summary -- "N files
 * changed +X -Y" right after a turn's reply instead of raw diffs inline.
 * Collapsed by default (.fc-list hidden); each row is independently
 * expandable to its own diff text once the summary itself is opened. */
.file-change-summary {
  width: min(100%, 640px); margin: 4px auto; border: 1px solid var(--line);
  border-radius: var(--radius-lg); background: var(--surface-2); overflow: hidden;
}
.fc-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 12px; cursor: pointer; user-select: none; font-size: 12.5px; font-weight: 650;
}
.fc-total { font-weight: 600; font-variant-numeric: tabular-nums; }
.fc-add { color: var(--ok); }
.fc-del { color: var(--bad); }
.fc-list { display: none; border-top: 1px solid var(--line); }
.file-change-summary.expanded .fc-list { display: block; }
.fc-row {
  display: flex; align-items: center; gap: 8px; padding: 7px 12px; font-size: 12px;
  border-top: 1px solid var(--line);
}
.fc-row:first-child { border-top: none; }
.fc-row.expandable { cursor: pointer; }
.fc-row.expandable:hover { background: var(--surface); }
.fc-check { color: var(--ok); }
.fc-path { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.fc-stat { flex: none; font-variant-numeric: tabular-nums; font-size: 11px; }
.fc-stat.fc-tag { color: var(--ink-faint); text-transform: uppercase; letter-spacing: .03em; font-size: 9.5px; }
.fc-diff {
  margin: 0 12px 10px; padding: 8px; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-md); font-size: 11px; line-height: 1.5; overflow-x: auto;
  white-space: pre; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
@media (max-width: 640px) {
  .file-change-summary { width: 100%; }
}

/* 2026-09-15 (transcript redesign §21): council-live-card is a `.live-activity`
 * (same collapsed-headline/expand-chevron shell as "Currently doing") that
 * embeds a `.council-panel-grid` per-member status grid instead of the
 * finished panel's confidence badges + answer text -- status only, no
 * content, while the round is still running. */
.council-panel-col.live { transition: border-color .2s, opacity .2s; }
.council-panel-col.live.queued { opacity: .55; }
.council-panel-col.live.running { border-color: color-mix(in srgb, var(--activity-thinking, var(--secondary)) 55%, var(--line)); }
.council-panel-col.live.done { border-color: color-mix(in srgb, var(--ok) 40%, var(--line)); }
.council-panel-col.live.failed { border-color: color-mix(in srgb, var(--bad) 45%, var(--line)); }
.council-panel-col.live.skipped { opacity: .55; }
.council-status {
  padding: 1px 6px; border-radius: 999px; font-size: 9px; text-transform: uppercase;
  background: var(--surface-2); color: var(--ink-faint);
}
.council-status-running { color: color-mix(in srgb, var(--secondary) 70%, var(--ink)); animation: pulse 1.6s ease-in-out infinite; }
.council-status-done { color: color-mix(in srgb, var(--ok) 65%, var(--ink)); }
.council-status-failed { color: color-mix(in srgb, var(--bad) 65%, var(--ink)); }
/* .live-activity's own expand rule targets `ul` (the generic activity
 * list) specifically -- this card uses a `.council-panel-grid` div instead,
 * so it needs the same show/hide pairing or it would stay visible
 * regardless of the collapsed/expanded state. */
.live-activity .council-panel-grid { display: none; margin: 0 12px 10px; }
.live-activity.expanded .council-panel-grid { display: grid; }
/* §31's prefers-reduced-motion requirement (2026-09-16 accessibility pass:
 * found this was ALREADY fully covered, not a gap) -- a universal
 * *, *::before, *::after rule further down this file (search
 * prefers-reduced-motion) already neutralizes every animation/transition
 * on the page via animation-iteration-count:1 + near-zero durations, so a
 * per-animation override here was redundant duplication, not a real fix.
 * Removed rather than left as dead weight. */

/* Creator-attribution tags on thread/project cards (multi-user infra ask) */
.t-tag.t-creator-test { background: color-mix(in srgb, var(--bad) 16%, var(--surface-2)); color: color-mix(in srgb, var(--bad) 60%, var(--ink-dim)); }
.t-tag.t-creator-agent { background: color-mix(in srgb, var(--secondary) 16%, var(--surface-2)); color: var(--secondary); }
.t-tag.t-creator-system { background: var(--surface-2); color: var(--ink-faint); }
/* Composer shape (2026-09-17, owner's ask: match the reference mockups
   exactly) -- a real structural change, not spacing/color: the mockups show
   a standalone rounded message box (with its own expand affordance in the
   top-right corner) sitting ABOVE a separate row of independent circular/
   pill buttons, not one shared pill bar with everything inline. Previously
   .composer-row was that single shared bar (background/border/shadow) with
   the textarea + every button as flex children; now .composer-box owns the
   bordered rounded-rectangle chrome for just the textarea, and .composer-row
   is a plain unstyled flex row beneath it for the buttons alone. */
.composer-box {
  position: relative; width: 100%; max-width: 840px; min-width: 0; margin: 0 auto 8px;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius-xl);
  box-shadow: 0 9px 28px rgba(0,0,0,.13); transition: border-color 150ms, box-shadow 150ms;
}
.composer-box:focus-within { border-color: color-mix(in srgb, var(--accent) 72%, var(--line)); box-shadow: var(--glow); }
#input { display: block; width: 100%; box-sizing: border-box; min-width: 0; border: 0; background: transparent; resize: none; padding: 14px 40px 14px 16px; max-height: 30vh; line-height: 1.45; outline: none; }
#input::placeholder { color: var(--ink-faint); }
/* Recommended-next-prompt ghost text (owner's ask, 2026-09-21): the
   suggestion sits in #input's real value, selected -- styling the browser's
   own ::selection gray (instead of the usual accent-color highlight) is
   what makes it actually LOOK like inline ghost text rather than a normal
   text selection. Scoped to .ghost-active only, so a real selection the
   owner makes themselves (copy/paste, editing) still looks normal. */
#input.ghost-active::selection { background: color-mix(in srgb, var(--ink-faint) 35%, transparent); color: var(--ink-faint); }
.composer-expand {
  position: absolute; top: 8px; right: 8px; width: 26px; height: 26px; border: 0; border-radius: var(--radius-sm);
  display: grid; place-items: center; background: transparent; color: var(--ink-faint); opacity: .7;
  transition: opacity 150ms, background 150ms, color 150ms;
}
.composer-expand:hover { opacity: 1; background: var(--surface-2); color: var(--ink); }
.composer-box.expanded #input { max-height: 60vh; }
.composer-row {
  width: 100%; max-width: 840px; min-width: 0; margin: auto; display: flex; align-items: center; gap: 8px;
}
.composer-row .mic-wrap { margin-left: auto; }
/* Pill shape with a visible "Council" label (2026-09-17, owner's ask,
   matching the reference mockups) -- was a narrow icon+count square with
   no label at all. Scoped changes only touch this button and the two
   composer-only icon buttons below, not the app-wide .icon class dozens of
   other buttons (topbar, panels) share -- the ask was about the composer
   specifically, not a global icon-button reskin. */
.council-toggle {
  display: flex; align-items: center; gap: 5px; height: 44px; flex: none;
  border-radius: 999px; border: 1px solid var(--line);
  background: var(--surface-2); color: var(--ink-dim); font-weight: 850; padding: 0 12px 0 10px;
}
.council-toggle-label { font-size: 13px; font-weight: 750; }
.council-toggle small {
  min-width: 16px; height: 16px; display: grid; place-items: center; border-radius: 999px;
  background: var(--bg-elevated); color: var(--ink-faint); font-size: 10px; line-height: 1; padding: 0 3px;
}
.council-toggle.on { border-color: color-mix(in srgb, var(--secondary) 60%, var(--line)); color: var(--secondary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--secondary) 12%, transparent); }
.council-toggle.on small { background: var(--secondary); color: #001a20; }
/* Composer's own plus/mic buttons (2026-09-17): the shared .icon class is
   transparent until hover everywhere else in the app; the mockups show
   these two as always-visible bordered circles, matching the send/stop
   buttons' own always-visible circular treatment right next to them. */
.composer-row > .attach-wrap > .icon, .composer-row .mic-wrap > .icon {
  width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--line); background: var(--surface-2);
}
.composer-row > .attach-wrap > .icon:hover, .composer-row .mic-wrap > .icon:hover { background: var(--surface-3); }
@media (max-width: 480px) {
  .council-toggle-label { display: none; }
  .council-toggle { padding: 0 9px; }
}
.send, .stop { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; border: 0; flex: none; }
.send { background: linear-gradient(135deg, var(--accent), var(--violet)); color: var(--accent-ink); box-shadow: 0 6px 16px rgba(99,102,241,.25); }
.send.council-send { background: linear-gradient(135deg, var(--secondary), var(--accent)); color: #001a20; }
.send:disabled { background: var(--surface-2); color: var(--ink-faint); box-shadow: none; }
.stop { background: var(--ink); color: var(--bg); }
.icon.rec { color: var(--bad); animation: mic-pulse 1.1s ease-in-out infinite; }
.icon.busy { opacity: 0.55; pointer-events: none; }
@keyframes mic-pulse {
  0%, 100% { filter: drop-shadow(0 0 0 transparent); }
  50% { filter: drop-shadow(0 0 8px color-mix(in srgb, var(--bad) 70%, transparent)); }
}


/* Update prompt */
.update-bar {
  position: fixed; left: 50%; bottom: calc(env(safe-area-inset-bottom, 0px) + 76px); transform: translateX(-50%);
  z-index: 60; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 9px;
  width: min(430px, calc(100vw - 20px)); padding: 16px 44px 13px 14px;
  border-radius: var(--radius-md); background: var(--surface-2); border: 1px solid var(--line-strong);
  box-shadow: var(--shadow); font-size: 12px; color: var(--ink);
}
.update-bar #updateText { grid-column: 1 / -1; min-width: 0; line-height: 1.35; padding-right: 2px; font-weight: 650; }
.update-bar .update-btn { justify-self: start; border: 0; border-radius: var(--radius-sm); padding: 8px 12px; font-size: 11px; font-weight: 700; background: var(--accent); color: var(--accent-ink); white-space: nowrap; }
.update-bar .update-btn:disabled { opacity: .5; }
.update-bar .update-x {
  position: absolute; top: 8px; right: 8px; display: grid; place-items: center;
  width: 27px; height: 27px; padding: 0; border: 1px solid color-mix(in srgb, var(--bad) 75%, white);
  border-radius: 50%; background: color-mix(in srgb, var(--bad) 86%, #1a0b0b); color: white;
  font-size: 13px; font-weight: 900; line-height: 1; box-shadow: 0 6px 14px rgba(0,0,0,.18);
}
.update-bar .update-x:hover, .update-bar .update-x:focus-visible { filter: brightness(1.08); }
.panel-open .update-bar { opacity: 0; pointer-events: none; }

/* Manage panels */
/* Manage — modal bottom sheet (ChatGPT / Claude-app style) */
.panel-host {
  position: fixed; inset: 0; z-index: 40;
  display: flex; align-items: flex-end; justify-content: center;
  background: color-mix(in srgb, #000 50%, transparent);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  opacity: 0; transition: opacity 220ms ease;
}
.panel-host.open { opacity: 1; }
.panel-sheet {
  width: 100%; max-width: 840px; max-height: 92dvh;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--line-strong); border-bottom: 0;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  box-shadow: 0 -24px 64px rgba(0, 0, 0, .42);
  transform: translateY(100%);
  transition: transform 320ms cubic-bezier(.32, .72, 0, 1);
}
.panel-host.open .panel-sheet { transform: translateY(0); }
.sheet-handle { flex: none; width: 40px; height: 4px; margin: 8px auto 2px; border-radius: 999px; background: var(--line-strong); }
.panel-topbar {
  display: flex; align-items: center; gap: 4px; min-height: 52px; padding: 6px 8px 10px;
  border-bottom: 1px solid var(--line); background: transparent; font-weight: 750; font-size: 15px;
}
.panel-topbar #panelTitle { flex: 1; }
.manage-tabs {
  flex: none; display: flex; gap: 6px; overflow-x: auto; overscroll-behavior-x: contain;
  padding: 0 12px 10px; border-bottom: 1px solid var(--line); scrollbar-width: none;
}
.manage-tabs::-webkit-scrollbar { display: none; }
.manage-tab {
  flex: 0 0 auto; min-height: 34px; padding: 7px 10px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink-dim); font-size: 11px; font-weight: 750;
}
.manage-tab:hover { border-color: var(--line-strong); color: var(--ink); background: var(--surface-2); }
.manage-tab.active {
  border-color: color-mix(in srgb, var(--accent) 70%, var(--line));
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 72%, var(--surface)), color-mix(in srgb, var(--violet) 62%, var(--surface)));
  color: var(--accent-ink);
}
.pview[data-focus="agents"] .models-only,
.pview[data-focus="models"] .agents-only,
.pview[data-focus="connectors"] .skills-only,
.pview[data-focus="connectors"] .plugins-only,
.pview[data-focus="connectors"] .tools-only,
.pview[data-focus="skills"] .connectors-only,
.pview[data-focus="skills"] .plugins-only,
.pview[data-focus="skills"] .tools-only,
.pview[data-focus="plugins"] .connectors-only,
.pview[data-focus="plugins"] .skills-only,
.pview[data-focus="plugins"] .tools-only,
.pview[data-focus="automation"] .council-only,
.pview[data-focus="council"] .automation-only {
  display: none !important;
}
.panel-scroll {
  flex: 1; overflow-y: auto; overscroll-behavior: contain;
  padding: 14px 14px calc(24px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 12px;
}
.panel-scroll .pview { animation: pv-in 200ms ease; }
@keyframes pv-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* New-chat modal */
.modal { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; padding: 18px; }
.modal-scrim { position: absolute; inset: 0; background: color-mix(in srgb, #000 52%, transparent); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); opacity: 0; transition: opacity 180ms ease; }
.modal.open .modal-scrim { opacity: 1; }
.modal-card {
  position: relative; width: min(100%, 400px); display: flex; flex-direction: column; gap: 12px;
  background: var(--bg-elevated); border: 1px solid var(--line-strong); border-radius: var(--radius-lg);
  box-shadow: var(--shadow); padding: 16px;
  transform: translateY(12px) scale(.97); opacity: 0; transition: transform 200ms cubic-bezier(.32,.72,0,1), opacity 200ms ease;
}
.modal.open .modal-card { transform: none; opacity: 1; }
.modal-head { display: flex; align-items: center; justify-content: space-between; }
.modal-head h2 { font-size: 15px; font-weight: 750; }
.modal-card label { display: grid; gap: 5px; font-size: 12px; color: var(--ink-dim); }
.modal-card select, .modal-card input {
  width: 100%; min-height: 44px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-2); padding: 9px 11px; color: var(--ink); font-size: 14px;
}
.modal-card select:focus, .modal-card input:focus { outline: none; border-color: var(--accent); }
.modal-actions { display: grid; grid-template-columns: 1fr 1.4fr; gap: 8px; margin-top: 4px; }
.modal-actions button { min-height: 44px; border-radius: var(--radius-sm); border: 1px solid var(--accent); background: var(--accent); color: var(--accent-ink); font-weight: 700; }
.modal-actions button.ghost { background: var(--surface-2); border-color: var(--line); color: var(--ink-dim); }
.pv-card h3 { font-size: 13px; font-weight: 700; }
.pview { width: min(100%, 1040px); margin: 0 auto; }
.pview:not([hidden]) { display: flex; flex-direction: column; gap: 12px; }
.pview-head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 14px;
  padding: 2px 2px 6px; border-bottom: 1px solid color-mix(in srgb, var(--line) 72%, transparent);
}
.pview-head h2 { font-size: 20px; }
.pview-head p { max-width: 36ch; text-align: right; }
.pv-grid { display: grid; grid-template-columns: 1fr; gap: 12px; align-items: start; }
.pv-card { border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface); padding: 14px; display: flex; flex-direction: column; gap: 11px; box-shadow: 0 8px 22px rgba(0,0,0,.07); }
.pv-card h2 { font-size: 14px; letter-spacing: 0; }
.pv-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.pv-row-actions { display: flex; align-items: center; gap: 8px; }
.add-connector-reqs { margin: 4px 0 0; padding-left: 18px; color: var(--ink-dim); font-size: 12px; line-height: 1.5; }
.pv-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.pview label { display: grid; gap: 5px; color: var(--ink-dim); font-size: 12px; min-width: 0; }
.pview label.field-label { gap: 2px; }
.field-label span { color: var(--ink-faint); font-size: 10.5px; line-height: 1.35; }
.pview input, .pview select, .pview textarea { width: 100%; min-height: 42px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-elevated); padding: 9px 10px; color: var(--ink); }
.pview textarea { resize: vertical; }
.pview button { min-height: 44px; border-radius: var(--radius-sm); border: 1px solid var(--accent); background: var(--accent); color: var(--accent-ink); font-weight: 700; padding: 8px 12px; }
.pview button.ghost { min-height: 36px; background: var(--surface-2); border-color: var(--line); color: var(--ink-dim); }
.pv-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.voice-engine-order { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.voice-engine-order li { display: flex; align-items: center; gap: 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); padding: 8px 10px; }
.voice-engine-order .voice-engine-rank { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 999px; background: var(--accent); color: var(--accent-ink); font-size: 12px; font-weight: 700; flex-shrink: 0; }
.voice-engine-order .voice-engine-label { flex: 1; min-width: 0; font-size: 13px; }
.voice-engine-order .voice-engine-label small { display: block; color: var(--ink-faint); font-size: 11px; font-weight: 400; }
.voice-engine-order .voice-engine-reorder { display: flex; gap: 4px; }
.voice-engine-order .voice-engine-reorder button { min-height: 30px; min-width: 30px; padding: 0; font-size: 13px; }
.voice-engine-order .voice-engine-reorder button:disabled { opacity: .35; cursor: default; }
.voice-web-access-row { display: flex !important; flex-direction: row !important; align-items: center; gap: 8px; }
.voice-web-access-row input { width: auto !important; min-height: 0 !important; }
.pv-actions .ghost { flex: 1 1 150px; }
.pview code { background: var(--bg-elevated); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; color: var(--secondary); font-size: .85em; }
.pv-list { display: flex; flex-direction: column; gap: 8px; }
/* Connectors specifically (2026-09-17 redesign pass) -- the mockups show a
   card grid, not a single stacked column, for a list that's mostly short
   "icon + name + status badge" cards with room to spare. Scoped to this one
   container (.connectors-grid), not .pv-list itself, since that class is
   shared by many other panels (agents/skills/plugins/...) where a stacked
   list is still the right call -- their rows carry more text per item. */
.pv-list.connectors-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); align-items: start; }
.field-block {
  display: grid; gap: 7px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg-elevated); padding: 10px;
}
.field-title { color: var(--ink-dim); font-size: 12px; font-weight: 750; }
.project-edit-panel { margin-top: 6px; background: var(--surface-2); }
.root-checks { display: grid; grid-template-columns: 1fr; gap: 6px; max-height: 230px; overflow: auto; padding-right: 2px; }
.root-choice {
  min-height: 46px; align-items: flex-start !important; padding: 8px 9px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface);
}
.root-choice span, .connector-choice span { display: grid; gap: 2px; min-width: 0; }
.root-choice b { color: var(--ink); font-size: 12px; }
.root-choice small { color: var(--ink-faint); font-size: 10.5px; overflow-wrap: anywhere; }
.repo-output { max-height: 260px; overflow: auto; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; line-height: 1.5; white-space: pre-wrap; word-break: break-word; background: var(--bg-elevated); border: 1px solid var(--line); border-radius: var(--radius-md); padding: 10px; margin: 8px 0; color: var(--ink-faint); }
.project-manager-item { gap: 8px; transition: box-shadow 0.4s ease, border-color 0.4s ease; }
.project-row-highlight { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent); }
.project-manager-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.project-hidden { border-style: dashed; background: color-mix(in srgb, var(--surface-2) 68%, var(--bg-elevated)); }
.project-system { border-color: color-mix(in srgb, var(--secondary) 30%, var(--line)); }
.project-hidden-toggle {
  flex: 0 0 auto; display: inline-flex !important; flex-direction: row !important; align-items: center; gap: 6px;
  min-height: 30px; padding: 5px 8px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink-dim) !important; font-size: 10.5px; font-weight: 800;
}
.project-hidden-toggle input { width: auto; min-height: 0; accent-color: var(--accent); }
.project-hidden-toggle:has(input:checked) { color: var(--secondary) !important; border-color: color-mix(in srgb, var(--secondary) 55%, var(--line)); }
.project-hidden-toggle:has(input:disabled) { opacity: .55; }
.project-root-pills { display: flex; flex-wrap: wrap; gap: 5px; }
.project-root-pills span {
  max-width: 100%; padding: 3px 7px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface-2); color: var(--ink-dim); font-size: 10.5px; font-weight: 750;
}
.compact-check { min-height: 28px !important; color: var(--ink-dim) !important; font-size: 11px; }
.connector-checks { display: grid; grid-template-columns: 1fr; gap: 6px; max-height: 220px; overflow: auto; padding-right: 2px; }
.connector-choice {
  min-height: 44px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); padding: 7px 8px;
}
.connector-choice span { display: grid; gap: 1px; min-width: 0; }
.connector-choice b { color: var(--ink); font-size: 12px; overflow-wrap: anywhere; }
.connector-choice small { color: var(--ink-faint); font-size: 10.5px; overflow-wrap: anywhere; }
.item { border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-elevated); padding: 11px; display: grid; gap: 5px; }
.item .title { font-weight: 650; overflow-wrap: anywhere; }
.wf-cols { display: grid; grid-template-columns: 1fr; gap: 12px; margin-top: 4px; }
@media (min-width: 620px) { .wf-cols { grid-template-columns: 1fr 1fr; } }
.wf-h { margin: 0 0 4px; font-size: 12px; font-weight: 650; color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0; }
.wf-list { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.5; display: flex; flex-direction: column; gap: 4px; }
.item .meta { color: var(--ink-faint); font-size: 11px; display: flex; flex-wrap: wrap; gap: 4px 10px; overflow-wrap: anywhere; }
.item-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 3px; }
.item-actions button { min-height: 36px; padding: 6px 10px; flex: 0 1 auto; }
.agent-lanes { display: flex; flex-direction: column; gap: 8px; }
.agent-lane {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 10px;
  min-height: 54px; padding: 10px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg-elevated);
}
.agent-lane strong { display: block; font-size: 13px; }
.agent-lane small { display: block; margin-top: 2px; color: var(--ink-faint); font-size: 11px; line-height: 1.35; }
/* Same --engine-* variables the message accent bars use (see :root) — a
 * dot and its own message bubble can no longer show two different colors
 * for the same engine. */
.agent-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--engine-zen); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-zen) 60%, transparent); }
.agent-dot.codex { background: var(--engine-codex); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-codex) 55%, transparent); }
.agent-dot.claude { background: var(--engine-claude); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-claude) 55%, transparent); }
.agent-dot.local { background: var(--engine-local); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-local) 55%, transparent); }
.agent-dot.local-agent { background: var(--engine-local-agent); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-local-agent) 55%, transparent); }
.agent-dot.zen { background: var(--engine-zen); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-zen) 60%, transparent); }
.agent-dot.chatgpt-web { background: var(--engine-chatgpt-web); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-chatgpt-web) 55%, transparent); }
.agent-dot.claude-web { background: var(--engine-claude-web); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-claude-web) 55%, transparent); }
.agent-dot.grok { background: var(--engine-grok); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-grok) 55%, transparent); }
.agent-dot.openrouter { background: var(--engine-openrouter); box-shadow: 0 0 9px color-mix(in srgb, var(--engine-openrouter) 55%, transparent); }
.agent-grid, .skill-grid { display: grid; grid-template-columns: 1fr; gap: 8px; }
.agent-card, .skill-card, .route-card {
  min-width: 0; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg-elevated); padding: 11px; display: grid; gap: 8px;
}
.agent-card-head, .skill-card-head {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 9px;
}
.agent-card-head strong, .skill-card-head strong { display: block; font-size: 13px; overflow-wrap: anywhere; }
.agent-card-head small { display: block; color: var(--ink-faint); font-size: 10.5px; margin-top: 1px; }
.agent-tags { display: flex; flex-wrap: wrap; gap: 5px; }
.agent-runtime {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px;
}
.agent-runtime span {
  min-width: 0; border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 7px; background: var(--surface); overflow: hidden;
}
.agent-runtime b { display: block; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-runtime small { display: block; margin-top: 2px; color: var(--ink-faint); font-size: 10px; text-transform: uppercase; letter-spacing: 0; }
.agent-meter {
  position: relative; height: 6px; overflow: hidden; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--line);
}
.agent-meter i { display: block; height: 100%; background: var(--ok); }
.agent-meter.orange i, .agent-meter.warn i { background: var(--warn); }
.agent-meter.red i, .agent-meter.bad i { background: var(--bad); }
.agent-meter.unknown i { background: var(--ink-faint); }
.route-grid { display: grid; gap: 8px; }
.route-card strong { font-size: 13px; }
.route-card small { display: block; margin-top: 2px; color: var(--ink-faint); font-size: 11px; line-height: 1.35; overflow-wrap: anywhere; }
.skill-card p { margin: 0; color: var(--ink-dim); font-size: 12px; line-height: 1.45; overflow-wrap: anywhere; }
.connector-card, .model-card, .plugin-card, .observer-card { border-radius: var(--radius-sm); }
/* 2026-09-15: real per-connector/per-skill icons (Grok's Imagine-2 set, owner's ask) --
   falls back to no icon at all (onerror="this.remove()" in app.js) rather than a broken
   image glyph if a filename ever drifts from the real connector/skill id. */
.skill-icon { width: 28px; height: 28px; border-radius: 8px; object-fit: cover; align-self: start; }
.agent-icon-wrap { display: flex; align-items: center; gap: 6px; }
.agent-icon { width: 30px; height: 30px; border-radius: 9px; object-fit: cover; }
.connector-icon {
  width: 20px; height: 20px; border-radius: 6px; object-fit: cover;
  vertical-align: middle; margin-right: 7px; margin-bottom: 2px;
}
.model-runtime {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px;
}
.model-runtime span,
.setting-preview span,
.legend-grid span {
  min-width: 0; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg-elevated); padding: 8px 9px; color: var(--ink); font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.model-runtime small {
  display: block; margin-top: 2px; color: var(--ink-faint); font-size: 10px; text-transform: uppercase; letter-spacing: 0;
}
.theme-choice-row, .legend-grid, .setting-preview {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px;
}
.theme-choice-row button.on {
  border-color: color-mix(in srgb, var(--accent) 70%, var(--line));
  background: color-mix(in srgb, var(--accent) 14%, var(--surface-2));
  color: var(--ink);
}
.legend-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.legend-grid span { display: flex; align-items: center; gap: 8px; }
.sys-controls-row { display: flex; flex-wrap: wrap; gap: 8px; }
.sys-controls-row button { flex: 1 1 auto; min-width: 120px; }
.watchdog-item { padding: 10px 0; border-top: 1px solid var(--line); }
.watchdog-item:first-child { border-top: none; padding-top: 0; }
.watchdog-item .pv-row { margin-bottom: 4px; }
.watchdog-item .detail { white-space: pre-wrap; font-size: 12px; color: var(--ink-faint); margin: 4px 0; }
/* Notifications panel + Debug threads (System) — email-inbox-style rows:
 * unread bold + a tinted background, back to normal once opened/marked read. */
.notif-list { display: grid; gap: 6px; margin-top: 8px; }
/* `.pview button` (a blanket "every plain button in a Manage panel is a
 * solid-accent CTA" default, elsewhere in this file) beats a single class
 * on specificity (class+element > one class) — these rows need the extra
 * `.notif-list` ancestor qualifier just to win that tie, not because the
 * rule is wrong on its own. */
.notif-list .notif-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; text-align: left; min-height: 44px; padding: 9px 10px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-elevated); color: var(--ink-dim); font-weight: 500;
}
.notif-list .notif-row.unread { font-weight: 750; color: var(--ink); background: color-mix(in srgb, var(--accent) 12%, var(--bg-elevated)); border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.notif-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.notif-meta { flex: none; display: flex; align-items: center; gap: 6px; font-size: 10.5px; color: var(--ink-faint); font-weight: 500; }
.notif-row.unread .notif-meta { color: var(--ink-dim); }
/* Local-agent model switch: a real GPU-load is underway (bench() forces
 * Ollama to actually load + answer), not just a preference write — this
 * is the "wheel to indicate it's loading" the owner asked for. */
.spinner-dot {
  display: inline-block; width: 9px; height: 9px; margin-right: 2px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--accent) 35%, transparent); border-top-color: var(--accent);
  animation: spinner-spin .7s linear infinite; vertical-align: -1px;
}
@keyframes spinner-spin { to { transform: rotate(360deg); } }
.engine-color-list { display: grid; gap: 6px; }
.engine-color-row {
  display: grid; grid-template-columns: minmax(0, 1fr) 44px; align-items: center; gap: 8px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-elevated); padding: 8px 9px;
}
.engine-color-row span { font-size: 12.5px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.engine-color-row input[type="color"] {
  width: 40px; height: 28px; padding: 0; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: transparent; cursor: pointer;
}
.setting-preview { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.setting-preview span { text-align: center; color: var(--ink-dim); }
.council-default-choice { align-items: flex-start; }
.mini-actions { display: flex; gap: 6px; flex-wrap: wrap; }
#memHandoffOutput { max-height: 56vh; }
ul.mem-list { margin: 2px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--ink-dim); overflow-wrap: anywhere; }
#memoryView .item-actions button.danger { color: #ff9da3; border-color: color-mix(in srgb, var(--bad) 42%, var(--line)); }
.badge { display: inline-block; border-radius: 999px; padding: 2px 8px; font-size: 10px; font-weight: 800; border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-dim); }
.badge.ok { border-color: var(--ok); color: var(--ok); }
.badge.bad { border-color: var(--bad); color: var(--bad); }
.badge.warn { border-color: var(--warn); color: var(--warn); }
.badge.mut { opacity: .72; }
.checkline { display: flex !important; flex-direction: row !important; align-items: center; gap: 8px; color: var(--ink) !important; min-height: 36px; }
.checkline input { width: auto; min-height: 0; accent-color: var(--accent); }
pre { overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 12px; line-height: 1.55; color: var(--ink-dim); background: var(--bg-elevated); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 11px; max-height: 45vh; }

/* Project navigation */
.project-heading { display: flex; align-items: center; border-radius: var(--radius-md); margin-top: 8px; }
.project-heading.active { background: var(--surface-2); }
.project-heading button { min-height: 46px; border: 0; background: transparent; color: inherit; }
.project-toggle, .project-add { flex: 0 0 44px; padding: 0; font-size: 20px; }
.project-name { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 650; }
.project-threads { margin-left: 20px; padding-left: 6px; border-left: 1px solid var(--line-strong); }
.project-empty { color: var(--ink-faint); font-size: 12px; padding: 8px; margin: 0; }
.project-heading button:focus-visible { outline: 2px solid var(--secondary); outline-offset: -2px; }

@media (min-width: 720px) {
  .quick-actions { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .panel-scroll { padding: 22px; }
  .pv-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pv-span { grid-column: 1 / -1; }
  .agent-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .skill-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .connector-checks { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .model-runtime { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .council-agent-picker { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .council-composer-options { grid-template-columns: minmax(0, 1fr) 116px minmax(0, .8fr) minmax(0, .7fr); align-items: end; }
}

@media (min-width: 960px) {
  #app { grid-template-columns: 310px minmax(0, 1fr); grid-template-rows: auto 1fr; }
  #drawer { position: relative; grid-column: 1; grid-row: 1 / 3; width: 310px; height: 100%; transform: none; z-index: 15; box-shadow: none; }
  #scrim { display: none !important; }
  #menuBtn { display: inline-flex; }
  .topbar { grid-column: 2; grid-row: 1; padding-left: 18px; padding-right: 18px; }
  #chat { grid-column: 2; grid-row: 2; }
  .topbar-title { text-align: left; }
  .topbar-subtitle { justify-content: flex-start; }
  .panel-host { align-items: center; }
  .panel-sheet { max-width: min(1120px, calc(100vw - 42px)); max-height: 86vh; border: 1px solid var(--line-strong); border-radius: var(--radius-xl); }
  .panel-host:not(.open) .panel-sheet { transform: translateY(24px); }
  .update-bar { bottom: 24px; }
  /* 2026-09-26 (owner's live report): desktop had no way to hide the
     sidebar at all -- #menuBtn (the only toggle) was force-hidden here,
     and the mobile swipe-to-close gesture is touch-only, so a trackpad/
     mouse user had zero path to reclaim that width. Reusing the same
     button as a real collapse/expand toggle on desktop instead of a
     mobile-only "open the overlay" button. */
  #app.drawer-collapsed { grid-template-columns: 0 minmax(0, 1fr); }
  #app.drawer-collapsed #drawer { display: none; }
}

@media (max-width: 420px) {
  .messages { padding-left: 10px; padding-right: 10px; }
  .msg.user { max-width: 88%; }
  .quick-action { padding: 9px; }
  .quick-action small { display: none; }
  .pv-2 { grid-template-columns: 1fr; }
  .pview-head { align-items: flex-start; flex-direction: column; }
  .pview-head p { text-align: left; }
  .topbar { gap: 5px; padding-left: 7px; padding-right: 7px; }
  .topbar-engine { max-width: 92px; }
  .session-settings-menu { inset: auto 0 0 0; width: 100%; max-height: min(82vh, 650px); overflow-y: auto; border-radius: 22px 22px 0 0; padding: 17px 14px max(18px, env(safe-area-inset-bottom)); }
  .session-option { min-height: 62px; }
  .composer { padding-left: 8px; padding-right: 8px; }
}


@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

/* ---------- System panel (Phase 7) ---------- */
.sys-summary { font-size: 12px; line-height: 1.5; padding: 2px 2px 6px; }
.sys-banner { font-size: 11px; font-weight: 700; border-radius: var(--radius-md); padding: 7px 10px; border: 1px solid var(--line); }
.sys-banner.ok { border-color: var(--ok); color: var(--ok); background: color-mix(in srgb, var(--ok) 8%, transparent); }
.sys-banner.warn { border-color: var(--warn); color: var(--warn); background: color-mix(in srgb, var(--warn) 10%, transparent); }
.sys-picks { display: flex; flex-direction: column; gap: 6px; margin-bottom: 4px; }
.sys-pick-row { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-dim); text-transform: capitalize; }
.sys-pick-row select { margin-left: auto; max-width: 62%; font-size: 12px; }
.sys-chip { font-size: 10px; padding: 3px 7px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--line); color: var(--ink-dim); white-space: nowrap; }
.sys-pull { gap: 6px; }
.sys-pull input { flex: 1; min-width: 0; }
.item .meta.bad { color: var(--bad); }


.engine-usage-control {
  display: flex; flex: 0 1 128px; min-width: 86px; align-items: center; overflow: hidden;
  border-radius: 16px; box-shadow: inset 0 1px rgba(255,255,255,.07), 0 6px 18px rgba(0,0,0,.12);
}
.engine-usage-control .topbar-engine { width: 100%; min-width: 0; }
.engine-usage-control:has(select[hidden]) { display: none; }
/* #enginePicker is real state now (every other call site still reads/
   writes its .value/.hidden/.disabled), not a rendered control -- its
   `hidden` attribute is toggled for that state (the :has() rule above
   reads it), not for its own visibility, so it needs an unconditional,
   always-on display:none independent of that attribute. Without this a
   native <select> box rendered at its natural (long-option-text-driven)
   content width fights #enginePickerBtn for space in the same row and
   flex-shrinks the button down to almost nothing -- a real bug caught live
   in-browser, not a hypothetical. */
#enginePicker { display: none !important; }
[data-quota="green"] { --quota-color: var(--ok); }
[data-quota="orange"] { --quota-color: var(--warn); }
[data-quota="red"] { --quota-color: var(--bad); }
[data-quota="unknown"] { --quota-color: var(--ink-faint); }
.topbar-engine[data-quota] {
  position: relative; z-index: 1; font-weight: 800;
  background: linear-gradient(90deg, color-mix(in srgb, var(--quota-color) 38%, var(--surface-2)) 0 var(--quota-fill, 0%), var(--surface-2) var(--quota-fill, 0%) 100%);
  box-shadow: inset 0 1px rgba(255,255,255,.08), inset 0 -8px 16px rgba(0,0,0,.10);
}
.session-settings-menu { max-height: calc(100dvh - 90px); overflow-y: auto; }
.quota-settings { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.quota-settings h3 { font-size: 13px; margin: 0 0 8px; }
.quota-card { padding: 10px; margin-bottom: 8px; background: var(--bg-elevated); border: 1px solid var(--line); border-radius: var(--radius-md); }
.quota-card-head { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.quota-percent { color: var(--quota-color); flex: 1; font-weight: 600; }
.quota-card button, .quota-timer button { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 7px 9px; font-size: 12px; }
.quota-details, .quota-help { color: var(--ink-faint); font-size: 11px; line-height: 1.5; margin-top: 6px; overflow-wrap: anywhere; }
.quota-timer { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.quota-timer label { flex: 1; }
.quota-timer input { width: 70px; min-width: 0; padding: 6px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm); }

.council-preset-row {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.council-preset-row button {
  min-height: 32px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink-dim); font-size: 11px; font-weight: 750;
}
.council-composer-panel .council-preset-row button {
  min-height: 30px; background: var(--bg-elevated);
}
.council-preset-row button:hover { border-color: var(--line-strong); color: var(--ink); }
.council-preset-row button.on, .council-preset-row button[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--secondary) 62%, var(--line));
  background: color-mix(in srgb, var(--secondary) 14%, var(--surface));
  color: var(--ink);
}
.pview .council-preset-row button {
  min-height: 34px; background: var(--surface-2); border-color: var(--line); color: var(--ink-dim);
}
.pview .council-preset-row button.on, .pview .council-preset-row button[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--secondary) 62%, var(--line));
  background: color-mix(in srgb, var(--secondary) 14%, var(--surface));
  color: var(--ink);
}
.delegate-chips {
  width: min(100%, 840px); margin: 0 auto 8px; display: flex; flex-wrap: wrap; gap: 6px;
}
.delegate-chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 28px; padding: 4px 10px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--surface-2);
  color: var(--ink-dim); font-size: 11px; font-weight: 700;
}
.delegate-chip.running { border-color: color-mix(in srgb, var(--warn) 55%, var(--line)); color: var(--warn); }
.delegate-chip.ok { border-color: color-mix(in srgb, var(--ok) 55%, var(--line)); color: var(--ok); }
.delegate-chip.bad { border-color: color-mix(in srgb, var(--bad) 55%, var(--line)); color: var(--bad); }
.health-line {
  margin: 0; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px; line-height: 1.5; color: var(--ink-dim);
  background: var(--bg-elevated); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 11px; overflow-wrap: anywhere;
}
.observe-report { white-space: pre-wrap; font-size: 12px; line-height: 1.5; color: var(--ink-dim); margin: 0; }
.err { color: var(--bad); }
#chiefView .item-actions button.danger { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 42%, var(--line)); background: var(--surface-2); }
.chief-board { display: flex; flex-direction: column; gap: 16px; }
.chief-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.chief-group-head h3 { margin: 0; font-size: 13px; font-weight: 650; color: var(--ink-dim); letter-spacing: 0.02em; text-transform: uppercase; }
.chief-group-body { display: flex; flex-direction: column; gap: 8px; }
.chief-card-summary {
  display: block; width: 100%; text-align: left; background: transparent; border: 0;
  color: inherit; padding: 0; cursor: pointer;
}
.chief-card.open { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.chief-chip {
  display: inline-flex; align-items: center; padding: 1px 7px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--ink-faint); font-size: 11px; margin-right: 4px;
}
.chief-card-detail { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.chief-route-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
@media (max-width: 640px) { .chief-route-grid { grid-template-columns: 1fr; } }
.chief-plan-steps {
  margin: 0; white-space: pre-wrap; font-size: 12px; line-height: 1.45; color: var(--ink-dim);
  background: var(--bg-elevated); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px;
}
:root[data-theme="light"] .chief-chip { color: var(--ink-dim); }

/* 2026-09-15 visual refinement — ChatGPT redesign, merged onto live UI */
#app { user-select: none; }
#messages, #messages .msg, #messages .md, #messages .msg-body, #messages .council-panel { user-select: text; }
.msg-actions, .msg-actions * { user-select: none; }
/* 2026-09-17 real bug found (owner's ask: Android's native paste-suggestion
 * strip wasn't appearing over the message box) -- the #app-wide
 * user-select:none above was only ever overridden back to `text` for
 * message-bubble content, never for actual editable form fields. Every
 * <input>/<textarea> in the app (composer included) was inheriting
 * user-select:none, which is exactly the kind of thing that makes Chrome-
 * on-Android suppress its own text-selection/paste-suggestion UI on a
 * field, since that UI's whole premise is "this text can be selected."
 * The app-wide rule above was clearly meant to stop accidental selection
 * of UI chrome (buttons/labels) while scrolling, not to disable selection
 * inside fields the owner actually types into. */
#app input, #app textarea, #app [contenteditable] { user-select: text; }

.jump-bottom {
  grid-row: 3; grid-column: 1; align-self: end; justify-self: center; z-index: 18;
  width: 48px; height: 48px; margin-bottom: 12px; display: grid; place-items: center;
  border-radius: 50%; border: 1px solid var(--line-strong);
  background: color-mix(in srgb, var(--surface-2) 94%, transparent); color: var(--ink);
  box-shadow: 0 10px 30px rgba(0,0,0,.28); backdrop-filter: blur(14px);
}
.jump-bottom[hidden] { display: none; }

.composer { min-width: 0; overflow-x: hidden; padding: 8px 10px max(10px, env(safe-area-inset-bottom)); }
.composer-row { min-width: 0; overflow: hidden; }
.composer-box #input { min-height: 40px; max-height: 36vh; }
.council-composer-panel {
  width: min(100%, 840px); max-height: min(58vh, 560px); overflow: auto; box-sizing: border-box;
}
.council-agent-picker, .council-composer-options, .council-agent { min-width: 0; }
.council-mode-tabs, .council-preset-row { max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.council-mode-tabs::-webkit-scrollbar, .council-preset-row::-webkit-scrollbar { display: none; }

.message-edit-card { border-radius: 24px; padding: 14px; }
.message-edit-card textarea { min-height: 220px; border-radius: 16px; }
.message-edit-actions { align-items: center; flex-wrap: wrap; }
.message-edit-actions .edit-start { margin-right: auto; }

.live-activity li.live-info::before { background: var(--secondary); }
.live-activity li.live-write::before { background: var(--warn); }
.live-activity li.live-wait::before { background: var(--ink-faint); }

@media (max-width: 720px) {
  .topbar { gap: 5px; padding-inline: 7px; }
  .topbar-logo { width: 24px; height: 24px; }
  .engine-usage-control { flex-basis: 112px; }
  .council-composer-panel { max-height: 52vh; }
  .msg.user { max-width: 88%; }
  /* Verified live at 390px (2026-09-16): .msg-actions button was 30x30 with
     no mobile override, and .topbar .icon was shrunk to 38x38 here -- both
     under the 44px touch-target minimum, worst exactly where touch is the
     only input. msg-actions-bottom already wraps (flex-wrap: wrap), so
     growing the hit area doesn't risk new overflow. */
  .msg-actions button { width: 44px; height: 44px; }
  .msg-actions span { font-size: 16px; }

  #app { grid-template-rows: auto 1fr auto; }
  .mobile-tab-bar {
    display: grid; grid-template-columns: repeat(5, 1fr);
    border-top: 1px solid var(--line); background: var(--surface); padding: 4px 2px calc(4px + env(safe-area-inset-bottom, 0px));
  }
  .mt-tab {
    display: grid; justify-items: center; gap: 2px; padding: 6px 2px; min-height: 48px;
    background: none; border: none; color: var(--ink-faint); font-size: 10px; font-weight: 650;
  }
  .mt-tab[aria-current="page"] { color: var(--secondary); }
}
@media (max-width: 480px) {
  .topbar-logo { display: none; }
  .engine-usage-control { flex-basis: 104px; min-width: 72px; }
  .topbar-title { text-align: left; }
  .topbar-subtitle { justify-content: flex-start; }
}

/* Reference-led interface refresh: consistent glyphs, compact primary controls. */
.composer { border-top: 1px solid var(--line-strong); background: var(--bg-elevated); }
.composer-box { border-color: color-mix(in srgb, var(--secondary) 28%, var(--line)); border-radius: 18px; }
.composer-row { gap: 10px; padding-top: 8px; }
.composer-row .icon, .composer-row .send, .composer-row .stop { width: 46px; height: 46px; flex: 0 0 46px; border-radius: 50%; }
.composer-row .icon { border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink-dim); }
.composer-row .send { background: linear-gradient(135deg, var(--accent), #087dff); box-shadow: 0 4px 16px color-mix(in srgb, var(--accent) 25%, transparent); }
.council-toggle { min-height: 44px; border-color: color-mix(in srgb, var(--violet) 42%, var(--line)); }
.council-toggle > span:first-child, .council-composer-icon, #threadCouncilBtn .session-option-icon { color: var(--violet); }
.council-toggle[aria-pressed="true"] { background: color-mix(in srgb, var(--violet) 22%, var(--surface)); border-color: var(--violet); }
#attachMenu { width: min(300px, calc(100vw - 24px)); padding: 8px; border-radius: 18px; }
#attachMenu button { display: grid; grid-template-columns: 30px 1fr; column-gap: 10px; min-height: 64px; align-items: center; padding: 10px; }
#attachMenu button svg { grid-row: span 2; color: var(--secondary); }
#attachMenu button small { grid-column: 2; margin: 0; }
.session-settings-trigger[aria-expanded="true"] { color: var(--secondary); border-color: var(--secondary); background: var(--surface-2); }
.session-options { gap: 8px; }
.session-option { border-radius: 14px; min-height: 72px; }
#threadCouncilBtn { --mode-color: var(--violet); }
#observeBtn { --mode-color: var(--secondary); }
#fullHostBtn { --mode-color: var(--ok); }
#approveAllBtn { --mode-color: var(--warn); }
#privacyBtn { --mode-color: var(--accent); }
.session-option .session-option-icon { color: var(--mode-color); background: color-mix(in srgb, var(--mode-color) 10%, var(--surface)); border-radius: 50%; }
.session-option[aria-pressed="true"] { border-color: color-mix(in srgb, var(--mode-color) 60%, var(--line)); background: color-mix(in srgb, var(--mode-color) 8%, var(--surface)); }
.session-option[aria-pressed="true"] .session-option-state { color: var(--mode-color); }
.msg-actions-bottom { gap: 6px; border-top: 1px solid var(--line); padding-top: 10px; }
.msg-actions-bottom button { width: 46px; height: 46px; border: 1px solid var(--line); border-radius: 13px; background: var(--surface); }
.msg-actions-bottom button svg { width: 19px; height: 19px; }
.msg-actions-bottom button[data-message-action="delete"] { color: var(--bad); margin-left: auto; }
.manage-tabs { flex-wrap: wrap; overflow: visible; padding-top: 8px; gap: 6px; }
.manage-tab { min-height: 40px; border-radius: 10px; }
.manage-more { width: 100%; color: var(--ink-dim); font-size: 12px; }
.manage-more summary { cursor: pointer; padding: 10px 4px; min-height: 40px; }
.manage-more-items { display: flex; flex-wrap: wrap; gap: 6px; padding-bottom: 8px; max-height: 160px; overflow: auto; }
.manage-card { border-radius: 16px; transition: border-color .15s, background .15s; }
.manage-card .mc-icon { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 13px; background: color-mix(in srgb, var(--secondary) 10%, var(--surface)); color: var(--secondary); }
.manage-card[data-panel="council"] .mc-icon, .manage-card[data-panel="skills"] .mc-icon { color: var(--violet); background: color-mix(in srgb, var(--violet) 12%, var(--surface)); }
.manage-card[data-panel="projects"] .mc-icon { color: var(--ok); }
.manage-card[data-panel="security"] .mc-icon { color: var(--warn); }
.manage-card:hover { border-color: var(--secondary); background: var(--surface-2); }
.mt-tab[aria-current="page"] { background: color-mix(in srgb, var(--accent) 18%, var(--surface)); border-radius: 12px; color: var(--ink); }
button:focus-visible, summary:focus-visible { outline: 2px solid var(--secondary); outline-offset: 3px; }
@media (max-width: 720px) {
  .topbar { flex-wrap: wrap; }
  .topbar-title { flex: 1; min-width: 90px; }
  #topRefresh { display: none; }
  .manage-tabs > .manage-tab { min-height: 40px; }
  .manage-tabs { gap: 4px; }
  .manage-tabs > .manage-tab:nth-of-type(n+6) { display: none; }
  .composer-row { gap: 7px; }
  .mobile-tab-bar { padding-inline: 6px; gap: 4px; }
}
@media (prefers-reduced-motion: reduce) { .manage-card { transition: none; } }
/* Explicit labels remain readable on phones; state colors match their mode. */
.council-toggle-label { display: inline; }
.session-option.on .session-option-state,
#observeBtn.on .session-option-state,
#fullHostBtn.on .session-option-state,
#privacyBtn.on .session-option-state { color: var(--bg); background: var(--mode-color); }
@media (max-width: 400px) {
  .composer-row { gap: 5px; }
  .composer-row .icon, .composer-row .send, .composer-row .stop { width: 44px; height: 44px; flex-basis: 44px; }
  .council-toggle { padding-inline: 9px; gap: 5px; }
}
.message-more { margin-left: auto; }
.message-more summary { min-height: 46px; padding: 12px; cursor: pointer; color: var(--ink-dim); border: 1px solid var(--line); border-radius: 13px; font-size: 12px; }
.message-more[open] { flex-basis: 100%; }
.message-more-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.msg-actions .message-more-actions button { width: auto; min-width: 64px; height: auto; min-height: 44px; gap: 6px; padding: 9px; }
.msg-actions .message-more-actions small { position: static; width: auto; height: auto; clip-path: none; font-size: 11px; }
.connector-card .title { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.connector-card .connector-icon { width: 36px; height: 36px; object-fit: contain; flex: 0 0 36px; }
.connector-card .item-actions button { min-height: 44px; background: var(--surface-2); color: var(--ink-dim); border: 1px solid var(--line-strong); }

/* Owner's September 19 visual handoff — compact density pass. */
:root {
  --ah-primary-gradient: linear-gradient(135deg,#275cff 0%,#6248ff 56%,#7b36ff 100%);
  --ah-selection-gradient: linear-gradient(90deg,rgba(35,88,255,.34),rgba(103,62,255,.22));
}
:root[data-theme="dark"] {
  --bg: #06111f; --bg-elevated: #030914; --surface: #0b192b;
  --surface-2: #10223a; --surface-3: #142a47; --line: #1b4a73;
  --line-strong: #276798; --ink: #f5f8ff; --ink-dim: #b3c8e4; --ink-faint: #8fa6c2;
  --accent: #7048ff; --secondary: #00d8ff; --violet: #7048ff;
  --ok: #00e49a; --warn: #ffc62a; --bad: #ff4d5a;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #06111f; --bg-elevated: #030914; --surface: #0b192b;
    --surface-2: #10223a; --surface-3: #142a47; --line: #1b4a73;
    --line-strong: #276798; --ink: #f5f8ff; --ink-dim: #b3c8e4; --ink-faint: #8fa6c2;
    --accent: #7048ff; --secondary: #00d8ff; --violet: #7048ff;
    --ok: #00e49a; --warn: #ffc62a; --bad: #ff4d5a;
  }
}
/* 2026-09-26 (owner's live report, real bug): this width formula (92vw
   capped at 390px) is sized for a mobile overlay drawer -- unscoped, it
   was also winning (later in source order) over the desktop grid-column
   width set above, at both 310px and later 360px, so the drawer rendered
   wider than the grid track allotted to it and visibly overflowed into
   the topbar/chat column on desktop, clipping the thread title's leading
   characters. Scoped to below the 960px desktop breakpoint; the desktop
   rule right after this makes the drawer just fill its grid column
   instead of hardcoding a second px value that has to be kept in sync. */
@media (max-width: 959px) {
  #drawer { width: min(92vw,390px); }
}
@media (min-width: 960px) {
  #drawer { width: 100%; }
}
#drawer { background: var(--bg); padding-top: env(safe-area-inset-top); }
#scrim { backdrop-filter: blur(22px); }
.drawer-brand { padding: 14px 16px; gap: 8px; border: 0; flex-shrink: 0; }
.drawer-brand .brand-img { width: 46px; height: 46px; flex-shrink: 0; }
.drawer-brand > div:nth-child(2) { overflow: hidden; }
.drawer-brand strong { font-size: 22px; font-weight: 730; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer-brand span { font-size: 13px; color: var(--ink-faint); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer-status-row { display: flex; align-items: center; gap: 6px; margin-left: auto; padding: 0; flex-shrink: 0; }
.connection-pill { display: inline-flex; gap: 5px; align-items: center; height: 30px; padding: 0 8px; border: 1px solid color-mix(in srgb,var(--connection-color) 35%,transparent); border-radius: 16px; color: var(--connection-color); background: color-mix(in srgb,var(--connection-color) 6%,var(--bg)); font-size: 12px; white-space: nowrap; }
.connection-pill[data-connection="connected"] { --connection-color: var(--ok); }
.connection-pill[data-connection="reconnecting"] { --connection-color: var(--warn); }
.connection-pill[data-connection="disconnected"] { --connection-color: var(--bad); }
.connection-pill[data-connection="offline"] { --connection-color: var(--ink-faint); }
.connection-pill .dot { background: var(--connection-color); width: 7px; height: 7px; box-shadow: 0 0 8px color-mix(in srgb,var(--connection-color) 40%,transparent); }
.connection-pill[data-connection="reconnecting"] .dot { animation: dotBounce 1.8s ease-in-out infinite; }

/* F11 (2026-09-25 review): the connection-pill above already tracks live
   websocket state (setConn()), but it's tucked inside the side drawer --
   invisible unless the drawer happens to be open. This banner surfaces the
   SAME state (same dataset.connection values) at the top of the main chat
   view, where a dropped connection is actually likely to be noticed. */
.reconnect-bar {
  display: none; align-items: center; gap: 7px; flex-shrink: 0;
  padding: 7px 14px; font-size: 12px; font-weight: 650; color: var(--connection-color);
  background: color-mix(in srgb, var(--connection-color) 12%, var(--bg));
  border-bottom: 1px solid color-mix(in srgb, var(--connection-color) 30%, transparent);
}
.reconnect-bar[data-connection="reconnecting"], .reconnect-bar[data-connection="offline"] { display: flex; }
.reconnect-bar[data-connection="reconnecting"] { --connection-color: var(--warn); }
.reconnect-bar[data-connection="offline"] { --connection-color: var(--ink-faint); }
.reconnect-bar .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--connection-color); flex-shrink: 0; }
.reconnect-bar[data-connection="reconnecting"] .dot { animation: dotBounce 1.8s ease-in-out infinite; }
.drawer-head { padding: 4px 16px 8px; gap: 10px; flex-shrink: 0; align-items: center; }
.drawer-head .new-btn { min-height: 56px; padding: 8px 14px; border-radius: 16px; color: #fff; font-size: 19px; font-weight: 700; background: var(--ah-primary-gradient); border: 1px solid #8b82ff; box-shadow: inset 0 1px 0 #ffffff42,0 0 16px #7048ff28; display: flex; align-items: center; gap: 8px; }
.new-btn img { width: 22px; height: 22px; }
#drawerMenuBtn { width: 52px; height: 52px; border-radius: 14px; border: 1px solid var(--line); background: var(--surface); }
#drawerMenu { z-index: 30; }
#drawerMenu #manageBtn { width: 100%; justify-content: flex-start; }
#drawerMenu #themeButton { width: 100%; margin: 0; text-align: left; border-radius: 0; }
.thread-search { height: 46px; min-height: 46px; margin: 0 16px 10px; padding: 0 12px; border-radius: 14px; border: 1px solid var(--line); flex-shrink: 0; }
.thread-search > img { width: 18px; height: 18px; }
.thread-search input { font-size: 15px; }
.thread-search-kbd { flex: none; font-size: 11px; font-weight: 600; color: var(--ink-faint); border: 1px solid var(--line); border-radius: 7px; padding: 4px 7px; line-height: 1; height: 26px; display: inline-flex; align-items: center; box-sizing: border-box; }
.thread-list { padding: 0 16px 8px; }
.sidebar-project { border: 1px solid var(--line); border-radius: 14px; margin-bottom: 8px; overflow: visible; }
.project-heading { min-height: 50px; padding: 2px; gap: 0; border-radius: 12px; background: var(--surface); border-bottom: 1px solid var(--line); }
.project-heading .project-toggle, .project-heading .project-add { min-width: 40px; min-height: 40px; }
.project-heading .project-name { display: flex; gap: 8px; align-items: center; font-size: 18px; font-weight: 680; min-height: 40px; }
.project-count { padding: 3px 9px; background: var(--surface-3); border-radius: 14px; color: var(--ink-dim); font-size: 12px; min-height: 22px; display: inline-flex; align-items: center; box-sizing: border-box; }
.project-brand { width: 22px; height: 22px; object-fit: contain; }
.project-threads { padding: 2px; }
.thread-wrap { border-radius: 12px; margin-bottom: 2px; }
.thread { min-height: 66px; padding: 10px 8px; gap: 10px; border-radius: 12px; background: var(--bg); border: 1px solid transparent; border-bottom-color: color-mix(in srgb,var(--line) 50%,transparent); }
.thread.active, .thread.active.has-job { border: 1px solid var(--violet); background: var(--ah-selection-gradient); box-shadow: inset 3px 0 var(--secondary),0 0 10px #7048ff44; animation: none; }
.thread-engine-tile { width: 40px; height: 40px; flex: 0 0 40px; display: grid; place-items: center; border-radius: 12px; border: 1px solid var(--eng); background: color-mix(in srgb,var(--eng) 12%,var(--bg-elevated)); box-shadow: 0 0 8px color-mix(in srgb,var(--eng) 12%,transparent); }
.thread-engine-tile .vendor-icon { width: 28px; height: 28px; }
.thread-engine-tile > svg { width: 22px; height: 22px; }
.vendor-icon { width: 100%; height: 100%; object-fit: contain; display: block; border-radius: 3px; }
.who-badge:has(.vendor-icon) { background: var(--surface-2); padding: 2px; }
.t-title { font-size: 16px; font-weight: 700; }
.t-sub { margin-top: 3px; gap: 5px; font-size: 13px; }
.t-sub .state-dot { flex: 0 0 6px; width: 6px; height: 6px; }
.t-time { margin-left: 0; }
.drawer-foot { padding: 8px 16px calc(8px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); flex-shrink: 0; }
.drawer-user { min-height: 64px; display: flex; align-items: center; gap: 10px; min-width: 0; }
.drawer-user > img { width: 40px; height: 40px; padding: 7px; border-radius: 50%; background: var(--ah-primary-gradient); border: 1px solid #9180ff; }
.drawer-user > div { display: grid; gap: 3px; min-width: 0; }
.drawer-user strong { font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer-user small { font-size: 12px; color: var(--ink-faint); }
.drawer-settings-btn { width: 44px; height: 44px; min-width: 44px; flex: 0 0 44px; border-radius: 50%; border: 1px solid var(--line); background: var(--surface); color: var(--ink-faint); transition: color .15s, border-color .15s; }
.drawer-settings-btn:hover { color: var(--ink); border-color: var(--line-strong); }
.drawer-settings-btn svg { width: 22px; height: 22px; }
.session-settings-trigger { width: 40px; height: 40px; }
.topbar-logo { display: none; }
.topbar { min-height: 54px; }
.engine-usage-control { flex: 1 1 110px; max-width: 200px; }
.topbar-title { text-align: left; }
.topbar-subtitle { justify-content: flex-start; }
#app:not(:has(#chat[hidden])) > .mobile-tab-bar { display: none; }
.composer-row { max-width: 100%; }
#councilToggleBtn { gap: 5px; }
#councilToggleCount { position: static; }
@media (max-width: 719px) {
  .topbar-title { display: none; }
  .topbar { gap: 6px; padding: 5px 8px; }
  .engine-usage-control { flex: 1 1 90px; }
  #topRefresh { width: 34px; min-width: 34px; }
}
@media (prefers-reduced-motion: reduce) {
  .connection-pill .dot, .thread.has-job { animation: none; }
}
@media (min-width: 960px) {
  #app { grid-template-columns: 360px minmax(0,1fr); }
}
.t-sub .state-dot.st-ok { background: var(--ok); }
.t-sub .state-dot.st-bad { background: var(--bad); }
.t-sub .state-dot.st-wait { background: var(--warn); }
.project-heading { margin-top: 0; }
.engine-usage-control .topbar-engine { flex: 1 1 auto; max-width: none; min-height: 36px; height: 36px; }
#councilToggleCount { width: auto; min-width: 18px; height: 18px; padding: 0 4px; font-size: 10px; }
.thread-search > img, .drawer-head .new-btn img, .drawer-user > img { filter: invert(1); }
:root[data-theme="light"] .thread-search > img { filter: none; }
.selected-engine-icon { width: 24px; height: 24px; margin-left: 8px; flex: 0 0 24px; display: grid; place-items: center; }
.selected-engine-icon > svg { width: 18px; height: 18px; }
.engine-usage-control { border: 1px solid var(--line); }
.engine-usage-control .topbar-engine { border: 0; border-radius: 0; box-shadow: none; }

/* ---- Top bar + composer neon shell (2026-09-19 handoff, visual only) ----
   Scoped to .topbar/.composer descendants rather than the shared .icon /
   .popover-menu classes those elements borrow, so this doesn't bleed into
   the drawer, session-settings panel or other menus that reuse the same
   base classes. Every state below binds to a real, already-toggled
   class/attribute (aria-pressed, aria-expanded, hidden, data-quota, .rec,
   .on) -- nothing here invents new state. */
.topbar {
  min-height: 82px; gap: 10px; padding: 12px 14px;
  background: linear-gradient(180deg, rgba(6,17,31,.98), rgba(3,9,20,.96));
  border-bottom: 1px solid rgba(27,74,115,.85);
  box-shadow: 0 10px 30px rgba(0,0,0,.22);
}
.topbar > .icon {
  width: 48px; height: 48px; min-width: 48px; border-radius: 16px;
  border: 1px solid rgba(27,74,115,.95);
  background: linear-gradient(180deg, var(--surface-2), var(--bg-elevated));
  color: var(--ink);
  box-shadow: 0 0 0 1px rgba(25,120,255,.2), 0 0 14px rgba(0,216,255,.10);
  transition: border-color 150ms, box-shadow 150ms, transform 150ms, background 150ms;
}
.topbar > .icon:hover { background: linear-gradient(180deg, var(--surface-3), var(--surface-2)); color: var(--ink); }
.topbar > .icon:active { transform: scale(.95); }
.topbar .session-settings-trigger.has-overrides,
.topbar .icon[aria-expanded="true"] {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(112,72,255,.7), 0 0 18px rgba(112,72,255,.32);
}
.topbar .notif-bell-badge { box-shadow: 0 0 0 2px var(--bg-elevated), 0 0 10px rgba(255,77,90,.65); }
.topbar .icon.spinning { border-color: var(--secondary); box-shadow: 0 0 0 1px rgba(0,216,255,.5), 0 0 14px rgba(0,216,255,.3); }

.engine-usage-control {
  min-height: 54px; border-radius: 18px;
  border: 1px solid rgba(25,120,255,.55);
  background: linear-gradient(180deg, rgba(11,25,43,.92), rgba(6,15,28,.96));
  box-shadow: 0 0 0 1px rgba(25,120,255,.16), 0 0 16px rgba(0,216,255,.10);
}
.engine-usage-control .topbar-engine { height: 52px; min-height: 52px; font-size: 14px; font-weight: 720; }
.selected-engine-icon { width: 30px; height: 30px; flex: 0 0 30px; margin-left: 10px; border-radius: 9px; background: var(--surface-3); }
.selected-engine-icon > svg { width: 20px; height: 20px; }
[data-quota="green"] { --quota-color: var(--secondary); }
.topbar-engine[data-quota] {
  box-shadow: inset 0 1px rgba(255,255,255,.08), inset 0 -8px 16px rgba(0,0,0,.10), 0 0 12px color-mix(in srgb, var(--quota-color) 35%, transparent);
}
.engine-picker-btn {
  display: flex; align-items: center; gap: 8px; width: 100%; height: 100%;
  border: 0; background: transparent; padding: 0 12px; text-align: left; font: inherit; color: inherit;
}
.engine-picker-btn:disabled { opacity: .5; pointer-events: none; }
.engine-picker-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Composer shell */
.composer {
  padding: 10px 14px max(14px, env(safe-area-inset-bottom));
  background: linear-gradient(180deg, rgba(3,9,20,0), rgba(3,9,20,.92) 20%, rgba(3,9,20,.99));
  border-top: 1px solid rgba(27,74,115,.7);
}
.composer-box {
  border-radius: 24px;
  border: 1px solid rgba(20,156,255,.7);
  background: linear-gradient(180deg, var(--surface), rgba(7,19,34,.96));
  box-shadow: 0 0 0 1px rgba(112,72,255,.16), 0 0 20px rgba(0,216,255,.12);
}
.composer-box:focus-within {
  border-color: rgba(112,72,255,.85);
  box-shadow: 0 0 0 1px rgba(112,72,255,.5), 0 0 26px rgba(0,216,255,.22);
}
#input { min-height: 30px; font-size: 16px; }

/* + / attach button */
.composer-row > .attach-wrap > .icon {
  border: 1px solid rgba(27,74,115,.95);
  background: linear-gradient(180deg, var(--surface-2), var(--bg-elevated));
  box-shadow: 0 0 0 1px rgba(25,120,255,.2), 0 0 12px rgba(0,216,255,.10);
}
.composer-row > .attach-wrap > .icon[aria-expanded="true"] {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(112,72,255,.7), 0 0 18px rgba(112,72,255,.4);
  color: #fff;
}

/* Council chip -- count already lives inside the button (.council-toggle
   small), matching the spec; this only reskins colour/glow per state. */
.council-toggle {
  border-radius: 999px;
  border: 1px solid rgba(112,72,255,.55);
  background: linear-gradient(180deg, rgba(16,28,53,.92), rgba(9,17,32,.96));
  box-shadow: 0 0 0 1px rgba(112,72,255,.12), 0 0 10px rgba(112,72,255,.10);
  color: var(--ink);
}
.council-toggle > span:first-child { color: var(--accent); }
.council-toggle small { background: rgba(6,17,31,.7); border: 1px solid rgba(255,255,255,.14); color: var(--ink); }
.council-toggle.on {
  background: linear-gradient(135deg, #5329d8, #8f42ff);
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(112,72,255,.7), 0 0 22px rgba(112,72,255,.4);
  color: #fff;
}
.council-toggle.on small { background: rgba(6,17,31,.55); border-color: rgba(255,255,255,.3); color: #fff; }

/* Mic + voice-active state (.rec is the real toggled class, see dictation
   code in app.js -- no waveform/listening-timer panel exists in the live
   app to restyle, so only the button treatment is implemented here). */
.composer-row .mic-wrap > .icon {
  border: 1px solid rgba(27,74,115,.95);
  background: linear-gradient(180deg, var(--surface-2), var(--bg-elevated));
  box-shadow: 0 0 0 1px rgba(25,120,255,.2), 0 0 12px rgba(0,216,255,.10);
}
.composer-row .mic-wrap > .icon.rec {
  color: #fff; border-color: var(--bad);
  background: radial-gradient(circle, #a51f43 0%, #32101e 62%, #0d1c31 100%);
  box-shadow: 0 0 0 3px rgba(255,77,90,.14), 0 0 22px rgba(255,77,90,.58);
  animation: mic-pulse 1.25s ease-in-out infinite;
}

/* Send / Stop */
.composer-row .send {
  background: linear-gradient(135deg, #275cff 0%, #6248ff 56%, #00c9ff 100%);
  box-shadow: 0 0 0 1px rgba(25,120,255,.3), 0 0 20px rgba(25,120,255,.45);
}
.composer-row .send:active { transform: scale(.95); }
.composer-row .send:disabled { background: var(--surface-2); box-shadow: none; color: var(--ink-faint); }
.composer-row .stop {
  background: #22111c; border: 1px solid var(--bad); color: #fff;
  box-shadow: 0 0 0 1px rgba(255,77,90,.3), 0 0 20px rgba(255,77,90,.5);
}
.composer-row .stop:active { transform: scale(.95); box-shadow: 0 0 0 2px rgba(255,77,90,.4), 0 0 26px rgba(255,77,90,.65); }

/* + menu: frosted navy popover with per-item accent glow, matching the
   colour mapping in the handoff's ICON_MAP (file=cyan, image=purple). */
#attachMenu.popover-menu {
  min-width: 220px; padding: 8px; gap: 4px; border-radius: 18px;
  border: 1px solid rgba(27,74,115,.95);
  background: rgba(8,21,37,.96);
  box-shadow: 0 18px 48px rgba(0,0,0,.45), 0 0 20px rgba(0,216,255,.08);
  backdrop-filter: blur(18px);
}
#attachMenu .am-item {
  display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 13px;
  border: 1px solid rgba(27,74,115,.6); background: rgba(11,25,43,.6);
}
#attachMenu .am-item:hover, #attachMenu .am-item:focus-visible { background: rgba(16,34,58,.85); }
#attachMenu .am-item .am-copy small { display: block; color: var(--ink-faint); margin-top: 2px; font-size: 11px; }
#attachMenu .am-item[data-kind="file"] { color: var(--secondary); }
#attachMenu .am-item[data-kind="file"]:hover { border-color: var(--secondary); box-shadow: 0 0 14px rgba(0,216,255,.22); }
#attachMenu .am-item[data-kind="image"] { color: var(--accent); }
#attachMenu .am-item[data-kind="image"]:hover { border-color: var(--accent); box-shadow: 0 0 14px rgba(112,72,255,.26); }
#attachMenu .am-item .am-copy { color: var(--ink); }

/* Engine picker popover (2026-09-20, owner's ask): replaces the old bare
   native <select> list, which could only ever take a couple of CSS
   properties on <option> (many WebViews ignore even those, painting native
   OS picker chrome instead) and had no way to hold per-row icons. Every row
   reuses the exact same quotaView() the topbar box and Usage tab already
   compute, so an engine with no live quota data honestly renders as the
   grey "unknown" fill rather than a fabricated color -- previously the
   closed box only ever showed ONE engine's color at a time (whichever was
   selected), which made it look like the fill only worked for Codex/Claude
   when really every engine shares this same logic, most others just don't
   have live quota data most of the time. */
/* Deliberately doesn't redeclare colors here -- .popover-menu (base class,
   already on this element) supplies border/background/shadow from
   var(--surface)/var(--line-strong)/var(--shadow), which already flip with
   :root[data-theme="light"] for free. Only position/sizing need overriding
   for the body-reparented fixed-position placement (same technique as
   .mic-mode-menu above). */
.engine-picker-menu {
  position: fixed; top: auto; bottom: auto; right: auto; left: auto;
  min-width: 240px; max-width: 280px; max-height: 70vh; overflow-y: auto;
}
.engine-picker-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 10px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--surface-2); color: var(--ink); text-align: left; font-size: 13px;
}
.engine-picker-item:hover, .engine-picker-item:focus-visible { background: var(--surface-3); }
.engine-picker-item:disabled { opacity: .45; pointer-events: none; }
.engine-picker-item[aria-selected="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px rgba(112,72,255,.5); }
.engine-picker-item[data-quota] {
  background: linear-gradient(90deg, color-mix(in srgb, var(--quota-color) 32%, var(--surface-2)) 0 var(--quota-fill, 0%), var(--surface-2) var(--quota-fill, 0%) 100%);
}
.engine-picker-item-icon { width: 22px; height: 22px; flex: 0 0 22px; display: grid; place-items: center; border-radius: 7px; background: var(--surface-3); }
.engine-picker-item-icon > svg { width: 16px; height: 16px; }
.engine-picker-item-icon .vendor-icon { width: 16px; height: 16px; }
.engine-picker-item-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 650; }
.engine-picker-item-status { flex: 0 0 auto; font-size: 11px; font-weight: 700; color: var(--quota-color, var(--ink-faint)); }

/* "/" chat commands (2026-09-22) -- opens upward from the composer, see
   web/app.js's slashMenu. Reuses .engine-picker-item's row styling; adds a
   second description line since a command has no icon/status to show. */
.slash-menu-item { flex-direction: column; align-items: flex-start; gap: 2px; }
.slash-menu-desc { font-size: 12px; color: var(--ink-faint); font-weight: 400; }

.drawer-brand { flex-wrap: wrap; gap: 12px; }
.drawer-brand .brand-img { width: 56px; height: 56px; }
.drawer-brand strong { font-size: 27px; }
.drawer-brand .drawer-status-row { flex: 0 0 100%; justify-content: space-between; }
.drawer-brand .connection-pill { display: inline-flex; height: 36px; color: var(--connection-color); }
.drawer-head .new-btn { min-height: 70px; border-radius: 20px; }
#drawerMenuBtn { width: 60px; height: 60px; border-radius: 18px; }
.thread-search { height: 52px; min-height: 52px; border-radius: 16px; }
.project-heading { min-height: 54px; }
.thread { min-height: 78px; }
.thread-engine-tile { width: 48px; height: 48px; flex-basis: 48px; }
.thread-engine-tile .vendor-icon { width: 34px; height: 34px; }
.drawer-user { min-height: 70px; }

.thread .t-title { font-size: 16px; font-weight: 700; }
.thread .t-sub { font-size: 12px; }
.connection-pill #connText { color: inherit; }
/* Keep the existing light theme readable alongside the navy default. */
:root[data-theme="light"] .composer { background: var(--bg); }
:root[data-theme="light"] .composer-box,
:root[data-theme="light"] #attachMenu.popover-menu,
:root[data-theme="light"] #attachMenu .am-item,
:root[data-theme="light"] .council-toggle:not(.on) { background: var(--surface); }
:root[data-theme="light"] .council-toggle:not(.on) small { background: var(--surface-2); }
/* ---- Left drawer top shell + Manage tile nav (2026-09-20, final neon
   handoff). Brand row keeps the real logo/title; connection state and
   search moved out of it per spec. New/overflow/settings all reuse their
   existing ids and click handlers -- only markup position and skin
   changed. */
.drawer-brand { flex-wrap: nowrap; }
.drawer-brand-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-shrink: 0; }
/* Plain neon gear (2026-09-20, owner's ask): reverted the 4-socket radial
   mode-wheel a different concurrent thread had put here -- this button
   only ever needs to say "open Manage", not display live Council/Observe/
   Full-Access/Auto state (the topbar's #sessionSettingsBtn still shows
   that, unchanged, whenever a thread is open). */
.drawer-settings-btn {
  width: 48px; height: 48px; flex: 0 0 48px;
  border-color: rgba(0,216,255,.45);
  box-shadow: 0 0 0 1px rgba(0,216,255,.16), 0 0 14px rgba(0,216,255,.14);
}

/* Overflow (Select multiple / Delete all chats / Theme / Manage shortcut)
   moved out of the brand row -- it was crowding the logo/title next to the
   settings gear. Lives beside search now, same trigger/popover/handlers,
   just relocated. */
.drawer-search-row { display: flex; align-items: center; gap: 8px; padding: 0 16px 10px; }
.drawer-search-row .thread-search { flex: 1; min-width: 0; margin: 0; }
.drawer-search-row .drawer-head-menu { position: relative; flex: none; }
.drawer-search-row #drawerMenuBtn {
  width: 46px; height: 46px; border-radius: 14px; flex: 0 0 46px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-faint);
}
.drawer-search-row #drawerMenuBtn:hover { color: var(--ink); border-color: var(--line-strong); }
.drawer-search-row .popover-menu { right: 0; left: auto; }

.drawer-quickbar {
  display: grid; grid-template-columns: 1.2fr .9fr 1fr; gap: 10px;
  padding: 6px 16px 12px; flex-shrink: 0;
}
.dq-btn {
  min-height: 58px; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 0 10px; border-radius: 14px; border: 1px solid rgba(20,156,255,.5);
  background: linear-gradient(180deg, var(--surface-2), var(--bg-elevated));
  color: var(--ink); font-weight: 700; font-size: 13px;
  box-shadow: 0 0 0 1px rgba(25,120,255,.14), 0 0 10px rgba(0,216,255,.08);
}
.dq-btn img { width: 20px; height: 20px; flex: none; }
.dq-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dq-primary.new-btn {
  min-height: 58px; padding: 0 14px; border-radius: 14px; font-size: 16px; font-weight: 700;
  color: #fff; background: var(--ah-primary-gradient); border: 1px solid #8b82ff;
  box-shadow: inset 0 1px 0 #ffffff42, 0 0 16px #7048ff28;
}
.dq-primary.new-btn img { width: 20px; height: 20px; }

/* Manage dashboard: left nav rail + right content pane (2026-09-20, FINAL
   Manage dashboard neon handoff). Replaces the 2-col pin-tile grid from the
   previous pass -- no pins anywhere in this version, per that handoff's
   explicit "NO PINS" directive. .panel-sheet becomes a column of
   [sticky header][.manage-body], and .manage-body is the two-zone row:
   nav rail left (independently scrollable), .panel-scroll right
   (independently scrollable) -- avoids the nested-scroll trap the spec
   calls out. */
.panel-sheet { border-radius: 28px 28px 0 0; }
.panel-topbar { position: sticky; top: 0; z-index: 2; background: var(--bg-elevated); }
.manage-body { display: flex; flex: 1; min-height: 0; overflow: hidden; }
.manage-body .panel-scroll { min-width: 0; }
.manage-nav-rail {
  flex: 0 0 140px; width: 140px; overflow-y: auto; overscroll-behavior: contain;
  padding: 10px 8px; border-right: 1px solid var(--line); background: color-mix(in srgb, var(--bg-elevated) 60%, var(--bg));
}
.manage-nav-group { display: flex; flex-direction: column; gap: 4px; }
.manage-nav-divider { height: 1px; margin: 8px 4px; background: color-mix(in srgb, var(--secondary) 18%, var(--line)); }
.manage-nav-item {
  position: relative; min-height: 48px; display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 14px; border: 1px solid transparent;
  color: var(--ink-dim); text-align: left; cursor: pointer;
}
.manage-nav-item:hover { background: var(--surface-2); color: var(--ink); }
.manage-nav-item.active {
  color: #fff; border-color: rgba(0,216,255,.55);
  background: linear-gradient(100deg, rgba(112,72,255,.95), rgba(25,120,255,.55) 70%, rgba(0,216,255,.55));
  box-shadow: 0 0 18px rgba(112,72,255,.32), inset 0 0 14px rgba(0,216,255,.10);
}
.manage-nav-item.active .mni-icon { color: #fff; filter: none; }
.mni-icon { flex: 0 0 26px; width: 26px; height: 26px; display: grid; place-items: center; }
.mni-icon svg { width: 20px; height: 20px; }
.mni-icon-img img { width: 22px; height: 22px; border-radius: 6px; object-fit: contain; }
.mni-label { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc-cyan { color: var(--secondary); }
.acc-blue { color: #1978FF; }
.acc-purple { color: var(--accent); }
.acc-magenta { color: #A447FF; }
.acc-green { color: var(--ok); }
.acc-amber { color: var(--warn); }
.acc-coral { color: #FF8C68; }
.acc-white { color: var(--ink); }
@media (max-width: 359px) {
  .manage-nav-rail { flex-basis: 64px; width: 64px; }
  .mni-label { display: none; }
  .manage-nav-item { justify-content: center; padding: 6px 0; }
}
@media (min-width: 720px) {
  .manage-nav-rail { flex-basis: 260px; width: 260px; }
  .mni-label { font-size: 14px; }
}

/* Bottom user card: connection state now lives here (real state, same
   #connDot/#connText the app already updates) instead of the brand row. */
.drawer-user > div { gap: 4px; }
.drawer-user .connection-pill { height: 22px; padding: 0 7px; font-size: 11px; gap: 4px; width: fit-content; }

/* An unrelated concurrent edit re-inflated the brand title to 27px after
   this session's own 22px fix (see styles.css history around line 1924 vs
   2166) -- with the new brand-actions cluster now sharing the row, 27px
   truncates to "Agent H…" at 390px. Re-assert the compact size here, last
   in the cascade, so "Agent Hub" fits next to the actions cluster. */
.drawer-brand strong { font-size: 21px; font-weight: 730; }

/* Manage Overview card rearrangement (2026-09-20, FINAL Manage dashboard
   handoff): hero + decorative orbit, AI OS status card, greeting, Quick
   Actions, System Health, then existing real content (recent chats +
   the richer os-snapshot grid) lower down. */
.manage-hero { position: relative; overflow: hidden; display: block; }
.manage-hero-orbit {
  position: absolute; top: -30px; right: -30px; width: 150px; height: 150px; border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, rgba(112,72,255,.45), rgba(25,120,255,.22) 55%, transparent 75%);
  filter: blur(2px); pointer-events: none;
}
.manage-hero .manage-kicker { position: relative; }
.manage-hero h2 { position: relative; font-size: 26px; font-weight: 750; margin: 2px 0 0; }
.manage-hero-sub { color: var(--ink-faint) !important; }

.manage-status-card {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px; width: 100%;
  padding: 14px 16px; border-radius: 20px; border: 1px solid rgba(42,140,220,.58);
  background: linear-gradient(145deg, rgba(16,34,58,.95), rgba(7,22,40,.96));
  color: var(--ink); text-align: left; cursor: pointer;
}
.manage-status-card:hover { border-color: var(--secondary); }
.manage-status-card:active { transform: scale(.985); }
.msc-icon {
  flex: 0 0 52px; width: 52px; height: 52px; display: grid; place-items: center; border-radius: 50%;
  border: 1px solid rgba(0,216,255,.5); color: var(--secondary);
  box-shadow: 0 0 14px rgba(0,216,255,.18);
}
.msc-body { flex: 1 1 200px; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.msc-title-row { display: flex; align-items: center; gap: 10px; font-size: 16px; font-weight: 750; }
.msc-status { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 700; color: var(--ok); }
.msc-sub { font-size: 12px; color: var(--ink-dim); }
.msc-stats {
  display: flex; width: 100%; gap: 8px; padding-top: 12px; margin-top: 2px;
  border-top: 1px solid color-mix(in srgb, var(--secondary) 14%, var(--line));
}
.msc-stat { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.msc-stat span { font-size: 18px; font-weight: 750; font-variant-numeric: tabular-nums; }
.msc-stat small { font-size: 11px; color: var(--ink-faint); }

.manage-health-row {
  display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 8px;
  padding: 14px 10px; border-radius: 18px; border: 1px solid rgba(42,140,220,.58);
  background: linear-gradient(145deg, rgba(16,34,58,.95), rgba(7,22,40,.96));
}
.health-cell { display: flex; flex-direction: column; align-items: center; gap: 5px; text-align: center; }
.health-cell strong { font-size: 11px; font-weight: 700; color: var(--ink-dim); }
.health-cell small { font-size: 11px; color: var(--ink-faint); }
.health-cell .state-dot { width: 16px; height: 16px; border-radius: 50%; background: transparent; border: 2px solid var(--ink-faint); }
.health-cell .state-dot.completed { border-color: var(--ok); box-shadow: 0 0 8px color-mix(in srgb, var(--ok) 55%, transparent); }
.health-cell .state-dot.waiting_approval { border-color: var(--warn); }
.health-cell .state-dot.failed { border-color: var(--bad); }
@media (max-width: 480px) { .manage-health-row { grid-template-columns: repeat(2, minmax(0,1fr)); } }

.manage-tip-card {
  display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px;
  border-radius: 16px; border: 1px solid var(--line); background: var(--bg-elevated);
}
.manage-tip-card .tip-icon { flex: none; font-size: 16px; filter: drop-shadow(0 0 6px rgba(164,71,255,.5)); }
.manage-tip-card strong { font-size: 12px; }
.manage-tip-card p { margin: 2px 0 0; font-size: 12px; color: var(--ink-dim); }

.dq-icon { width: 18px; height: 18px; display: inline-flex; }
.dq-icon svg { width: 18px; height: 18px; }

/* Manage UI: full-screen mobile sheet + collapsible nav-rail drawer
   (2026-09-20, owner's ask: "give more space for the right panel... so
   its easy to use"). Below the existing 960px side-by-side breakpoint, the
   sheet takes the whole viewport and the nav rail becomes an overlay
   drawer (position:absolute, off-canvas via transform) instead of a
   permanent flex sibling -- .panel-scroll is always full width now, the
   rail floats on top of it only while open. Desktop keeps the previous
   always-visible side-by-side rail unchanged. */
@media (max-width: 959px) {
  .panel-host { align-items: stretch; background: var(--bg); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .panel-sheet { max-width: 100%; height: 100dvh; max-height: 100dvh; border-radius: 0; border: 0; box-shadow: none; }
  .manage-body { position: relative; }
  .manage-nav-rail {
    position: absolute; inset: 0 auto 0 0; z-index: 5; width: min(78vw, 260px);
    box-shadow: 16px 0 40px rgba(0,0,0,.5); border-right: 1px solid rgba(0,153,255,.5);
    background: var(--bg-elevated);
    transform: translateX(0); transition: transform 240ms cubic-bezier(.32,.72,0,1);
  }
  .manage-nav-rail .mni-label { display: block; font-size: 14px; }
  .manage-nav-rail.collapsed { transform: translateX(-100%); }
  .manage-scrim {
    position: absolute; inset: 0; z-index: 4; background: rgba(0,4,10,.55);
    opacity: 1; transition: opacity 220ms ease;
  }
  .manage-scrim[hidden] { display: block; opacity: 0; pointer-events: none; }
}
@media (min-width: 960px) { #manageNavToggle { display: none; } }

/* Topbar thread-settings gear (2026-09-20, owner's ask, round 3): rounds 1-2
   gave this its own bigger circular treatment, distinct from its siblings.
   The owner's device photos showed that circle doubled up with a native
   Android gear the app used to draw on top of the WebView for the same
   button -- that native gear is now removed outright (this is the only
   settings entry point in the app again), and per the same photo feedback
   this one should look like its neighbours, not stand out: no more
   dedicated size/shape override here, it just inherits the plain
   `.topbar > .icon` 48px rounded-square treatment like the hamburger/bell
   next to it. */
/* Hide the gear (not the rest of the topbar) whenever an overlay it would
   otherwise sit underneath/behind is open -- Manage, its own thread-
   settings menu, or the left drawer -- rather than leaving it visibly
   "stuck" in the background across all of them. visibility (not display)
   keeps the topbar's own layout/alignment stable when it reappears. */
html.panel-open #sessionSettingsBtn,
html.session-settings-open #sessionSettingsBtn,
#app.drawer-open #sessionSettingsBtn {
  visibility: hidden; pointer-events: none;
}

/* Thread-settings engine usage summary (2026-09-20, owner's ask) --
   compact, real quota data via renderThreadEngineUsage() in app.js
   (same quotaView()/engineUsage the topbar picker and Usage tab already
   compute). Sits right under the settings-menu intro copy. */
.session-engine-usage {
  margin: 10px 0 14px; padding: 12px 14px; border-radius: 14px;
  border: 1px solid var(--line); background: var(--bg-elevated);
}
.seu-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.seu-row strong { font-size: 14px; }
.seu-detail { margin: 4px 0 8px; font-size: 12px; display: grid; gap: 3px; }
#seuViewAll.manage-link, .manage-link {
  background: none; border: none; color: var(--secondary); font-size: 11px; font-weight: 700; padding: 0; min-height: 0; cursor: pointer;
}

/* Click-to-open file panel (web/file-panel.js) */
code.file-ref { cursor: pointer; text-decoration: underline dotted; }
code.file-ref:hover { background: var(--bg-elevated); }
#filePanel { position: fixed; top: 0; right: 0; bottom: 0; width: min(520px, 100vw); z-index: 60; display: flex; flex-direction: column; background: var(--bg-elevated, #0f1a2b); border-left: 1px solid var(--line); box-shadow: -8px 0 24px rgba(0,0,0,.35); }
#filePanel[hidden] { display: none; }
#filePanel header { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-bottom: 1px solid var(--line); }
#filePanel .fp-title { flex: 1; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#filePanel header button { background: none; border: 0; color: inherit; font-size: 18px; cursor: pointer; opacity: .6; padding: 2px 6px; }
#filePanel header button:hover, #filePanel .fp-pin[aria-pressed="true"] { opacity: 1; }
#filePanel .fp-path { padding: 4px 10px; font-size: 11px; opacity: .6; word-break: break-all; }
#filePanel .fp-body { flex: 1; min-height: 0; margin: 0; padding: 0; overflow: auto; font-size: 12px; word-break: break-word; user-select: text; position: relative; display: flex; flex-direction: column; }
@media (min-width: 900px) { body.file-panel-pinned #app { padding-right: min(520px, 100vw); box-sizing: border-box; } }

/* Multi-user: login form, account menu, modals (share-dialog.js / account-ui.js) */
.pair .login-card input { text-align: left; font-size: 16px; padding: 11px 12px; letter-spacing: 0; }
.pair details.pair-alt { width: min(380px, calc(100vw - 32px)); margin-top: 10px; text-align: left; }
.pair details.pair-alt > summary { cursor: pointer; color: var(--ink-dim); font-size: 13px; padding: 6px 2px; }
.pair details.pair-alt .pair-card { margin-top: 6px; }
.pair .ah-bad, .ah-modal .ah-bad { color: var(--bad, #ff6b6b); }
.ah-modal-scrim { position: fixed; inset: 0; z-index: 1000; background: rgba(0,0,0,.55); display: flex; align-items: center; justify-content: center; padding: 16px; }
.ah-modal { width: min(520px, 100%); max-height: 90vh; overflow: auto; background: var(--surface); color: var(--ink); border: 1px solid var(--line-strong); border-radius: var(--radius-lg, 14px); box-shadow: var(--shadow); }
.ah-modal-head { display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; border-bottom: 1px solid var(--line); }
.ah-modal-body { padding: 14px 16px; display: grid; gap: 10px; }
.ah-x { border: 0; background: transparent; color: var(--ink-dim); font-size: 22px; line-height: 1; }
.ah-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.ah-row > .ah-grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ah-modal input:not([type=checkbox]), .ah-modal select { padding: 8px 10px; border-radius: var(--radius-sm); border: 1px solid var(--line-strong); background: var(--bg-elevated); color: var(--ink); }
.ah-modal label { display: grid; gap: 4px; font-size: 13px; }
.ah-modal label.ah-check { display: flex; align-items: center; gap: 8px; }
.ah-share-list { display: grid; gap: 8px; }
.ah-msg { min-height: 1em; margin: 0; }
.drawer-account { position: relative; }
.drawer-account .acct-btn { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; border: 0; background: transparent; color: var(--ink); padding: 4px 0; }
.drawer-account .acct-menu { position: absolute; left: 0; bottom: calc(100% + 4px); right: 0; }
.t-tag.t-shared { background: var(--surface-2); }
.ro-banner { padding: 8px 14px; font-size: 13px; color: var(--ink-dim); background: var(--surface-2); border-top: 1px solid var(--line); text-align: center; }

/* Session dock: neon glass, sized to the sidebar (tokens from the dock handover, mapped onto the hub palette). */
.session-dock { --d-cyan:#12d8ff; --d-blue:#2188ff; --d-violet:#873cff; --d-green:#16e6a1; --d-red:#ff5d72; --d-gold:#ffc83d; --d-t2:#a9bdd8; --d-t3:#6f89a8; --d-line:rgba(44,169,255,.22); --d-ease:cubic-bezier(.2,.8,.2,1); }
.drawer-foot:has(.session-dock) { display:block; padding:10px 8px max(10px, env(safe-area-inset-bottom)); flex-shrink:0; }
.session-dock { color:#f6f9ff; border:1px solid rgba(20,155,255,.55); border-radius:20px; background:linear-gradient(135deg,rgba(5,25,45,.96),rgba(3,15,29,.94)); box-shadow:0 10px 30px rgba(0,0,0,.4),0 0 22px rgba(18,216,255,.10); backdrop-filter:blur(18px) saturate(130%); -webkit-backdrop-filter:blur(18px) saturate(130%); transition:box-shadow 200ms var(--d-ease),border-color 200ms var(--d-ease); }
.session-dock[data-expanded="true"] { border-color:rgba(18,216,255,.7); box-shadow:0 12px 36px rgba(0,0,0,.5),0 0 26px rgba(18,216,255,.2); }
.session-dock .acct-btn { display:grid; grid-template-columns:auto minmax(0,1fr) auto 16px; align-items:center; gap:10px; width:100%; padding:10px 12px; min-height:68px; color:inherit; border-radius:20px; cursor:pointer; text-align:left; }
.session-dock :is(button,summary):focus-visible { outline:2px solid var(--d-cyan); outline-offset:3px; }
.dock-avatar-ring { width:46px; height:46px; padding:3px; border-radius:50%; background:linear-gradient(135deg,var(--d-cyan),var(--d-blue) 48%,var(--d-violet)); box-shadow:0 0 18px rgba(65,98,255,.4); flex:0 0 auto; }
.dock-avatar-ring-lg { width:54px; height:54px; }
.dock-avatar { display:grid; place-items:center; width:100%; height:100%; border-radius:50%; background:#041323; color:#fff; font-weight:750; font-size:14px; letter-spacing:.02em; }
.dock-identity { display:grid; gap:4px; min-width:0; }
.dock-name-row { display:flex; align-items:center; gap:7px; min-width:0; }
.dock-identity strong { font-size:15px; line-height:1.15; font-weight:750; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; flex:0 1 auto; }
.dock-role { display:inline-flex; align-items:center; padding:2px 7px; border:1px solid rgba(135,60,255,.7); border-radius:7px; background:rgba(98,43,215,.2); color:#e7ddff; font-size:9px; font-weight:800; letter-spacing:.07em; text-transform:uppercase; flex:0 0 auto; }
.dock-device-line { display:flex; align-items:center; gap:6px; color:var(--d-t2); font-size:12px; min-width:0; }
.dock-device-summary { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
.dock-ico { width:15px; height:15px; flex:0 0 auto; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; color:var(--d-cyan); }
.session-dock .connection-pill { height:auto; font-size:11px; font-weight:700; padding:5px 9px; gap:6px; border-radius:999px; color:var(--connection-color); border:1px solid color-mix(in srgb,var(--connection-color) 45%,transparent); background:color-mix(in srgb,var(--connection-color) 14%,transparent); }
.dock-chevron { width:16px; height:16px; fill:none; stroke:var(--d-t2); stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round; transition:transform 180ms var(--d-ease); transform:rotate(180deg); }
.acct-btn[aria-expanded=true] .dock-chevron { transform:rotate(0); }
.session-dock .session-panel { position:absolute; bottom:calc(100% + 10px); left:0; right:0; width:auto; max-height:min(70dvh,620px); overflow:auto; overscroll-behavior:contain; padding:14px; border:1px solid rgba(20,155,255,.55); border-radius:20px; background:linear-gradient(180deg,#071b2e,#041020); box-shadow:0 14px 40px rgba(0,0,0,.55),0 0 26px rgba(18,216,255,.14); z-index:70; color:#f6f9ff; box-sizing:border-box; animation:dockRise 200ms var(--d-ease); }
@keyframes dockRise { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }
.dock-panel-head { display:flex; align-items:center; gap:12px; padding-bottom:12px; border-bottom:1px solid var(--d-line); }
.dock-panel-who { display:grid; gap:5px; justify-items:start; min-width:0; flex:1; }
.dock-panel-who strong { font-size:17px; overflow-wrap:anywhere; }
.session-panel button { min-height:40px; border:1px solid var(--d-line); background:rgba(5,27,48,.66); color:var(--d-t2); border-radius:12px; padding:8px 12px; font-weight:650; cursor:pointer; transition:border-color 160ms,color 160ms,box-shadow 160ms; }
.session-panel button:hover { color:#f6f9ff; border-color:rgba(18,216,255,.5); box-shadow:0 0 0 1px rgba(18,216,255,.18),0 0 16px rgba(18,216,255,.14); }
.session-panel .dock-x { min-height:36px; width:36px; padding:0; font-size:20px; line-height:1; align-self:flex-start; }
.dock-section { margin-top:12px; border:1px solid var(--d-line); border-radius:14px; background:rgba(3,16,30,.52); }
.dock-section > summary, .dock-advanced > summary { display:flex; align-items:center; gap:9px; cursor:pointer; padding:11px 12px; font-size:13px; font-weight:650; list-style:none; }
.dock-section > summary::-webkit-details-marker, .dock-device > summary::-webkit-details-marker, .dock-advanced > summary::-webkit-details-marker { display:none; }
.dock-settings { display:grid; gap:8px; padding:0 12px 12px; }
.dock-devices-heading { display:flex; align-items:center; justify-content:space-between; gap:8px; margin:16px 0 8px; }
.dock-devices-heading h3 { margin:0; color:#87a6c8; font-size:11px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; }
.dock-count { margin-left:6px; padding:2px 7px; border-radius:999px; background:rgba(22,230,161,.14); border:1px solid rgba(22,230,161,.4); color:var(--d-green); letter-spacing:.02em; text-transform:none; font-size:10px; }
.session-panel .dock-mini { min-height:28px; padding:3px 10px; font-size:11px; border-radius:9px; }
.dock-muted { margin:0 0 8px; color:var(--d-t3); font-size:12px; line-height:1.45; overflow-wrap:anywhere; }
.dock-devices { display:grid; gap:8px; }
.dock-device { border:1px solid var(--d-line); border-radius:14px; background:rgba(3,16,30,.52); transition:border-color 160ms,box-shadow 160ms; }
.dock-device:hover, .dock-device[open] { border-color:rgba(18,216,255,.45); box-shadow:0 0 0 1px rgba(18,216,255,.18),0 0 20px rgba(18,216,255,.12); }
.dock-device > summary { display:grid; grid-template-columns:38px minmax(0,1fr) auto; gap:10px; align-items:center; padding:10px; cursor:pointer; list-style:none; }
.dock-tile { display:grid; place-items:center; width:38px; height:38px; border:1px solid var(--d-line); border-radius:11px; background:rgba(5,27,48,.75); }
.dock-device-main { display:grid; gap:3px; min-width:0; }
.dock-device-name { display:flex; flex-wrap:wrap; align-items:center; gap:6px; font-size:13px; font-weight:700; overflow-wrap:anywhere; }
.dock-current { padding:1px 6px; border:1px solid rgba(18,216,255,.5); border-radius:6px; color:var(--d-cyan); font-size:9px; font-weight:800; letter-spacing:.07em; }
.dock-device-sub { color:var(--d-t3); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.dock-state { display:inline-flex; align-items:center; gap:6px; font-size:11px; font-weight:700; color:var(--d-t3); }
.dock-state::before { content:""; width:7px; height:7px; border-radius:50%; background:currentColor; }
.dock-device[data-status=connected] .dock-state { color:var(--d-green); }
.dock-device[data-status=connected] .dock-state::before { box-shadow:0 0 9px currentColor; }
.dock-device[data-status=idle] .dock-state { color:var(--d-gold); }
.dock-device[data-status=offline] .dock-state { color:var(--d-t3); }
.dock-device-details { display:grid; grid-template-columns:auto 1fr; gap:5px 12px; margin:0; padding:2px 12px 12px; border-top:1px solid var(--d-line); padding-top:10px; font-size:12px; }
.dock-device-details dt { color:var(--d-t3); }
.dock-device-details dd { margin:0; color:var(--d-t2); overflow-wrap:anywhere; }
.dock-advanced { margin:0 12px 8px; }
.dock-advanced > summary { padding:6px 0; color:var(--d-t3); font-size:11px; }
.dock-advanced code { display:block; margin-bottom:6px; padding:6px 8px; border-radius:8px; background:rgba(0,0,0,.3); color:var(--d-t2); font-size:11px; overflow-wrap:anywhere; }
.session-panel .dock-link-danger { display:block; margin:0 12px 12px; min-height:34px; width:calc(100% - 24px); color:#ffb9c3; border-color:rgba(255,93,114,.3); background:rgba(108,26,42,.14); font-size:12px; }
.session-panel > .dock-link-danger { margin:10px 0 0; width:100%; }
.session-panel .dock-link-danger:hover { border-color:rgba(255,93,114,.55); box-shadow:0 0 14px rgba(255,93,114,.14); }
.session-panel footer { margin-top:14px; padding-top:12px; border-top:1px solid var(--d-line); }
.session-panel .dock-signout { display:flex; align-items:center; justify-content:center; gap:8px; width:100%; min-height:44px; color:#ffd7dd; border-color:rgba(255,93,114,.35); background:rgba(108,26,42,.18); }
.session-panel .dock-signout .dock-ico { color:var(--d-red); }
.session-panel .dock-signout:hover { border-color:rgba(255,93,114,.6); box-shadow:0 0 18px rgba(255,93,114,.16); }
@media(max-width:699px) { .session-dock .session-panel { position:fixed; left:8px; right:8px; bottom:max(8px,env(safe-area-inset-bottom)); max-height:70dvh; padding-bottom:max(14px,env(safe-area-inset-bottom)); border-radius:22px; } }
@media(max-width:359px) { .session-dock .connection-pill #connText { display:none; } .session-dock .connection-pill { padding:6px; } .dock-device > summary { grid-template-columns:34px minmax(0,1fr); } .dock-state { grid-column:2; } }
@media(prefers-reduced-motion:reduce) { .dock-chevron, .session-dock, .dock-device, .session-panel button { transition:none; } .session-dock .session-panel { animation:none; } }

.dock-avatar.has-photo, .u-ring span.has-photo { background-size:cover; background-position:center; color:transparent; }
.session-panel .dock-avatar-btn { min-height:0; padding:3px; border:0; border-radius:50%; background:linear-gradient(135deg,var(--d-cyan),var(--d-blue) 48%,var(--d-violet)); cursor:pointer; position:relative; }
.dock-avatar-btn::after { content:"+"; position:absolute; right:-2px; bottom:-2px; width:18px; height:18px; border-radius:50%; display:grid; place-items:center; background:var(--d-cyan); color:#041323; font-size:13px; font-weight:800; line-height:1; }
.dock-devices-heading { flex-wrap:wrap; }
.dock-devices-heading h3 { display:flex; align-items:center; flex-wrap:wrap; gap:4px 6px; white-space:nowrap; }
.dock-count { white-space:nowrap; margin-left:0; }
.session-dock .session-panel { touch-action:pan-y; -webkit-overflow-scrolling:touch; }
.dock-alias { display:flex; align-items:center; gap:8px; padding:0 12px 10px; }
.dock-alias label { color:var(--d-t3); font-size:12px; }
.dock-alias-input { flex:1; min-width:0; min-height:34px; padding:6px 10px; border:1px solid var(--d-line); border-radius:10px; background:#061a2e; color:#f6f9ff; font-size:13px; }
.dock-alias-input:focus { outline:2px solid var(--d-cyan); outline-offset:1px; }
.dock-device-name > span:first-child { overflow-wrap:anywhere; }

.msg-time { display: block; margin: 2px 4px 0; font-size: 11px; line-height: 1.3; color: var(--ink-dim, #7d8aa3); opacity: .85; }
.msg.user .msg-time { text-align: right; }
.day-divider { align-self: center; margin: 14px auto 6px; padding: 2px 12px; border-radius: 999px; font-size: 11px; color: var(--ink-dim, #7d8aa3); border: 1px solid var(--line); background: var(--surface-2, transparent); }

/* Search bar: 16px input (Android Chrome zooms the whole page into smaller focused fields, which pushed the close button off-screen); close button always visible */
.in-thread-search-bar { overflow: hidden; }
.in-thread-search-bar input { font-size: 16px; }
.in-thread-search-bar button.icon { flex: 0 0 auto; min-width: 36px; min-height: 36px; font-size: 20px; }
.in-thread-search-bar #inThreadSearchClose { border: 1px solid var(--line); border-radius: 50%; }

/* Engine picker gets the room the bell used to take */
.topbar .engine-usage-control { flex: 1 1 150px; max-width: 260px; min-width: 110px; }
.topbar .topbar-engine { max-width: none; flex-basis: auto; font-size: 13px; }

/* Bell now lives in the sidebar header next to Manage */
.drawer-brand-actions { display: flex; align-items: center; gap: 8px; }
.drawer-brand-actions .notif-bell { width: 44px; height: 44px; min-width: 44px; border-radius: 50%; border: 1px solid var(--line); background: var(--surface); color: var(--ink-faint); position: relative; }
.drawer-brand-actions .notif-bell:hover { color: var(--ink); }
.drawer-brand-actions .notif-bell-badge { position: absolute; top: -4px; right: -4px; }

/* ---- Sidebar cleanup: quickbar gone, "+" next to search, richer chat-list menu, content search, neon Shared group ---- */
.drawer-quickbar { display: none !important; }
.drawer-search-row { align-items: center; gap: 8px; }
.drawer-new-quick { flex: 0 0 auto; width: 46px; height: 46px; border-radius: 14px; border: 1px solid #8b82ff; color: #fff; background: var(--ah-primary-gradient, linear-gradient(135deg,#4f6bff,#8b3dff)); box-shadow: inset 0 1px 0 #ffffff42, 0 0 14px #7048ff40; display: grid; place-items: center; }
.drawer-new-quick:hover { filter: brightness(1.12); }
.drawer-menu-rich { min-width: 230px; padding: 6px; display: flex; flex-direction: column; gap: 2px; border-color: color-mix(in srgb, var(--secondary, #12d8ff) 40%, var(--line)); box-shadow: 0 12px 34px rgba(0,0,0,.5), 0 0 22px color-mix(in srgb, var(--secondary, #12d8ff) 18%, transparent); }
.drawer-menu-rich .dm-item { display: flex; align-items: center; gap: 12px; width: 100%; padding: 11px 12px; border: 0; border-radius: 10px; background: transparent; color: var(--ink); font-size: 15px; text-align: left; cursor: pointer; }
.drawer-menu-rich .dm-item:hover, .drawer-menu-rich .dm-item:focus-visible { background: color-mix(in srgb, var(--secondary, #12d8ff) 14%, transparent); outline: none; }
.drawer-menu-rich .dm-item.danger { color: var(--bad, #ff6b7a); }
.drawer-menu-rich .dm-item svg, .drawer-menu-rich .dm-item img, .drawer-menu-rich .dq-icon { width: 20px; height: 20px; flex: 0 0 20px; }
.drawer-menu-rich .dm-glyph { width: 20px; text-align: center; opacity: .85; }
.drawer-menu-rich .dm-sep { height: 1px; margin: 4px 6px; background: var(--line); }
.dock-settings .theme-button { width: 100%; margin-left: 0; font-size: 14px; text-align: left; }

.sidebar-content-hits .project-heading { padding: 8px 12px; }
.content-hit { display: grid; gap: 2px; width: 100%; padding: 9px 12px; margin: 2px 0; text-align: left; border: 1px solid transparent; border-radius: 12px; background: transparent; color: var(--ink); cursor: pointer; }
.content-hit:hover, .content-hit.active { border-color: color-mix(in srgb, var(--secondary, #12d8ff) 40%, var(--line)); background: color-mix(in srgb, var(--secondary, #12d8ff) 8%, transparent); }
.content-hit .ch-title { font-weight: 650; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.content-hit .ch-snippet { font-size: 12.5px; color: var(--ink-dim); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.content-hit .ch-snippet mark { background: color-mix(in srgb, var(--warn, #ffc83d) 45%, transparent); color: inherit; border-radius: 3px; padding: 0 2px; }
.content-hit .ch-meta { font-size: 11px; color: var(--ink-faint); }

.sidebar-shared > .project-heading { border-color: color-mix(in srgb, #873cff 55%, var(--line)); background: linear-gradient(135deg, color-mix(in srgb, #12d8ff 14%, transparent), color-mix(in srgb, #873cff 18%, transparent)); box-shadow: 0 0 18px color-mix(in srgb, #873cff 28%, transparent), inset 0 1px 0 #ffffff1a; }
.sidebar-shared > .project-heading .project-name { background: linear-gradient(90deg, #12d8ff, #b58bff); -webkit-background-clip: text; background-clip: text; color: transparent; font-weight: 800; }
.sidebar-shared .project-count { box-shadow: 0 0 10px color-mix(in srgb, #12d8ff 40%, transparent); }
.t-tag.t-shared { white-space: nowrap; max-width: 110px; overflow: hidden; text-overflow: ellipsis; text-transform: none; letter-spacing: 0; color: #9fdcff; border-color: color-mix(in srgb, #12d8ff 35%, var(--line)); background: color-mix(in srgb, #12d8ff 10%, transparent); }

.project-shared-card { border-color: color-mix(in srgb, #873cff 50%, var(--line)); background: linear-gradient(135deg, color-mix(in srgb, #12d8ff 8%, var(--surface)), color-mix(in srgb, #873cff 12%, var(--surface))); box-shadow: 0 0 20px color-mix(in srgb, #873cff 20%, transparent); }
.project-shared-card .shared-glyph { display: inline-grid; place-items: center; width: 26px; height: 26px; margin-right: 6px; border-radius: 8px; color: #fff; background: linear-gradient(135deg, #12d8ff, #873cff); box-shadow: 0 0 12px #873cff80; }
.project-shared-card .shared-badge { color: #9fdcff; border-color: color-mix(in srgb, #12d8ff 40%, var(--line)); }

/* search row: the search box takes the full width (New chat lives in the three-dots menu) */
.drawer-search-row .thread-search { flex: 1 1 auto; min-width: 0; }

/* project heading: title ellipsizes, the count pill never gets clipped (it showed "1" for "16") */
.project-heading .project-name .proj-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-heading .project-name .project-count { flex: 0 0 auto; min-width: 26px; justify-content: center; padding: 2px 9px; font-weight: 700; font-size: 12px; color: #9fdcff; background: color-mix(in srgb, #12d8ff 12%, var(--surface-3)); border: 1px solid color-mix(in srgb, #12d8ff 38%, var(--line)); box-shadow: 0 0 10px color-mix(in srgb, #12d8ff 22%, transparent); }
.project-heading .project-name { overflow: visible; }
.search-pending { color: var(--ink-faint); font-size: 12px; padding: 6px 12px; margin: 0; }

/* Regular users only get the Manage sections they can actually use; the rest are administrator tools */
body[data-role="user"] .manage-nav-item:not([data-user-ok]) { display: none !important; }
body[data-role="user"] .manage-nav-group:not(:has([data-user-ok])) { display: none !important; }
body[data-role="user"] [data-admin-only] { display: none !important; }

/* Search magnifiers are black SVG files: invert them in dark themes so they read as white like the other top-bar icons, leave them dark in light theme */
html[data-theme="dark"] #threadSearchBtn img, html[data-theme="dark"] .thread-search > img, html[data-theme="dark"] .in-thread-search-bar > img { filter: invert(1); }
html[data-theme="light"] #threadSearchBtn img, html[data-theme="light"] .thread-search > img, html[data-theme="light"] .in-thread-search-bar > img { filter: none; }
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]):not([data-theme="dark"]) #threadSearchBtn img, html:not([data-theme="light"]):not([data-theme="dark"]) .thread-search > img, html:not([data-theme="light"]):not([data-theme="dark"]) .in-thread-search-bar > img { filter: invert(1); }
}
#threadSearchBtn img { opacity: 1; }

.item-system { opacity: .85; border-style: dashed; }
.item-system .system-account summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.item-system .system-account p { margin: 8px 0 0; font-size: 12px; line-height: 1.5; }

#sendBtn.sending { opacity: .85; transform: scale(.94); box-shadow: 0 0 14px color-mix(in srgb, var(--secondary, #12d8ff) 55%, transparent); }

/* File panel: smart viewer toolbar, engine toggle, per-kind viewers (web/file-panel.js, web/file-code-view.js) */
#filePanel .fp-seg { display: inline-flex; border: 1px solid var(--line-strong); border-radius: 8px; overflow: hidden; flex: none; }
#filePanel .fp-seg[hidden] { display: none; }
#filePanel .fp-seg button { font-size: 11px; padding: 3px 8px; opacity: .75; border-radius: 0; }
#filePanel .fp-seg button[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink, #fff); opacity: 1; }
#filePanel .fp-bar { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 10px; border-bottom: 1px solid var(--line); }
#filePanel .fp-bar button, #filePanel .fp-sheets button {
  min-height: 0; padding: 4px 10px; font-size: 12px; border: 1px solid var(--line-strong); border-radius: 8px; background: var(--surface-2); color: var(--ink-dim);
}
#filePanel .fp-bar button:hover, #filePanel .fp-sheets button:hover { border-color: var(--secondary); color: var(--ink); }
#filePanel .fp-bar button[aria-pressed="true"], #filePanel .fp-sheets button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink, #fff); }
#filePanel .fp-bar button[hidden] { display: none; }
#filePanel .fp-notice { padding: 6px 10px; font-size: 11px; color: var(--warn); border-bottom: 1px solid var(--line); }
#filePanel .fp-notice[hidden] { display: none; }
#filePanel .fp-codehost { flex: 1; min-height: 0; overflow: auto; font-size: var(--fp-font, 12px); }
#filePanel .fp-code { margin: 0; padding: 8px 0; counter-reset: ln; font: inherit; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; line-height: 1.5; background: transparent !important; border: 0; border-radius: 0; box-shadow: none; tab-size: 4; min-width: max-content; }
#filePanel .fp-code code.hljs, #filePanel .fp-code.hljs { background: transparent; padding: 0; display: block; font: inherit; }
#filePanel .fp-line { display: block; white-space: pre; padding-right: 12px; }
#filePanel .fp-line::before { counter-increment: ln; content: counter(ln); display: inline-block; width: 4ch; margin-right: 12px; padding-right: 8px; text-align: right; color: var(--ink-faint); border-right: 1px solid var(--line); user-select: none; position: sticky; left: 0; background: var(--bg-elevated, #0f1a2b); }
#filePanel .fp-codehost.fp-wrap .fp-code { min-width: 0; }
#filePanel .fp-codehost.fp-wrap .fp-line { white-space: pre-wrap; word-break: break-word; padding-left: calc(4ch + 21px); text-indent: calc(-4ch - 21px); }
#filePanel .fp-md, #filePanel .fp-doc, #filePanel .fp-card { padding: 12px; font-size: var(--fp-font, 13px); }
#filePanel .fp-doc img { max-width: 100%; height: auto; }
#filePanel .fp-img { flex: 1; min-height: 0; overflow: auto; display: grid; place-items: center; padding: 10px; }
#filePanel .fp-img img { max-width: 100%; max-height: 100%; object-fit: contain; cursor: zoom-in; background: repeating-conic-gradient(var(--surface-3) 0 25%, transparent 0 50%) 50% / 16px 16px; border-radius: 6px; }
#filePanel .fp-img.zoomed { display: block; }
#filePanel .fp-img.zoomed img { max-width: none; max-height: none; cursor: zoom-out; }
#filePanel .fp-pdf { flex: 1; width: 100%; border: 0; background: #fff; }
#filePanel .fp-audio { width: calc(100% - 20px); margin: 14px 10px; }
#filePanel .fp-video { width: 100%; max-height: 100%; background: #000; }
#filePanel .fp-table-wrap { overflow: auto; max-height: 100%; }
#filePanel .fp-table { border-collapse: collapse; font-size: 12px; }
#filePanel .fp-table th, #filePanel .fp-table td { border: 1px solid var(--line); padding: 3px 8px; white-space: nowrap; text-align: left; max-width: 320px; overflow: hidden; text-overflow: ellipsis; }
#filePanel .fp-table th { position: sticky; top: 0; background: var(--surface-3); color: var(--ink); }
#filePanel .fp-note { padding: 6px 10px; font-size: 11px; color: var(--ink-faint); }
#filePanel .fp-sheets { display: flex; gap: 6px; padding: 6px 10px; overflow-x: auto; flex: none; }
#filePanel .fp-card .download-card-btn { border: 0; cursor: pointer; }
@media (max-width: 899px) { #filePanel { width: 100vw; border-left: 0; } #filePanel .fp-bar button { padding: 6px 12px; } }

/* Composer glow fix: .composer-row's overflow:hidden clipped the mic/send glow into a lit rectangle. Let the glow
   spill out of the row; clip only sideways (clip, unlike hidden, keeps the vertical axis visible) so mobile
   overflow protection stays. */
.composer { overflow-x: clip; overflow-y: visible; }
.composer-row { overflow: visible; }

/* Tap flash fix: Android paints a square highlight on a pressed button for a split second. The round composer buttons
   (and every other button) now suppress it; their own :active styling is the press feedback. */
button, .icon, .send, .stop { -webkit-tap-highlight-color: transparent; }
.composer-row .icon:focus:not(:focus-visible), .composer-row .send:focus:not(:focus-visible), .composer-row .stop:focus:not(:focus-visible) { outline: none; }

/* P10 context-pressure card */
.context-card .context-card-actions { display: flex; gap: 8px; padding: 0 12px 10px 28px; flex-wrap: wrap; }
.context-card .context-card-actions button { min-height: 36px; }

/* Claude-unrestricted power switch */
.apunrestricted { border: 1px solid var(--warn, #f59e0b); border-radius: 10px; padding: 8px 10px; }

/* Claude unrestricted: prominent switch + header chip */
.unr-block { display: flex; gap: 12px; align-items: center; justify-content: space-between; border: 1px solid var(--line, #334); border-radius: 12px; padding: 10px 12px; margin-bottom: 6px; }
.unr-block.on { border-color: #f59e0b; box-shadow: 0 0 0 1px rgba(245, 158, 11, .35), 0 0 18px rgba(245, 158, 11, .18); }
.unr-text p { margin: 4px 0 0; }
.unr-switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; flex: none; }
.unr-switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.unr-track { width: 46px; height: 26px; border-radius: 13px; background: #556; position: relative; transition: background .15s; }
.unr-knob { position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; transition: left .15s; }
.unr-switch input:checked + .unr-track { background: #f59e0b; }
.unr-switch input:checked + .unr-track .unr-knob { left: 23px; }
.unr-switch input:focus-visible + .unr-track { outline: 2px solid var(--secondary, #38bdf8); outline-offset: 2px; }
.unr-state { min-width: 28px; font-weight: 700; }
.unr-pill { border: 1px solid #f59e0b; color: #f59e0b; background: rgba(245, 158, 11, .12); border-radius: 999px; padding: 4px 10px; font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap; }

/* ---- Thread settings redesign (2026-10-06): neon sheet, grouped switches ----
   Same tokens as the topbar/composer shell: cyan->violet gradient accents, round pills, and one glow colour per
   state (data-tone). All element ids / .on / aria-pressed hooks from the old panel are unchanged; the old
   "On/Off" pill is now a round-knob switch (text kept in the DOM for assistive tech, hidden visually). */
.session-settings-menu {
  --tone: var(--accent); padding: 18px 16px 16px; border-radius: 22px;
  border: 1px solid color-mix(in srgb, var(--secondary) 45%, var(--line));
  background: linear-gradient(165deg, rgba(8,22,42,.97), rgba(4,12,26,.98));
  box-shadow: 0 24px 60px rgba(0,0,0,.55), 0 0 28px color-mix(in srgb, var(--secondary) 16%, transparent);
  backdrop-filter: blur(18px) saturate(130%); -webkit-backdrop-filter: blur(18px) saturate(130%);
  scrollbar-width: thin;
}
:root[data-theme="light"] .session-settings-menu { background: linear-gradient(165deg, #fff, #eef3fb); box-shadow: 0 24px 60px rgba(29,41,57,.2), 0 0 24px color-mix(in srgb, var(--secondary) 14%, transparent); }
.ss-grab { display: none; width: 38px; height: 4px; margin: -6px auto 12px; border-radius: 4px; background: color-mix(in srgb, var(--secondary) 40%, var(--line-strong)); }
.session-settings-head { align-items: flex-start; }
.ss-headtxt { min-width: 0; }
.session-settings-head .brand-kicker { letter-spacing: .16em; font-size: 10.5px; background: linear-gradient(90deg, var(--secondary), var(--violet)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.session-settings-head h2 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); } /* title lives in the kicker; kept for aria-labelledby */
.ss-thread { margin: 3px 0 0; font-size: 18px; font-weight: 750; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.session-settings-head > .icon { flex: none; width: 40px; height: 40px; border-radius: 50%; font-size: 24px; line-height: 1; border: 1px solid color-mix(in srgb, var(--secondary) 35%, var(--line)); background: var(--surface-2); box-shadow: 0 0 12px color-mix(in srgb, var(--secondary) 14%, transparent); }
.ss-summary { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 4px; }
.ss-chip { --tone: var(--accent); padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 750; color: color-mix(in srgb, var(--tone) 60%, #fff); border: 1px solid color-mix(in srgb, var(--tone) 60%, transparent); background: color-mix(in srgb, var(--tone) 14%, transparent); box-shadow: 0 0 10px color-mix(in srgb, var(--tone) 28%, transparent); }
:root[data-theme="light"] .ss-chip { color: color-mix(in srgb, var(--tone) 80%, #000); }
.ss-chip-default { --tone: var(--ink-faint); box-shadow: none; color: var(--ink-faint); }
[data-tone="amber"] { --tone: #f59e0b; } [data-tone="violet"] { --tone: #8b5cf6; } [data-tone="cyan"] { --tone: #06d6f0; }
[data-tone="green"] { --tone: #10b981; } [data-tone="blue"] { --tone: #3b82f6; } [data-tone="red"] { --tone: #ef4444; }

/* engine usage card */
.session-engine-usage { margin: 10px 0 6px; padding: 12px 14px; border-radius: 16px; border: 1px solid color-mix(in srgb, var(--secondary) 28%, var(--line)); background: linear-gradient(145deg, color-mix(in srgb, var(--secondary) 7%, var(--bg-elevated)), var(--bg-elevated)); }
.seu-meter { height: 8px; margin: 10px 0 8px; border-radius: 999px; background: var(--surface-3); overflow: hidden; box-shadow: inset 0 1px 3px rgba(0,0,0,.35); }
.seu-meter > i { display: block; height: 100%; width: 0; border-radius: 999px; transition: width 400ms cubic-bezier(.2,.8,.2,1); background: var(--ink-faint); }
.seu-meter > i[data-level="green"] { background: linear-gradient(90deg, #06b6d4, #10b981); box-shadow: 0 0 10px rgba(16,185,129,.6); }
.seu-meter > i[data-level="orange"] { background: linear-gradient(90deg, #f59e0b, #fb923c); box-shadow: 0 0 10px rgba(245,158,11,.6); }
.seu-meter > i[data-level="red"] { background: linear-gradient(90deg, #ef4444, #ff5d72); box-shadow: 0 0 10px rgba(239,68,68,.7); }
.session-engine-usage .seu-detail { margin: 0 0 6px; font-size: 11.5px; color: var(--ink-dim); }
.session-engine-usage .badge { box-shadow: 0 0 8px color-mix(in srgb, currentColor 30%, transparent); }

/* grouped option rows */
.session-options { gap: 8px; margin-top: 4px; }
.ss-group, .session-settings-menu .quota-settings h3 { margin: 14px 2px 2px; font-size: 10.5px; font-weight: 800; letter-spacing: .15em; text-transform: uppercase; color: color-mix(in srgb, var(--secondary) 70%, var(--ink-faint)); }
.session-options > .ss-group:first-child { margin-top: 10px; }
.session-option { --tone: var(--accent); min-height: 62px; padding: 9px 12px 9px 10px; grid-template-columns: 42px minmax(0, 1fr) auto; border-radius: 16px; border: 1px solid var(--line); background: var(--bg-elevated); -webkit-tap-highlight-color: transparent; transition: border-color 160ms, background 160ms, box-shadow 160ms, transform 100ms; }
.session-option:hover { border-color: color-mix(in srgb, var(--tone) 45%, var(--line)); background: color-mix(in srgb, var(--tone) 5%, var(--bg-elevated)); }
.session-option:active { transform: scale(.985); }
.session-option:focus-visible { outline: 2px solid var(--secondary); outline-offset: 2px; }
.session-option.on { border-color: color-mix(in srgb, var(--tone) 70%, transparent); background: linear-gradient(135deg, color-mix(in srgb, var(--tone) 16%, var(--surface)), var(--bg-elevated) 80%); box-shadow: 0 0 16px color-mix(in srgb, var(--tone) 24%, transparent), inset 0 0 14px color-mix(in srgb, var(--tone) 8%, transparent); }
.session-option-icon { width: 42px; height: 42px; border-radius: 50%; color: var(--ink-dim); border: 1px solid var(--line); background: var(--surface-2); transition: color 160ms, border-color 160ms, box-shadow 160ms; }
.session-option.on .session-option-icon { color: var(--tone); border-color: color-mix(in srgb, var(--tone) 70%, transparent); box-shadow: 0 0 12px color-mix(in srgb, var(--tone) 45%, transparent); }
.session-option-copy strong { font-size: 13.5px; }
.session-option-copy small { font-size: 11px; line-height: 1.35; }
/* On/Off text -> round-knob switch */
.session-option-state, .session-option.on .session-option-state, #fullHostBtn.on .session-option-state, #privacyBtn.on .session-option-state, #observeBtn.on .session-option-state {
  position: relative; display: block; flex: none; width: 44px; min-width: 44px; height: 26px; padding: 0; border-radius: 999px; font-size: 0; color: transparent;
  background: var(--surface-3); border: 1px solid var(--line-strong); transition: background 160ms, border-color 160ms, box-shadow 160ms;
}
.session-option-state::after { content: ""; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 50%; background: #cbd5e1; box-shadow: 0 1px 3px rgba(0,0,0,.4); transition: transform 180ms cubic-bezier(.2,.8,.2,1), background 160ms; }
.session-option.on .session-option-state, #fullHostBtn.on .session-option-state, #privacyBtn.on .session-option-state, #observeBtn.on .session-option-state { background: color-mix(in srgb, var(--tone) 78%, #000); border-color: var(--tone); box-shadow: 0 0 12px color-mix(in srgb, var(--tone) 55%, transparent); }
.session-option.on .session-option-state::after { transform: translateX(18px); background: #fff; }

/* secondary cards (project, model & account pickers) */
.session-settings-menu .quota-settings { margin-top: 12px; padding: 12px 14px; border: 1px solid var(--line); border-top: 1px solid var(--line); border-radius: 16px; background: var(--bg-elevated); }
.session-settings-menu .quota-settings > h3.ss-group { margin: 0 0 8px; }
.session-settings-menu .quota-settings select { width: 100%; min-height: 42px; border-radius: 12px; }
.session-settings-menu .pi-manage-link { margin-top: 8px; min-height: 40px; border-radius: 999px; padding: 6px 14px; }
.session-settings-actions { margin-top: 14px; }
.reset-session-button { min-height: 44px; border-radius: 999px; background: color-mix(in srgb, var(--bad) 8%, var(--surface-2)); color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, var(--line)); }
.reset-session-button:hover:not(:disabled) { color: var(--bad); border-color: var(--bad); box-shadow: 0 0 14px color-mix(in srgb, var(--bad) 28%, transparent); }
@media (max-width: 720px) { .ss-grab { display: block; } .session-settings-menu { border-radius: 24px 24px 0 0; } }
@media (prefers-reduced-motion: reduce) { .session-option, .session-option-state, .session-option-state::after, .seu-meter > i { transition: none; } }

/* ---- Thread settings: risk-tiered neon palette (2026-10-06, from the owner's phone screenshot) ----
   purple = base/intelligence, green = safe/private, cyan = info, yellow = costs tokens, orange = elevated, red = danger. */
[data-tone="purple"] { --tone: #a66bff; } [data-tone="yellow"] { --tone: #ffc83d; } [data-tone="orange"] { --tone: #ff8a2b; }
[data-tone="green"] { --tone: #16e6a1; } [data-tone="red"] { --tone: #ff4d6a; } [data-tone="cyan"] { --tone: #12d8ff; }
.ss-risk { font-weight: 850; letter-spacing: .04em; text-transform: uppercase; font-size: 10.5px; box-shadow: 0 0 14px color-mix(in srgb, var(--tone) 55%, transparent); }
.ss-risk::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 6px; border-radius: 50%; background: var(--tone); box-shadow: 0 0 8px var(--tone); vertical-align: 1px; }
.session-option[data-tone="red"].on { animation: ss-danger 2.4s ease-in-out infinite alternate; }
@keyframes ss-danger { from { box-shadow: 0 0 12px color-mix(in srgb, var(--tone) 22%, transparent), inset 0 0 12px color-mix(in srgb, var(--tone) 8%, transparent); } to { box-shadow: 0 0 24px color-mix(in srgb, var(--tone) 48%, transparent), inset 0 0 16px color-mix(in srgb, var(--tone) 14%, transparent); } }
.session-option[data-tone]:not(.on) .session-option-icon { color: color-mix(in srgb, var(--tone) 70%, var(--ink-dim)); border-color: color-mix(in srgb, var(--tone) 30%, var(--line)); }
.session-option .session-option-icon.full-icon, .session-option .session-option-icon.auto-icon, .session-option .session-option-icon.local-icon, .session-option .session-option-icon.observe-icon { color: inherit; }
.session-option[data-tone]:not(.on) .session-option-icon.full-icon, .session-option[data-tone]:not(.on) .session-option-icon.auto-icon,
.session-option[data-tone]:not(.on) .session-option-icon.local-icon, .session-option[data-tone]:not(.on) .session-option-icon.observe-icon { color: color-mix(in srgb, var(--tone) 70%, var(--ink-dim)); }
.session-option .session-option-icon { background: color-mix(in srgb, var(--tone) 9%, var(--surface-2)); }
@media (prefers-reduced-motion: reduce) { .session-option[data-tone="red"].on { animation: none; } }

/* collapsible Project & model */
.ss-adv { margin-top: 14px; border-radius: 16px; border: 1px solid color-mix(in srgb, var(--secondary) 22%, var(--line)); background: color-mix(in srgb, var(--secondary) 3%, transparent); }
.ss-adv > summary { list-style: none; display: flex; align-items: center; justify-content: space-between; min-height: 46px; padding: 0 14px; cursor: pointer; font-size: 10.5px; font-weight: 800; letter-spacing: .15em; text-transform: uppercase; color: color-mix(in srgb, var(--secondary) 70%, var(--ink-faint)); }
.ss-adv > summary::-webkit-details-marker { display: none; }
.ss-adv > summary::after { content: ""; width: 8px; height: 8px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg); transition: transform 160ms; }
.ss-adv[open] > summary::after { transform: rotate(-135deg); }
.ss-adv > .quota-settings { margin: 0 10px 10px; }
.ss-adv > .quota-settings:first-of-type { margin-top: 0; }
.session-settings-menu label { display: grid; gap: 6px; font-size: 12px; color: var(--ink-dim); }
.session-settings-menu .quota-settings select { max-width: 100%; padding: 0 12px; font-size: 14px; background: var(--surface-2); border: 1px solid var(--line-strong); }
.session-settings-menu .pi-manage-link { color: var(--secondary); background: color-mix(in srgb, var(--secondary) 10%, transparent); border: 1px solid color-mix(in srgb, var(--secondary) 40%, transparent); }

.ss-adv-options { margin: 0 10px 10px; }
.ss-adv > .quota-settings:first-of-type { margin-top: 10px; }

/* ---- file panel: folder explorer ---- */
#filePanel .fp-dir { display: flex; flex-direction: column; min-height: 0; flex: 1; }
#filePanel .fp-dirbar { display: flex; align-items: center; gap: 6px; padding: 6px 10px; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
#filePanel .fp-dirbar button, #filePanel .fp-searchnote button { font-size: 12px; padding: 3px 8px; border: 1px solid var(--line-strong, var(--line)); border-radius: 6px; background: none; color: inherit; cursor: pointer; }
#filePanel .fp-dirbar button:disabled { opacity: .35; cursor: default; }
#filePanel .fp-filter { flex: 1; min-width: 110px; font-size: 12px; padding: 4px 8px; border: 1px solid var(--line-strong, var(--line)); border-radius: 6px; background: transparent; color: inherit; }
#filePanel .fp-hid { font-size: 11px; opacity: .8; display: inline-flex; align-items: center; gap: 3px; }
#filePanel .fp-crumbs { padding: 6px 10px; font-size: 12px; display: flex; flex-wrap: wrap; align-items: center; gap: 2px; border-bottom: 1px solid var(--line); }
#filePanel .fp-crumb { background: none; border: 0; color: var(--accent, #6af); cursor: pointer; padding: 1px 3px; font-size: 12px; border-radius: 4px; }
#filePanel .fp-crumb:hover { text-decoration: underline; }
#filePanel .fp-sep { opacity: .4; }
#filePanel .fp-dirhead { display: grid; grid-template-columns: 1fr 76px 150px 52px; gap: 6px; padding: 4px 10px 4px 38px; font-size: 11px; opacity: .75; border-bottom: 1px solid var(--line); }
#filePanel .fp-dirhead button { background: none; border: 0; color: inherit; text-align: left; cursor: pointer; padding: 0; font-size: 11px; }
#filePanel .fp-dirhead button:nth-child(2) { text-align: right; }
#filePanel .fp-searchnote { padding: 6px 10px; font-size: 12px; border-bottom: 1px solid var(--line); display: flex; gap: 8px; align-items: center; }
#filePanel .fp-list { list-style: none; margin: 0; padding: 0; overflow: auto; flex: 1; min-height: 0; }
#filePanel .fp-row { display: grid; grid-template-columns: 22px 1fr 76px 150px 52px; gap: 6px; align-items: center; padding: 5px 10px; font-size: 12px; cursor: pointer; border-bottom: 1px solid color-mix(in srgb, var(--line) 50%, transparent); }
#filePanel .fp-row:hover, #filePanel .fp-row:focus { background: color-mix(in srgb, var(--accent, #6af) 14%, transparent); outline: none; }
#filePanel .fp-row.fp-dim { opacity: .45; cursor: not-allowed; }
#filePanel .fp-ico { text-align: center; }
#filePanel .fp-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#filePanel .fp-size { text-align: right; opacity: .7; font-variant-numeric: tabular-nums; }
#filePanel .fp-date { opacity: .6; font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#filePanel .fp-racts { display: flex; gap: 2px; justify-content: flex-end; opacity: 0; }
#filePanel .fp-row:hover .fp-racts, #filePanel .fp-row:focus .fp-racts { opacity: 1; }
#filePanel .fp-racts button { background: none; border: 0; color: inherit; cursor: pointer; font-size: 13px; padding: 0 3px; }
#filePanel .fp-linkmark { font-size: 10px; opacity: .6; font-style: normal; border: 1px solid var(--line); border-radius: 4px; padding: 0 3px; }
#filePanel .fp-empty { padding: 18px 12px; opacity: .65; font-size: 12px; }
#filePanel .fp-dirfoot { padding: 5px 10px; font-size: 11px; opacity: .65; border-top: 1px solid var(--line); }
@media (max-width: 560px) { #filePanel .fp-dirhead, #filePanel .fp-row { grid-template-columns: 22px 1fr 64px 40px; } #filePanel .fp-dirhead button:nth-child(3), #filePanel .fp-date { display: none; } #filePanel .fp-racts { opacity: 1; } }

/* ---- Unified Council card (2026-10-10): Local / Online / Max ----
   One card, three scopes. Round pills like the Thread settings sheet; each scope glows in its own colour:
   Local = green (private, on this machine), Online = cyan (cloud engines), Max = purple->gold (everything together). */
.council-mode-tabs { grid-template-columns: repeat(3, minmax(0, 1fr)); border-radius: 999px; padding: 4px; }
.council-mode-tabs button { border-radius: 999px; min-height: 36px; -webkit-tap-highlight-color: transparent; transition: background 160ms, box-shadow 160ms, color 160ms; }
.council-mode-tabs button[data-council-mode="local"].on { background: color-mix(in srgb, #16e6a1 18%, var(--surface-2)); box-shadow: 0 0 14px color-mix(in srgb, #16e6a1 40%, transparent), inset 0 0 0 1px color-mix(in srgb, #16e6a1 60%, transparent); }
.council-mode-tabs button[data-council-mode="online"].on { background: color-mix(in srgb, #12d8ff 18%, var(--surface-2)); box-shadow: 0 0 14px color-mix(in srgb, #12d8ff 40%, transparent), inset 0 0 0 1px color-mix(in srgb, #12d8ff 60%, transparent); }
.council-mode-tabs button[data-council-mode="max"].on { color: #fff; background: linear-gradient(100deg, #6d3df0, #a66bff 55%, #ffc83d); box-shadow: 0 0 18px color-mix(in srgb, #a66bff 55%, transparent), 0 0 8px color-mix(in srgb, #ffc83d 35%, transparent); }
.council-preset-row button[data-council-preset="max"].on { border-color: #a66bff; box-shadow: 0 0 12px color-mix(in srgb, #a66bff 45%, transparent); }

.live-voice-overlay { position: fixed; inset: 0; z-index: 1000; background: #050b1a; }
.live-voice-overlay iframe { width: 100%; height: 100%; border: 0; display: block; }

/* ---- Composer row never pushes Stop off-screen (2026-10-12) ----
   Live voice added a 6th control, and the Council pill carried a count dot, so on a 360-412px phone the red Stop button
   slid past the right edge. Fixes: (1) the count dot is hidden while the council is off, and when it is on it becomes a
   tiny corner badge instead of taking row width; (2) the Council pill is more compact; (3) the row tightens its gaps and
   shrinks round buttons a little on narrow screens; (4) Stop is kept last and can never shrink or be clipped. */
.composer-row { gap: 6px; }
.council-toggle { position: relative; padding: 0 10px 0 8px; gap: 4px; }
.council-toggle-label { font-size: 12.5px; }
.council-toggle small { display: none; }
.council-toggle.on small, .council-toggle[aria-pressed="true"] small {
  display: grid; position: absolute; top: -5px; right: -3px; min-width: 17px; height: 17px; font-size: 10px; font-weight: 800;
  box-shadow: 0 0 8px color-mix(in srgb, var(--secondary) 55%, transparent);
}
.composer-row .stop, .composer-row .send { flex: 0 0 auto; }
.composer-row .stop { margin-left: 0; }
/* Round buttons as big as the row allows. Budget (411px phone): 395px row = Council pill ~105 + 5 gaps x5 + 5 buttons,
   so 5 buttons can be up to ~53px; 48px leaves ~25px spare. Steps down only on narrower phones so Stop never leaves the screen. */
@media (max-width: 440px) {
  .composer-row { gap: 5px; }
  .composer-row .icon, .composer-row .send, .composer-row .stop, .composer-row > .attach-wrap > .icon, .composer-row .mic-wrap > .icon { width: 48px; height: 48px; flex-basis: 48px; }
  .council-toggle { min-height: 48px; height: 48px; padding: 0 10px 0 8px; }
}
@media (max-width: 390px) {
  .composer-row .icon, .composer-row .send, .composer-row .stop, .composer-row > .attach-wrap > .icon, .composer-row .mic-wrap > .icon { width: 45px; height: 45px; flex-basis: 45px; }
  .council-toggle { min-height: 45px; height: 45px; }
}
@media (max-width: 360px) {
  .composer-row .icon, .composer-row .send, .composer-row .stop, .composer-row > .attach-wrap > .icon, .composer-row .mic-wrap > .icon { width: 41px; height: 41px; flex-basis: 41px; }
  .council-toggle { min-height: 41px; height: 41px; }
}
@media (max-width: 370px) { .council-toggle-label { display: none; } }
