:root {
  --bg: #f7f6f2;
  --panel: #ffffff;
  --panel-2: #f1efe8;
  --border: #e3e0d6;
  --text: #24221f;
  --muted: #6b675f;
  --accent: #b0552f;
  --accent-soft: #f6e3da;
  --on-accent: #ffffff;
  --accent-ink: #a04c2a;
  --user-bg: #efece3;
  --link: #2f6fb3;
  --add-bg: #e6f4ea;
  --add-fg: #1f6b35;
  --del-bg: #fdecea;
  --del-fg: #a3271c;
  --hunk: #6a5acd;
  --code-bg: #f6f8fa;
  --mark: #ffe58a;
  --mark-cur: #ff9f43;
  --shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 2px 8px rgba(0, 0, 0, .04);
  --cat-shell: #3b82f6;
  --cat-edit: #16a34a;
  --cat-read: #8b5cf6;
  --cat-search: #0891b2;
  --cat-agent: #db2777;
  --cat-ask: #d97706;
  --cat-todo: #65a30d;
  --cat-web: #0ea5e9;
  --cat-mcp: #a855f7;
  --cat-other: #6b7280;
  --chat-bg: #efeae2;
  --bubble-user: #d9fdd3;
  --bubble-user-border: #c3e8bb;
  --bubble-ai: #ffffff;
  --bubble-time: #5f6e66;
  --notice-bg: #fff6d9;
  --mono: ui-monospace, "Cascadia Code", "SF Mono", Consolas, Menlo, monospace;
  --sans: -apple-system, "Segoe UI", system-ui, "Microsoft YaHei", "PingFang SC", sans-serif;
  --topbar-h: 52px;
}

[data-theme="dark"] {
  --bg: #1c1b19;
  --panel: #262523;
  --panel-2: #2e2d2a;
  --border: #3a3935;
  --text: #e9e6df;
  --muted: #9b968b;
  --accent: #e07a55;
  --accent-soft: #3d2a22;
  --on-accent: #1c1b19;
  --accent-ink: var(--accent);
  --user-bg: #32302c;
  --link: #6aa9ef;
  --add-bg: #17331f;
  --add-fg: #7ee09a;
  --del-bg: #3d1a17;
  --del-fg: #ff9b90;
  --hunk: #a99cf2;
  --code-bg: #161b22;
  --mark: #7a6420;
  --mark-cur: #c26b1a;
  --shadow: none;
  --chat-bg: #0b141a;
  --bubble-user: #005c4b;
  --bubble-user-border: #005c4b;
  --bubble-ai: #202c33;
  --bubble-time: #b9c9c0;
  --notice-bg: #182229;
}

* { box-sizing: border-box; }

html, body { margin: 0; background: var(--bg); color: var(--text); font: 15px/1.6 var(--sans); }
body { display: flex; min-height: 100vh; }
.app { flex: 1; min-width: 0; }

a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; }
code, pre { font-family: var(--mono); font-size: 13px; }
.muted { color: var(--muted); }
.mono { font-family: var(--mono); font-size: 12px; }

/* Focus ring. --accent clears the 3:1 minimum for focus indicators on every
   surface in both themes (light 4.6-5.1:1, dark 5.2-5.8:1). The previous
   --accent-soft ring measured 1.15:1, i.e. invisible. */
a:focus-visible,
button:focus-visible,
select:focus-visible,
summary:focus-visible,
input:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------ topbar */

.topbar {
  position: sticky; top: 0; z-index: 20;
  height: var(--topbar-h);
  display: flex; align-items: center; gap: 16px;
  padding: 0 16px;
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
}
.brand { font-weight: 700; color: var(--accent); white-space: nowrap; }
.session-title { flex: 1; min-width: 0; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.search { display: flex; align-items: center; gap: 4px; flex: 0 1 356px; min-width: 0; }
.search input {
  width: 100%; min-width: 0; padding: 6px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text); font: inherit; font-size: 13px;
}
.search input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.search-count { font-size: 12px; color: var(--muted); min-width: 56px; text-align: right; }
.toolbar { display: flex; align-items: center; gap: 8px; }
.view-options {
  display: flex; align-items: center; gap: 10px;
  padding: 3px 8px; border-radius: 8px; background: var(--panel-2);
}
.view-options .btn { padding: 4px 8px; font-size: 12px; }
.toggle { font-size: 13px; display: flex; align-items: center; gap: 4px; cursor: pointer; user-select: none; color: var(--muted); }
.btn, .icon-btn {
  font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
  padding: 5px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
  white-space: nowrap;
}
.icon-btn { padding: 4px 8px; }
.btn:hover, .icon-btn:hover { background: var(--panel-2); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:disabled:hover { background: var(--panel); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.primary:hover { filter: brightness(1.05); }
/* Same family as the primary button, one step down: outlined rather than
   filled. The hover fill needs --accent-ink, since --accent on --accent-soft is
   only 4.04:1. */
.btn.secondary { border-color: var(--accent); color: var(--accent); }
.btn.secondary:hover { background: var(--accent-soft); color: var(--accent-ink); }
.btn.danger { color: var(--del-fg); }
.btn.danger:hover { background: var(--del-bg); }
.no-session .search, .no-session .view-options { display: none; }

/* ------------------------------------------------------------------ files panel */

.files-panel {
  position: sticky; top: 0; align-self: flex-start;
  width: 270px; height: 100vh; flex-shrink: 0;
  display: flex; flex-direction: column;
  background: var(--panel-2); border-right: 1px solid var(--border);
  font-size: 13px;
}
.files-collapsed .files-panel { display: none; }
.files-head {
  height: var(--topbar-h); flex-shrink: 0;
  display: flex; align-items: center; padding: 0 14px;
  border-bottom: 1px solid var(--border);
}
.files-heading { font-weight: 700; }
.files-controls { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.files-controls input, .files-controls select {
  width: 100%; padding: 6px 10px; border-radius: 8px; font: inherit;
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
}
.files-controls input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.files-buttons { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; }
.files-buttons .btn { padding: 5px 4px; font-size: 12px; }
.files-buttons .btn[hidden] { display: none; }
.file-list { flex: 1; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 6px; }
.files-foot { flex-shrink: 0; padding: 10px 12px 12px; border-top: 1px solid var(--border); }
.files-feedback-prompt { margin: 0 0 6px; color: var(--muted); font-size: 11px; line-height: 1.4; }
.files-feedback {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; padding: 6px 10px; border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, var(--border));
  color: var(--accent); font-size: 12px; font-weight: 600;
}
.files-feedback svg { flex-shrink: 0; }
.files-feedback:hover {
  background: var(--accent-soft); color: var(--accent-ink); text-decoration: none;
}
.files-feedback:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.files-empty { color: var(--muted); padding: 12px 6px; line-height: 1.5; }
.file-item {
  position: relative; padding: 8px 10px; border-radius: 8px; cursor: pointer;
  background: var(--panel); border: 1px solid var(--border);
}
.file-item:hover { border-color: var(--muted); }
.file-item:focus-visible { outline: 2px solid var(--accent); }
.file-item.active { border-color: var(--accent); background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.file-row { display: flex; align-items: flex-start; gap: 6px; }
.file-title {
  flex: 1; min-width: 0; font-weight: 600; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word;
}
.file-close {
  flex-shrink: 0; width: 20px; height: 20px; padding: 0; line-height: 18px; border-radius: 4px;
  border: none; background: transparent; color: var(--muted); cursor: pointer; font-size: 16px; opacity: 0;
}
.file-item:hover .file-close, .file-item.active .file-close,
.file-item:focus-within .file-close { opacity: 1; }
.file-close:hover { background: var(--del-bg); color: var(--del-fg); }
.file-rename {
  flex-shrink: 0; width: 20px; height: 20px; padding: 0; border-radius: 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--muted); cursor: pointer; opacity: 0;
}
.file-rename svg { width: 13px; height: 13px; }
.file-rename:hover { background: var(--panel-2); color: var(--text); }
.file-item:hover .file-rename, .file-item.active .file-rename,
.file-item:focus-within .file-rename { opacity: 1; }
.file-title-input {
  flex: 1; min-width: 0; font: inherit; font-weight: 600;
  padding: 1px 6px; border-radius: 6px;
  border: 1px solid var(--accent); background: var(--panel); color: var(--text);
}
.file-title-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.file-sub { margin-top: 2px; color: var(--muted); font-family: var(--mono); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-meta { margin-top: 4px; display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 11px; white-space: nowrap; overflow: hidden; }
.file-meta .chip { font-size: 10px; line-height: 16px; padding: 0 6px; }
.file-hits {
  margin-top: 6px; padding-top: 5px; border-top: 1px dashed var(--border);
  font-size: 12px; font-weight: 600; color: var(--accent);
}
.file-hits.muted { color: var(--muted); font-weight: 400; }
.files-search-status { font-size: 12px; color: var(--muted); }
.files-search-status[hidden] { display: none; }

/* File groups: agent → project → rows. Native <details> supplies the folding;
   an inline SVG caret rotates with [open], so no icon assets are needed. */
.file-group { display: block; }
.agent-group { margin-bottom: 2px; }
.project-group { margin: 1px 0 1px 4px; }
.group-summary {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 8px; border-radius: 6px; cursor: pointer; user-select: none;
  list-style: none; color: var(--muted);
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
}
.group-summary::-webkit-details-marker { display: none; }
.group-caret { display: inline-flex; flex-shrink: 0; color: var(--muted); transition: transform .12s; }
.group-caret svg { width: 14px; height: 14px; stroke-width: 2.4; }
details[open] > .group-summary > .group-caret { transform: rotate(90deg); }
.group-summary:hover { background: var(--panel-2); color: var(--text); }
.group-summary:focus-visible { outline: 2px solid var(--accent); }
.project-group > .group-summary { text-transform: none; letter-spacing: 0; font-size: 12px; }
.group-icon { display: inline-flex; flex-shrink: 0; }
/* The category icon leads the row, so it runs larger than the project folder
   and takes the accent colour instead of the muted header text. */
.agent-group > .group-summary .group-icon { color: var(--accent); }
.group-icon svg { width: 13px; height: 13px; }
.agent-group > .group-summary .group-icon svg { width: 17px; height: 17px; stroke-width: 2; }
.project-group > .group-summary .group-icon svg { width: 12px; height: 12px; }
.group-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.group-count { font-variant-numeric: tabular-nums; font-weight: 600; opacity: .75; }
.group-items { display: flex; flex-direction: column; gap: 6px; padding: 2px 0 6px 6px; }
.agent-group > .group-items { padding-left: 2px; }

/* ------------------------------------------------------------------ layout */

.layout { display: flex; }
.sidebar {
  position: sticky; top: var(--topbar-h);
  width: 280px; flex-shrink: 0;
  height: calc(100vh - var(--topbar-h));
  overflow-y: auto;
  padding: 16px 12px 24px;
  border-right: 1px solid var(--border);
  background: var(--panel);
  font-size: 13px;
}
.no-session .sidebar { display: none; }
.main { flex: 1; min-width: 0; padding: 24px 24px 160px; background: var(--chat-bg); min-height: calc(100vh - var(--topbar-h)); }
.no-session .main { background: var(--bg); }
.conversation { max-width: 1040px; margin: 0 auto; }

.info-title { font-size: 15px; font-weight: 700; margin-bottom: 6px; word-break: break-word; }
.info-badges { display: flex; gap: 6px; margin-bottom: 10px; flex-wrap: wrap; }
.info-row { display: flex; gap: 8px; padding: 2px 0; }
.info-label { width: 72px; flex-shrink: 0; color: var(--muted); }
.info-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.outline-head { margin: 18px 0 6px; font-weight: 700; color: var(--muted); text-transform: uppercase; font-size: 11px; letter-spacing: .06em; }
.outline { display: flex; flex-direction: column; gap: 1px; }
.outline-item { display: flex; gap: 8px; padding: 5px 8px; border-radius: 6px; color: var(--text); }
.outline-item:hover { background: var(--panel-2); text-decoration: none; }
.outline-item.active { background: var(--accent-soft); }
.o-idx { color: var(--muted); font-variant-numeric: tabular-nums; min-width: 18px; text-align: right; }
.o-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ------------------------------------------------------------------ welcome */

.welcome { display: none; }
.no-session .welcome { display: flex; justify-content: center; padding: 6vh 16px 64px; }
.welcome-inner { width: 100%; max-width: 760px; display: flex; flex-direction: column; gap: 28px; }
.drop-card {
  width: 100%; max-width: 640px; margin: 0 auto; padding: 40px 40px 32px;
  border: 2px dashed var(--border); border-radius: 16px; background: var(--panel);
  text-align: center;
}
.welcome-icon { width: 40px; height: 40px; color: var(--muted); }
.drop-card h1 { margin: 14px 0 6px; font-size: 22px; }
.welcome-intro { margin: 0 auto 12px; max-width: 52ch; color: var(--muted); line-height: 1.6; }
.welcome-intro a { color: var(--link); }
.welcome-lede {
  margin: 0 auto 22px; max-width: 46ch;
  color: var(--text); font-size: 16px; font-weight: 600; line-height: 1.5;
}
.welcome-lede code {
  padding: 2px 7px; border-radius: 6px;
  background: var(--accent-soft); color: var(--accent-ink);
  font-size: 14px; font-weight: 700;
}
.welcome-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-bottom: 28px; }
.welcome-actions .btn { padding: 8px 18px; }

/* The list is the reference half of this card, so it reads left-aligned inside
   a centred stack. */
.welcome-supported { border-top: 1px solid var(--border); padding-top: 20px; text-align: left; }
.welcome-supported-head { font-size: 13px; font-weight: 700; margin: 0 0 10px; }
.welcome-list { display: grid; grid-template-columns: max-content 1fr; gap: 7px 16px; margin: 0; font-size: 13px; }
.welcome-list dt { font-weight: 600; white-space: nowrap; }
.welcome-list dd { margin: 0; min-width: 0; }
.welcome-list code { font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.welcome-feedback { margin: 14px 0 0; font-size: 13px; color: var(--muted); }
.welcome-feedback a { color: var(--link); font-weight: 600; }
.welcome-note {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin: 0 0 24px; padding: 10px 16px; border-radius: 10px;
  background: var(--accent-soft); color: var(--accent-ink);
  font-size: 13px; font-weight: 600;
}
.welcome-note-icon { width: 16px; height: 16px; flex-shrink: 0; }

/* Crawlable product copy below the drop card. It is part of the welcome screen,
   so it is in the initial HTML and disappears with the card once a log opens. */
.home-content { display: flex; flex-direction: column; gap: 18px; text-align: left; line-height: 1.65; }
.home-content > section {
  padding: 20px 22px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--panel); scroll-margin-top: calc(var(--topbar-h) + 16px);
}
.home-content > section:target { border-color: var(--accent); }
.home-content h2 { margin: 0 0 10px; font-size: 18px; }
.home-content h3 { margin: 16px 0 4px; font-size: 14px; }
.home-content h3:first-of-type { margin-top: 12px; }
.home-content p { margin: 0 0 10px; color: var(--muted); }
.home-content p:last-child { margin-bottom: 0; }
.home-content ul, .home-content ol { margin: 0; padding-left: 22px; color: var(--muted); }
.home-content li { margin: 0 0 6px; }
.home-content li:last-child { margin-bottom: 0; }
.home-content strong { color: var(--text); }
.home-content a { color: var(--link); }
.welcome-intro a:focus-visible, .home-content a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.home-content code { font-size: 12px; }
/* --accent-ink is the brand orange in dark, which only reaches 4.6:1 on the
   tinted band. A pale warm tint reads cleanly and stays in the palette. */
[data-theme="dark"] .welcome-note { color: #f6d9c9; }
.drop-overlay {
  display: none; position: fixed; inset: 0; z-index: 50;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  align-items: center; justify-content: center; font-size: 22px; font-weight: 700; color: var(--accent);
  border: 4px dashed var(--accent);
}
.dragging .drop-overlay { display: flex; }

/* ------------------------------------------------------------------ messages */

.msg { display: flex; gap: 10px; margin: 18px 0; scroll-margin-top: calc(var(--topbar-h) + 12px); }
.msg.user { flex-direction: row-reverse; }
.avatar {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: #fff; margin-top: 2px;
}
.avatar.user { background: #5b6170; }
.avatar.assistant { background: var(--accent); color: var(--on-accent); }
.msg-main { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; }
.msg.user .msg-main { align-items: flex-end; }
.msg-head { display: flex; align-items: center; gap: 8px; margin: 0 4px 4px; font-size: 12px; color: var(--muted); }
.msg-head .who { color: var(--text); }
.who { font-weight: 700; }
.idx { color: var(--muted); }
.time { color: var(--muted); font-size: 12px; margin-left: auto; white-space: nowrap; }
.chip {
  display: inline-block; padding: 0 8px; border-radius: 999px; font-size: 11px; line-height: 18px;
  background: var(--panel-2); color: var(--muted); border: 1px solid var(--border); white-space: nowrap;
}
.chip.model { color: var(--accent); }
.chip.claude { background: var(--accent-soft); color: var(--accent-ink); border-color: transparent; }
.chip.cursor { background: #e0e7ff; color: #3730a3; border-color: transparent; }
.chip.copilot { background: #dcfce7; color: #166534; border-color: transparent; }
.chip.codex { background: #e2e8f0; color: #334155; border-color: transparent; }
[data-theme="dark"] .chip.codex { background: #334155; color: #e2e8f0; }

.bubble {
  position: relative; min-width: 120px; max-width: 100%;
  padding: 8px 12px 6px; border-radius: 10px;
  box-shadow: 0 1px 1px rgba(0, 0, 0, .1);
}
.bubble::before {
  content: ""; position: absolute; top: 0; width: 0; height: 0;
  border-style: solid; border-width: 0 10px 10px 0;
}
.msg.user .bubble {
  max-width: 78%; background: var(--bubble-user); border-top-right-radius: 0;
}
.msg.user .bubble::before { right: -9px; border-width: 0 0 10px 10px; border-color: transparent transparent transparent var(--bubble-user); }
.msg.assistant .bubble {
  width: fit-content; max-width: 88%; background: var(--bubble-ai); border-top-left-radius: 0;
}
.msg.assistant .bubble::before { left: -9px; border-color: transparent var(--bubble-ai) transparent transparent; }
.bubble-time {
  display: flex; justify-content: flex-end; gap: 10px;
  margin-top: 4px; font-size: 11px; color: var(--bubble-time); white-space: nowrap;
}
.turn-dur::before { content: "⏱ "; }
[data-theme="dark"] .msg.user .bubble { color: #e9edef; }
[data-theme="dark"] .msg.user .bubble .md code { background: rgba(0, 0, 0, .25); }
.command { font-family: var(--mono); font-size: 13px; }
.cmd-name { color: var(--accent); font-weight: 700; }
.sidechain { border-left: 3px solid var(--cat-agent); padding-left: 10px; }

.turn-body > * + * { margin-top: 8px; }
.msg.user .md code { background: rgba(0, 0, 0, .06); }

/* ------------------------------------------------------------------ markdown */

.md { overflow-wrap: anywhere; }
.md > :first-child { margin-top: 0; }
.md > :last-child { margin-bottom: 0; }
.md p { margin: .5em 0; }
.md h1, .md h2, .md h3, .md h4 { margin: 1em 0 .4em; line-height: 1.3; }
.md h1 { font-size: 1.4em; } .md h2 { font-size: 1.25em; } .md h3 { font-size: 1.1em; } .md h4 { font-size: 1em; }
.md ul, .md ol { padding-left: 1.5em; margin: .4em 0; }
.md li + li { margin-top: .15em; }
.md blockquote { margin: .5em 0; padding: .2em 1em; border-left: 3px solid var(--border); color: var(--muted); }
.md code { background: var(--panel-2); padding: .1em .35em; border-radius: 4px; font-size: .88em; }
.md pre { position: relative; background: var(--code-bg); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; overflow: auto; }
.md pre code { background: none; padding: 0; font-size: 13px; }
.md pre code.hljs { padding: 0; background: transparent; }
.md table { border-collapse: collapse; margin: .6em 0; display: block; overflow-x: auto; font-size: 14px; }
.md th, .md td { border: 1px solid var(--border); padding: 5px 10px; text-align: left; vertical-align: top; }
.md th { background: var(--panel-2); }
.md hr { border: none; border-top: 1px solid var(--border); margin: 1em 0; }
.md img { max-width: 100%; }

/* ------------------------------------------------------------------ tools */

.tool-group { display: flex; flex-direction: column; gap: 4px; }
.bubble .tool { background: color-mix(in srgb, var(--bubble-ai) 94%, var(--text)); box-shadow: none; }
.tool, .ctx, .thinking {
  border: 1px solid var(--border); border-radius: 10px; background: var(--panel); box-shadow: var(--shadow);
}
.tool > summary, .ctx > summary, .thinking > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 12px; font-size: 13px; min-width: 0;
}
.tool > summary::-webkit-details-marker, .ctx > summary::-webkit-details-marker, .thinking > summary::-webkit-details-marker { display: none; }
.tool > summary::before, .ctx > summary::before, .thinking > summary::before {
  content: "▸"; color: var(--muted); font-size: 11px; transition: transform .12s; flex-shrink: 0;
}
.tool[open] > summary::before, .ctx[open] > summary::before, .thinking[open] > summary::before { transform: rotate(90deg); }
.tool > summary:hover { background: var(--panel-2); border-radius: 10px; }
.tool[open] > summary { border-bottom: 1px solid var(--border); }
.tool-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--cat-other); }
.cat-shell .tool-dot { background: var(--cat-shell); }
.cat-edit .tool-dot { background: var(--cat-edit); }
.cat-read .tool-dot { background: var(--cat-read); }
.cat-search .tool-dot { background: var(--cat-search); }
.cat-agent .tool-dot { background: var(--cat-agent); }
.cat-ask .tool-dot { background: var(--cat-ask); }
.cat-todo .tool-dot { background: var(--cat-todo); }
.cat-web .tool-dot { background: var(--cat-web); }
.cat-mcp .tool-dot { background: var(--cat-mcp); }
.tool-name { font-weight: 600; white-space: nowrap; }
.tool-sum { color: var(--muted); min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--mono); font-size: 12px; }
.tool-stats { display: flex; gap: 6px; font-family: var(--mono); font-size: 12px; }
.stat.add { color: var(--add-fg); }
.stat.del { color: var(--del-fg); }
.tool-status { color: var(--add-fg); font-weight: 700; }
.tool.error { border-color: color-mix(in srgb, var(--del-fg) 45%, var(--border)); }
.tool.error .tool-status { color: var(--del-fg); }
.tool-body { padding: 10px 12px; display: flex; flex-direction: column; gap: 10px; }
.tool-label { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; margin-bottom: 4px; word-break: break-all; }

pre.code {
  /* No height cap of its own: a long result is folded by .collapsible instead,
     so that the whole block disappears rather than scrolling inside itself. */
  position: relative; margin: 0; overflow: auto;
  background: var(--code-bg); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px;
  white-space: pre-wrap; word-break: break-word;
}
pre.code code.hljs { padding: 0; background: transparent; }
.copy-btn {
  position: sticky; float: right; top: 0; margin: -4px -6px 0 8px;
  font: 11px var(--sans); padding: 2px 8px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--border); background: var(--panel); color: var(--muted); opacity: 0; transition: opacity .1s;
}
pre:hover > .copy-btn, pre:focus-within > .copy-btn { opacity: 1; }
.link-btn { margin-top: 4px; background: none; border: none; color: var(--link); cursor: pointer; font: inherit; font-size: 12px; padding: 0; }

/* Per-message copy: lives in the message header, so it stays reachable while a
   long reply is folded. Always visible; it claims the free space, and the fold
   toggle keeps the far right. */
.copy-reply-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; margin-left: auto;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--panel); color: var(--muted); cursor: pointer;
}
.copy-reply-btn:hover { background: var(--panel-2); color: var(--text); }
.copy-reply-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.msg-head > .copy-reply-btn ~ .collapse-btn.in-head { margin-left: 0; }

/* A foldable block carries a round −/+ toggle in its top right corner: the
   primary button in miniature, so it reads as a control rather than as one more
   piece of chrome. It is sticky, so it rides the window while the block is on
   screen: reaching it must not mean scrolling to the end of the very block you
   want out of the way. The float parks it in the first line's margin, the way
   .copy-btn does inside a code block.
   The glyph is drawn, not set in type: − and + sit on the font's math axis,
   which is above the line box centre the button actually centres, so as text
   they always look a couple of pixels high. Two bars keep them on the optical
   centre regardless of the font. They are painted as backgrounds rather than as
   absolutely positioned pseudo-elements: a sticky float does not act as their
   containing block in Chrome, so the bars would park at the page centre.
   aria-expanded is already kept in sync by setCollapsed, so it doubles as the
   plus/minus switch. */
.collapse-btn {
  display: none;
  position: sticky; float: right; top: calc(var(--topbar-h) + 8px); z-index: 5;
  align-items: center; justify-content: center;
  width: 26px; height: 26px; margin: 2px 0 8px 10px; padding: 0;
  border: 1px solid var(--accent); border-radius: 50%;
  background-color: var(--accent);
  background-image: linear-gradient(var(--on-accent), var(--on-accent));
  background-size: 10px 2px; background-position: center; background-repeat: no-repeat;
  color: transparent; font-size: 0; cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
}
.collapse-btn[aria-expanded="false"] {
  background-image:
    linear-gradient(var(--on-accent), var(--on-accent)),
    linear-gradient(var(--on-accent), var(--on-accent));
  background-size: 10px 2px, 2px 10px;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
}
.collapse-btn:hover { filter: brightness(1.08); }
.collapsible.tall > .collapse-btn { display: inline-flex; }
/* In a message header there is no block to float in — the row is already a flex
   line, so the toggle just takes the free space at its end. */
/* Even bar lengths keep the centre on a whole pixel: the 22px button has a
   20px content box, where an odd bar leaves a 0.5px half-pixel to round. */
.collapse-btn.in-head { position: static; float: none; margin: 0 0 0 auto; width: 22px; height: 22px; background-size: 8px 2px; }
.collapse-btn.in-head[aria-expanded="false"] { background-size: 8px 2px, 2px 8px; }
.msg-head.foldable > .collapse-btn.in-head { display: inline-flex; }

/* Folded, not hidden: the text stays in the DOM so the in-page search still
   matches it (and unfolds the block before scrolling to a hit). The mask fades
   the last lines into whatever is behind them, so no bubble colour has to be
   repeated here. */
.collapsible.collapsed > .collapsible-body {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 44px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 44px), transparent);
}
/* The way back out, under the fold: outlined like the secondary buttons, with a
   caret so it reads as "there is more, this way". */
.collapse-more { display: none; }
.collapsible.collapsed > .collapse-more {
  display: block; width: fit-content; margin: 6px auto 2px; padding: 4px 14px;
  border: 1px solid var(--accent); border-radius: 999px;
  background: var(--panel); color: var(--accent);
  font-size: 13px; font-weight: 600;
}
.collapsible.collapsed > .collapse-more::before { content: "▾ "; font-size: 11px; }
.collapsible.collapsed > .collapse-more:hover { background: var(--accent-soft); color: var(--accent-ink); }

.diff { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.diff-file { padding: 4px 10px; font-family: var(--mono); font-size: 12px; background: var(--panel-2); border-bottom: 1px solid var(--border); word-break: break-all; }
.diff-body { margin: 0; max-height: 560px; overflow: auto; background: var(--code-bg); font-size: 12.5px; line-height: 1.5; }
.dl { display: block; padding: 0 10px; white-space: pre-wrap; word-break: break-word; }
.dl.add { background: var(--add-bg); color: var(--add-fg); }
.dl.del { background: var(--del-bg); color: var(--del-fg); }
.dl.hunk { color: var(--hunk); background: var(--panel-2); }

.todos { list-style: none; margin: 0; padding: 0; }
.todo { display: flex; gap: 8px; align-items: baseline; padding: 2px 0; }
.todo-box {
  width: 16px; height: 16px; flex-shrink: 0; border: 1.5px solid var(--muted); border-radius: 4px;
  font-size: 11px; line-height: 13px; text-align: center; transform: translateY(2px);
}
.todo.completed { color: var(--muted); text-decoration: line-through; }
.todo.completed .todo-box { background: var(--cat-todo); border-color: var(--cat-todo); color: #fff; }
.todo.in_progress .todo-box { color: var(--accent); border-color: var(--accent); }
.todo.in_progress { font-weight: 600; }

.question { border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; }
.q-head { display: flex; gap: 8px; align-items: center; font-weight: 600; margin-bottom: 6px; }
.q-options { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.q-options li { padding: 4px 10px; border-radius: 6px; border: 1px solid var(--border); }
.q-options li.chosen { border-color: var(--accent); background: var(--accent-soft); }
.q-options li.chosen .q-label::before { content: "✓ "; color: var(--accent); }
.q-label { font-weight: 600; }
.q-desc { display: block; color: var(--muted); font-size: 13px; }

.thinking > summary { color: var(--muted); font-style: italic; }
.thinking .md { padding: 4px 14px 10px; color: var(--muted); font-size: 14px; }
.inline-img { max-width: 100%; border-radius: 8px; border: 1px solid var(--border); margin-top: 6px; }

/* ------------------------------------------------------------------ context */

.ctx { background: transparent; box-shadow: none; border-style: dashed; }
.ctx > summary { padding: 3px 10px; font-size: 12px; }
.ctx-label { font-weight: 600; color: var(--muted); white-space: nowrap; }
.ctx-sum { color: var(--muted); opacity: .8; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--mono); font-size: 11px; }
.ctx > pre.code, .ctx > .code-wrap { margin: 0 10px 10px; }
.ctx-group { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.ctx-group.top { margin: 8px auto; max-width: 76%; }

body:not(.show-context) .ctx,
body:not(.show-context) .ctx-group.top { display: none; }
body.hide-tools .tool { display: none; }
body.hide-thinking .thinking { display: none; }
/* A tool group whose cards are all hidden still stacks its own top margin, and
   dozens of them pile up into a blank stretch inside the reply. Hide the empty
   wrapper whenever nothing inside it can be seen. */
body.hide-tools:not(.show-context) .tool-group,
body.hide-tools .tool-group:not(:has(.ctx)),
body:not(.show-context) .tool-group:not(:has(.tool)) { display: none; }

/* ------------------------------------------------------------------ events */

.event { margin: 14px auto; max-width: 76%; font-size: 13px; }
.event.divider { display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 12px; max-width: 60%; }
.event.divider::before, .event.divider::after { content: ""; flex: 1; border-top: 1px dashed var(--muted); opacity: .5; }
.event.divider > span { background: var(--notice-bg); padding: 2px 10px; border-radius: 8px; box-shadow: 0 1px 1px rgba(0, 0, 0, .08); }
.event.interrupt { color: var(--del-fg); }
.event.pr {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: fit-content;
  background: var(--notice-bg); padding: 4px 12px; border-radius: 8px; box-shadow: 0 1px 1px rgba(0, 0, 0, .08);
}
.event.output { width: fit-content; min-width: 40%; }
.event.output .event-title { justify-content: center; }
.event.card {
  border: none; border-top: 3px solid var(--muted); border-radius: 8px; padding: 8px 14px;
  background: var(--notice-bg); box-shadow: 0 1px 1px rgba(0, 0, 0, .08);
}
.event.card.recap { border-top-color: var(--cat-ask); }
.event.card.notification { border-top-color: var(--cat-agent); }
.event.card.error { border-top-color: var(--del-fg); }
.event-title { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13px; margin-bottom: 4px; }
.event-details > summary { cursor: pointer; color: var(--link); font-size: 13px; }
.event-details .md { margin-top: 6px; }
.event.output .event-title { color: var(--muted); font-weight: 500; }

/* ------------------------------------------------------------------ actions */

.fab-stack {
  position: fixed; right: 24px; bottom: 24px; z-index: 30;
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
}
.fab {
  display: flex; align-items: center; gap: 6px;
  padding: 9px 14px; border: none; border-radius: 999px; cursor: pointer;
  font: 600 13px var(--sans);
  transition: transform .1s, filter .1s;
}
/* Labels change with language and live state, so the live row and export
   button share one width: both outer edges stay aligned instead of resizing. */
.export-fab {
  width: 100%; justify-content: space-between;
  border: 1px solid var(--accent); background: var(--panel); color: var(--accent);
  box-shadow: 0 3px 10px rgba(0, 0, 0, .18);
}
.export-fab:hover { background: var(--accent-soft); color: var(--accent-ink); }
.export-fab[aria-expanded="true"] { background: var(--accent-soft); color: var(--accent-ink); border-color: transparent; }
.fab-svg { flex-shrink: 0; }
.export-caret { flex-shrink: 0; opacity: .7; }

/* Export is a low-frequency action, so it opens a menu instead of keeping two
   permanent buttons next to the live controls. */
.export-control { position: relative; }
.export-menu {
  position: absolute; right: 0; bottom: calc(100% + 8px); width: 268px;
  display: flex; flex-direction: column; gap: 2px; padding: 6px;
  max-height: calc(100vh - 120px); overflow-y: auto;
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .22);
}
.export-menu[hidden] { display: none; }
.export-menu-title {
  padding: 6px 8px; font-size: 11px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted);
}
.export-item {
  display: flex; flex-direction: column; gap: 1px; width: 100%;
  padding: 7px 8px; border: 0; border-radius: 8px; text-align: left;
  background: transparent; color: var(--text); font: inherit; cursor: pointer;
}
.export-item:hover, .export-item:focus-visible { background: var(--panel-2); }
.export-item:disabled { opacity: .5; cursor: progress; }
.export-item-name { font-weight: 600; font-size: 13px; }
.export-item-desc { font-size: 11px; color: var(--muted); }
.export-divider { height: 1px; margin: 4px 2px; background: var(--border); }
.export-options { display: flex; flex-wrap: wrap; gap: 8px 12px; padding: 4px 8px 2px; }
.export-options .toggle { font-size: 12px; color: var(--text); }
.export-theme {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 6px 8px 2px; font-size: 12px; color: var(--muted);
}
.export-theme select {
  padding: 3px 6px; border-radius: 6px; font: inherit; font-size: 12px;
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
}
.export-note { padding: 4px 8px 6px; font-size: 11px; line-height: 1.45; color: var(--muted); }

/* Live state and manual reload share one row: the switch is the automation of
   the button next to it, so its state has to be visible, not implied. */
.refresh-row { display: flex; align-items: center; gap: 4px; }
.live-fab {
  display: flex; align-items: center; gap: 6px;
  min-width: 72px; white-space: nowrap;
  padding: 6px 8px; border-radius: 999px; cursor: pointer; user-select: none;
  border: 1px solid var(--accent); background: var(--panel); color: var(--muted);
  font-size: 12px; font-weight: 600; box-shadow: 0 3px 10px rgba(0, 0, 0, .18);
}
.live-fab:hover { background: var(--accent-soft); }
.live-fab input { position: absolute; width: 0; height: 0; opacity: 0; }
.live-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--muted); }
.live-fab.is-live { background: var(--accent-soft); color: var(--accent-ink); }
.live-fab.is-live .live-dot { background: var(--add-fg); outline: 1.5px solid var(--add-fg); }
.live-fab.is-paused .live-dot { background: var(--cat-ask); }
.live-fab.is-unavailable { color: var(--muted); border-color: var(--border); cursor: not-allowed; }
.live-fab.is-unavailable .live-dot { background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted); }
.live-fab:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.live-dot.pulse { animation: live-pulse .7s ease-out; }
@keyframes live-pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--add-fg) 45%, transparent); }
  100% { box-shadow: 0 0 0 7px transparent; }
}

.reload-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0; border-radius: 999px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, var(--border));
  background: var(--panel); color: var(--accent);
  font-size: 17px; line-height: 1; box-shadow: 0 3px 10px rgba(0, 0, 0, .18);
}
.reload-btn:hover { background: var(--accent-soft); border-color: transparent; color: var(--accent-ink); }
.reload-btn.spinning span { display: inline-block; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* New items wait in a pill instead of pulling the reader away from where they
   are: clicking it jumps to the first message that arrived. */
.new-items-pill { position: fixed; left: 50%; bottom: 24px; z-index: 31; transform: translateX(-50%); }
.new-items-pill[hidden] { display: none; }
.new-items-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 16px; border: 1px solid var(--accent); border-radius: 999px;
  background: var(--accent); color: var(--on-accent); font: 600 13px var(--sans);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .25); cursor: pointer;
}
.new-items-btn:hover { filter: brightness(1.06); }
.new-items-arrow { font-size: 14px; }

.no-session .fab-stack, .no-session .new-items-pill { display: none; }

.toast {
  position: fixed; right: 24px; bottom: 132px; z-index: 30; max-width: 360px;
  padding: 8px 14px; border-radius: 8px; font-size: 13px;
  background: var(--text); color: var(--bg); box-shadow: 0 4px 14px rgba(0, 0, 0, .2);
  opacity: 0; transform: translateY(6px); pointer-events: none; transition: opacity .15s, transform .15s;
}
.toast.show { opacity: 1; transform: none; }
.toast.error { background: var(--del-fg); color: #fff; }
/* ------------------------------------------------------------------ search */

mark.hit { background: var(--mark); color: inherit; border-radius: 2px; padding: 0; }
mark.hit.current { background: var(--mark-cur); color: #000; }

/* ------------------------------------------------------------------ responsive */

/* The side columns are fixed-width, so a narrow window used to force the whole
   document wider than the viewport (measured: 895px of content in a 480px
   window, down to 489px once these rules apply). Below their breakpoints they
   leave the flow and become drawers, so the transcript gets the full width and
   neither column — especially the prompts outline, the main way to navigate —
   becomes unreachable. */
.btn-sidebar { display: none; }
.drawer-backdrop { display: none; position: fixed; inset: 0; z-index: 34; background: rgba(0, 0, 0, .32); }

/* One breakpoint for both columns. The file list is fixed-width too, so when it
   stayed in flow the topbar no longer fitted between it and the viewport edge
   (at 1000px it needed 754px of a 697px bar, which crushed the session title and
   clipped the theme button). Below this width both columns step aside together
   and the transcript gets the full width. */
@media (max-width: 1100px) {
  .topbar { gap: 8px; }
  .brand { display: none; }
  .view-options { gap: 6px; padding: 2px 6px; }
  .files-panel { position: fixed; top: 0; left: 0; height: 100vh; z-index: 40; }
  body:not(.files-collapsed) .drawer-backdrop { display: block; }
  body:not(.files-collapsed) .topbar { z-index: 42; }

  .sidebar {
    position: fixed; top: var(--topbar-h); left: 0; z-index: 41;
    width: min(320px, 86vw); height: calc(100vh - var(--topbar-h));
    transform: translateX(-101%); transition: transform .18s ease;
  }
  body.sidebar-open .sidebar { transform: none; }
  body.sidebar-open .drawer-backdrop { display: block; }
  /* Keep the toggles clickable above the scrim, like the header of a drawer. */
  body.sidebar-open .topbar { z-index: 42; }
  /* One drawer at a time: the sidebar wins while it is open. */
  body.sidebar-open .files-panel { display: none; }

  .btn-sidebar { display: inline-flex; }
  .search { flex-basis: 256px; }
}

@media (max-width: 760px) {
  /* The toolbar needs more room than a phone gives it. Scrolling the bar
     sideways keeps every control reachable without widening the document,
     which would push the fixed action dock off the right edge. */
  .topbar { overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
  .topbar::-webkit-scrollbar { display: none; }
  .view-options { gap: 4px; padding: 2px 4px; flex-shrink: 0; }
  .toolbar { flex-shrink: 0; }
  .search { flex: 0 0 150px; }
  .search-count { min-width: 0; }
  .drop-card { padding: 28px 22px 24px; }
  .welcome-list { grid-template-columns: 1fr; gap: 2px 0; }
  .welcome-list dd { margin-bottom: 8px; }
  .main { padding: 12px 12px 160px; }
  .event, .ctx-group.top { max-width: 100%; }
  .msg.user .bubble, .msg.assistant .bubble { max-width: 100%; }
  .avatar { display: none; }
  .fab-stack { right: 12px; bottom: 12px; }
  .new-items-pill { bottom: 100px; }
  .export-menu { width: min(268px, calc(100vw - 24px)); }
  .toast { right: 12px; bottom: 118px; max-width: calc(100vw - 24px); }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar { transition: none; }
  .live-dot.pulse { animation: none; }
  .reload-btn.spinning span { animation: none; }
}

/* Touch devices never hover, so the two hover-only controls would be
   unreachable there. Show them permanently. */
@media (hover: none) {
  .file-close, .file-rename, .copy-btn { opacity: 1; }
}

@media print {
  .topbar, .sidebar, .files-panel, .fab-stack, .new-items-pill, .toast { display: none; }
  .tool, .ctx { break-inside: avoid; }
  /* The fold height is set inline by render.js and the toggle is shown by a
     two-class rule, so both overrides have to outrank them. */
  .collapsible-body {
    max-height: none !important; overflow: visible !important;
    -webkit-mask-image: none !important; mask-image: none !important;
  }
  .collapse-btn, .collapse-more, .copy-reply-btn { display: none !important; }
}
