/* aanya PWA — strict dark mode, monochrome, one purposeful accent.
   No gradients, no neon, no purple. Amber (#EDB561) is aanya's existing
   color from the desktop HUD — reused here rather than inventing a new one. */

:root {
  --bg: #0b0d10;
  --bg-elevated: #121419;
  --panel: #171a20;
  --panel-2: #1d2129;
  --line: #262b34;
  --line-soft: #1c2028;
  --text: #e8eaed;
  --text-dim: #98a1b0;
  --text-faint: #5f6673;
  --accent: #edb561;
  --accent-soft: rgba(237, 181, 97, .14);
  --success: #7fae86;
  --warn: #edb561;
  --danger: #e5686c;
  --danger-soft: rgba(229, 104, 108, .13);
  --radius: 14px;
  --safe-t: env(safe-area-inset-top);
  --safe-b: env(safe-area-inset-bottom);
  --safe-l: env(safe-area-inset-left);
  --safe-r: env(safe-area-inset-right);
  /* Extra bottom padding while the keyboard is genuinely open (focus-
     tracked in app.js) — 0 the rest of the time. See #app's own comment
     for why keyboard avoidance lives here instead of resizing #app. */
  --kb-inset: 0px;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* Pin the outer page itself. iOS Safari (especially installed/standalone
   PWAs) will otherwise let the LAYOUT viewport rubber-band/scroll behind
   the keyboard or after a lock/unlock cycle, leaving a black gap above the
   header or dead space below the composer even though #app itself never
   scrolls. position:fixed + inset:0 removes the outer page as a scroll
   surface entirely — only #chat (and the drawers) scroll internally. */
html, body {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
  overscroll-behavior-y: none;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15.5px/1.5 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.icon-btn svg, .drawer-close svg {
  width: 20px; height: 20px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

#app {
  /* STRETCHED between top:0 and bottom:0 — deliberately NO height property.
     Confirmed on a real device (build stamp verified in the screenshot):
     `height:100dvh` renders SHORT of the real screen in the installed
     standalone PWA, leaving dead space below the composer. A fixed element
     with both top and bottom set derives its height from the containing
     block — for fixed positioning that's the initial containing block
     (the viewport) — which WebKit resolves separately from, and more
     reliably than, the dvh unit. Nothing here depends on a measurement
     that can come back wrong: no dvh, no JS-set height.
     Keyboard avoidance is additive instead — a --kb-inset on #composer's
     own padding (see app.js) — so a bad keyboard reading can only offset
     the composer, never shrink the shell. */
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  /* --kb-inset is 0px at rest, so this is a plain `bottom: 0` and the shell
     depends on no measurement at all (see above). While the keyboard is up
     it becomes the covered height, shrinking the shell to sit ON TOP of the
     keyboard. That is what makes this behave like a native app: the composer
     is already inside the visible area when focus lands, so iOS never needs
     to auto-scroll the page to reveal it — which is what used to drag the
     top bar and everything else out of place. */
  bottom: var(--kb-inset, 0px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ---------- top bar ---------- */

#topbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: calc(var(--safe-t) + 10px) calc(var(--safe-r) + 8px) 10px calc(var(--safe-l) + 8px);
  border-bottom: 1px solid var(--line);
  background: var(--bg-elevated);
}

#title-block { display: flex; align-items: center; gap: 8px; margin-left: 2px; }
#title-block h1 { font-size: 16px; font-weight: 600; margin: 0; letter-spacing: .2px; }

.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-faint); transition: background .25s; }
.dot[data-state="busy"] { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.dot[data-state="error"] { background: var(--danger); box-shadow: 0 0 0 3px var(--danger-soft); }

/* Server build / last-restart stamp — deliberately in the topbar, not only
   in Settings, so "did my fix actually deploy" is answerable at a glance. */
#build-stamp {
  margin-left: 8px;
  font-size: 10.5px;
  line-height: 1.2;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
#build-stamp:empty { display: none; }

.sp { flex: 1; }

.icon-btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px;
  border-radius: 10px; border: 1px solid transparent;
  background: transparent; color: var(--text-dim);
  cursor: pointer;
}
.icon-btn:active { background: var(--panel-2); }
.icon-btn[aria-expanded="true"] { color: var(--accent); background: var(--accent-soft); }
.icon-btn.primary { color: var(--bg); background: var(--accent); }
.icon-btn.primary svg { stroke: var(--bg); }
.icon-btn:disabled { opacity: .4; cursor: default; }
.icon-btn:focus-visible, button:focus-visible, textarea:focus-visible, input:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px;
}

.badge {
  position: absolute; top: 6px; right: 6px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
}

/* ---------- chat ---------- */

/* min-height:0 is required so a flex/grid child can shrink below its
   content height and scroll internally — without it, long message history
   grows #chat past the viewport and pushes #composer off-screen. */
#chat {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
}

#messages {
  display: flex; flex-direction: column; gap: 14px;
  padding: 16px calc(var(--safe-r) + 14px) 16px calc(var(--safe-l) + 14px);
  max-width: 800px; margin: 0 auto;
  width: 100%;
}

#empty-state { color: var(--text-faint); text-align: center; padding: 20vh 20px 0; font-size: 14.5px; }

.msg { display: flex; }
.msg-user { justify-content: flex-end; }
.msg-aanya, .msg-error { justify-content: flex-start; }

.msg-body {
  max-width: 86%;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.bubble {
  max-width: 100%;
  padding: 10px 14px;
  border-radius: var(--radius);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 15px;
}
.msg-user .bubble {
  max-width: 86%;
  background: var(--panel-2);
  border-bottom-right-radius: 4px;
}
.msg-aanya .bubble { background: var(--panel); border: 1px solid var(--line-soft); border-bottom-left-radius: 4px; }
.msg-error .bubble {
  max-width: 86%;
  background: var(--danger-soft);
  border: 1px solid rgba(229,104,108,.3);
  color: #f3c7c8;
  border-bottom-left-radius: 4px;
}

/* ---------- inline thoughts / activity (Cursor-style) ---------- */

.thoughts {
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  background: var(--bg-elevated);
  overflow: hidden;
}
.thoughts-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  border: none;
  background: transparent;
  color: var(--text-dim);
  font: 12.5px/1.3 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  cursor: pointer;
  text-align: left;
}
.thoughts-toggle:hover { background: rgba(255,255,255,.03); color: var(--text); }
.thoughts-label { font-weight: 550; color: var(--text); flex: 0 1 auto; min-width: 0; }
.thoughts-meta { color: var(--text-faint); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.thoughts-chevron {
  color: var(--text-faint);
  font-size: 11px;
  transition: transform .18s ease;
  flex: 0 0 auto;
}
.thoughts:not(.open) .thoughts-chevron { transform: rotate(-90deg); }
.thoughts:not(.open) .thoughts-panel { display: none; }
.thoughts.open .thoughts-panel { display: block; }

.thoughts-spinner {
  width: 10px; height: 10px; border-radius: 50%;
  border: 1.5px solid var(--line);
  border-top-color: var(--accent);
  flex: 0 0 auto;
  opacity: 0;
}
.thoughts.live .thoughts-spinner {
  opacity: 1;
  animation: spin .7s linear infinite;
}
.thoughts:not(.live) .thoughts-spinner {
  border: none;
  background: var(--accent);
  opacity: .85;
  width: 7px; height: 7px;
  margin: 0 1.5px;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .thoughts.live .thoughts-spinner { animation: none; opacity: .8; }
}

.thoughts-panel {
  border-top: 1px solid var(--line-soft);
  max-height: 360px;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  padding: 4px 0 6px;
}
.thought-step {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 8px;
  padding: 5px 12px;
  font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: var(--text-dim);
  align-items: start;
}
.thought-step + .thought-step { border-top: 1px solid transparent; }
.thought-step .ts-icon {
  width: 16px; height: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 4px;
  background: var(--panel-2);
  color: var(--text-faint);
  font-size: 10px;
  margin-top: 1px;
  flex-shrink: 0;
}
.thought-step.kind-tool .ts-icon,
.thought-step.kind-tool-done .ts-icon { color: var(--accent); background: var(--accent-soft); }
.thought-step.kind-tool-fail .ts-icon { color: var(--danger); background: var(--danger-soft); }
.thought-step.kind-sub { color: var(--text-faint); padding-left: 22px; grid-template-columns: 14px 1fr; }
.thought-step.kind-sub .ts-icon { background: transparent; font-size: 11px; }
.thought-step.kind-task .ts-icon { color: var(--accent); }
.thought-step.kind-error { color: #f3b1b3; }
.thought-step .ts-body { min-width: 0; overflow-wrap: anywhere; white-space: pre-wrap; }
.thought-step .ts-name { color: var(--text); font-weight: 550; }
.thought-step .ts-args { color: var(--text-faint); }
.thought-step .ts-status {
  margin-left: 8px;
  font-size: 10px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.thought-step.kind-tool-done .ts-status { color: var(--success); }
.thought-step.kind-tool-fail .ts-status { color: var(--danger); }
.thought-step > summary {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 8px;
  cursor: pointer;
  list-style: none;
  align-items: start;
}
.thought-step > summary::-webkit-details-marker { display: none; }
.thought-step .ts-detail {
  margin: 0 12px 8px 38px;
  display: grid;
  gap: 6px;
}
.thought-step:not([open]) .ts-detail { display: none; }
.thought-step .ts-args-block,
.thought-step .ts-output {
  margin: 0;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--bg);
  border: 1px solid var(--line-soft);
  color: var(--text-dim);
  font: 11.5px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 160px;
  overflow: auto;
}
.thought-step .ts-output { color: var(--text); }
.thought-step.running .ts-icon::after {
  content: "";
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}

.task-chips {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.task-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font: 11.5px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  padding: 5px 9px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--text-dim);
  cursor: pointer;
}
.task-chip:hover { border-color: var(--accent); color: var(--accent); }
.task-chip .tc-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
}
.task-chip.done .tc-dot { background: var(--success); }
.task-chip.failed .tc-dot, .task-chip.cancelled .tc-dot { background: var(--danger); }

.bubble p { margin: 0 0 8px; }
.bubble p:last-child { margin-bottom: 0; }
.bubble strong { font-weight: 650; color: #fff; }
.bubble em { color: var(--text); }
.bubble code {
  font: 13px/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  background: rgba(237,181,97,.10); color: var(--accent);
  padding: 1px 5px; border-radius: 5px;
}
.bubble pre {
  background: var(--bg-elevated); border: 1px solid var(--line-soft);
  border-radius: 10px; padding: 10px 12px; overflow-x: auto; margin: 6px 0;
}
.bubble pre code { background: none; padding: 0; color: var(--text); }
.bubble ul, .bubble ol { margin: 4px 0; padding-left: 20px; }
.bubble li { margin: 2px 0; }
.bubble h1, .bubble h2, .bubble h3 { font-size: 15px; margin: 4px 0; color: #fff; }

/* GFM tables — header separation, alignment, horizontal scroll on overflow. */
.md-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
  margin: 8px 0;
  white-space: normal;
  overflow-wrap: normal;
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  background: var(--bg-elevated);
}
.bubble table {
  width: max-content;
  min-width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
  line-height: 1.4;
}
.bubble th, .bubble td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--line-soft);
  border-right: 1px solid var(--line-soft);
  vertical-align: top;
  overflow-wrap: anywhere;
}
.bubble th:last-child, .bubble td:last-child { border-right: none; }
.bubble thead th {
  background: var(--panel-2);
  font-weight: 650;
  color: #fff;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.bubble tbody tr:last-child td { border-bottom: none; }
.bubble tbody tr:nth-child(even) td { background: rgba(255,255,255,.02); }
.bubble th.md-align-left, .bubble td.md-align-left { text-align: left; }
.bubble th.md-align-center, .bubble td.md-align-center { text-align: center; }
.bubble th.md-align-right, .bubble td.md-align-right { text-align: right; }

/* Mermaid diagrams — dark/monochrome, scale or pan, never overflow the bubble. */
.mermaid-block, .mermaid-wrap {
  margin: 8px 0;
  max-width: 100%;
  white-space: normal;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  background: var(--bg-elevated);
  padding: 10px 12px;
}
.mermaid-wrap svg {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  fill: unset;
  stroke: unset;
  stroke-width: unset;
}
.mermaid-block .mermaid-fallback {
  margin: 0;
  background: transparent;
  border: none;
  padding: 0;
}
.mermaid-block.mermaid-error {
  border-color: rgba(229,104,108,.35);
  background: var(--danger-soft);
}
.mermaid-error-msg {
  font-size: 12.5px;
  color: #f3c7c8;
  margin: 0 0 8px;
  white-space: normal;
}

.typing { display: inline-flex; gap: 4px; padding: 2px 0; }
.typing i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--text-faint);
  animation: bounce 1.1s infinite ease-in-out;
}
.typing i:nth-child(2) { animation-delay: .12s; }
.typing i:nth-child(3) { animation-delay: .24s; }
@keyframes bounce { 0%, 60%, 100% { opacity: .35; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce) { .typing i { animation: none; opacity: .7; } }

.msg-time { font-size: 11px; color: var(--text-faint); margin-top: 4px; }

/* ---------- composer ---------- */

#composer {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* No --kb-inset here: the SHELL shrinks above the keyboard (see #app), so
     the composer is already clear of it. Adding it here too would double up. */
  padding: 10px calc(var(--safe-r) + 10px) calc(var(--safe-b) + 10px) calc(var(--safe-l) + 10px);
  border-top: 1px solid var(--line);
  background: var(--bg-elevated);
}

.attachment-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  width: 100%;
  max-width: 800px;
  margin-bottom: 8px;
  padding: 0 2px;
}

.attachment-strip[hidden] { display: none !important; }

.attachment-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: min(100%, 280px);
  padding: 6px 8px 6px 6px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--panel);
  font-size: 12px;
  color: var(--text-muted);
}

.attachment-chip.uploading { opacity: .65; }

.attachment-chip .att-thumb {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  object-fit: cover;
  background: var(--panel-2);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.attachment-chip .att-thumb svg {
  width: 18px;
  height: 18px;
  stroke: var(--text-faint);
  fill: none;
  stroke-width: 1.8;
}

.attachment-chip .att-meta {
  flex: 1;
  min-width: 0;
}

.attachment-chip .att-name {
  display: block;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.attachment-chip .att-size {
  display: block;
  font-size: 11px;
  color: var(--text-faint);
}

.attachment-chip .att-remove {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
}

.attachment-chip .att-remove:hover { color: var(--text); background: var(--panel-2); }

.msg-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}

.msg-attachment {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 220px;
  padding: 6px 10px 6px 6px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(255,255,255,.03);
  font-size: 12px;
}

.msg-attachment img {
  width: 44px;
  height: 44px;
  border-radius: 8px;
  object-fit: cover;
  flex: 0 0 auto;
}

.msg-attachment .att-icon {
  width: 44px;
  height: 44px;
  border-radius: 8px;
  background: var(--panel-2);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}

.msg-attachment .att-icon svg {
  width: 20px;
  height: 20px;
  stroke: var(--text-faint);
  fill: none;
  stroke-width: 1.8;
}

.msg-attachment .att-label {
  min-width: 0;
  color: var(--text-muted);
}

.msg-attachment .att-label strong {
  display: block;
  color: var(--text);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#composer.drag-over {
  outline: 2px dashed var(--accent);
  outline-offset: -4px;
  background: rgba(237, 181, 97, .04);
}

.composer-inner {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  width: 100%;
  max-width: 800px;
}

#input {
  flex: 1;
  min-width: 0;
  resize: none;
  font: inherit;
  /* MUST stay >= 16px. iOS Safari force-zooms the page when focusing any
     input with a smaller font, and it ignores maximum-scale/user-scalable
     for accessibility — so the zoom cannot be blocked via the viewport meta.
     That zoom is what made the whole shell (top bar included) pannable the
     moment the keyboard opened: once zoomed, the visual viewport is smaller
     than the layout viewport, so the page becomes draggable. Inheriting the
     body's 15.5px was enough to trigger it. */
  font-size: 16px;
  color: var(--text); background: var(--panel);
  border: 1px solid var(--line); border-radius: 18px;
  padding: 10px 15px; max-height: 140px; line-height: 1.4;
}

.mic-btn, #mic-btn { background: var(--panel); border: 1px solid var(--line); }
#mic-btn.hidden, .icon-btn.hidden { display: none !important; }
#mic-btn[aria-pressed="true"] {
  color: #fff; background: var(--danger); border-color: var(--danger);
  animation: pulse 1.4s infinite;
}
@keyframes pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(229,104,108,.4); } 50% { box-shadow: 0 0 0 8px rgba(229,104,108,0); } }
@media (prefers-reduced-motion: reduce) { #mic-btn[aria-pressed="true"] { animation: none; } }

/* ---------- drawers (conversations + activity) ---------- */

/* Stacking (all inside #app's stacking context):
     content / topbar / composer  → auto
     #scrim                       → 30  (dims content; never covers drawers)
     #convo-drawer / #activity-drawer → 40  (interactive, full opacity) */
#scrim {
  position: absolute; inset: 0;
  background: rgba(0,0,0,.5);
  z-index: 30;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s;
}
#scrim.show {
  opacity: 1;
  pointer-events: auto;
}
#scrim[hidden] { display: none; }

#convo-drawer {
  position: absolute; top: 0; left: 0; bottom: 0;
  width: min(300px, 84vw);
  padding-top: var(--safe-t);
  background: var(--bg-elevated); border-right: 1px solid var(--line);
  z-index: 40;
  transform: translateX(-100%);
  transition: transform .22s ease;
  display: flex; flex-direction: column;
  /* Closed drawers must not intercept taps; only .open is interactive. */
  pointer-events: none;
  opacity: 1;
}
#convo-drawer.open {
  transform: translateX(0);
  pointer-events: auto;
}

.drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 14px 10px;
  border-bottom: 1px solid var(--line);
}

.convo-list { flex: 1; overflow-y: auto; overscroll-behavior-y: contain; padding: 6px; }
.convo-item {
  display: block; width: 100%; text-align: left;
  padding: 10px 10px; border-radius: 10px; border: none;
  background: transparent; color: var(--text); font: inherit; cursor: pointer;
}
.convo-item:active { background: var(--panel-2); }
.convo-item.active { background: var(--accent-soft); color: var(--accent); }
.convo-item .ci-title { font-size: 14px; font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.convo-item .ci-meta { font-size: 12px; color: var(--text-faint); margin-top: 2px; }
.convo-empty { color: var(--text-faint); font-size: 13.5px; padding: 16px 10px; }

#activity-drawer {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: min(60vh, 520px);
  background: var(--bg-elevated); border-top: 1px solid var(--line);
  border-radius: 16px 16px 0 0;
  z-index: 40;
  transform: translateY(100%);
  transition: transform .22s ease;
  display: flex; flex-direction: column;
  padding-bottom: var(--safe-b);
  touch-action: pan-y;
  pointer-events: none;
  opacity: 1;
}
#activity-drawer.open {
  transform: translateY(0);
  pointer-events: auto;
}
#activity-drawer.dragging { transition: none; }

.drawer-handle {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 6px;
  padding: 16px 8px 8px;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  position: relative;
}
.drawer-handle:active { cursor: grabbing; }
.grip {
  position: absolute; top: 6px; left: 50%; transform: translateX(-50%);
  width: 36px; height: 4px; border-radius: 2px;
  background: var(--line); pointer-events: none;
}
.drawer-tabs { display: flex; gap: 4px; flex: 1; min-width: 0; }
.tab-btn {
  font: inherit; font-size: 13px; padding: 6px 12px; border-radius: 8px;
  border: 1px solid transparent; background: transparent; color: var(--text-dim); cursor: pointer;
}
.tab-btn.active { background: var(--panel-2); color: var(--text); border-color: var(--line); }

.text-btn { font: inherit; font-size: 13px; border: none; background: none; color: var(--text-dim); cursor: pointer; padding: 6px 8px; border-radius: 6px; }
.text-btn:active { color: var(--text); }
/* #settings-close carries `autofocus` (see index.html) purely to keep
   showModal() off the API token field — it draws the browser's default
   focus rectangle around the button on open even though nothing was
   actually navigated to it via keyboard/switch control. A visible ring is
   right when focus reflects real keyboard navigation (kept for
   :focus-visible in general, e.g. tabbing through Settings) but wrong for
   one that fires on every single open — replaced with a quieter tint that
   still shows SOMETHING is focused (accessibility) without reading as a
   rendering glitch. */
#settings-close:focus { outline: none; background: var(--accent-soft); }
#settings-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.drawer-close {
  flex: 0 0 auto; width: 34px; height: 34px;
  color: var(--text-dim);
}
.drawer-close:active { color: var(--text); background: var(--panel-2); }
.drawer-close svg { width: 18px; height: 18px; }

.activity-pane { flex: 1; overflow-y: auto; overscroll-behavior-y: contain; padding: 4px 12px 12px; }

.log-line {
  font: 12.5px/1.55 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: pre-wrap; overflow-wrap: anywhere;
  padding: 2px 0; color: var(--text-dim);
  border-left: 2px solid transparent; padding-left: 8px;
}
.log-line.lvl-error { color: #f3b1b3; border-left-color: var(--danger); }
.log-line.lvl-warn { color: var(--accent); border-left-color: var(--accent); }
.log-line.lvl-success { color: var(--success); border-left-color: var(--success); }
.log-line.lvl-sub { color: var(--text-faint); padding-left: 20px; }
.log-empty { color: var(--text-faint); font-size: 13px; padding: 14px 4px; }

.tasks-toolbar { display: flex; justify-content: flex-end; padding: 2px 0 6px; }
.task-card {
  border: 1px solid var(--line-soft); border-radius: 10px; margin-bottom: 8px;
  background: var(--panel);
  overflow: hidden;
}
.task-card-head {
  display: block; width: 100%; text-align: left;
  padding: 10px 12px; border: none; background: transparent;
  color: var(--text); font: inherit; cursor: pointer;
}
.task-card-head:hover { background: rgba(255,255,255,.03); }
.task-card .t-title {
  display: flex; align-items: center; gap: 8px;
  font-size: 13.5px; font-weight: 550;
}
.task-card .t-title-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.task-card .t-chevron {
  color: var(--text-faint); font-size: 11px; transition: transform .18s ease;
}
.task-card:not(.expanded) .t-chevron { transform: rotate(-90deg); }
.task-card .t-meta { font-size: 12px; color: var(--text-faint); margin-top: 3px; }
.task-status { font-size: 11px; padding: 2px 7px; border-radius: 6px; border: 1px solid var(--line); text-transform: uppercase; letter-spacing: .3px; flex: 0 0 auto; }
.task-status.running, .task-status.queued { color: var(--accent); border-color: var(--accent); }
.task-status.done { color: var(--success); border-color: var(--success); }
.task-status.failed, .task-status.cancelled { color: var(--danger); border-color: var(--danger); }

.task-detail {
  border-top: 1px solid var(--line-soft);
  padding: 8px 12px 12px;
  display: none;
}
.task-card.expanded .task-detail { display: block; }
.task-detail-section { margin-top: 8px; }
.task-detail-section:first-child { margin-top: 0; }
.task-detail-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--text-faint); margin-bottom: 4px;
}
.task-detail-body {
  font: 12px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: var(--text-dim);
  white-space: pre-wrap; overflow-wrap: anywhere;
  max-height: 220px; overflow-y: auto;
  background: var(--bg-elevated);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  padding: 8px 10px;
}
.task-detail-actions { display: flex; gap: 8px; margin-top: 10px; }
.task-detail-actions .pill-btn { font-size: 12px; padding: 5px 11px; }

/* ---------- settings dialog ---------- */

dialog {
  background: var(--panel); color: var(--text); border: 1px solid var(--line);
  border-radius: 16px; padding: 18px; max-width: 92vw; width: 360px;
}
dialog::backdrop { background: rgba(0,0,0,.6); }
.settings-form { display: flex; flex-direction: column; gap: 14px; }
.settings-form > strong { font-size: 15px; }
.settings-hint {
  margin: 0; padding: 10px 12px; border-radius: 9px; font-size: 13px; line-height: 1.4;
  color: var(--accent); background: rgba(237, 181, 97, 0.12); border: 1px solid rgba(237, 181, 97, 0.35);
}
.empty-hint { color: var(--text-dim); font-size: 13px; margin-top: 6px; }
.empty-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--text-dim); }
.field .hint { color: var(--text-faint); font-weight: 400; }
.field input {
  font: inherit; padding: 10px 11px; border-radius: 9px;
  border: 1px solid var(--line); background: var(--bg); color: var(--text);
}
.toggle-row { display: flex; align-items: center; justify-content: space-between; font-size: 14px; }
.toggle-row input { width: 38px; height: 22px; accent-color: var(--accent); }
.settings-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
.settings-build-info {
  margin: 0; font-size: 11.5px; color: var(--text-faint); text-align: center;
  font-variant-numeric: tabular-nums; cursor: pointer;
}
.settings-build-info:empty { display: none; }

/* Viewport diagnostics — revealed by tapping the build line. Exists because
   this shell's height has now been mis-measured on a real device in ways
   not reproducible from a desktop browser; real numbers beat guessing. */
.viewport-diag {
  margin: 0; padding: 8px 10px; border-radius: 8px;
  background: var(--bg); border: 1px solid var(--line);
  color: var(--text-dim); font-size: 10.5px; line-height: 1.45;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap; overflow-x: auto;
}
.viewport-diag[hidden] { display: none; }
.pill-btn {
  font: inherit; font-size: 13.5px; padding: 8px 14px; border-radius: 20px;
  border: 1px solid var(--line); background: var(--panel-2); color: var(--text); cursor: pointer;
}
.pill-btn.primary { background: var(--accent); color: var(--bg); border-color: var(--accent); font-weight: 600; }

/* ---------- tablet / desktop (≥768px) ----------
   Replace the old flex-wrap row layout (which put #chat and #composer on
   separate wrap rows at mismatched widths and let #chat grow past the
   viewport, hiding the composer). CSS Grid pins:
     topbar  → full width
     sidebar → left column spanning chat+composer rows
     chat    → scrollable middle (min-height:0)
     composer→ pinned to bottom of the main column
   Activity drawer becomes a right-edge side panel overlay. */

@media (min-width: 768px) {
  #app {
    display: grid;
    grid-template-columns: 240px minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "topbar topbar"
      "sidebar chat"
      "sidebar composer";
  }

  #scrim { grid-area: 1 / 1 / -1 / -1; }

  #topbar {
    grid-area: topbar;
    width: auto;
  }

  #convo-drawer {
    grid-area: sidebar;
    position: relative;
    top: auto; left: auto; bottom: auto;
    width: auto;
    height: auto;
    min-height: 0;
    padding-top: 0;
    transform: none;
    border-right: 1px solid var(--line);
    pointer-events: auto; /* always interactive as a persistent sidebar */
    z-index: auto;
  }
  /* .open is a no-op visually on desktop — sidebar is always shown. */
  #convo-drawer.open { transform: none; }

  #convo-toggle { display: none; }

  #chat {
    grid-area: chat;
    min-height: 0;
    min-width: 0;
    overflow-y: auto;
  }

  #composer {
    grid-area: composer;
    width: auto;
    min-width: 0;
  }

  /* Right-edge activity panel — overlays the main column without reshaping
     the grid. Closed state slides off to the right (translateX), not down. */
  #activity-drawer {
    top: 0;
    right: 0;
    left: auto;
    bottom: 0;
    width: min(400px, 42vw);
    height: auto;
    max-height: none;
    border-radius: 0;
    border-top: none;
    border-left: 1px solid var(--line);
    padding-bottom: 0;
    transform: translateX(100%);
  }
  #activity-drawer.open { transform: translateX(0); }
  /* Hide the mobile bottom-sheet grip; desktop uses the close button. */
  #activity-drawer .grip { display: none; }
  #activity-drawer .drawer-handle {
    padding-top: 10px;
    cursor: default;
    touch-action: auto;
  }
}

/* Wide desktop — slightly roomier sidebar; chat/composer already cap at 800px. */
@media (min-width: 1024px) {
  #app {
    grid-template-columns: 280px minmax(0, 1fr);
  }
  #activity-drawer {
    width: min(420px, 36vw);
  }
}
