@spzxg/cli-ui 0.6.5 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +109 -30
  3. package/dist/cli-ui-embed-CB7ibAtF.js +49558 -0
  4. package/dist/{cli-ui-index-D4qfPHMd.js → cli-ui-index-BmwOLWFI.js} +2 -2
  5. package/dist/{cli-ui-jszip.min-DC9898pC.js → cli-ui-jszip.min-BKNOJnhm.js} +1 -1
  6. package/dist/{cli-ui-jszip.min-DpEl0G1z.js → cli-ui-jszip.min-Cq0WjNYb.js} +2 -2
  7. package/dist/{cli-ui-xlsx-zs7oEtPj.js → cli-ui-xlsx-Sl7ypvSe.js} +1 -1
  8. package/dist/cli-ui.css +1 -1
  9. package/dist/cli-ui.js +1 -1
  10. package/package.json +11 -8
  11. package/src/board/BrowserPane.tsx +198 -53
  12. package/src/board/CliBoard.tsx +128 -100
  13. package/src/board/FileViewer.tsx +276 -136
  14. package/src/board/FilesPane.tsx +129 -40
  15. package/src/board/HtmlReadingPreview.tsx +52 -0
  16. package/src/board/MarkdownPreview.tsx +134 -0
  17. package/src/board/PanelControls.tsx +19 -7
  18. package/src/board/fileKind.ts +138 -0
  19. package/src/board/fileOps.ts +9 -2
  20. package/src/board/fileScope.ts +29 -0
  21. package/src/board/fileSync.ts +343 -0
  22. package/src/board/fileSyncCache.ts +250 -0
  23. package/src/board/fileSyncProcessor.ts +71 -0
  24. package/src/board/fileSyncQueue.ts +56 -0
  25. package/src/board/fileSyncTransport.ts +85 -0
  26. package/src/board/fileWatch.ts +177 -70
  27. package/src/board/folderDownload.ts +39 -5
  28. package/src/board/frameQuote.ts +12 -10
  29. package/src/board/htmlReading.ts +148 -0
  30. package/src/board/textLoad.ts +18 -41
  31. package/src/board/useBoardUpload.tsx +51 -0
  32. package/src/board/useBoardVisibility.ts +35 -0
  33. package/src/board/workspace.ts +53 -11
  34. package/src/chat/CliChat.tsx +105 -55
  35. package/src/chat/Composer.tsx +55 -21
  36. package/src/chat/GroupChat.tsx +113 -0
  37. package/src/chat/RunControls.tsx +132 -42
  38. package/src/chat/draft.ts +5 -2
  39. package/src/core/blocks.ts +17 -5
  40. package/src/core/client.ts +88 -19
  41. package/src/core/conversation.ts +1 -0
  42. package/src/core/documentUpload.ts +196 -0
  43. package/src/core/provider.tsx +7 -0
  44. package/src/core/store.ts +134 -36
  45. package/src/core/types.ts +31 -10
  46. package/src/index.ts +3 -0
  47. package/src/layout/split.ts +67 -30
  48. package/src/msglist/CliMsgList.tsx +18 -5
  49. package/src/operator/node/Chat.tsx +7 -8
  50. package/src/operator/node/Composer.tsx +99 -72
  51. package/src/operator/node/Orchestrator.tsx +1 -1
  52. package/src/operator/node/SessionRail.tsx +71 -32
  53. package/src/operator/node/SessionView.tsx +25 -25
  54. package/src/operator/node/Transcript.tsx +28 -11
  55. package/src/operator/node/boardBackend.ts +6 -23
  56. package/src/operator/node/boardEvents.ts +21 -3
  57. package/src/operator/node/boardState.ts +18 -1
  58. package/src/operator/node/boardWorkspace.ts +4 -1
  59. package/src/operator/node/composerDraft.ts +6 -2
  60. package/src/operator/node/format.ts +4 -2
  61. package/src/operator/node/liveStream.ts +14 -2
  62. package/src/operator/node/protocol/types.ts +2 -2
  63. package/src/operator/node/useTaskStream.ts +8 -5
  64. package/src/operator.base.css +148 -37
  65. package/src/operator.css +148 -37
  66. package/src/styles.css +274 -32
  67. package/src/ui/Markdown.tsx +2 -2
  68. package/src/ui/Popover.tsx +32 -14
  69. package/src/ui/QueuedMessages.tsx +69 -0
  70. package/src/ui/ReferenceCard.tsx +28 -0
  71. package/src/ui/TextBlock.tsx +6 -4
  72. package/src/ui/Transcript.tsx +27 -12
  73. package/src/ui/UploadProgress.tsx +46 -0
  74. package/src/ui/WorkspaceDrawer.tsx +64 -0
  75. package/src/ui/WorkspaceTabs.tsx +60 -0
  76. package/src/ui/format.ts +3 -1
  77. package/src/ui/reference.ts +40 -0
  78. package/src/ui/useChatScrollbar.ts +29 -0
  79. package/src/ui/useComposerAutosize.ts +54 -0
  80. package/dist/cli-ui-embed-BmLN2Jjg.js +0 -43290
@@ -1,12 +1,15 @@
1
+ import type { WorkspaceRefreshOptions } from '../../board/fileWatch';
1
2
  import { createWorkspace } from '../../board/workspace';
2
3
  import { cloneBoardView } from '../../board/context';
3
4
  import { getOperatorBoardBackend } from './boardBackend';
4
5
  import { readBoardState } from './boardState';
5
6
  import { openOperatorBoard } from './boardInteraction';
7
+ import { refreshOperatorWorkspaceFiles } from './boardEvents';
6
8
  /** Host API for the node workspace. Uses the same cloud-facing file API as the board. */
7
9
  export function createOperatorWorkspace(taskId:string){
8
- return createWorkspace({backend:getOperatorBoardBackend(),key:taskId,
10
+ const workspace=createWorkspace({backend:getOperatorBoardBackend(),key:taskId,
9
11
  view:()=>{const view=readBoardState(taskId);return view?.visible?cloneBoardView(view):undefined;},
10
12
  context:()=>{const view=readBoardState(taskId);return view?cloneBoardView(view):null;},
11
13
  open:path=>openOperatorBoard({kind:'file',taskId,path})});
14
+ return {...workspace,refresh:(options?:WorkspaceRefreshOptions)=>refreshOperatorWorkspaceFiles(taskId,options)};
12
15
  }
@@ -1,5 +1,9 @@
1
- export type Quote = { id: string; author: string; text: string };
1
+ import type { UploadPhase } from "../../core/documentUpload";
2
+
3
+ export type Quote = { id: string; author: string; text: string; sourceTaskId?: string };
2
4
  export type Attachment = {
5
+ progress?: number;
6
+ phase?: UploadPhase; bytes?: number; size?: number;
3
7
  key: string; kind: "image" | "file"; name: string; preview: string; path: string;
4
8
  status: "uploading" | "ready" | "error"; error?: string;
5
9
  };
@@ -15,7 +19,7 @@ export function readDraft(id: string): ComposerDraft {
15
19
  const raw = localStorage.getItem(key(id));
16
20
  if (raw) {
17
21
  const d = JSON.parse(raw) as ComposerDraft;
18
- if (typeof d.text === "string" && Array.isArray(d.attachments)) return { ...d, attachments: d.attachments.map((a) => a.status === "uploading" ? { ...a, preview: "", status: "error", error: "上传已中断,请移除后重新添加。" } : a) };
22
+ if (typeof d.text === "string" && Array.isArray(d.attachments)) return { ...d, attachments: d.attachments.map((a) => a.status === "uploading" ? { ...a, preview: "", status: "error", error: "上传已中断,请重新选择文件。" } : a) };
19
23
  }
20
24
  return { ...emptyDraft(), text: localStorage.getItem(`orch:draft:${id}`) ?? "" };
21
25
  } catch { return emptyDraft(); }
@@ -279,9 +279,11 @@ export function splitAttachments(content: string): { text: string; attachments:
279
279
  for (const line of content.split("\n")) {
280
280
  const m = ATTACHMENT_RE.exec(line.trim());
281
281
  const parts = m ? m[2].split(/[\\/]/).filter(Boolean) : [];
282
- if (m && parts.length >= 3 && parts[parts.length - 3] === "uploads") {
282
+ const upload = parts.length >= 3 && parts[parts.length - 3] === "uploads";
283
+ const managed = parts.length >= 4 && parts[parts.length - 4] === ".workspace" && parts[parts.length - 3] === "attachments";
284
+ if (m && (upload || managed) && parts.slice(-2).every(part => part !== "." && part !== "..")) {
283
285
  const [taskId, file] = parts.slice(-2);
284
- attachments.push({ path: m[2], url: `/api/tasks/${taskId}/uploads/${file}`, kind: m[1] === "image" ? "image" : "file", name: file });
286
+ attachments.push({ path: m[2], url: `/api/tasks/${encodeURIComponent(taskId)}/uploads/${encodeURIComponent(file)}`, kind: m[1] === "image" ? "image" : "file", name: file });
285
287
  } else {
286
288
  kept.push(line);
287
289
  }
@@ -45,6 +45,18 @@ const BACKOFF_MS = [500, 1000, 2000, 4000, 8000];
45
45
  const PROBE_MS = 30_000;
46
46
 
47
47
  const subs = new Map<number, Sub>();
48
+ const observers = new Map<string, Set<(data: string) => void>>();
49
+ /** Observe an existing route without opening a connection or server subscription. */
50
+ export function observeLiveMessages(path: string, listener: (data: string) => void): () => void {
51
+ const key = path.split("?")[0];
52
+ const listeners = observers.get(key) ?? new Set(); observers.set(key, listeners); listeners.add(listener);
53
+ return () => { listeners.delete(listener); if (!listeners.size) observers.delete(key); };
54
+ }
55
+ function deliver(s: Sub, data: string) {
56
+ if (subs.get(s.id) !== s) return;
57
+ for (const listener of [...observers.get(s.url.split("?")[0]) ?? []]) notifyCallback(listener, data);
58
+ if (subs.get(s.id) === s) s.h.onMessage(data);
59
+ }
48
60
  let nextId = 1;
49
61
  let mode: "ws" | "sse" | null = null;
50
62
  let ws: WebSocket | null = null;
@@ -91,7 +103,7 @@ function openEventSource(s: Sub) {
91
103
  const es = new EventSource(s.url);
92
104
  const active = () => subs.get(s.id) === s && s.es === es;
93
105
  es.onopen = () => { if (!active()) return; if (s.retry) { clearTimeout(s.retry); s.retry = undefined; } s.fails = 0; s.h.onOpen?.(); };
94
- es.onmessage = (event) => { if (active()) s.h.onMessage(event.data); };
106
+ es.onmessage = (event) => { if (active()) deliver(s, event.data); };
95
107
  es.onerror = () => {
96
108
  if (!active()) return;
97
109
  notifyCallback(s.h.onError, new Error("实时事件连接中断,正在等待恢复"));
@@ -203,7 +215,7 @@ function onFrame(text: string) {
203
215
  const nl = text.indexOf("\n");
204
216
  if (nl <= 0) return;
205
217
  const s = subs.get(Number(text.slice(0, nl)));
206
- if (s) s.h.onMessage(text.slice(nl + 1));
218
+ if (s) deliver(s, text.slice(nl + 1));
207
219
  }
208
220
 
209
221
  function connect() {
@@ -239,9 +239,9 @@ export type StreamEvent =
239
239
  | { type: "tool"; id: string; title: string; detail: string; peek?: ToolPeek; diff?: DiffLine[] }
240
240
  | { type: "tool_result"; id: string; content: string; isError: boolean; peek?: ToolPeek }
241
241
  | { type: "ask"; id: string; questions: AskQuestion[] }
242
- | { type: "ask_answered"; id: string; answers: AskAnswers }
242
+ | { type: "ask_answered"; id: string; answers: AskAnswers; awaiting_input?: 0 | 1 }
243
243
  // An input card was raised or settled (the whole card each time; upsert by msgId).
244
- | { type: "input"; input: InputRequest }
244
+ | { type: "input"; input: InputRequest; awaiting_input?: 0 | 1 }
245
245
  | { type: "suggested"; title: string }
246
246
  | { type: "usage"; usage: TurnUsage }
247
247
  | { type: "notice"; content: string } // a quiet, non-error system note (e.g. "caught up to main")
@@ -149,15 +149,16 @@ export function useTaskStream({ selTask, selProjRef, agentsRef, setTaskRunning,
149
149
  // Only drop the flag once every parked ask on this task is answered.
150
150
  const open = openAsksRef.current[taskId];
151
151
  open?.delete(ev.id);
152
- if (!open || open.size === 0) {
153
- setTasks((prev) => prev.map((x) => (x.id === taskId ? { ...x, awaiting_input: 0 } : x)));
154
- }
152
+ const reported = ev.awaiting_input;
153
+ const awaiting = reported === 0 || reported === 1 ? reported : open?.size ? 1 : 0;
154
+ setTasks((prev) => prev.map((x) => (x.id === taskId ? { ...x, awaiting_input: awaiting } : x)));
155
155
  } else if (ev.type === "input") {
156
156
  // browser_ask_user card raised or settled: the event carries the whole card.
157
157
  const data: ToolData = { title: "需要你提供信息", input: ev.input };
158
158
  upsertMsg(taskId, { id: ev.msgId ?? `in-${ev.input.id}`, role: "tool", content: JSON.stringify(data), generation: gen });
159
+ const reported = ev.awaiting_input;
159
160
  const waiting = ev.input.status === "pending";
160
- setTasks((prev) => prev.map((x) => (x.id === taskId ? { ...x, awaiting_input: waiting ? 1 : x.awaiting_input && openAsksRef.current[taskId]?.size ? 1 : 0 } : x)));
161
+ setTasks((prev) => prev.map((x) => (x.id === taskId ? { ...x, awaiting_input: reported === 0 || reported === 1 ? reported : waiting ? 1 : x.awaiting_input && openAsksRef.current[taskId]?.size ? 1 : 0 } : x)));
161
162
  } else if (ev.type === "usage") {
162
163
  // Live cumulative spend: add this turn's totals to the task's figure.
163
164
  // Context occupancy, by contrast, is the latest turn's INPUT-side
@@ -231,12 +232,14 @@ export function useTaskStream({ selTask, selProjRef, agentsRef, setTaskRunning,
231
232
  setOlderByTask(drop);
232
233
  for (const t of evicted) { delete openAsksRef.current[t]; delete loadingOlderRef.current[t]; }
233
234
  }
235
+ let active = true;
234
236
  const sub = openLive(`/api/tasks/${id}/messages?tail=${SNAPSHOT_TAIL}`, {
235
237
  onMessage: (data) => {
238
+ if (!active) return;
236
239
  try { handleStreamEventRef.current(id, JSON.parse(data) as TaskStreamEvent); } catch {}
237
240
  },
238
241
  });
239
- return () => sub.close();
242
+ return () => { active = false; sub.close(); };
240
243
  }, [selTask]);
241
244
 
242
245
  // Page in the next batch of earlier messages for a task (the transcript calls
@@ -606,9 +606,10 @@ button{font-family:inherit;color:inherit;cursor:pointer;border:none;background:n
606
606
  /* Wrapper exists so the nav cluster anchors to the transcript's bottom edge —
607
607
  i.e. always just above the composer, however tall the composer grows. */
608
608
  .transcript-wrap{position:relative;flex:1;min-height:0;display:flex;flex-direction:column;}
609
- .msg-nav{position:absolute;right:18px;bottom:12px;z-index:5;display:flex;flex-direction:column;gap:6px;}
610
- .msg-nav-btn{width:34px;height:34px;border-radius:999px;display:grid;place-items:center;background:var(--surface);border:1px solid var(--line);color:var(--ink-2);box-shadow:0 4px 14px rgba(0,0,0,.18);cursor:pointer;transition:transform .12s ease,background .12s ease;}
611
- .msg-nav-btn:hover{background:var(--surface-2);transform:translateY(-1px);}
609
+ .msg-nav{position:absolute;right:14px;bottom:12px;z-index:5;display:flex;flex-direction:column;gap:2px;padding:3px;border:1px solid var(--line);border-radius:10px;background:var(--surface);box-shadow:0 2px 10px rgba(0,0,0,.06);}
610
+ .msg-nav-btn{width:32px;height:32px;border-radius:6px;display:grid;place-items:center;background:transparent;color:var(--ink-3);cursor:pointer;transition:background .12s ease;}
611
+ .msg-nav-btn:hover{background:var(--surface-2);color:var(--ink);}
612
+ .msg-nav-btn:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;}
612
613
  .msg-nav-btn svg{width:16px;height:16px;}
613
614
 
614
615
  /* ===== workspace split: transcript beside the DIFF/PREVIEW/CONTEXT rail ===== */
@@ -616,9 +617,10 @@ button{font-family:inherit;color:inherit;cursor:pointer;border:none;background:n
616
617
  driven by an inline gridTemplateColumns from layout state (resizable); the
617
618
  --col-rail value here is only the SSR/fallback default. */
618
619
  .sess-split{flex:1;min-height:0;display:grid;grid-template-columns:minmax(0,1fr) 0px var(--col-rail);}
619
- .sess-main{position:relative;min-width:0;min-height:0;display:flex;flex-direction:column;border-right:1px solid var(--line);}
620
- .sess-rail{min-width:0;min-height:0;display:flex;flex-direction:column;background:var(--bg-2);}
621
- .rail-tabs{flex:0 0 auto;display:flex;gap:2px;padding:0 14px;border-bottom:1px solid var(--line);}
620
+ .sess-main{position:relative;min-width:0;min-height:0;display:flex;flex-direction:column;border-right:1px solid var(--line-2);}
621
+ .sess-split>.sess-main + .col-rail.rail-right{border-left:0;}
622
+ .sess-rail{min-width:0;min-height:0;display:flex;flex-direction:column;background:var(--bg-2);container-type:inline-size;}
623
+ .rail-tabs{flex:0 0 auto;display:flex;gap:2px;padding:0 14px;border-bottom:1px solid var(--line-2);}
622
624
  .rail-tab{font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--ink-4);background:transparent;border:none;border-bottom:2px solid transparent;padding:14px 13px 12px;cursor:pointer;transition:color .12s;}
623
625
  .rail-tab.on{color:var(--ink);border-bottom-color:var(--accent);}
624
626
  .rail-tab:not(.on):hover{color:var(--ink-2);}
@@ -671,7 +673,7 @@ button{font-family:inherit;color:inherit;cursor:pointer;border:none;background:n
671
673
  .ctxw-desc{font-family:var(--mono);font-size:11px;color:var(--ink-3);line-height:1.6;margin-top:4px;}
672
674
  .ctxw-clear{width:100%;justify-content:center;margin-top:20px;}
673
675
  .ctxw-foot{margin-top:12px;font-family:var(--mono);font-size:10px;line-height:1.7;color:var(--ink-4);text-align:center;}
674
- .sess-head{flex:0 0 auto;display:flex;align-items:center;gap:12px;flex-wrap:wrap;min-height:60px;padding:11px 18px;border-bottom:1px solid var(--line);background:var(--surface);}
676
+ .sess-head{flex:0 0 auto;display:flex;align-items:center;gap:12px;flex-wrap:wrap;min-height:60px;padding:11px 18px;border-bottom:1px solid var(--line-2);background:var(--surface);}
675
677
  .sess-head .sh-main{min-width:150px;flex:1;}
676
678
  .sess-head .crumb{font-family:var(--mono);font-size:10.5px;color:var(--ink-3);display:flex;align-items:center;gap:6px;}
677
679
  .sess-head .crumb .sep{opacity:.5;}
@@ -790,7 +792,7 @@ a.tc-btn{display:inline-flex;align-items:center;text-decoration:none;line-height
790
792
  .transcript{flex:1;overflow-y:auto;padding:26px 0 18px;}
791
793
  .tw{max-width:760px;margin:0 auto;padding:0 28px;}
792
794
  .msg{margin-bottom:22px;}
793
- .msg .who{display:flex;align-items:center;gap:8px;font-family:var(--mono);font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);margin-bottom:7px;}
795
+ .msg .who{display:flex;align-items:center;gap:7px;font-size:11px;font-weight:500;color:var(--ink-3);margin-bottom:9px;}
794
796
  .msg .who .badge{font-size:9px;padding:1px 5px;border-radius:4px;background:var(--surface-2);color:var(--ink-3);letter-spacing:.04em;}
795
797
  .msg .who .msg-time{font-weight:400;letter-spacing:.03em;text-transform:none;color:var(--ink-3);opacity:.75;}
796
798
  .msg .who .av{width:18px;height:18px;border-radius:5px;display:grid;place-items:center;color:#fff;font-size:10px;}
@@ -806,15 +808,15 @@ a.tc-btn{display:inline-flex;align-items:center;text-decoration:none;line-height
806
808
  .msg .who .av.cc.codex{color:var(--ink);}
807
809
  .msg .who .av svg{width:11px;height:11px;}
808
810
  .msg .who .av.cc svg{width:16px;height:16px;}
809
- .msg-body{font-size:14px;line-height:1.6;color:var(--ink);}
811
+ .msg-body{font-size:15px;line-height:1.75;color:var(--ink);}
810
812
  .msg-body p{margin:0 0 10px;}
811
813
  .msg-body p:last-child{margin-bottom:0;}
812
814
  .msg-body code{font-family:var(--mono);font-size:12.5px;background:var(--surface-2);border:1px solid var(--line-2);padding:1px 5px;border-radius:5px;color:var(--accent-ink);}
813
815
  [data-theme="dark"] .msg-body code{color:#E0A07F;}
814
816
  .msg-body strong{font-weight:700;}
815
817
 
816
- .msg.user .msg-body{background:var(--accent-soft);border:1px solid rgba(194,96,60,.2);border-radius:var(--r-lg);padding:13px 15px;}
817
- .msg.user.initial .msg-body{background:var(--surface);border:1px solid var(--accent);box-shadow:var(--sh-1);}
818
+ .msg.user .msg-body{background:var(--surface-2);border:1px solid var(--line-2);border-radius:16px;padding:14px 16px;}
819
+ .msg.user.initial .msg-body{background:var(--surface);border-color:var(--line);}
818
820
  /* queued follow-up: a dimmed user bubble waiting its turn, with a cancel × */
819
821
  .msg.user.queued{opacity:.62;}
820
822
  .msg.user.queued .msg-body{background:var(--surface-2);border:1px dashed var(--line-2);position:relative;padding-right:34px;}
@@ -827,7 +829,8 @@ a.tc-btn{display:inline-flex;align-items:center;text-decoration:none;line-height
827
829
 
828
830
  /* tool call block (expandable) */
829
831
  .tool{font-family:var(--mono);font-size:12px;border-radius:var(--r);border:1px solid var(--line-2);background:var(--surface-2);overflow:hidden;}
830
- .tool-h{display:flex;align-items:center;gap:8px;padding:8px 12px;color:var(--ink-2);width:100%;text-align:left;font-family:var(--mono);font-size:12px;}
832
+ .tool-h{display:flex;align-items:center;gap:8px;padding:9px 12px;min-height:38px;color:var(--ink-2);width:100%;text-align:left;font-family:var(--mono);font-size:12px;}
833
+ .tool-h:focus-visible{outline:2px solid var(--accent);outline-offset:-3px;}
831
834
  .tool-h:hover{background:var(--panel-2);}
832
835
  .tool-h .tchev{flex:0 0 auto;color:var(--ink-4);display:inline-flex;transition:transform .14s;}
833
836
  .tool-h .tchev svg{width:13px;height:13px;}
@@ -910,16 +913,16 @@ button.tpeek-more:hover{color:var(--accent-ink);}
910
913
  .md li{margin-bottom:4px;}
911
914
  .md li::marker{color:var(--ink-3);}
912
915
  .md h1,.md h2,.md h3,.md h4{margin:16px 0 8px;font-weight:700;letter-spacing:-.01em;line-height:1.3;}
913
- .md h1{font-size:18px;}
914
- .md h2{font-size:16px;}
915
- .md h3{font-size:14.5px;}
916
+ .md h1{font-size:20px;}
917
+ .md h2{font-size:18px;}
918
+ .md h3{font-size:16px;}
916
919
  .md h4{font-size:13px;}
917
920
  .md code{font-family:var(--mono);font-size:12.5px;background:var(--surface-2);border:1px solid var(--line-2);padding:1px 5px;border-radius:5px;color:var(--accent-ink);}
918
921
  [data-theme="dark"] .md code{color:#E0A07F;}
919
922
  .md pre{margin:0 0 12px;background:var(--panel-2);border:1px solid var(--line-2);border-radius:var(--r);padding:12px 14px;overflow-x:auto;}
920
923
  .md pre code{display:block;background:none;border:none;padding:0;color:var(--ink);font-size:12.5px;line-height:1.55;}
921
- .md blockquote{margin:8px 0;padding:2px 0 2px 14px;border-left:3px solid var(--line-strong);color:var(--ink-2);}
922
- .md hr{border:none;border-top:1px solid var(--line);margin:14px 0;}
924
+ .md blockquote{margin:12px 0;padding:4px 0 4px 14px;border-left:2px solid var(--line);color:var(--ink-2);}
925
+ .md hr{border:none;border-top:1px solid var(--line-2);margin:14px 0;}
923
926
  .md table{border-collapse:collapse;margin:8px 0;font-size:13px;width:100%;}
924
927
  .md th,.md td{border:1px solid var(--line-2);padding:6px 10px;text-align:left;}
925
928
  .md th{background:var(--surface-2);font-weight:700;}
@@ -973,7 +976,7 @@ button.tpeek-more:hover{color:var(--accent-ink);}
973
976
  .sbreak .card .ct b{color:var(--ink);}
974
977
 
975
978
  .session-label{display:flex;align-items:center;gap:9px;margin:0 0 20px;font-family:var(--mono);font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-4);}
976
- .session-label .ln{flex:1;height:1px;background:var(--line);}
979
+ .session-label .ln{flex:1;height:1px;background:var(--line-2);}
977
980
 
978
981
  /* windowed transcript: reveal earlier rows */
979
982
  .load-older{display:flex;justify-content:center;margin:0 0 18px;}
@@ -1013,7 +1016,7 @@ button.tpeek-more:hover{color:var(--accent-ink);}
1013
1016
  .comp-box{border:1px solid var(--line-strong);border-radius:24px;background:var(--raise);box-shadow:0 4px 20px rgba(0,0,0,.04);transition:border-color .15s,box-shadow .15s;overflow:hidden;}
1014
1017
  .comp-box:focus-within{border-color:var(--ink-4);box-shadow:0 4px 24px rgba(0,0,0,.07);}
1015
1018
  .comp-area{padding:18px 20px 8px;}
1016
- .comp-area textarea{display:block;width:100%;min-width:0;border:none;background:none;resize:none;outline:none;font-family:var(--sans);font-size:15px;line-height:1.6;color:var(--ink);max-height:200px;min-height:62px;}
1019
+ .comp-area textarea{display:block;width:100%;min-width:0;padding:0;border:none;background:none;resize:none;outline:none;font-family:var(--sans);font-size:15px;line-height:1.6;color:var(--ink);min-height:3.2em;max-height:12.8em;overflow-y:hidden;scrollbar-width:thin;overscroll-behavior:contain;}
1017
1020
  .comp-area textarea::placeholder{color:var(--ink-4);}
1018
1021
  .comp-toolbar{display:flex;align-items:center;gap:7px;padding:4px 12px 12px;min-width:0;}
1019
1022
  .comp-add{width:36px;height:36px;display:grid;place-items:center;border-radius:50%;flex:none;color:var(--ink-2);background:transparent;}
@@ -1025,7 +1028,6 @@ button.tpeek-more:hover{color:var(--accent-ink);}
1025
1028
  .comp-setting svg{width:14px;height:14px;}
1026
1029
  .comp-setting.elevated{color:var(--amber);}
1027
1030
  .comp-model-name{min-width:0;max-width:220px;overflow:hidden;text-overflow:ellipsis;}
1028
- .comp-reasoning{color:var(--ink-3);font-size:11px;}
1029
1031
  .comp-setting:disabled,.comp-add:disabled{opacity:.5;cursor:default;}
1030
1032
  .send{width:36px;height:36px;flex:none;border-radius:50%;background:var(--accent);color:var(--on-accent);display:grid;place-items:center;transition:filter .12s,opacity .12s;}
1031
1033
  .send:hover{filter:brightness(1.07);}
@@ -1052,16 +1054,9 @@ button.tpeek-more:hover{color:var(--accent-ink);}
1052
1054
 
1053
1055
  .send-group{display:flex;align-items:center;gap:6px;flex:none;}
1054
1056
  .send svg{width:19px;height:19px;}
1055
- .comp-caption{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:4px;padding:8px 6px 0;font-size:10px;color:var(--ink-4);}
1056
- .comp-caption button{display:flex;align-items:center;gap:4px;background:transparent;color:var(--ink-3);font-size:10px;}
1057
- .comp-caption button:disabled{opacity:.45;cursor:default;}
1058
1057
  .comp-error,.control-error{padding:8px 10px;font-size:12px;line-height:1.5;color:var(--red);overflow-wrap:anywhere;}
1059
1058
  .comp-upload-status{padding:6px 10px;font-size:11px;color:var(--ink-3);}
1060
- .comp-quote{display:flex;align-items:flex-start;gap:10px;margin:12px 14px 0;padding:10px 12px;border-left:3px solid var(--accent);border-radius:5px 12px 12px 5px;background:var(--surface-2);font-size:12px;}
1061
- .comp-quote>div{flex:1;min-width:0;}
1062
- .comp-quote strong{font-weight:500;color:var(--ink-2);}
1063
- .comp-quote p{margin:4px 0 0;color:var(--ink-3);overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow-wrap:anywhere;white-space:pre-wrap;}
1064
- .comp-quote .icon-btn{width:24px;height:24px;flex:none;}
1059
+ .comp-quote{margin:12px 14px 0;}
1065
1060
  .hero-controls{display:flex;align-items:center;gap:12px;padding:12px 20px;border-bottom:1px solid var(--line);}
1066
1061
  .hero-controls .comp-model{margin-left:0;}
1067
1062
  .compact-chat{flex:1;}
@@ -1070,7 +1065,8 @@ button.tpeek-more:hover{color:var(--accent-ink);}
1070
1065
  .compact-session .sess-head{flex-wrap:wrap;}
1071
1066
  .compact-session .sh-tools{flex-wrap:wrap;}
1072
1067
  .msg-actions{display:flex;margin-top:6px;}
1073
- .msg-actions button{display:flex;align-items:center;gap:4px;padding:4px 6px;border-radius:6px;background:transparent;font-size:11px;color:var(--ink-4);}
1068
+ .msg-actions button{display:flex;align-items:center;gap:5px;min-height:32px;padding:5px 8px;border-radius:6px;background:transparent;font-size:12px;color:var(--ink-3);}
1069
+ .msg-actions button svg{width:14px;height:14px;}
1074
1070
  .msg-actions button:hover,.msg-actions button:focus-visible{background:var(--surface-2);color:var(--ink);}
1075
1071
  .msg-body{overflow-wrap:anywhere;min-width:0;}
1076
1072
  button.pop-item{width:100%;text-align:left;background:transparent;color:var(--ink);font:inherit;}
@@ -1084,7 +1080,6 @@ button.pop-item:hover{background:var(--surface-2);}
1084
1080
  .comp-setting{font-size:11px;padding:5px;gap:4px;}
1085
1081
  .comp-model-name{max-width:145px;}
1086
1082
  .comp-area{padding:14px 16px 6px;}
1087
- .comp-caption{font-size:9px;}
1088
1083
  }
1089
1084
  @container (max-width:310px){
1090
1085
  .comp-control:has(.permission){flex:1;}
@@ -1353,10 +1348,111 @@ button.pop-item:hover{background:var(--surface-2);}
1353
1348
  .pop-item .pi-check svg{width:14px;height:14px;}
1354
1349
  .pop-item .pi-sub{font-family:var(--mono);font-size:10px;color:var(--ink-3);font-weight:400;}
1355
1350
  .pop-sec{padding:8px 13px 4px;font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);}
1356
- .pop-custom-model{border-top:1px solid var(--line);padding-bottom:10px;}
1351
+ .pop-custom-model{border-top:1px solid var(--line-2);padding-bottom:10px;}
1357
1352
  .pop-custom-row{display:flex;gap:7px;padding:5px 10px;}
1358
1353
  .pop-custom-row input{min-width:260px;flex:1;font-size:11px;}
1359
1354
  .pop-custom-model>.pi-sub{max-width:360px;padding:0 11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
1355
+ .run-agent-list{width:260px;max-width:100%;}
1356
+ .run-agent-option{min-height:44px;}
1357
+ .run-agent-trailing{margin-left:auto;display:flex;align-items:center;gap:8px;color:var(--ink-3);}
1358
+ .run-agent-trailing svg{width:14px;height:14px;}
1359
+ .run-settings{width:320px;max-width:100%;}
1360
+ .run-settings-head{display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line-2);}
1361
+ .run-settings-head .run-settings-back{width:auto;font-size:12px;}
1362
+ .run-settings-back svg{width:14px;height:14px;}
1363
+ .run-settings-field{padding:4px 2px 10px;}
1364
+ .run-settings-note{margin:6px 0 0;font-size:11px;line-height:1.5;color:var(--ink-3);overflow-wrap:anywhere;}
1365
+ .run-settings .pop-custom-row input{width:100%;min-height:38px;padding:6px 10px;border:1px solid var(--line-strong);border-radius:8px;background:var(--surface);color:var(--ink);font:inherit;font-size:13px;}
1366
+ .run-settings .pop-custom-row button{min-height:38px;}
1367
+ /* Composer menus share one card treatment without changing task or board menus. */
1368
+ .popover.composer-popover{--composer-reasoning:var(--operator);width:348px;padding:8px;border-radius:20px;border-color:var(--line-strong);background:var(--raise);box-shadow:0 12px 40px rgba(0,0,0,.16),0 2px 8px rgba(0,0,0,.06);}
1369
+ [data-theme="light"] .composer-popover{--composer-reasoning:#7c3aed;}
1370
+ .composer-menu-heading{padding:8px 10px 10px;font-size:12px;font-weight:500;color:var(--ink-3);}
1371
+ .composer-menu-note{margin:0;padding:0 10px 10px;color:var(--ink-3);font-size:11px;line-height:1.5;}
1372
+ .composer-popover .composer-option{display:flex;align-items:center;text-align:left;width:100%;min-height:56px;gap:11px;padding:11px 10px;border-radius:12px;font-size:14px;line-height:1.4;}
1373
+ .composer-popover .composer-option:hover:not(:disabled),.composer-popover .composer-option[aria-pressed="true"]{background:var(--surface-2);}
1374
+ .composer-option-icon{display:grid;place-items:center;flex:none;width:24px;height:26px;color:var(--ink-3);}
1375
+ .composer-option-icon svg{width:19px;height:19px;}
1376
+ .composer-option-copy{display:block;flex:1;min-width:0;}
1377
+ .composer-option-title{display:block;color:var(--ink);font-size:14px;font-weight:500;overflow-wrap:anywhere;}
1378
+ .composer-option-sub{display:block;margin-top:3px;color:var(--ink-3);font-size:12px;font-weight:400;line-height:1.45;overflow-wrap:anywhere;}
1379
+ .composer-option-trailing{margin-left:auto;display:flex;align-items:center;gap:6px;flex:none;color:var(--accent);}
1380
+ .composer-option-trailing svg{width:16px;height:16px;}
1381
+ .composer-menu-key{color:var(--ink-4);font-size:12px;}
1382
+ .composer-popover .pop-sec{padding:8px 10px;font-size:12px;font-weight:500;letter-spacing:0;text-transform:none;}
1383
+ .composer-popover .run-agent-list,.composer-popover .run-settings{width:auto;max-width:none;}
1384
+ .composer-popover .run-settings-head{margin:0 2px 10px;padding-bottom:4px;}
1385
+ .composer-popover .run-settings-back{min-height:40px;border-radius:10px;font-size:13px;}
1386
+ .composer-popover .run-models-back{display:flex;align-items:center;gap:8px;width:auto;min-height:40px;border-radius:10px;font-size:13px;}
1387
+ .run-models-back svg{width:14px;height:14px;}
1388
+ .run-field-label{display:block;color:var(--ink-3);font-size:12px;font-weight:500;padding:0 8px 8px;}
1389
+ .composer-popover .run-model-entry{border:1px solid var(--line);background:var(--surface);}
1390
+ .run-model-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
1391
+ .run-model-list{max-height:min(46vh,320px);overflow-y:auto;overscroll-behavior:contain;}
1392
+ .run-model-group-title{padding:12px 10px 4px;color:var(--ink-3);font-size:11px;}
1393
+ .run-reasoning-card{margin:4px 2px 10px;padding:14px;border:1px solid var(--line);border-radius:16px;background:linear-gradient(145deg,color-mix(in srgb,var(--composer-reasoning) 8%,var(--raise)),var(--raise) 80%);}
1394
+ .run-reasoning-head{display:flex;align-items:center;justify-content:space-between;gap:10px;}
1395
+ .run-reasoning-head .run-field-label{padding:0;}
1396
+ .run-reasoning-value{min-width:0;color:var(--composer-reasoning);font-size:18px;font-weight:600;overflow-wrap:anywhere;text-align:right;}
1397
+ .run-reasoning-note{margin:8px 0 14px;color:var(--ink-3);font-size:12px;line-height:1.5;}
1398
+ .run-reasoning-options{display:flex;flex-wrap:wrap;gap:5px;}
1399
+ .run-reasoning-option{flex:1 1 60px;min-height:38px;padding:7px 8px;border:1px solid var(--line);border-radius:9px;background:var(--raise);color:var(--ink-2);font-size:12px;line-height:1.3;overflow-wrap:anywhere;}
1400
+ .run-reasoning-option:hover:not(:disabled){border-color:var(--composer-reasoning);}
1401
+ .run-reasoning-option[aria-pressed="true"]{background:var(--composer-reasoning);border-color:transparent;color:var(--raise);font-weight:600;}
1402
+ .run-reasoning-option:disabled,.run-reasoning-reset:disabled{opacity:.5;cursor:default;}
1403
+ .run-reasoning-reset{display:flex;justify-content:center;align-items:center;gap:6px;width:100%;min-height:36px;margin-top:10px;padding:6px;border-radius:9px;color:var(--ink-3);font-size:12px;}
1404
+ .run-reasoning-reset svg{width:14px;height:14px;}
1405
+ .run-reasoning-reset:hover:not(:disabled),.run-reasoning-reset[aria-pressed="true"]{color:var(--composer-reasoning);background:color-mix(in srgb,var(--composer-reasoning) 8%,transparent);}
1406
+ .run-settings .pop-custom-model{padding-top:8px;}
1407
+ .run-settings .pop-custom-model>.composer-menu-heading{display:block;padding-bottom:4px;}
1408
+ .run-settings .pop-custom-row input:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
1409
+ .composer-popover .control-error{margin:4px 2px;border-radius:10px;background:var(--red-soft);}
1410
+ .comp-add.on{color:var(--ink);}
1411
+ .comp-add.on svg{transform:rotate(45deg);}
1412
+ .composer .comp-setting{min-height:38px;border-radius:6px;padding:7px 10px;background:transparent;}
1413
+ .composer .comp-add{width:38px;height:38px;border-radius:6px;background:transparent;}
1414
+ .composer .comp-setting:hover:not(:disabled),.composer .comp-add:hover:not(:disabled){background:var(--surface-2);}
1415
+ .composer .send{width:38px;height:38px;}
1416
+ .composer .comp-box{border-radius:26px;border-color:var(--line);box-shadow:0 4px 20px rgba(0,0,0,.035);}
1417
+ .composer .comp-box:focus-within{border-color:var(--line-strong);box-shadow:0 6px 24px rgba(0,0,0,.055);}
1418
+ .composer .comp-toolbar{gap:6px;padding:6px 12px 12px;}
1419
+ .composer .comp-area{padding:18px 20px 12px;}
1420
+ .composer .attach-chip.image{width:108px;height:88px;border-radius:12px;}
1421
+ .composer .attach-chip.image>img{height:100%;object-fit:cover;}
1422
+ .composer .attach-chip .attach-x{width:26px;height:26px;top:4px;right:4px;font-size:16px;}
1423
+ .composer .attach-chip.file{border-radius:10px;}
1424
+ .composer .attach-row{gap:10px;padding:14px 16px 4px;flex-wrap:nowrap;overflow-x:auto;}
1425
+ .composer .attach-row .attach-chip{flex:none;}
1426
+ .composer .cli-blocks{max-height:min(30vh,180px);}
1427
+ @container(max-width:420px){
1428
+ .composer .comp-area{padding:14px 16px 8px;}
1429
+ .composer .comp-toolbar{gap:4px;padding:6px 10px 10px;}
1430
+ .composer .comp-setting{padding:6px 9px;}
1431
+ .composer .attach-chip.image{width:86px;height:76px;}
1432
+ }
1433
+ @container(max-width:360px){
1434
+ .composer .comp-toolbar{flex-wrap:nowrap;padding-left:8px;padding-right:8px;}
1435
+ .composer .comp-toolbar>.comp-control{flex:0 0 auto;}
1436
+ .composer .comp-toolbar>.comp-model{flex:0 1 auto;min-width:44px;margin-left:auto;}
1437
+ .composer .comp-setting{font-size:11px;gap:0;padding-left:6px;padding-right:6px;}
1438
+ .composer .comp-setting>svg{display:none;}
1439
+ .composer .comp-model-name{max-width:42px;}
1440
+ .composer .comp-toolbar:not(:has(.send.stop)) .comp-setting{gap:4px;font-size:12px;}
1441
+ .composer .comp-toolbar:not(:has(.send.stop)) .permission>svg:first-child{display:block;width:14px;height:14px;}
1442
+ .composer .comp-toolbar:not(:has(.send.stop)) .comp-model .comp-setting>svg{display:block;width:12px;height:12px;}
1443
+ .composer .comp-foot{flex-wrap:wrap;gap:6px;}
1444
+ .composer .comp-foot>.send-group{margin-left:auto;}
1445
+ }
1446
+ @media(pointer:coarse){
1447
+ .composer-popover .composer-option{min-height:52px;}
1448
+ .composer .comp-add,.composer .comp-setting,.composer .send{min-width:44px;min-height:44px;}
1449
+ .composer .attach-chip .attach-x{min-width:32px;min-height:32px;}
1450
+ }
1451
+ @media(prefers-reduced-motion:reduce){.popover.composer-popover{animation:none;}}
1452
+ @media(pointer:coarse){
1453
+ .run-settings .pop-custom-row input{min-height:44px;font-size:16px;}
1454
+ .run-settings-back,.run-models-back,.run-settings .pop-custom-row button,.run-reasoning-option,.run-reasoning-reset{min-height:44px;}
1455
+ }
1360
1456
 
1361
1457
  /* ⌘K command palette */
1362
1458
  .palette-scrim{position:fixed;inset:0;background:rgba(0,0,0,.38);backdrop-filter:blur(3px);z-index:240;display:flex;align-items:flex-start;justify-content:center;padding-top:13vh;animation:fadein .12s ease;}
@@ -1453,7 +1549,6 @@ button.pop-item:hover{background:var(--surface-2);}
1453
1549
  the home indicator. The keyboard hints are mouse-era noise on a phone. */
1454
1550
  .app.mobile .composer{padding:10px 12px calc(12px + env(safe-area-inset-bottom));}
1455
1551
  .app.mobile .comp-area textarea{font-size:16px;}
1456
- .app.mobile .comp-caption>span{display:none;}
1457
1552
  .app.mobile .send{width:40px;height:40px;}
1458
1553
 
1459
1554
  /* Ask card options are tap targets — give them room. */
@@ -1659,6 +1754,14 @@ button.pop-item:hover{background:var(--surface-2);}
1659
1754
  .bp-handoff{border:1px solid var(--coral);background:var(--coral-soft);border-radius:var(--r-sm);padding:10px 12px;font-size:12.5px;line-height:1.6;color:var(--ink);}
1660
1755
  .bp-handoff-sub{margin-top:4px;font-family:var(--mono);font-size:10.5px;color:var(--ink-3);}
1661
1756
  .bp-viewer{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;background:var(--panel);box-shadow:var(--sh-2);position:relative;}
1757
+ .bp-tabs{display:flex;gap:4px;overflow-x:auto;overscroll-behavior-x:contain;padding:6px 6px 0;border-bottom:1px solid var(--line-2);background:var(--surface-2);scrollbar-width:thin;}
1758
+ .bp-tab{display:flex;align-items:center;gap:6px;flex:0 0 auto;min-width:72px;max-width:200px;padding:7px 10px;border-radius:6px 6px 0 0;border-bottom:2px solid transparent;color:var(--ink-3);font-size:12px;text-align:left;}
1759
+ .bp-tab > span:first-child{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}
1760
+ .bp-tab.active{background:var(--panel);border-bottom-color:var(--accent);color:var(--ink);}
1761
+ .bp-tab:not(:disabled):hover{background:var(--panel);color:var(--ink);}
1762
+ .bp-tab:disabled{cursor:default;}
1763
+ .bp-tab:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;}
1764
+ .bp-tab-wait{flex:none;color:var(--accent);}
1662
1765
  .bp-chrome{gap:6px;}
1663
1766
  .bp-nav{width:24px;height:24px;border-radius:4px;color:var(--ink-3);font-size:15px;line-height:1;}
1664
1767
  .bp-nav:not(:disabled):hover{background:var(--surface-2);color:var(--ink);}
@@ -1716,8 +1819,9 @@ button.pop-item:hover{background:var(--surface-2);}
1716
1819
  .sess-head .sh-tools{gap:8px;flex-wrap:nowrap;flex-shrink:0;}
1717
1820
  .session-more{width:32px;height:32px;}
1718
1821
  .session-viewbar{display:flex;align-items:center;gap:16px;min-height:42px;padding:0 22px;border-bottom:1px solid var(--line-2);}
1719
- .session-agent-label{color:var(--ink-3);font-size:12px;}
1720
- .session-branch{margin-left:auto;min-width:0;display:flex;align-items:center;gap:6px;color:var(--ink-4);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
1822
+ .session-origin{display:flex;align-items:center;gap:6px;}
1823
+ .session-origin svg{width:14px;height:14px;flex:none;}
1824
+ .session-origin span{min-width:0;overflow-wrap:anywhere;}
1721
1825
  .session-viewbar .viewseg{flex-shrink:0;}
1722
1826
  .compact-session .sh-tools{flex-wrap:nowrap;}
1723
1827
  .composer{padding:16px 24px 12px;}
@@ -1725,9 +1829,16 @@ button.pop-item:hover{background:var(--surface-2);}
1725
1829
  .comp-area{padding:18px 20px 10px;}
1726
1830
  .comp-toolbar{padding:4px 14px 12px;}
1727
1831
  .comp-setting{font-size:13px;}
1728
- .comp-caption{font-size:11px;padding-top:9px;}
1729
- .comp-caption button{font-size:11px;}
1730
- .transcript .tw{max-width:800px;}
1832
+ /* Transcript and composer share one column; only a wide, isolated chat is capped. */
1833
+ [data-chat-layout]{--cli-chat-gutter:16px;--cli-chat-content-max:100%;container:chat-column / inline-size;}
1834
+ [data-chat-layout="centered"]{--cli-chat-content-max:50vw;}
1835
+ .body[data-chat-sidebars="open"]>.col-session [data-chat-layout="centered"]{--cli-chat-content-max:100%;}
1836
+ [data-chat-layout] .transcript>.tw{width:calc(100% - 2 * var(--cli-chat-gutter));max-width:var(--cli-chat-content-max);margin-inline:auto;padding-inline:0;}
1837
+ .session [data-chat-layout]>.composer{padding-inline:var(--cli-chat-gutter);padding-inline-end:calc(var(--cli-chat-gutter) + var(--cli-chat-scrollbar,0px));}
1838
+ [data-chat-layout]>.composer>.composer-inner{width:100%;max-width:var(--cli-chat-content-max);margin-inline:auto;}
1839
+ [data-chat-layout]>.cli-refs,[data-chat-layout]>.cli-queue{width:calc(100% - 2 * var(--cli-chat-gutter) - var(--cli-chat-scrollbar,0px));max-width:var(--cli-chat-content-max);margin-inline:auto;margin-inline-start:max(var(--cli-chat-gutter),calc((100% - var(--cli-chat-scrollbar,0px) - var(--cli-chat-content-max)) / 2));flex-shrink:0;}
1840
+ @container chat-column (max-width:900px){[data-chat-layout]>*{--cli-chat-content-max:100%;}}
1841
+ @container chat-column (max-width:640px){[data-chat-layout]>*{--cli-chat-gutter:12px;}}
1731
1842
  .task-origin{display:flex;align-items:center;gap:5px;font-size:10px;color:var(--ink-3);padding-top:7px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
1732
1843
  .fork-sources{display:flex;flex-wrap:wrap;gap:6px;padding:12px 14px 0;}
1733
1844
  .fork-sources>span{max-width:100%;display:flex;align-items:center;gap:6px;padding:6px 8px;border:1px solid var(--line);background:var(--surface-2);border-radius:8px;font-size:11px;color:var(--ink-2);overflow-wrap:anywhere;}