agentus 0.2.0 → 0.3.1
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.
- package/NOTICE +8 -3
- package/package.json +1 -1
- package/packages/server/src/acp/registry.ts +51 -2
- package/packages/server/src/acp/session-manager.ts +213 -40
- package/packages/server/src/index.ts +85 -10
- package/packages/server/src/notify/center.ts +12 -1
- package/packages/server/src/settings.ts +64 -1
- package/packages/server/src/store/store.ts +35 -3
- package/packages/shared/src/index.ts +11 -1
- package/packages/web/dist/assets/index-Cqb6QVmU.css +32 -0
- package/packages/web/dist/assets/index-YJcTF0IM.js +283 -0
- package/packages/web/dist/index.html +2 -2
- package/packages/web/dist/assets/index-D667PX2c.css +0 -32
- package/packages/web/dist/assets/index-d9NzwPFu.js +0 -283
|
@@ -114,6 +114,24 @@ export const CALL_DEFAULT: CallSettings = {
|
|
|
114
114
|
|
|
115
115
|
export const INTERRUPT_MODES: InterruptMode[] = ["voice", "button"];
|
|
116
116
|
|
|
117
|
+
/** How the cockpit treats AGENT PROCESSES — as opposed to what a conversation contains. AionUi
|
|
118
|
+
* ships the same knob in 设置 → 系统 as 「Agent 空闲超时(分钟)」 (default 5, 1–60, step 5) with the
|
|
119
|
+
* honest description 「空闲超过该时长后自动终止 Agent 进程以释放内存」. Agentus keeps that meaning
|
|
120
|
+
* and adds ONE thing AionUi does not have: 0 = 关闭. A cockpit deliberately left holding a
|
|
121
|
+
* long-running slot (a build, a tunnel watcher, a call) must be able to say "never reclaim this",
|
|
122
|
+
* and "set it to 60 and hope" is not the same statement. */
|
|
123
|
+
export interface AgentSettings {
|
|
124
|
+
/** minutes of no activity before a live slot's agent process is stopped to reclaim memory;
|
|
125
|
+
* 0 = never. The row and its transcript always survive — this only stops the process. */
|
|
126
|
+
idleKillMin: number;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export const AGENT_DEFAULT: AgentSettings = { idleKillMin: 5 };
|
|
130
|
+
|
|
131
|
+
/** What the settings page may offer: the ends of the number field. Server-side enforcement uses
|
|
132
|
+
* the same pair, so a hand-written request cannot store a nonsense value. */
|
|
133
|
+
export const AGENT_IDLE_RANGE: [number, number] = [0, 60];
|
|
134
|
+
|
|
117
135
|
/** The NUMERIC knobs. `interruptMode` is a two-way choice, not a slider, so it is deliberately
|
|
118
136
|
* outside both the range table and the loops that validate numbers. */
|
|
119
137
|
export const CALL_NUMERIC = ["bargeSensitivity", "bargeMs", "silenceMs", "minChars"] as const;
|
|
@@ -147,6 +165,7 @@ export interface Settings {
|
|
|
147
165
|
theme: ThemeSettings;
|
|
148
166
|
call: CallSettings;
|
|
149
167
|
prefs: PrefsSettings;
|
|
168
|
+
agent: AgentSettings;
|
|
150
169
|
updatedAt: number;
|
|
151
170
|
}
|
|
152
171
|
|
|
@@ -173,7 +192,7 @@ let db: Store | null = null;
|
|
|
173
192
|
let legacyFile = "";
|
|
174
193
|
let cache: Settings = {
|
|
175
194
|
voice: { ...DEFAULTS }, theme: { ...THEME_DEFAULT }, call: { ...CALL_DEFAULT },
|
|
176
|
-
prefs: { ...PREFS_DEFAULT }, updatedAt: 0,
|
|
195
|
+
prefs: { ...PREFS_DEFAULT }, agent: { ...AGENT_DEFAULT }, updatedAt: 0,
|
|
177
196
|
};
|
|
178
197
|
/** keys that came from env/.env (shown as "auto-detected" and used when settings are empty) */
|
|
179
198
|
let envCreds: { apiKey: string; baseUrl: string; source: string } | null = null;
|
|
@@ -237,6 +256,7 @@ export function initSettings(dataDir: string, store: Store): Settings {
|
|
|
237
256
|
theme: { ...THEME_DEFAULT, ...(stored.theme ?? {}) },
|
|
238
257
|
call: pickCall(stored.call),
|
|
239
258
|
prefs: pickPrefs(stored.prefs),
|
|
259
|
+
agent: pickAgent(stored.agent),
|
|
240
260
|
updatedAt: Number((stored as Settings).updatedAt ?? 0),
|
|
241
261
|
};
|
|
242
262
|
// an unset baseUrl/apiKey bootstrap from the environment: the operator said the
|
|
@@ -266,6 +286,20 @@ function pickCall(raw: unknown): CallSettings {
|
|
|
266
286
|
return out;
|
|
267
287
|
}
|
|
268
288
|
|
|
289
|
+
/** The agent-process knobs. Out-of-range or unparseable values fall back to the shipped default
|
|
290
|
+
* rather than throwing: this section decides whether a slot's process is reclaimed, and a settings
|
|
291
|
+
* row that cannot be read must never leave the reaper in an undefined state (an undefined `> 0`
|
|
292
|
+
* comparison would silently turn reclaiming OFF — the safe failure is the documented default). */
|
|
293
|
+
function pickAgent(raw: unknown): AgentSettings {
|
|
294
|
+
const out = { ...AGENT_DEFAULT };
|
|
295
|
+
if (raw && typeof raw === "object") {
|
|
296
|
+
const v = Number((raw as Record<string, unknown>).idleKillMin);
|
|
297
|
+
const [lo, hi] = AGENT_IDLE_RANGE;
|
|
298
|
+
if (Number.isFinite(v) && v >= lo && v <= hi) out.idleKillMin = v;
|
|
299
|
+
}
|
|
300
|
+
return out;
|
|
301
|
+
}
|
|
302
|
+
|
|
269
303
|
function pickPrefs(raw: unknown): PrefsSettings {
|
|
270
304
|
const out = { ...PREFS_DEFAULT };
|
|
271
305
|
if (raw && typeof raw === "object") {
|
|
@@ -289,6 +323,7 @@ function persist(): void {
|
|
|
289
323
|
db.setSetting("theme", cache.theme);
|
|
290
324
|
db.setSetting("call", cache.call);
|
|
291
325
|
db.setSetting("prefs", cache.prefs);
|
|
326
|
+
db.setSetting("agent", cache.agent);
|
|
292
327
|
} catch (e) {
|
|
293
328
|
console.error(`[agentus] cannot write settings: ${(e as Error).message}`);
|
|
294
329
|
}
|
|
@@ -331,6 +366,9 @@ export function publicSettings(): Record<string, unknown> {
|
|
|
331
366
|
hotwordLimit: v.hotwordLimit,
|
|
332
367
|
prefs: cache.prefs,
|
|
333
368
|
prefsDefaults: PREFS_DEFAULT,
|
|
369
|
+
agent: cache.agent,
|
|
370
|
+
agentDefaults: AGENT_DEFAULT,
|
|
371
|
+
agentIdleRange: AGENT_IDLE_RANGE,
|
|
334
372
|
// the defaults, so the UI can offer "reset to Bailian defaults"
|
|
335
373
|
defaults: { ...DEFAULTS, apiKey: undefined, baseUrl: undefined },
|
|
336
374
|
updatedAt: cache.updatedAt,
|
|
@@ -456,6 +494,31 @@ export function savePrefs(patch: Record<string, unknown>): Settings {
|
|
|
456
494
|
return cache;
|
|
457
495
|
}
|
|
458
496
|
|
|
497
|
+
/** Agent-process knobs: its own update, like theme/call, so a bad number here cannot lock the
|
|
498
|
+
* operator out of the page that would fix it. Range-checked against AGENT_IDLE_RANGE before it is
|
|
499
|
+
* stored — this number decides whether agent processes get killed, so it is not a text field. */
|
|
500
|
+
export function saveAgent(patch: Record<string, unknown>): Settings {
|
|
501
|
+
const a = { ...cache.agent };
|
|
502
|
+
if ("idleKillMin" in patch) {
|
|
503
|
+
const raw = typeof patch.idleKillMin === "number" ? patch.idleKillMin : Number(patch.idleKillMin);
|
|
504
|
+
const [lo, hi] = AGENT_IDLE_RANGE;
|
|
505
|
+
if (!Number.isFinite(raw) || raw < lo || raw > hi) {
|
|
506
|
+
throw new Error(`invalid idleKillMin: ${JSON.stringify(patch.idleKillMin)} (expected ${lo}…${hi} minutes, 0 = off)`);
|
|
507
|
+
}
|
|
508
|
+
a.idleKillMin = raw;
|
|
509
|
+
}
|
|
510
|
+
cache = { ...cache, agent: a, updatedAt: Date.now() };
|
|
511
|
+
persist();
|
|
512
|
+
return cache;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/** The agent-process knobs as the reaper reads them — on every tick, so a settings change applies
|
|
516
|
+
* without a restart. Returns the live cache object, not a copy: a caller that wants a snapshot has
|
|
517
|
+
* no business holding this one. */
|
|
518
|
+
export function agentSettings(): AgentSettings {
|
|
519
|
+
return cache.agent;
|
|
520
|
+
}
|
|
521
|
+
|
|
459
522
|
/** Normalise the two URL shapes operators paste: MaaS root or .../compatible-mode/v1. */
|
|
460
523
|
export function dashscopeUrls(baseUrl: string): { root: string; compat: string; ws: string } {
|
|
461
524
|
const trimmed = baseUrl.replace(/\/+$/, "");
|
|
@@ -75,6 +75,9 @@ export interface SessionRow {
|
|
|
75
75
|
pid: number | null;
|
|
76
76
|
createdAt: number;
|
|
77
77
|
closedAt: number | null;
|
|
78
|
+
/** When the OPERATOR put this session away (已归档). Null = it belongs in 工作空间. A storage
|
|
79
|
+
* state: it says nothing about whether a process is running (see SessionInfo.archivedAt). */
|
|
80
|
+
archivedAt: number | null;
|
|
78
81
|
/** JSON round-trip of the ACP mode state + config options, so a resumed
|
|
79
82
|
* session (M4-lite) comes back with the operator's mode/effort intact. */
|
|
80
83
|
modes?: unknown;
|
|
@@ -105,7 +108,7 @@ export interface SessionRow {
|
|
|
105
108
|
interface RawSessionRow {
|
|
106
109
|
id: string; backend: BackendId; acp_session_id: string | null; cwd: string;
|
|
107
110
|
title: string; auto_title?: string | null; status: SessionStatus; pid: number | null;
|
|
108
|
-
created_at: number; closed_at: number | null;
|
|
111
|
+
created_at: number; closed_at: number | null; archived_at?: number | null;
|
|
109
112
|
modes?: string | null; config_options?: string | null;
|
|
110
113
|
usage?: string | null; commands?: string | null;
|
|
111
114
|
workspace?: string | null;
|
|
@@ -169,7 +172,7 @@ function rowToSession(r: RawSessionRow): SessionRow {
|
|
|
169
172
|
return {
|
|
170
173
|
id: r.id, backend: r.backend, acpSessionId: r.acp_session_id, cwd: r.cwd,
|
|
171
174
|
title: r.title, autoTitle: r.auto_title ?? null, status: r.status, pid: r.pid,
|
|
172
|
-
createdAt: r.created_at, closedAt: r.closed_at,
|
|
175
|
+
createdAt: r.created_at, closedAt: r.closed_at, archivedAt: r.archived_at ?? null,
|
|
173
176
|
modes: parseJson(r.modes), configOptions: parseJson(r.config_options) ?? [],
|
|
174
177
|
usage: parseJson(r.usage), commands: parseJson(r.commands) ?? [],
|
|
175
178
|
workspace: r.workspace ?? null,
|
|
@@ -182,6 +185,7 @@ function rowToSession(r: RawSessionRow): SessionRow {
|
|
|
182
185
|
interface RawBackendRow {
|
|
183
186
|
id: string; label: string; kind: string; cmd: string; args: string; env: string;
|
|
184
187
|
home: string | null; profile: string | null; cwd: string | null; notes: string;
|
|
188
|
+
default_mode: string | null;
|
|
185
189
|
native_plan_source: string | null;
|
|
186
190
|
builtin: number; created_at: number; updated_at: number;
|
|
187
191
|
// health snapshot (M6.1) — system-written, see registry.BackendHealth
|
|
@@ -212,6 +216,9 @@ function rowToBackend(r: RawBackendRow): BackendRow {
|
|
|
212
216
|
home: r.home ?? null,
|
|
213
217
|
profile: r.profile ?? null,
|
|
214
218
|
cwd: r.cwd ?? null,
|
|
219
|
+
// A row predating the column (or a seeded one) says nothing: send no mode at all, so the agent
|
|
220
|
+
// keeps its own default. No mode name is invented here — "缺省" must mean "不上手".
|
|
221
|
+
defaultMode: (r.default_mode ?? "").trim() || null,
|
|
215
222
|
notes: r.notes ?? "",
|
|
216
223
|
builtin: r.builtin === 1,
|
|
217
224
|
health: {
|
|
@@ -304,6 +311,8 @@ export class Store {
|
|
|
304
311
|
id text primary key, label text not null, kind text not null,
|
|
305
312
|
cmd text not null, args text not null default '[]', env text not null default '{}',
|
|
306
313
|
home text, profile text, cwd text, notes text not null default '',
|
|
314
|
+
-- the ACP mode a NEW session from this row starts in (null = the agent's own default)
|
|
315
|
+
default_mode text,
|
|
307
316
|
builtin integer not null default 0,
|
|
308
317
|
created_at integer not null, updated_at integer not null
|
|
309
318
|
);
|
|
@@ -334,6 +343,13 @@ export class Store {
|
|
|
334
343
|
this.#db.exec("update sessions set auto_title = title where auto_title is null or auto_title = ''");
|
|
335
344
|
// integer column, so it gets its own migration (the loop above assumes text)
|
|
336
345
|
if (!cols.has("context_limit")) this.#db.exec("alter table sessions add column context_limit integer");
|
|
346
|
+
// WHEN THE OPERATOR PUT THE SESSION AWAY (已归档 — a STORAGE state). Before this column the rail
|
|
347
|
+
// inferred "archived" from "has no process", so a slot that merely crashed (or was killed by an
|
|
348
|
+
// idle reap) filed itself under 已归档 next to the ones the operator really put away, and
|
|
349
|
+
// 「我在归档一栏里看到的」 stopped meaning anything. NULL is the honest default for every existing
|
|
350
|
+
// row: nobody ever archived them, they were just dead. The 已归档 section starts empty and fills
|
|
351
|
+
// with what the operator actually archives.
|
|
352
|
+
if (!cols.has("archived_at")) this.#db.exec("alter table sessions add column archived_at integer");
|
|
337
353
|
// The session's own ACTIVITY clock — when the operator or the agent last really said something
|
|
338
354
|
// in it. A COLUMN, not a derived `max(messages.created_at)` (AionUi's model: `modified_at` on
|
|
339
355
|
// the conversation row, indexed, which is what its sidebar sorts by): every ingestion path
|
|
@@ -362,6 +378,9 @@ export class Store {
|
|
|
362
378
|
// P1 (plan service): which channel carries this backend's plan, `acp` | `none`. Nullable on
|
|
363
379
|
// purpose — a row that predates it follows the same default as a seeded one (see rowToBackend).
|
|
364
380
|
"native_plan_source",
|
|
381
|
+
// The permission mode a new session starts in. Nullable like the rest: a row that predates the
|
|
382
|
+
// column means "send nothing" (the agent's own default), not "some mode we invented".
|
|
383
|
+
"default_mode",
|
|
365
384
|
]) {
|
|
366
385
|
if (!beCols.has(col)) this.#db.exec(`alter table backends add column ${col} text`);
|
|
367
386
|
}
|
|
@@ -693,6 +712,16 @@ export class Store {
|
|
|
693
712
|
}
|
|
694
713
|
}
|
|
695
714
|
|
|
715
|
+
/** Put this session away — or take it back out (已归档). Its OWN statement, like `home`: the
|
|
716
|
+
* archive flag is the one thing the operator sets directly, and a routine row upsert (a status
|
|
717
|
+
* change, a rename, an idle reap) must not be able to clear it. Returns whether a row matched. */
|
|
718
|
+
setArchived(sessionId: string, at: number | null): boolean {
|
|
719
|
+
const info = this.#db
|
|
720
|
+
.prepare("update sessions set archived_at = ? where id = ?")
|
|
721
|
+
.run(at, sessionId);
|
|
722
|
+
return Number(info.changes ?? 0) > 0;
|
|
723
|
+
}
|
|
724
|
+
|
|
696
725
|
/** Record (or adopt) the home a session was created under. Used when a legacy row — created
|
|
697
726
|
* before the column existed — is resumed successfully: the successful load is itself the
|
|
698
727
|
* proof of which home holds its state, so the row stops being ambiguous. */
|
|
@@ -1153,16 +1182,18 @@ export class Store {
|
|
|
1153
1182
|
this.#db
|
|
1154
1183
|
.prepare(
|
|
1155
1184
|
`insert into backends (id, label, kind, cmd, args, env, home, profile, cwd, notes,
|
|
1185
|
+
default_mode,
|
|
1156
1186
|
native_plan_source,
|
|
1157
1187
|
builtin, created_at, updated_at,
|
|
1158
1188
|
last_check_status, last_check_kind, last_check_error_code,
|
|
1159
1189
|
last_check_error_message, last_check_guidance, last_check_latency_ms,
|
|
1160
1190
|
last_check_at, last_success_at, last_failure_at, handshake, handshake_at)
|
|
1161
|
-
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1191
|
+
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1162
1192
|
on conflict(id) do update set
|
|
1163
1193
|
label = excluded.label, kind = excluded.kind, cmd = excluded.cmd, args = excluded.args,
|
|
1164
1194
|
env = excluded.env, home = excluded.home, profile = excluded.profile, cwd = excluded.cwd,
|
|
1165
1195
|
notes = excluded.notes,
|
|
1196
|
+
default_mode = excluded.default_mode,
|
|
1166
1197
|
native_plan_source = excluded.native_plan_source,
|
|
1167
1198
|
updated_at = excluded.updated_at,
|
|
1168
1199
|
-- the evidence travels with the row: a spawn-relevant edit replaces it with a cleared
|
|
@@ -1179,6 +1210,7 @@ export class Store {
|
|
|
1179
1210
|
.run(
|
|
1180
1211
|
row.id, row.label, row.kind, row.cmd, JSON.stringify(row.args), JSON.stringify(row.env ?? {}),
|
|
1181
1212
|
row.home, row.profile, row.cwd, row.notes ?? "",
|
|
1213
|
+
row.defaultMode ?? null,
|
|
1182
1214
|
row.nativePlanSource ?? null,
|
|
1183
1215
|
row.builtin ? 1 : 0, row.createdAt, row.updatedAt,
|
|
1184
1216
|
row.health?.status ?? null, row.health?.kind ?? null, row.health?.errorCode ?? null,
|
|
@@ -22,6 +22,7 @@ export type SessionStatus =
|
|
|
22
22
|
| "starting" // subprocess spawned, initialize/newSession in flight
|
|
23
23
|
| "ready" // accepts prompts
|
|
24
24
|
| "running" // a prompt turn is in flight
|
|
25
|
+
| "reaped" // no process: it was idle past the operator's threshold (settings.agent.idleKillMin)
|
|
25
26
|
| "error" // subprocess died or handshake failed
|
|
26
27
|
| "closed";
|
|
27
28
|
|
|
@@ -74,6 +75,15 @@ export interface SessionInfo {
|
|
|
74
75
|
* This — not `createdAt`, and not `lastSeq` (a per-session counter) — is what the rail
|
|
75
76
|
* orders by: "which of these did I last talk to". */
|
|
76
77
|
lastAt?: number;
|
|
78
|
+
/** The operator PUT THIS SESSION AWAY: it belongs in the rail's 已归档 section, whatever its
|
|
79
|
+
* process is doing. This is a STORAGE state, not a liveness one — the rail used to infer
|
|
80
|
+
* `archived` from `has no process`, which filed a crashed slot and a deliberately archived
|
|
81
|
+
* one in the same place (the operator's complaint: 「我设想的点击归档是一种存储态」). */
|
|
82
|
+
archivedAt?: number | null;
|
|
83
|
+
/** No agent process right now — it was closed, it crashed, or it was REAPED for being idle.
|
|
84
|
+
* Derived server-side and sent with the row, so the client never infers liveness from which
|
|
85
|
+
* list a row arrived in (that inference is what merged 已归档 with 死了). */
|
|
86
|
+
cold?: boolean;
|
|
77
87
|
}
|
|
78
88
|
|
|
79
89
|
export interface AvailableCommandView {
|
|
@@ -148,7 +158,7 @@ export interface PermissionDiff {
|
|
|
148
158
|
// ---- WS envelope (server -> browser) ----
|
|
149
159
|
export type ServerEvent =
|
|
150
160
|
| { t: "hello"; clientId: string; resumed: boolean }
|
|
151
|
-
| { t: "sessions"; sessions: SessionInfo[]; /** requests already waiting for an answer, so a page that connects or refreshes learns about them (they are STATE; the events happened before it existed) */ pending?: PermissionRequestView[] }
|
|
161
|
+
| { t: "sessions"; sessions: SessionInfo[]; /** rows on disk with NO process and no archive flag — they belong in 工作空间 beside the live ones (a crashed slot must not look archived, and must not vanish from the rail either) */ cold?: SessionInfo[]; /** rows the operator explicitly archived (archivedAt set) — the 已归档 section, whatever their process state */ archived?: SessionInfo[]; /** requests already waiting for an answer, so a page that connects or refreshes learns about them (they are STATE; the events happened before it existed) */ pending?: PermissionRequestView[] }
|
|
152
162
|
| { t: "session"; session: SessionInfo }
|
|
153
163
|
| { t: "messages"; sessionId: string; messages: StoredMessage[]; hasMore: boolean; partial?: boolean }
|
|
154
164
|
| { t: "message"; message: StoredMessage; /** text to APPEND for a streamed block that grew (absent
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
+
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
+
* https://github.com/chjj/term.js
|
|
5
|
+
* @license MIT
|
|
6
|
+
*
|
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
*
|
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
|
15
|
+
* all copies or substantial portions of the Software.
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
* THE SOFTWARE.
|
|
24
|
+
*
|
|
25
|
+
* Originally forked from (with the author's permission):
|
|
26
|
+
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
+
* http://bellard.org/jslinux/
|
|
28
|
+
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
+
* The original design remains. The terminal itself
|
|
30
|
+
* has been extended to include xterm CSI codes, among
|
|
31
|
+
* other features.
|
|
32
|
+
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}:root{--bg: #0c1116;--bg-panel: #121a22;--bg-raised: #182430;--line: #223140;--text: #e3ecf3;--text-dim: #b6bec3;--accent: #ffb454;--accent-rgb: 255, 180, 84;--accent-dim: #8a6230;--ok: #4ec9a0;--err: #e57373;--err-rgb: 229, 115, 115;--thought: #8f7bd7;--tool: #5ba8d4;--code-bg: #0a0f14;--code-fg: #d7e2ea;--code-bar: rgba(255, 255, 255, .06);--code-line: rgba(255, 255, 255, .1);--chip-bg: #1e2b38;--on-accent: #101820;--accent-text: #ffb454;--scrim: rgba(0, 0, 0, .55);--shadow: 0 18px 40px rgba(0, 0, 0, .45);--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace}:root[data-theme=light]{--bg: #f4f6f9;--bg-panel: #ffffff;--bg-raised: #eaeef4;--line: #d7dde6;--text: #1c2735;--text-dim: #3f4750;--accent: #d98116;--accent-rgb: 217, 129, 22;--accent-dim: #e0b070;--ok: #1f9d75;--err: #c2453f;--err-rgb: 194, 69, 63;--thought: #6d5bc4;--tool: #2f7fb5;--code-bg: #10171f;--code-fg: #cfd8e3;--code-bar: rgba(255, 255, 255, .07);--code-line: rgba(255, 255, 255, .12);--chip-bg: #e8ecf2;--accent-text: #9c5a08;--on-accent: #1b1206;--scrim: rgba(12, 17, 22, .42);--shadow: 0 18px 40px rgba(23, 36, 48, .18)}@media (prefers-color-scheme: light){:root[data-theme=system]{--bg: #f4f6f9;--bg-panel: #ffffff;--bg-raised: #eaeef4;--line: #d7dde6;--text: #1c2735;--text-dim: #3f4750;--accent: #d98116;--accent-rgb: 217, 129, 22;--accent-dim: #e0b070;--ok: #1f9d75;--err: #c2453f;--err-rgb: 194, 69, 63;--thought: #6d5bc4;--tool: #2f7fb5;--code-bg: #10171f;--code-fg: #cfd8e3;--code-bar: rgba(255, 255, 255, .07);--code-line: rgba(255, 255, 255, .12);--chip-bg: #e8ecf2;--accent-text: #9c5a08;--on-accent: #1b1206;--scrim: rgba(12, 17, 22, .42);--shadow: 0 18px 40px rgba(23, 36, 48, .18)}}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{background:var(--bg);color:var(--text);font:15px/1.5 -apple-system,Segoe UI,PingFang SC,Noto Sans SC,sans-serif;-webkit-font-smoothing:antialiased}button{font:inherit}.app{display:flex;height:100%;overflow:hidden}.sidebar{width:var(--rail-w, 268px);flex:0 0 var(--rail-w, 268px);background:var(--bg-panel);border-right:1px solid var(--line);display:flex;flex-direction:column;position:relative}.sidebar header{padding:14px 16px 10px;display:flex;align-items:baseline;gap:8px}.sidebar header .logo{color:var(--accent-text);font-weight:700;letter-spacing:.5px;display:inline-flex;align-items:center;gap:7px}.brand-mark{display:block;flex:0 0 auto}.sidebar header .tagline{font-size:11px;color:var(--text-dim)}.new-btn{margin:0 12px 10px;padding:9px;border-radius:8px;cursor:pointer;border:1px dashed var(--accent-dim);background:transparent;color:var(--accent-text)}.new-btn:hover{background:rgba(var(--accent-rgb),.08)}.rail-search{margin:0 8px 6px;padding:7px 9px;border-radius:8px;background:var(--bg-raised);color:var(--text);border:1px solid var(--line);font-size:12.5px;font-family:var(--mono)}.rail-search:focus{outline:none;border-color:var(--accent-dim)}.rail-search::placeholder{color:var(--text-dim);opacity:1}.load-earlier{display:flex;justify-content:center;margin-bottom:10px}.cold-purge{margin-left:auto;background:transparent;border:1px solid transparent;color:var(--text-dim);font-size:11px;line-height:1;padding:2px 5px;border-radius:5px;cursor:pointer}.session-item.cold:hover .cold-purge{border-color:var(--line);color:var(--err)}.session-list{flex:1;overflow-y:auto;padding:0 8px 8px}.session-item{padding:10px;border-radius:8px;cursor:pointer;margin-bottom:4px;border:1px solid transparent}.session-item:hover{background:var(--bg-raised)}.session-item.active{background:var(--bg-raised);border-color:var(--line)}.session-item .title{font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-item .meta{font-size:11.5px;color:var(--text-dim);display:flex;gap:8px;margin-top:3px;align-items:center}.dot{width:8px;height:8px;border-radius:50%;flex:0 0 8px}.dot.ready{background:var(--ok)}.dot.running{background:var(--accent);animation:pulse 1s infinite}.dot.starting{background:var(--text-dim)}.dot.error,.dot.closed{background:var(--err)}.rail-sep{display:flex;justify-content:space-between;align-items:baseline;padding:12px 10px 6px;font-size:11px;letter-spacing:.4px;text-transform:uppercase;color:var(--text-dim);border-top:1px solid var(--line);margin:8px 4px 0}.session-item.cold:hover{background:rgba(var(--accent-rgb),.06)}.dot.cold{background:transparent;border:1px solid var(--text-dim)}.hint{color:var(--text-dim)}@keyframes pulse{50%{opacity:.35}}.badge{font-size:10.5px;border:1px solid var(--line);border-radius:5px;padding:0 5px;color:var(--text-dim)}.badge.perm{border-color:var(--accent-dim);color:var(--accent-text)}.sidebar footer{padding:10px 14px;font-size:11.5px;color:var(--text-dim);border-top:1px solid var(--line)}.sidebar footer .conn.off{color:var(--err)}.main{flex:1;display:flex;flex-direction:column;min-width:0}.chat-head{padding:7px 10px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:6px;flex-wrap:nowrap;background:var(--bg-panel);min-height:46px}.chat-head .title{font-weight:600;font-size:14px;flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.icon-btn .spin,.sess-menu-item .spin{animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.icon-btn .spin,.sess-menu-item .spin{animation:none}}.head-spacer{flex:1 1 auto;min-width:4px}.turn-pulse{flex:0 0 auto;width:8px;height:8px;border-radius:50%;background:var(--ok);animation:pulse 1.4s infinite}.turn-pulse.quiet{background:var(--accent);animation-duration:2.6s}@media (prefers-reduced-motion: reduce){.turn-pulse{animation:none}}.head-actions{display:inline-flex;align-items:center;gap:0;flex:0 0 auto}.head-actions .icon-btn{width:28px;height:28px}.chat-head .icon-btn svg{width:18px;height:18px}.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;flex:0 0 auto;padding:0;background:transparent;border:1px solid transparent;border-radius:8px;color:var(--text-dim);cursor:pointer}.icon-btn:hover{background:var(--bg-raised);border-color:var(--line);color:var(--text)}.icon-btn.danger:hover{color:var(--err);border-color:var(--err)}.chip{display:inline-flex;align-items:center;gap:4px;flex:0 0 auto;font-size:11px;padding:2px 7px;border-radius:999px}.perm-chip{border:1px solid var(--accent-dim);color:var(--accent-text)}.perm-pulse{width:6px;height:6px;border-radius:50%;background:var(--accent);animation:pulse 1.2s infinite}.ghost-btn{background:transparent;border:1px solid var(--line);color:var(--text-dim);border-radius:6px;padding:4px 10px;cursor:pointer;font-size:12.5px}.ghost-btn:hover{color:var(--text);border-color:var(--text-dim)}.ghost-btn.danger:hover{color:var(--err);border-color:var(--err)}.stream-wrap{flex:1;min-height:0;position:relative;display:flex}.stream{flex:1;overflow-y:auto;padding:18px 0;overscroll-behavior:contain}.stream:focus{outline:none}.stream-hint{display:flex;align-items:center;gap:7px;padding:2px 0;color:var(--text-dim);font-size:12.5px}.stream-hint .elapsed{opacity:.75;font-variant-numeric:tabular-nums}.stream-spin{flex:0 0 auto;width:11px;height:11px;border-radius:50%;border:1.5px solid var(--line);border-top-color:var(--accent);animation:spin .8s linear infinite}@media (prefers-reduced-motion: reduce){.stream-spin{animation:none}}.jump-latest{position:absolute;left:50%;bottom:14px;transform:translate(-50%);width:34px;height:34px;border-radius:50%;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;background:var(--bg-raised);border:1px solid var(--line);color:var(--text-dim);box-shadow:0 6px 18px #0006}.jump-latest:hover{color:var(--text);border-color:var(--text-dim)}.jump-latest.has-new{color:var(--accent-text);border-color:var(--accent-dim)}.jump-dot{position:absolute;top:3px;right:3px;width:7px;height:7px;border-radius:50%;background:var(--accent);animation:pulse 1.2s infinite}.rail-search-wrap{position:relative;margin:0 8px 6px;display:flex;align-items:center}.rail-search-wrap>svg{position:absolute;left:9px;color:var(--text-dim);pointer-events:none}.rail-search-wrap .rail-search{margin:0;padding-left:27px;width:100%}.cold-resume{background:transparent;border:1px solid transparent;color:var(--text-dim);padding:2px 4px;border-radius:5px;cursor:pointer;line-height:1;display:inline-flex;align-items:center}.session-item.cold:hover .cold-resume{border-color:var(--line);color:var(--ok)}.stream-inner{margin:0;padding:0 20px}.msg{margin-bottom:14px;display:flex;flex-direction:column;align-items:flex-start;min-width:0}.msg>*{max-width:100%}.msg.user{align-items:flex-end}.msg.plan,.msg.meta{align-items:stretch}.msg .role{font-size:11px;color:var(--text-dim);margin-bottom:3px;letter-spacing:.4px}.msg .role.with-mark{display:flex;align-items:center;gap:5px}.agent-mark{flex:0 0 auto;width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;font-size:9.5px}.agent-mark img{display:block;width:16px;height:16px;border-radius:4px;object-fit:contain}.msg .bubble{border-radius:10px;padding:10px 14px;white-space:pre-wrap;overflow-wrap:anywhere}.msg .bubble:has(.md),.msg .bubble>.md{white-space:normal}.msg.user .bubble{background:var(--bg-raised);border:1px solid var(--line)}.msg.agent .bubble{background:transparent}.msg.thought .bubble{background:#8f7bd712;border-left:3px solid var(--thought);color:var(--text-dim);font-size:13.5px;white-space:pre-wrap}.thought-head{display:flex;align-items:center;gap:5px;background:none;border:none;padding:2px 4px;border-radius:6px;cursor:pointer;color:var(--text-dim);font:inherit;font-size:11px;letter-spacing:.4px}.thought-head:hover{background:var(--bg-raised);color:var(--text)}.thought-chev,.tool-chev{flex:0 0 auto;color:var(--text-dim);transition:transform .15s ease}.thought-chev.open,.tool-chev.open{transform:rotate(90deg)}.thought-meta{color:var(--text-dim);opacity:.75;font-variant-numeric:tabular-nums}.msg.thought.live .thought-head{color:var(--thought)}.msg.thought .bubble.live{max-height:6.6em;overflow-y:auto}.thought-stick{align-self:flex-start;display:inline-flex;align-items:center;gap:4px;margin:2px 0 0;padding:2px 8px;border-radius:999px;cursor:pointer;background:var(--bg-raised);border:1px solid var(--line);color:var(--text-dim);font:inherit;font-size:11px;letter-spacing:.3px}.thought-stick:hover{color:var(--text);border-color:var(--text-dim)}.work-run-head{display:flex;align-items:center;gap:6px;width:fit-content;max-width:100%;min-height:30px;padding:4px 8px;border:1px solid var(--line);border-radius:8px;background:var(--bg-raised);color:var(--text-dim);font:inherit;font-size:11.5px;text-align:left;cursor:pointer}.work-run.active{align-self:stretch}.work-run-head:hover,.work-run-head:focus-visible{outline:none;border-color:var(--accent-dim);background:rgba(var(--accent-rgb),.055)}.work-run.active .work-run-head{border-color:var(--accent-dim)}.work-chev{flex:0 0 auto;color:var(--text-dim);transition:transform .15s ease}.work-chev.open{transform:rotate(90deg)}.work-run-icon{flex:0 0 auto;color:var(--accent-text)}.work-run-count{flex:0 0 auto;font-weight:600;color:var(--text)}.work-run-names,.work-run-chars{flex:1 1 auto;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.work-run-state{flex:0 0 auto}.work-run-state.ok{color:var(--ok)}.work-run-state.err{color:var(--err)}.work-run-state.run{color:var(--accent-text)}.work-run-items{display:flex;flex-direction:column;gap:2px;margin:4px 0 0 11px;padding:3px 4px 3px 12px;border-left:1px solid var(--line);max-height:42vh;overflow-y:auto;overscroll-behavior:contain}.work-run-items .msg{margin-bottom:4px}.work-run-items .bubble{max-height:none}@media (max-width: 700px){.work-run-head{min-height:34px}.work-run-items{max-height:38vh}.msg.thought .bubble.live{max-height:7.4em}}.msg.meta .bubble{color:var(--err);font-size:13px;background:#e5737314}.usage-note{color:var(--text-dim);font-size:11.5px;line-height:1.5;max-width:46ch}.msg.plan .bubble{border-left:3px solid var(--ok);background:#4ec9a00f;font-size:13.5px}.plan-card{border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:8px;padding:3px 8px;background:var(--bg-panel)}.plan-card.completed{border-left-color:var(--ok)}.plan-head{display:flex;align-items:center;gap:8px;width:100%;padding:3px 0;border:0;background:none;color:var(--text);font:inherit;font-size:13px;cursor:pointer;text-align:start}.plan-head:hover{color:var(--accent-text)}.plan-title{font-weight:600;flex:0 0 auto}.plan-count{font-size:12px;color:var(--text-dim);font-variant-numeric:tabular-nums}.plan-state{font-size:11.5px;padding:0 6px;border-radius:999px;line-height:18px}.plan-state.running{color:var(--accent-text);background:rgba(var(--accent-rgb, 90, 140, 255),.12)}.plan-state.done{color:var(--ok);background:#4ec9a01f}.plan-state.terminal{color:var(--err);background:rgba(var(--err-rgb),.1)}.plan-head .tool-chev{margin-inline-start:auto}.plan-body{list-style:none;margin:2px 0 4px;padding:4px 0 0;border-top:1px dashed var(--line)}.plan-step{display:flex;align-items:baseline;gap:8px;padding:2.5px 0;font-size:13px}.plan-step .step-icon{flex:0 0 14px;text-align:center;color:var(--text-dim)}.plan-step.completed .step-icon{color:var(--ok)}.plan-step.completed .step-title{color:var(--text-dim)}.plan-step.in_progress .step-icon{color:var(--accent);animation:pulse 1.2s infinite}.plan-step.cancelled .step-icon{color:var(--err)}.plan-step.cancelled .step-title{color:var(--text-dim);text-decoration:line-through}.plan-step .step-title{flex:1;min-width:0;overflow-wrap:anywhere}.plan-explanation{margin:6px 0 2px;padding-top:4px;border-top:1px dashed var(--line);font-size:12px;opacity:.7;overflow-wrap:anywhere}.plan-bar{border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:8px;padding:1px 8px;margin-bottom:6px;background:var(--bg-panel)}.plan-bar.completed{border-left-color:var(--ok)}.plan-bar .plan-body{max-height:40vh;overflow-y:auto}.plan-dots{display:inline-flex;align-items:center;gap:2.5px;margin-inline-start:2px}.plan-dots .dot{width:5px;height:5px;border-radius:50%;background:var(--line);border:1px solid var(--text-dim);box-sizing:border-box}.plan-dots .dot.completed{background:var(--ok);border-color:var(--ok)}.plan-dots .dot.in_progress{background:var(--accent);border-color:var(--accent);animation:pulse 1.2s infinite}.plan-dots .dot.cancelled{background:var(--err);border-color:var(--err)}pre.code{background:var(--code-bg);color:var(--code-fg);border:1px solid var(--line);border-radius:8px;padding:10px 12px;overflow-x:auto;font-family:var(--mono);font-size:12.8px}code.inline{font-family:var(--mono);background:var(--chip-bg);color:var(--text);border:1px solid var(--line);padding:1px 5px;border-radius:4px;font-size:.92em}.bubble-actions{display:flex;align-items:center;gap:4px;margin-top:4px;opacity:0;transition:opacity .12s}.msg:hover .bubble-actions{opacity:1}@media (hover: none){.bubble-actions{opacity:.75}}.msg-at{font-size:10.5px;color:var(--text-dim);opacity:.9;font-variant-numeric:tabular-nums;white-space:nowrap;flex:0 0 auto}.bubble-actions .msg-at{flex:1 1 auto;text-align:left}.bubble-note{font-size:10.5px;color:var(--text-dim)}.bubble-files{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:6px}.bubble-file{display:inline-flex;align-items:center;gap:4px;font-size:11px;border:1px solid var(--line);border-radius:6px;padding:1px 6px;color:var(--text-dim)}.tool-card{border:1px solid var(--line);border-left:3px solid var(--tool);border-radius:8px;padding:3px 8px;background:var(--bg-panel)}.tool-head{display:flex;align-items:center;gap:6px;width:100%;min-width:0;background:transparent;border:none;padding:2px 0;cursor:pointer;color:var(--text);font-family:var(--mono);font-size:11.5px;text-align:left}.tool-head:hover{color:var(--accent-text)}.tool-title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tool-chev{flex:0 0 auto;opacity:.5;transition:transform .12s ease}.tool-chev.open{transform:rotate(90deg)}.tool-dot{flex:0 0 auto;width:7px;height:7px;border-radius:50%;background:var(--text-dim)}.tool-dot.running{background:var(--accent);animation:pulse 1.2s infinite}.tool-dot.ok{background:var(--ok)}.tool-dot.err{background:var(--err)}.tool-card.completed{border-left-color:var(--ok)}.tool-card.failed{border-left-color:var(--err)}.tool-card .tool-body{margin-top:8px;border-top:1px dashed var(--line);padding-top:6px}.tool-card .tool-body .lbl{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim)}.tool-card .tool-body pre{margin:4px 0 8px;padding:6px 9px;max-height:260px;overflow:auto;background:var(--bg);border:1px solid var(--line);border-radius:6px;font-family:var(--mono);font-size:11px;line-height:1.45;white-space:pre-wrap;word-break:break-word}.tool-card .tool-body pre.tool-meta{color:var(--text-dim);margin-bottom:6px}.ctx{display:inline-flex;align-items:center;gap:5px;flex:0 0 auto;color:var(--ok)}.ctx.warn{color:#d9a03a}.ctx.hot{color:var(--err)}.ctx .ctx-text{font-size:11px;font-family:var(--mono);color:var(--text-dim)}.slash-palette{position:absolute;bottom:calc(100% + 6px);left:0;right:0;max-height:260px;overflow:auto;background:var(--bg-panel);border:1px solid var(--line);border-radius:10px;padding:4px;box-shadow:0 10px 26px #00000059;z-index:5}.slash-item{display:flex;align-items:baseline;gap:8px;padding:6px 9px;border-radius:6px;cursor:pointer}.slash-item.sel{background:#ffffff0f}.slash-item .cmd{font-family:var(--mono);font-size:12.5px;color:var(--accent-text)}.slash-item .desc{font-size:11.5px;color:var(--text-dim);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.slash-item .src{font-size:10px;color:var(--text-dim);border:1px solid var(--line);border-radius:4px;padding:0 4px}.slash-item.empty{color:var(--text-dim);font-size:12px;cursor:default}.perm-card{border:1px solid var(--accent-dim);border-radius:10px;padding:12px 14px;background:rgba(var(--accent-rgb),.05)}.perm-card .q{font-size:13.5px;margin-bottom:4px}.perm-card .tc{font-family:var(--mono);font-size:12.5px;color:var(--text-dim);margin-bottom:10px;overflow-wrap:anywhere}.perm-card .opts{display:flex;gap:8px;flex-wrap:wrap}.perm-card .opts button{border-radius:7px;padding:6px 12px;cursor:pointer;font-size:13px;border:1px solid var(--line);background:var(--bg-raised);color:var(--text)}.perm-card .opts button.allow{border-color:var(--ok);color:var(--ok)}.perm-card .opts button.reject{border-color:var(--err);color:var(--err)}.perm-card.resolved{opacity:.55}.perm-card.resolved .picked{font-size:12px;color:var(--accent-text);margin-top:8px}.perm-dialog{max-width:560px;max-height:92vh;overflow-y:auto}.perm-ask{font-size:13px;line-height:1.5;color:var(--text)}.perm-file{display:flex;align-items:center;gap:6px;margin-top:10px;padding:6px 8px;border:1px solid var(--line);border-radius:8px;background:var(--bg-raised)}.perm-file code{font-family:var(--mono);font-size:12px;word-break:break-all;color:var(--accent-text)}.perm-changes{margin-top:10px}.perm-change-row{display:flex;align-items:center;gap:7px;width:100%;text-align:left;cursor:pointer;padding:7px 9px;border:1px solid var(--line);border-radius:8px;background:var(--bg-raised);color:var(--text);font:inherit}.perm-change-row:hover{border-color:var(--accent-dim)}.perm-change-row code{font-family:var(--mono);font-size:12px;color:var(--accent-text);flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.perm-counts{display:flex;gap:6px;font-family:var(--mono);font-size:11.5px;flex:0 0 auto}.perm-counts .add{color:var(--ok)}.perm-counts .del{color:var(--err)}.perm-caret{color:var(--text-dim);font-size:11px;flex:0 0 auto}.perm-diff{margin-top:6px;border:1px solid var(--line);border-radius:8px;background:var(--bg);max-height:34vh;overflow:auto;font-family:var(--mono);font-size:11.5px;line-height:1.5}.perm-diff-line{display:grid;grid-template-columns:3.2em 3.2em 1.2em 1fr;white-space:pre-wrap;overflow-wrap:anywhere;padding:0 6px}.perm-diff-line .no{color:var(--text-dim);text-align:right;padding-right:6px;-webkit-user-select:none;user-select:none}.perm-diff-line .sig{text-align:center}.perm-diff-line.add{background:#30a46c1f}.perm-diff-line.add .sig{color:var(--ok)}.perm-diff-line.del{background:#e25a501f}.perm-diff-line.del .sig{color:var(--err)}.perm-diff-line.ctx{color:var(--text-dim)}.perm-diff-gap{color:var(--text-dim);font-size:10.5px;text-align:center;padding:3px 0;background:#7f7f7f0f}.perm-cut{font-size:11px;color:var(--text-dim);margin-top:4px}.stale-banner{position:fixed;left:50%;transform:translate(-50%);bottom:calc(10px + env(safe-area-inset-bottom,0px));z-index:80;cursor:pointer;border:1px solid var(--accent-dim);border-radius:999px;background:var(--accent);color:var(--on-accent);font-weight:700;font-size:12.5px;padding:9px 16px;box-shadow:0 6px 18px #00000059}.stale-banner:hover{filter:brightness(1.06)}.perm-opts{margin-top:14px}.perm-note{font-size:11.5px;color:var(--text-dim);margin-top:10px;line-height:1.5}.ns-fixed-dir{display:flex;align-items:center;gap:6px;padding:9px 10px;border:1px solid var(--line);border-radius:8px;background:var(--bg-raised);color:var(--text-dim)}.ns-fixed-dir code{font-family:var(--mono);font-size:12px;word-break:break-all;color:var(--accent-text)}.composer{border-top:1px solid var(--line);background:var(--bg-panel);padding:8px 20px calc(10px + env(safe-area-inset-bottom))}.composer.drop-active .composer-box{border-color:var(--accent-text);background:rgba(var(--accent-rgb),.06)}.composer-inner{position:relative;display:flex;flex-direction:column;gap:6px}.composer-box{display:flex;flex-direction:column;background:var(--bg-raised);border:1px solid var(--line);border-radius:10px}.composer-box:focus-within{border-color:var(--accent-dim)}.composer textarea{flex:0 0 auto;resize:none;background:transparent;color:var(--text);border:none;padding:10px 12px 4px;font:inherit;min-height:42px;max-height:40vh;overflow-y:auto}.composer textarea:focus{outline:none}.composer-bar{display:flex;align-items:center;gap:3px;padding:2px 6px 6px}.icon-btn.on{background:var(--bg-panel);border-color:var(--accent-dim);color:var(--accent-text)}.icon-btn.rec{color:var(--err);border-color:var(--err);animation:pulse 1.4s infinite}.icon-btn.tiny{width:22px;height:22px;border-radius:6px}.send-btn{border:none;background:var(--accent);color:var(--on-accent);font-weight:700;border-radius:9px;padding:0;cursor:pointer;width:40px;height:34px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.send-btn.stop{background:var(--err);color:#180e0e}.send-btn:disabled{opacity:.4;cursor:default}.usage-row{display:flex;align-items:center;gap:8px;padding:0 2px;position:relative}.usage-text{background:transparent;border:none;padding:0;cursor:pointer;font-size:11px;color:var(--text-dim);font-family:var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:left;display:inline-flex;align-items:center;gap:5px}.usage-text:hover{color:var(--text)}.usage-row.warn .usage-text{color:var(--accent-text)}.usage-row.hot .usage-text{color:var(--err)}.usage-icon{flex:none;opacity:.75}.usage-bar{flex:1 1 auto;max-width:220px;height:5px;border-radius:3px;background:var(--line);overflow:hidden}.usage-bar>i{display:block;height:100%;background:var(--ok);transition:width .22s ease}.usage-row.warn .usage-bar>i{background:var(--accent)}.usage-row.hot .usage-bar>i{background:var(--err)}.usage-set{margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid var(--line)}.usage-set-head{display:flex;align-items:center;gap:5px;color:var(--text);margin-bottom:6px}.usage-set-scope{margin-left:auto;font-size:10px;color:var(--text-dim);border:1px solid var(--line);border-radius:999px;padding:0 6px}.usage-set-chips{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:6px}.usage-chip{background:var(--chip-bg);border:1px solid var(--line);border-radius:6px;color:var(--text-dim);font-family:inherit;font-size:11px;padding:4px 8px;cursor:pointer}.usage-chip:hover{color:var(--text);border-color:var(--accent-dim)}.usage-chip.sel{color:var(--bg);background:var(--accent);border-color:var(--accent)}.settings-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--effort, var(--text-dim));margin-right:6px}.usage-detail{position:absolute;left:0;right:auto;width:min(560px,100%);bottom:calc(100% + 8px);z-index:12;max-height:min(60vh,420px);overflow-y:auto;background:var(--bg-raised);border:1px solid var(--line);border-radius:10px;padding:8px 10px;font-size:11.5px;color:var(--text-dim);font-family:var(--mono);box-shadow:0 12px 30px #00000059}.draft-row{display:flex;flex-wrap:wrap;align-items:center;gap:5px}.draft{display:inline-flex;align-items:center;gap:5px;max-width:220px;border:1px solid var(--line);border-radius:8px;padding:2px 4px 2px 5px;background:var(--bg-raised);font-size:11.5px;color:var(--text-dim)}.draft img{width:20px;height:20px;object-fit:cover;border-radius:4px}.draft-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.draft-x{background:transparent;border:none;color:var(--text-dim);cursor:pointer;display:inline-flex;padding:0 2px}.draft-x:hover{color:var(--err)}.draft-clear{background:transparent;border:none;color:var(--text-dim);cursor:pointer;font-size:11px;text-decoration:underline}.draft-clear:hover{color:var(--text)}.queue-list{display:flex;flex-direction:column;gap:4px}.queue-head{display:flex;align-items:baseline;gap:8px;font-size:11px;color:var(--text-dim)}.queue-title{font-weight:600;letter-spacing:.3px;text-transform:uppercase}.queue-hint{opacity:.85}.queue-row{display:flex;align-items:flex-start;gap:7px;padding:5px 6px 5px 8px;border:1px solid var(--line);border-left:3px solid var(--accent-dim);border-radius:8px;background:var(--bg-raised);font-size:12.5px;color:var(--text)}.queue-row.inflight{border-left-color:var(--accent);opacity:.75}.queue-idx{flex:0 0 auto;min-width:14px;text-align:right;font-size:10.5px;color:var(--text-dim);font-variant-numeric:tabular-nums;padding-top:2px}.queue-text{flex:1 1 auto;min-width:0;white-space:pre-wrap;overflow-wrap:anywhere;max-height:5.6em;overflow:hidden}.queue-edit{flex:1 1 auto;min-width:0;font:inherit;font-size:12.5px;color:var(--text);background:var(--bg-panel);border:1px solid var(--accent-dim);border-radius:6px;padding:2px 6px;resize:vertical}.queue-actions{flex:0 0 auto;display:flex;align-items:center;gap:2px}.queue-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:1px solid var(--line);border-radius:6px;background:var(--bg-panel);color:var(--text-dim);cursor:pointer}.queue-btn:hover{color:var(--text);border-color:var(--accent-dim);background:rgba(var(--accent-rgb),.08)}.queue-btn.danger:hover{color:var(--err);border-color:var(--err);background:#e5737314}@media (max-width: 720px){.queue-btn{width:28px;height:28px}.queue-text{max-height:3.6em}}.composer-note{font-size:11.5px;color:var(--text-dim)}.composer-note.err{color:var(--err)}.dict-chip{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--accent-text);border:1px dashed var(--accent-dim);border-radius:8px;padding:4px 8px}.dict-chip.err{color:var(--err);border-color:var(--err)}.dict-chip .interim{color:var(--text-dim)}.dict-stop{margin-left:auto;background:transparent;border:1px solid var(--line);color:var(--text-dim);border-radius:6px;padding:1px 8px;cursor:pointer;font-size:11px}.dict-stop:hover{color:var(--err);border-color:var(--err)}.settings-pop{position:absolute;left:0;bottom:calc(100% + 8px);z-index:14;width:min(340px,92vw);max-height:70vh;overflow-y:auto;background:var(--bg-raised);border:1px solid var(--line);border-radius:12px;padding:8px 10px 10px;box-shadow:0 16px 40px #00000073}.settings-head{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-dim);text-transform:uppercase;letter-spacing:.06em;margin-bottom:6px}.settings-group{border-top:1px solid var(--line);padding:7px 0 4px}.settings-group:first-of-type{border-top:none}.settings-label{display:flex;align-items:center;gap:5px;font-size:11px;color:var(--text-dim);margin-bottom:5px}.settings-opt{display:block;width:100%;text-align:left;margin:2px 0;cursor:pointer;background:transparent;border:1px solid transparent;border-radius:7px;color:var(--text);font-size:12.5px;padding:5px 8px;font-family:inherit}.settings-opt:hover{background:var(--bg-panel);border-color:var(--line)}.settings-opt.sel{background:rgba(var(--accent-rgb),.1);border-color:var(--accent-dim);color:var(--accent-text)}.settings-toggle{display:flex;align-items:center;gap:7px;font-size:12.5px;margin:5px 0;cursor:pointer}.settings-select,.settings-input{width:100%;margin:3px 0;background:var(--bg-panel);color:var(--text);border:1px solid var(--line);border-radius:7px;padding:5px 7px;font-size:12px;font-family:inherit}.settings-select:focus,.settings-input:focus{outline:none;border-color:var(--accent-dim)}.settings-freeform{display:flex;gap:6px;align-items:center;margin-top:6px}.settings-freeform .settings-input{flex:1 1 auto;min-width:0}.settings-note{font-size:10.5px;color:var(--text-dim);margin-top:4px}.settings-range{display:block;font-size:11.5px;color:var(--text-dim);margin:5px 0}.settings-range input{width:100%}.empty{margin:auto;text-align:center;color:var(--text-dim)}.empty .big{font-size:42px;display:flex;justify-content:center;margin-bottom:4px}.modal-bg{position:fixed;top:0;right:0;bottom:0;left:0;background:#0000008c;display:flex;align-items:center;justify-content:center;z-index:35;padding:16px}.modal{background:var(--bg-panel);border:1px solid var(--line);border-radius:14px;padding:20px;width:100%;max-width:420px}.modal h3{margin:0 0 14px;font-size:16px}.modal label{display:block;font-size:12.5px;color:var(--text-dim);margin:10px 0 4px}.modal input,.modal select{width:100%;background:var(--bg-raised);color:var(--text);border:1px solid var(--line);border-radius:8px;padding:9px 10px;font:inherit}.modal .row{display:flex;gap:10px;margin-top:18px}.modal .row button{flex:1;padding:9px;border-radius:8px;cursor:pointer}.modal .row .cancel{background:transparent;border:1px solid var(--line);color:var(--text-dim)}.modal .row .go{background:var(--accent);border:none;color:var(--on-accent);font-weight:700}.modal .row .go.danger{background:var(--err);color:#fff}.modal .err{color:var(--err);font-size:12.5px;margin-top:10px}.blocked-homes{margin-top:12px;display:flex;flex-direction:column;gap:6px}.blocked-homes div{display:flex;gap:8px;align-items:baseline;font-size:12px}.blocked-homes span{color:var(--text-dim);min-width:104px;flex:none}.blocked-homes code{font-family:var(--mono);word-break:break-all}.backend-pick{display:flex;gap:8px}.backend-pick button{flex:1;padding:10px;border-radius:8px;cursor:pointer;background:var(--bg-raised);border:1px solid var(--line);color:var(--text)}.backend-pick button.sel{border-color:var(--accent-text);color:var(--accent-text)}.backend-pick button.retry{flex:0 0 42px;font-size:15px}.dim{color:var(--text-dim);font-size:12.5px;align-self:center}.hint{color:var(--text-dim);font-size:11.5px;margin-top:8px;font-family:ui-monospace,monospace;word-break:break-all}.net-banner{margin:8px 12px 0;padding:8px 10px;border-radius:8px;font-size:12.5px;background:rgba(var(--err-rgb),.12);border:1px solid rgba(var(--err-rgb),.45);color:var(--err);display:flex;gap:8px;align-items:center;justify-content:space-between}.net-banner button{background:transparent;border:1px solid rgba(var(--err-rgb),.55);color:var(--err);border-radius:6px;padding:3px 9px;cursor:pointer;font-size:12px}.menu-btn{display:none;background:none;border:none;color:var(--text);font-size:20px;padding:2px 8px;cursor:pointer}@media (max-width: 720px){.sidebar{position:fixed;inset:0 auto 0 0;z-index:30;width:min(82vw,320px);transform:translate(-105%);transition:transform .22s ease}.sidebar.open{transform:translate(0);box-shadow:0 0 40px #0009}.menu-btn{display:block}.scrim{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000073;z-index:25}.chip{padding:2px 6px}.perm-card button{min-height:44px;padding:10px 14px;font-size:14px}.perm-dialog{max-width:none;max-height:100%}.perm-dialog .perm-opts button{min-height:44px;padding:10px 14px;font-size:14px}.perm-diff{max-height:42vh}.perm-change-row{min-height:44px}.rail-group .group-add{width:32px;height:30px}.rail-section{min-height:34px;margin-top:6px}.slash-palette{max-height:40vh}.slash-item{min-height:44px}.msg{max-width:100%}.empty .big{font-size:42px}}.sidebar footer{display:flex;align-items:center;gap:6px}.sidebar footer .logout-btn{margin-left:auto;background:transparent;border:1px solid var(--line);color:var(--text-dim);border-radius:6px;padding:2px 8px;cursor:pointer;line-height:1.4}.sidebar footer .logout-btn:hover{color:var(--err);border-color:var(--err)}.auth-wrap{min-height:100%;display:flex;align-items:center;justify-content:center;padding:24px;background:radial-gradient(1000px 500px at 50% -10%,rgba(var(--accent-rgb),.07),transparent 60%),var(--bg)}.auth-card{width:100%;max-width:360px;background:var(--bg-panel);border:1px solid var(--line);border-radius:14px;padding:26px 24px 20px;display:flex;flex-direction:column;gap:12px;box-shadow:0 18px 50px #00000073}.auth-logo{color:var(--accent-text);font-weight:700;font-size:20px;letter-spacing:.5px;display:flex;align-items:center;justify-content:center;gap:9px}.auth-sub{font-size:11.5px;color:var(--text-dim);margin-top:-8px}.auth-note{font-size:12.5px;color:var(--text-dim);padding:6px 0}.auth-field{display:flex;flex-direction:column;gap:5px;font-size:12px;color:var(--text-dim)}.auth-field input{font:inherit;font-size:16px;padding:10px 11px;border-radius:8px;border:1px solid var(--line);background:var(--bg-raised);color:var(--text)}.auth-field input:focus{outline:none;border-color:var(--accent-dim)}.auth-btn{margin-top:4px;padding:11px;min-height:44px;border-radius:8px;cursor:pointer;border:1px solid var(--accent-dim);background:rgba(var(--accent-rgb),.12);color:var(--accent-text);font-weight:600}.auth-btn:disabled{opacity:.6;cursor:default}.auth-err{color:var(--err);font-size:12.5px;border-left:2px solid var(--err);padding-left:8px}.auth-warn{color:var(--accent-text);font-size:11.5px;line-height:1.5;opacity:.9}.auth-foot{color:var(--text-dim);font-size:11px;line-height:1.5;border-top:1px solid var(--line);padding-top:10px}.auth-card code{font-family:var(--mono);font-size:11px;color:var(--text)}@media (max-width: 480px){.auth-card{padding:20px 16px 16px}.sidebar footer .logout-btn{min-height:44px;padding:2px 12px}}.wp{display:flex;flex-direction:column;gap:5px}.wp-bar{display:flex;align-items:center;gap:6px}.wp-bar>svg{color:var(--text-dim);flex:0 0 auto}.wp-path{flex:1;min-width:0;padding:8px 10px;border-radius:8px;font-size:13px;background:var(--bg-raised);color:var(--text);border:1px solid var(--line);font-family:var(--mono)}.wp-path:focus{outline:none;border-color:var(--accent-dim)}.wp-now{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px}.wp-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:1px;font-size:11px}.wp-crumbs>span{display:inline-flex;align-items:center;color:var(--text-dim)}.wp-crumb{background:transparent;border:none;color:var(--text-dim);cursor:pointer;padding:2px 4px;border-radius:5px;font-size:11.5px}.wp-crumb:hover{color:var(--accent-text);background:var(--bg-raised)}.wp-list{max-height:210px;overflow-y:auto;border:1px solid var(--line);border-radius:8px;background:#0000002e;padding:3px}.wp-row{display:flex;align-items:center;gap:6px;padding:4px 7px;border-radius:6px;cursor:pointer;font-size:12.5px;color:var(--text)}.wp-row>svg{color:var(--text-dim);flex:0 0 auto}.wp-row:hover{background:var(--bg-raised)}.wp-row.sel{background:rgba(var(--accent-rgb),.1);outline:1px solid var(--accent-dim)}.wp-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wp-enter{background:transparent;border:1px solid transparent;border-radius:5px;color:var(--text-dim);cursor:pointer;padding:1px 3px;display:inline-flex}.wp-enter:hover{color:var(--accent-text);border-color:var(--line)}.wp-note{padding:10px;font-size:12px;color:var(--text-dim);text-align:center}.wp-note.err{color:var(--err)}.wp-recent{display:flex;flex-wrap:wrap;align-items:center;gap:4px}.wp-recent-label{font-size:11px;color:var(--text-dim)}.wp-chip{border:1px solid var(--line);background:var(--bg-raised);color:var(--text-dim);border-radius:999px;padding:3px 9px;font-size:11.5px;cursor:pointer;font-family:var(--mono)}.wp-chip:hover{color:var(--text);border-color:var(--text-dim)}.wp-chip.sel{color:var(--accent-text);border-color:var(--accent-dim)}.wp-picked{display:flex;align-items:center;gap:6px;min-width:0;color:var(--text-dim)}.wp-use{display:inline-flex;align-items:center;gap:5px;flex:0 0 auto;border:1px solid var(--line);background:transparent;color:var(--text-dim);border-radius:7px;padding:5px 9px;font-size:12px;cursor:pointer}.wp-use:hover:not(:disabled){color:var(--accent-text);border-color:var(--accent-dim)}.wp-use:disabled{opacity:.5;cursor:default}.wp-picked-path{font-size:11px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);font-size:11.5px;color:var(--accent-text)}@media (max-width: 480px){.wp-row{min-height:40px}.wp-chip{min-height:30px}.wp-path{font-size:16px}}.main-body{flex:1;display:flex;min-height:0}.chat-col{flex:1;display:flex;flex-direction:column;min-width:0;container-type:inline-size}.tool-panel{width:var(--panel-w, 430px);flex:0 0 auto;display:flex;flex-direction:column;min-height:0;border-left:1px solid var(--line);background:var(--bg-panel);position:relative}.panel-split{flex:1;display:flex;min-height:0;position:relative}.preview-col{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}.explorer-col{position:relative;flex:0 0 auto;width:var(--explorer-w, 300px);display:flex;flex-direction:column;min-height:0}.panel-split:not(.has-preview) .explorer-col{width:100%}.pane-handle{position:absolute;top:0;bottom:0;width:12px;z-index:12;display:flex;align-items:center;justify-content:center;cursor:col-resize;touch-action:none}.sidebar>.pane-handle{right:-6px}.tool-panel>.pane-handle{left:-6px}.explorer-col>.pane-handle{left:-6px}.pane-handle-line{width:2px;height:100%;background:transparent;transition:background .15s ease}.pane-handle:hover .pane-handle-line,.pane-handle:active .pane-handle-line{background:var(--accent-dim)}body.pane-dragging{cursor:col-resize;-webkit-user-select:none;user-select:none}body.pane-dragging *{cursor:col-resize!important}@media (max-width: 720px){.pane-handle{display:none}}@media (hover: none){.pane-handle{display:none}}.tool-tabs{display:flex;align-items:center;gap:3px;padding:4px 6px;border-bottom:1px solid var(--line)}.tool-tab{display:inline-flex;align-items:center;gap:5px;cursor:pointer;background:transparent;border:1px solid transparent;border-radius:7px;color:var(--text-dim);font-size:12px;padding:3px 8px;font-family:inherit}.tool-tab:hover{background:var(--bg-raised);color:var(--text)}.tool-tab.active{background:var(--bg-raised);border-color:var(--line);color:var(--accent-text)}.tool-body{flex:1;display:flex;flex-direction:column;min-height:0;overflow:hidden}.ws-root{display:flex;align-items:center;gap:5px;padding:6px 9px 0;font-size:11px;color:var(--text-dim);font-family:var(--mono)}.ws-root-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-bar{display:flex;align-items:center;gap:2px;padding:3px 6px;border-bottom:1px solid var(--line)}.file-bar-path{flex:1;min-width:0;font-size:10.5px;color:var(--text-dim);font-family:var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-list{flex:1;overflow-y:auto;padding:4px}.file-row{display:flex;align-items:center;gap:7px;width:100%;text-align:left;background:transparent;border:none;border-radius:6px;color:var(--text);font-size:12.5px;padding:4px 7px;cursor:pointer;font-family:inherit}.file-row:hover{background:var(--bg-raised)}.file-row.sel{background:rgba(var(--accent-rgb),.1)}.file-row>svg:first-child{color:var(--text-dim);flex:0 0 auto}.file-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-size{font-size:10.5px;color:var(--text-dim);font-family:var(--mono)}.file-enter{opacity:.45}.file-preview{flex:1;min-height:0;display:flex;flex-direction:column}.file-preview-head{display:flex;align-items:center;gap:6px;padding:4px 8px;font-size:11.5px;border-bottom:1px solid var(--line)}.file-preview-body{flex:1;min-height:0;overflow:auto;display:flex;flex-direction:column}.file-preview-body>*{min-height:0}.file-text{margin:0;padding:4px 9px 10px;overflow:auto;white-space:pre;font-family:var(--mono);font-size:11.5px;line-height:1.45;color:var(--text)}.file-image-wrap{display:flex;padding:8px;align-items:flex-start}.file-image{max-width:100%;border-radius:6px;border:1px solid var(--line)}.file-frame{flex:1;min-height:260px;width:100%;border:0;background:var(--bg-raised)}.file-audio{width:calc(100% - 16px);margin:8px}.file-video{max-width:100%;max-height:100%;margin:8px}.file-fallback{padding-top:6px}.file-view-toggle{display:flex;gap:6px;padding:4px 8px 0}.file-source{font-family:var(--mono);font-size:11.5px;line-height:1.45;padding:4px 0 10px;overflow-x:auto}.file-line{display:flex;gap:8px;padding:0 9px;white-space:pre}.file-line.hit{background:rgba(var(--accent-rgb),.14);box-shadow:inset 2px 0 0 var(--accent-text)}.file-ln{flex:0 0 34px;text-align:right;color:var(--text-dim);opacity:.6;-webkit-user-select:none;user-select:none}.file-lt{flex:1}.file-edit{flex:1;min-height:220px;border:0;outline:0;resize:none;padding:8px 10px;background:var(--code-bg);color:var(--code-fg);white-space:pre;overflow:auto;font-family:var(--mono);font-size:11.5px;line-height:1.5}.file-dirty{color:var(--accent-text)}.file-conflict{display:flex;align-items:center;gap:6px;padding:5px 8px;font-size:11.5px;color:var(--text);background:rgba(var(--accent-rgb),.12);border-bottom:1px solid var(--line)}.file-md{padding:6px 10px 12px}.tool-note{padding:8px;font-size:11.5px;color:var(--text-dim)}.tool-error{padding:6px 9px;font-size:11.5px;color:var(--err)}.term-bar{display:flex;align-items:center;gap:6px;padding:4px 8px;border-bottom:1px solid var(--line);font-size:11.5px;color:var(--text-dim)}.term-dot{width:8px;height:8px;border-radius:50%;background:var(--text-dim)}.term-dot.ready{background:var(--ok)}.term-dot.error{background:var(--err)}.term-dot.closed{background:var(--accent)}.term-cwd{font-family:var(--mono);color:var(--text)}.term-body{display:flex;flex-direction:column;min-height:0;padding:0}.term-host{flex:1;min-height:0;min-width:0;overflow:hidden;padding:4px 0 0 6px;background:var(--bg-1)}.term-host .xterm{height:100%}.term-host .xterm-viewport{background:transparent!important}.term-note{padding:4px 9px 7px;font-size:10.5px;color:var(--text-dim)}@media (max-width: 720px){.chat-head{padding:5px 8px;min-height:44px}.chat-head .title{font-size:14px}.chat-head .menu-btn,.chat-head .icon-btn{width:40px;height:40px}.chat-head .head-actions .icon-btn{width:28px;height:28px}.chat-head .head-actions .icon-btn svg{width:18px;height:18px}.composer{padding:6px 8px calc(8px + env(safe-area-inset-bottom,0px))}.composer textarea{font-size:16px;min-height:44px}.composer-bar .icon-btn{width:38px;height:38px}.send-btn{width:46px;height:38px}.usage-row .usage-bar{max-width:90px}.tb-list,.tb-list.wide{position:fixed;left:8px;right:8px;width:auto;max-width:none;bottom:calc(76px + env(safe-area-inset-bottom,0px));max-height:52vh}.settings-pop{width:min(340px,94vw);bottom:calc(100% + 6px)}.tool-panel{position:fixed;top:44px;right:0;bottom:0;left:0;z-index:22;width:auto;max-width:none;border-left:none}.panel-split.has-preview .explorer-col{display:none}.file-row{min-height:42px}.term-host{min-height:30vh}}.md{font-size:13.5px;line-height:1.55;overflow-wrap:anywhere;white-space:normal}.md>:first-child{margin-top:0}.md>:last-child{margin-bottom:0}.md h1,.md h2,.md h3,.md h4{margin:12px 0 6px;line-height:1.3;font-weight:650}.md h1{font-size:18px}.md h2{font-size:16px}.md h3{font-size:14.5px}.md h4{font-size:13.5px}.md p{margin:6px 0}.md ul,.md ol{margin:6px 0;padding-left:20px}.md li{margin:2px 0}.md li>ul,.md li>ol{margin:2px 0}.md blockquote{margin:6px 0;padding:2px 10px;color:var(--text-dim);border-left:3px solid var(--line)}.md a{color:var(--accent-text);text-decoration:none;border-bottom:1px solid var(--accent-dim)}.md a:hover{border-bottom-color:var(--accent-text)}.md a.md-file-link{font-family:var(--mono);font-size:.94em;padding:0 3px;border-bottom-color:transparent;border-radius:4px;background:rgba(var(--accent-rgb),.1)}.md a.md-file-link:hover{background:rgba(var(--accent-rgb),.2)}.md-file-line{color:var(--text-dim)}.md a.md-img-link{border-bottom:none;display:inline-block;max-width:100%}.md img.md-img{max-width:100%;border-radius:6px;border:1px solid var(--line);display:block;margin:6px 0}.md hr{border:none;border-top:1px solid var(--line);margin:10px 0}.md code{font-family:var(--mono);font-size:12px;padding:1px 4px;border-radius:4px;background:var(--chip-bg);color:var(--text);border:1px solid var(--line)}.md pre{margin:0;padding:8px 10px;overflow-x:auto;background:var(--code-bg);color:var(--code-fg)}.md pre code{padding:0;background:transparent;border:none;color:inherit;font-size:12px;line-height:1.5}.md table{border-collapse:collapse;margin:8px 0;font-size:12.5px;display:block;overflow-x:auto;max-width:100%}.md-table-bar{display:flex;align-items:center;gap:6px;margin:8px 0 -2px}.md-table-filter{flex:1;min-width:0;max-width:240px;font-size:11.5px;padding:3px 7px;background:var(--bg-input, var(--bg-raised));color:var(--text);border:1px solid var(--line);border-radius:5px}.md-table-btn{font-size:11px;line-height:1;padding:3px 7px;cursor:pointer;background:var(--bg-raised);color:var(--text-dim);border:1px solid var(--line);border-radius:5px}.md-table-btn:hover{color:var(--text);border-color:var(--accent-dim)}.md-table-sort{display:inline-flex;align-items:center;gap:4px;width:100%;font:inherit;font-weight:inherit;text-align:left;cursor:pointer;background:none;border:0;padding:0;color:inherit}.md-table-sort:hover{color:var(--accent-text)}.md-table-sort-indicator{font-size:9px;opacity:.55}.md th[aria-sort=ascending] .md-table-sort-indicator,.md th[aria-sort=descending] .md-table-sort-indicator{opacity:1;color:var(--accent-text)}.md-table-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:60;display:flex;flex-direction:column;background:#0000009e;-webkit-backdrop-filter:blur(1.5px);backdrop-filter:blur(1.5px)}.md-table-overlay .md-table-bar{margin:8px}.md-table-overlay .md-table-btn{background:var(--bg-panel);font-size:12px;padding:5px 10px}.md-table-stage{flex:1;min-height:0;position:relative;overflow:hidden}.md-table-zoom{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);max-width:96vw;max-height:96vh;overflow:auto;background:var(--bg-panel);border:1px solid var(--line);border-radius:8px;padding:8px}.md-table-zoom.rot{width:96vh;height:96vw;max-width:none;max-height:none;transform:translate(-50%,-50%) rotate(90deg);transform-origin:center}.md-table-zoom table{display:table;max-width:none;margin:0}.md th,.md td{border:1px solid var(--line);padding:4px 8px;text-align:left}.md th{background:var(--bg-raised);font-weight:600}.md-code{margin:8px 0;border:1px solid var(--line);border-radius:8px;overflow:hidden;background:var(--code-bg);color:var(--code-fg)}.md-code-bar{display:flex;align-items:center;gap:6px;padding:3px 8px;background:var(--code-bar);border-bottom:1px solid var(--code-line)}.md-lang{font-family:var(--mono);font-size:10.5px;color:#9fb0c0;text-transform:lowercase}.md-copy{margin-left:auto;background:transparent;border:1px solid transparent;border-radius:5px;color:#9fb0c0;font-size:10.5px;padding:0 5px;cursor:pointer;font-family:inherit}.md-copy:hover{color:#e3ebf4;border-color:var(--code-line)}.md .hljs-comment,.md .hljs-quote{color:#7f8c98;font-style:italic}.md .hljs-keyword,.md .hljs-selector-tag,.md .hljs-literal,.md .hljs-section,.md .hljs-doctag,.md .hljs-name{color:#c792ea}.md .hljs-string,.md .hljs-regexp,.md .hljs-addition,.md .hljs-attribute,.md .hljs-meta .hljs-string{color:#a5d6a7}.md .hljs-number,.md .hljs-symbol,.md .hljs-bullet,.md .hljs-variable,.md .hljs-template-variable{color:#f0a35e}.md .hljs-title,.md .hljs-title.class_,.md .hljs-title.function_{color:#82b1ff}.md .hljs-built_in,.md .hljs-type,.md .hljs-class .hljs-title{color:#ffd479}.md .hljs-attr,.md .hljs-property,.md .hljs-params{color:#ffcb6b}.md .hljs-deletion{color:#ff6b6b}.md .hljs-emphasis{font-style:italic}.md .hljs-strong{font-weight:700}.tb-wrap{position:relative;flex:0 0 auto}.tb-btn{display:inline-flex;align-items:center;gap:5px;max-width:190px;height:30px;padding:0 7px;background:transparent;border:1px solid transparent;border-radius:8px;color:var(--text-dim);font-size:12px;font-family:inherit;cursor:pointer}.tb-btn:hover{background:var(--bg-panel);border-color:var(--line);color:var(--text)}.tb-btn.on{background:var(--bg-panel);border-color:var(--accent-dim);color:var(--accent-text)}.tb-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tb-chev{opacity:.55}.tb-list{position:absolute;left:0;bottom:calc(100% + 6px);z-index:15;min-width:180px;max-width:min(420px,78vw);max-height:46vh;overflow-y:auto;background:var(--bg-raised);border:1px solid var(--line);border-radius:10px;padding:4px;box-shadow:0 14px 34px #00000073}.tb-list.wide{min-width:320px}.tb-search{width:100%;margin-bottom:3px;background:var(--bg-panel);color:var(--text);border:1px solid var(--line);border-radius:6px;padding:4px 6px;font-size:12px}.tb-search:focus{outline:none;border-color:var(--accent-dim)}.tb-opt{display:flex;flex-direction:column;gap:1px;width:100%;text-align:left;background:transparent;border:1px solid transparent;border-radius:7px;color:var(--text);font-size:12.5px;padding:4px 7px;cursor:pointer;font-family:inherit}.tb-opt:hover{background:var(--bg-panel);border-color:var(--line)}.tb-opt.sel{background:rgba(var(--accent-rgb),.1);border-color:var(--accent-dim);color:var(--accent-text)}.tb-opt.bad{border-color:var(--err);color:var(--err)}.tb-opt.bad:hover{background:rgba(var(--err-rgb),.08)}.tb-err{display:flex;flex-direction:column;gap:2px;margin:6px 4px;padding:6px 8px;border:1px solid var(--err);border-radius:7px;background:rgba(var(--err-rgb),.08);color:var(--err);font-size:11.5px;line-height:1.4;white-space:pre-wrap;word-break:break-word}.tb-err-id{font-family:var(--mono, monospace);font-size:11px;opacity:.85}.tb-err-text{color:var(--text)}.tb-opt-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tb-opt-hint{font-size:10.5px;color:var(--text-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tb-empty{padding:8px;font-size:11.5px;color:var(--text-dim);text-align:center}.usage-edit{display:flex;align-items:center;gap:5px;margin:6px 0 2px}.usage-edit input{flex:1;min-width:0;background:var(--bg-panel);color:var(--text);border:1px solid var(--line);border-radius:6px;padding:3px 6px;font-family:var(--mono);font-size:12px}.usage-edit input:focus{outline:none;border-color:var(--accent-dim)}.usage-edit-btn{background:transparent;border:1px solid var(--line);border-radius:6px;color:var(--text-dim);font-size:11px;padding:2px 8px;cursor:pointer;font-family:inherit}.usage-edit-btn:hover:not(:disabled){color:var(--accent-text);border-color:var(--accent-dim)}.usage-edit-btn:disabled{opacity:.45;cursor:default}.usage-edit-err{color:var(--err);font-size:11px;margin-top:3px}.usage-note{margin-top:6px;color:var(--text-dim);font-size:10.5px;line-height:1.4}@media (max-width: 720px){.tb-list,.tb-list.wide{min-width:0;width:min(86vw,420px)}.tb-btn{max-width:34vw}.md{font-size:14px}}.tb-wrap{flex:0 1 auto;min-width:0}.tb-btn,.tb-label{min-width:0}.tb-effort{padding:0 5px;gap:4px}.tb-pips{display:inline-flex;align-items:flex-end;gap:2px;height:12px}.tb-pips i{display:block;width:3px;border-radius:1px;background:var(--line)}.tb-pips i:nth-child(1){height:4px}.tb-pips i:nth-child(2){height:5px}.tb-pips i:nth-child(3){height:6px}.tb-pips i:nth-child(4){height:7px}.tb-pips i:nth-child(5){height:9px}.tb-pips i:nth-child(6){height:11px}.tb-pips i:nth-child(7){height:13px}.tb-dot{width:7px;height:7px;border-radius:50%;display:inline-block;margin-right:6px;vertical-align:middle}.tb-group{border-top:1px solid var(--line)}.tb-group:first-of-type{border-top:none}.tb-group-head{display:flex;align-items:center;gap:5px;width:100%;text-align:left;background:transparent;border:none;color:var(--text-dim);cursor:pointer;font-family:inherit;font-size:11px;letter-spacing:.03em;text-transform:uppercase;padding:5px 6px;border-radius:6px}.tb-group-head:hover{background:var(--bg-panel);color:var(--text)}.tb-group-chev{transition:transform .12s ease}.tb-group-chev.open{transform:rotate(90deg)}.tb-group-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tb-group-count{font-size:10px;color:var(--text-dim)}.tb-group-body{padding:0 0 4px 8px}@media (max-width: 720px){.tb-btn{max-width:34vw;padding:0 4px;gap:3px}.tb-btn .tb-chev{display:none}.tb-effort{max-width:none}.composer-bar{gap:2px;padding:2px 4px 4px}.composer-bar .icon-btn{width:36px;height:36px}.send-btn{width:44px;height:36px}}.rail-section{display:flex;align-items:center;gap:4px;width:calc(100% - 10px);margin:9px 10px 3px 0;background:transparent;border:none;font-family:inherit;text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-dim);padding:3px 2px;border-radius:6px;cursor:pointer}.rail-section:hover{color:var(--text)}.rail-section-chev{flex:0 0 auto;transition:transform .12s ease}.rail-section-chev.open{transform:rotate(90deg)}.rail-section-count{margin-left:auto;letter-spacing:0;font-variant-numeric:tabular-nums}.rail-section:first-child{margin-top:3px}.rail-placeholder{display:flex;align-items:center;gap:6px;margin:0 10px 2px;padding:5px 7px;border-radius:6px;border:1px dashed var(--line);color:var(--text-dim);font-size:11px;cursor:default}.rail-placeholder-name{color:var(--text);opacity:.75}.rail-placeholder-note{margin-left:auto;font-size:11px}.rail-group{margin-bottom:2px}.rail-group-row{display:flex;align-items:center;gap:2px}.rail-group-head{display:flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;text-align:left;background:transparent;border:none;cursor:pointer;color:var(--text);font-family:inherit;font-size:12px;padding:5px 6px;border-radius:6px;margin-left:0}.rail-group-head:hover{background:var(--bg-raised)}.group-add{flex:0 0 auto;opacity:0;transition:opacity .12s}.rail-group:hover .group-add,.rail-group:focus-within .group-add{opacity:1}@media (hover: none){.group-add{opacity:.7}}.rail-group-folder{flex:0 0 auto;color:var(--text-dim)}.rail-group-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rail-group-count{font-size:11px;color:var(--text-dim)}.rail-group-body{padding-left:28px}.rail-more{display:flex;align-items:center;gap:5px;width:calc(100% - 28px);margin:1px 0 4px 28px;padding:3px 6px;background:transparent;border:none;border-radius:6px;cursor:pointer;color:var(--text-dim);font-family:inherit;font-size:11px;text-align:left}.rail-more:hover{background:var(--bg-raised);color:var(--text)}.rail-more-chev{transition:transform .12s ease;opacity:.7}.rail-more-chev.open{transform:rotate(90deg)}.item-actions{display:inline-flex;align-items:center;gap:2px;margin-left:auto}.item-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:20px;padding:0;background:transparent;border:1px solid transparent;border-radius:5px;color:var(--text-dim);cursor:pointer;font-family:inherit;font-size:11px}.item-btn:hover{background:var(--bg-panel);border-color:var(--line);color:var(--accent-text)}.item-btn.danger:hover{color:var(--err);border-color:var(--err)}.item-btn:disabled{opacity:.5;cursor:default}.rail-error{margin:4px 8px;padding:5px 7px;border:1px solid var(--err);border-radius:6px;color:var(--err);font-size:11px;display:flex;align-items:center;gap:6px}.rail-error .draft-x{margin-left:auto}.rail-empty{padding:14px 10px;color:var(--text-dim);font-size:12.5px}.rail-gear{margin-left:auto;width:26px;height:26px;border-radius:7px}.set-head .title{display:inline-flex;align-items:center;gap:6px}.set-save{padding:6px 14px;border-radius:8px;cursor:pointer;font-weight:600;font-size:12.5px;background:var(--accent);color:var(--on-accent);border:1px solid var(--accent)}.set-save:disabled{background:transparent;color:var(--text-dim);border-color:var(--line);cursor:default}.set-toast{font-size:12px;color:var(--ok)}.set-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:14px}.set-main{flex:1;display:flex;min-height:0}.set-nav{width:196px;flex:0 0 auto;overflow-y:auto;padding:14px 10px 18px;border-right:1px solid var(--line);display:flex;flex-direction:column}.set-nav-group{display:flex;flex-direction:column;margin-bottom:10px}.set-nav-cat{text-align:left;font-size:11px;font-weight:600;color:var(--text-dim);background:none;border:0;cursor:pointer;padding:4px 8px 3px;border-radius:6px}.set-nav-cat:hover{color:var(--text);background:var(--chip-bg)}.set-nav-cat.on{color:var(--text);background:var(--chip-bg);box-shadow:inset 2px 0 0 var(--accent)}.set-nav-item{text-align:left;font-size:12.5px;color:var(--text-dim);background:none;border:0;border-left:2px solid transparent;cursor:pointer;padding:5px 8px;border-radius:0 6px 6px 0;line-height:1.4}.set-nav-item:hover{color:var(--text);background:var(--chip-bg)}.set-nav-item.on{color:var(--text);font-weight:600;border-left-color:var(--accent);background:var(--chip-bg)}.set-group{margin:4px 0 -6px;font-size:11.5px;font-weight:600;letter-spacing:.06em;color:var(--text-dim);max-width:900px;width:100%;align-self:center}.set-body[data-cat=account]>[data-setgroup]:not([data-setgroup=account]),.set-body[data-cat=agent]>[data-setgroup]:not([data-setgroup=agent]),.set-body[data-cat=notify]>[data-setgroup]:not([data-setgroup=notify]),.set-body[data-cat=look]>[data-setgroup]:not([data-setgroup=look]),.set-body[data-cat=voice]>[data-setgroup]:not([data-setgroup=voice]){display:none}.set-card{background:var(--bg-panel);border:1px solid var(--line);border-radius:12px;padding:14px 16px 16px;max-width:900px;width:100%;align-self:center}.set-card h3{margin:0 0 6px;font-size:13.5px}.set-hint{margin:6px 0 0;font-size:12px;color:var(--text-dim);line-height:1.6;display:flex;flex-wrap:wrap;gap:8px;align-items:center}.set-hint code{font-family:var(--mono);background:var(--chip-bg);color:var(--text);border:1px solid var(--line);padding:1px 5px;border-radius:4px;font-size:11.5px}.set-row{display:flex;gap:12px;align-items:flex-start;margin-top:12px}.set-row>label{flex:0 0 84px;font-size:12.5px;color:var(--text-dim);padding-top:7px}.set-input,.set-select,.set-textarea,.set-num{background:var(--bg-raised);color:var(--text);border:1px solid var(--line);border-radius:8px;padding:7px 9px;font-size:12.5px;font-family:var(--mono);min-width:0;flex:1 1 auto}.set-textarea{width:100%;margin-top:10px;resize:vertical;line-height:1.6}.set-num{flex:0 0 70px}.set-input:focus,.set-select:focus,.set-textarea:focus{outline:none;border-color:var(--accent-dim)}.set-pair{display:flex;gap:10px;flex-wrap:wrap;flex:1 1 320px;align-items:center;min-width:0}.set-check{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:var(--text-dim);white-space:nowrap}.set-seg{display:inline-flex;border:1px solid var(--line);border-radius:8px;overflow:hidden}.set-seg button{padding:6px 12px;background:transparent;color:var(--text-dim);border:none;border-right:1px solid var(--line);cursor:pointer;font-size:12.5px}.set-seg button:last-child{border-right:none}.set-seg button.on{background:var(--accent);color:var(--on-accent);font-weight:600}.set-swatches{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.set-swatch{width:22px;height:22px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0}.set-swatch.on{border-color:var(--text)}.set-color{width:26px;height:24px;padding:0;border:1px solid var(--line);border-radius:6px;background:var(--bg-raised)}.set-mini{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;padding:5px 9px;border-radius:7px;border:1px solid var(--line);background:var(--bg-raised);color:var(--text-dim);cursor:pointer}.set-mini:hover:not(:disabled){color:var(--text);border-color:var(--accent-dim)}.set-mini:disabled{opacity:.55;cursor:default}.set-hot{margin-top:12px;border-top:1px dashed var(--line);padding-top:10px}.set-hot-title{font-size:12px;color:var(--text-dim)}.set-hot-list{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}.set-chip{font-size:11.5px;font-family:var(--mono);padding:2px 7px;border-radius:6px;border:1px solid var(--line);background:var(--bg-raised);color:var(--text-dim)}.set-chip.fixed{border-color:var(--accent-dim);color:var(--text)}.set-chip.dynamic{border-style:dashed}.set-chip b{color:var(--accent-text);margin-left:4px;font-size:10.5px}.set-err{max-width:900px;width:100%;align-self:center;display:flex;gap:8px;align-items:center;font-size:12.5px;color:var(--err);background:var(--bg-panel);border:1px solid var(--err);border-radius:10px;padding:9px 12px}.set-inline-err{color:var(--err);font-size:12px}.set-actions{display:flex;gap:10px;align-items:center;max-width:900px;width:100%;align-self:center;padding-bottom:8px}@media (max-width: 720px){.set-row{flex-direction:column;gap:6px}.set-row>label{padding-top:0}.set-body{padding:10px}.set-main{flex-direction:column}.set-nav{width:auto;flex-direction:row;align-items:center;gap:6px;overflow-x:auto;overflow-y:hidden;padding:8px 10px;border-right:0;border-bottom:1px solid var(--line)}.set-nav-group{flex-direction:row;align-items:center;gap:6px;margin-bottom:0}.set-nav-cat{white-space:nowrap;font-size:12px;padding:4px 10px;border-radius:999px;border:1px solid var(--line);background:var(--chip-bg)}.set-nav-item{display:none}}.usage-row .usage-act{display:inline-flex;align-items:center;gap:4px;flex:0 0 auto;font-size:10.5px;padding:2px 7px;border-radius:6px;cursor:pointer;border:1px solid var(--line);background:var(--bg-raised);color:var(--text-dim)}.usage-row.hot .usage-act{border-color:rgba(var(--err-rgb),.5);color:var(--err)}.usage-row .usage-act:hover{color:var(--text);border-color:var(--accent-dim)}.usage-actions{display:flex;gap:6px;margin:6px 0 2px;flex-wrap:wrap}.usage-check{display:inline-flex;align-items:center;gap:4px;font-size:11px;color:var(--text-dim)}.usage-note code{background:var(--chip-bg);border:1px solid var(--line);border-radius:4px;padding:0 4px}@media (max-width: 720px){.usage-text{padding:9px 2px;margin:-9px -2px}.tb-btn,.tb-effort{min-width:40px}.item-btn{min-width:34px;min-height:32px}.set-swatch{width:32px;height:32px}.set-color{width:36px;height:32px}.set-seg button{padding:8px 12px}.usage-act{padding:5px 9px}}.acct-list{display:flex;flex-direction:column;gap:6px;margin-top:10px}.acct-row{display:flex;align-items:center;gap:10px;padding:8px 10px;background:var(--bg-raised);border:1px solid var(--line);border-radius:10px}.acct-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.acct-name{font-size:12.5px;color:var(--text);display:inline-flex;align-items:center;gap:6px}.acct-sub{font-size:11px;color:var(--text-dim);font-family:var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.acct-badge{font-size:10px;padding:1px 5px;border-radius:999px;color:var(--ok);border:1px solid rgba(var(--accent-rgb),.4);background:rgba(var(--accent-rgb),.12)}.acct-badge.danger{color:var(--err);border-color:rgba(var(--err-rgb),.45);background:rgba(var(--err-rgb),.12)}.acct-when{font-size:11px;color:var(--text-dim);font-family:var(--mono)}.acct-empty{font-size:12px;color:var(--text-dim);padding:6px 2px}.set-mini.danger{color:var(--err);border-color:rgba(var(--err-rgb),.35)}.set-mini.danger:hover:not(:disabled){color:var(--err);border-color:var(--err)}.pw-wrap{position:relative;display:flex;align-items:center}.pw-wrap input{padding-right:34px}.pw-eye{position:absolute;right:4px;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;color:var(--text-dim);cursor:pointer;border-radius:6px}.pw-eye:hover{color:var(--text);background:var(--bg-raised)}.modal-head{display:flex;align-items:center;gap:8px;margin-bottom:6px}.modal-head h3{margin:0;flex:1}@media (max-width: 720px){.pw-eye{width:34px;height:34px}.acct-row{padding:10px}.acct-row .set-mini{min-height:34px}.set-row .set-pair{flex:0 0 auto}.set-row>label{flex:0 0 auto}}.session-item{display:flex;align-items:center;gap:8px;padding:4px 6px;min-height:30px}.session-item .title{flex:1 1 auto;min-width:0}.session-item .badge.perm{flex:0 0 auto}.rail-at{flex:0 0 auto;font-size:11px;color:var(--text-dim);font-variant-numeric:tabular-nums;white-space:nowrap}.session-item.active .rail-at{color:var(--text-dim)}.unread-dot{flex:0 0 auto;width:8px;height:8px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 2px rgba(var(--accent-rgb),.18)}.be-avatar{position:relative;flex:0 0 auto;width:20px;height:20px;border-radius:6px;display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;letter-spacing:.2px;color:var(--be-tone, var(--text-dim));background:color-mix(in srgb,var(--be-tone, var(--text-dim)) 16%,transparent);border:1px solid color-mix(in srgb,var(--be-tone, var(--text-dim)) 40%,transparent)}.be-avatar.be-hermes{--be-tone: #a98bff}.be-avatar.be-qoder{--be-tone: #4f9bf5}.be-avatar.be-mock{--be-tone: #94a3b8}.be-avatar img{width:100%;height:100%;object-fit:cover;border-radius:inherit;display:block}.be-avatar .be-dot{position:absolute;right:-2px;bottom:-2px;width:7px;height:7px;border-radius:50%;border:1px solid var(--bg);background:var(--ok)}.be-avatar.live{animation:rail-live 1.8s ease-in-out infinite}@keyframes rail-live{0%,to{box-shadow:0 0 0 1.5px color-mix(in srgb,var(--ok) 55%,transparent)}50%{box-shadow:0 0 0 4px color-mix(in srgb,var(--ok) 10%,transparent)}}@media (prefers-reduced-motion: reduce){.be-avatar.live{animation:none;box-shadow:0 0 0 2px color-mix(in srgb,var(--ok) 55%,transparent)}}.title-input{flex:1 1 auto;min-width:0;font:inherit;font-size:13.5px;color:var(--text);background:var(--bg-panel);border:1px solid var(--accent-dim);border-radius:6px;padding:2px 6px}.title-input:focus{outline:none;border-color:var(--accent)}.row-menu{flex:0 0 auto;opacity:0;transition:opacity .12s}.session-item:hover .row-menu,.session-item.active .row-menu,.session-item:focus-within .row-menu{opacity:1}@media (hover: none){.row-menu{opacity:.7}}.sess-menu{position:fixed;z-index:40;width:max-content;max-width:min(320px,calc(100vw - 12px));background:var(--bg-panel);border:1px solid var(--line);border-radius:10px;box-shadow:var(--shadow);padding:5px;display:flex;flex-direction:column;gap:1px}.sess-menu-head{display:flex;align-items:center;gap:8px;padding:6px 7px 8px;margin-bottom:3px;border-bottom:1px solid var(--line)}.sess-menu-title{font-size:12.5px;color:var(--text);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sess-menu-item{display:flex;align-items:center;gap:9px;width:100%;padding:7px 8px;text-align:left;background:transparent;border:1px solid transparent;border-radius:7px;color:var(--text);font:inherit;font-size:13px;cursor:pointer}.sess-menu-item:hover{background:var(--bg-raised);border-color:var(--line)}.sess-menu-item.danger{color:var(--err)}.sess-menu-item.danger:hover{border-color:var(--err);background:rgba(var(--err-rgb),.08)}.sess-menu-item svg{flex:0 0 auto;color:var(--text-dim)}.sess-menu-item.danger svg{color:var(--err)}.bubble-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;padding:0;background:transparent;border:1px solid transparent;border-radius:6px;color:var(--text-dim);font:inherit;cursor:pointer}.bubble-btn:hover{background:var(--bg-panel);border-color:var(--line);color:var(--text)}.bubble-btn.copy.ok{color:var(--ok);border-color:var(--ok)}.bubble-btn.copy.no{color:var(--err);border-color:var(--err)}.bubble-btn.speak.on,.bubble-btn.fork:hover{color:var(--accent-text);border-color:var(--accent-dim)}.bubble-btn.fork.failed{color:var(--err);border-color:var(--err)}.bubble-btn.fork.working{opacity:.55}.bubble-btn:disabled{opacity:.55;cursor:default}@media (max-width: 720px){.sess-menu{left:8px!important;right:8px;top:auto!important;bottom:calc(10px + env(safe-area-inset-bottom,0px));width:auto!important;max-width:none;min-width:0}.sess-menu-item{padding:11px 10px;font-size:14px}.session-item{min-height:36px}.bubble-btn{width:34px;height:30px}}.call-mode{position:fixed;top:0;right:0;bottom:0;left:0;z-index:60;--bg-panel: rgba(255,255,255,.07);--bg-raised: rgba(255,255,255,.14);--line: rgba(255,255,255,.16);--text: #eef2f7;--text-dim: rgba(238,242,247,.6);--err: #f2555a;--on-accent: #0b1220;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:max(20px,env(safe-area-inset-top)) 18px calc(20px + env(safe-area-inset-bottom));background:radial-gradient(120% 90% at 50% 33%,#111827,#080a12 60%,#05060b);color:var(--text);overflow:hidden;animation:call-in .24s ease-out}@keyframes call-in{0%{opacity:0;transform:scale(1.015)}to{opacity:1;transform:none}}.call-mode[data-phase=connecting]{--call-tone: #7d91c8}.call-mode[data-phase=listening]{--call-tone: #38bdf8}.call-mode[data-phase=thinking]{--call-tone: #a78bfa}.call-mode[data-phase=speaking]{--call-tone: #fbbf24}.call-mode[data-phase=error]{--call-tone: #f87171}.call-mode:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;background:radial-gradient(26% 19% at 50% 37%,color-mix(in srgb,var(--call-tone, #38bdf8) 26%,transparent) 0%,transparent 100%),radial-gradient(62% 44% at 50% 37%,color-mix(in srgb,var(--call-tone, #38bdf8) 15%,transparent) 0%,transparent 74%);transition:background .5s ease}.call-head,.call-orb,.call-lines,.call-wave,.call-controls{position:relative}.call-head{display:flex;flex-direction:column;align-items:center;gap:4px}.call-title{font-size:17px;font-weight:600;letter-spacing:.03em;color:var(--call-tone, var(--text));text-shadow:0 0 18px color-mix(in srgb,var(--call-tone, #38bdf8) 45%,transparent)}.call-sub{font-size:11.5px;color:var(--text-dim);letter-spacing:.04em}.call-orb{height:min(46vh,76vw,380px);aspect-ratio:1;flex:0 1 auto;padding:0;border:none;background:transparent;cursor:pointer;-webkit-tap-highlight-color:transparent}.call-orb-canvas{display:block;width:100%;height:100%}.call-orb:focus-visible{outline:2px solid var(--call-tone, var(--accent));outline-offset:6px;border-radius:50%}.call-lines{display:flex;flex-direction:column;align-items:center;gap:6px;width:min(560px,92vw);min-height:60px;flex:0 1 auto;overflow:hidden}.call-heard{margin:0;font-size:15px;line-height:1.45;text-align:center}.call-reply{margin:0;font-size:13.5px;line-height:1.5;color:var(--text-dim);text-align:center;max-height:24vh;overflow-y:auto;white-space:pre-wrap}.call-hint{margin:0;font-size:12.5px;color:var(--text-dim)}.call-err{margin:0;font-size:12.5px;color:var(--err)}.call-note{margin:0;font-size:12.5px;color:var(--warn, #d08a2a)}.call-wave{width:min(420px,80vw);height:46px;display:block;flex:0 1 auto;min-height:34px;border-radius:12px;background:linear-gradient(to bottom,#ffffff03,#ffffff09)}.call-hist{width:min(560px,92vw);flex:0 1 auto;min-height:0;display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--line);border-radius:14px;background:#ffffff0a}.call-hist-bar{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:0 12px;border:0;background:transparent;color:var(--text-dim);cursor:pointer;text-align:left}.call-hist-bar:hover{color:var(--text)}.call-hist-title{font-size:12.5px;color:var(--text)}.call-hist-n{font-size:11.5px;color:var(--text-dim)}.call-hist-peek{flex:1 1 auto;min-width:0;font-size:11.5px;color:var(--text-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.call-hist-chev{margin-left:auto;display:inline-flex;transition:transform .18s ease}.call-hist[data-open=true] .call-hist-chev{transform:rotate(180deg)}.call-hist-list{flex:1 1 auto;min-height:0;max-height:min(38vh,300px);overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding:10px 12px 12px;display:flex;flex-direction:column;gap:9px;border-top:1px solid var(--line);scrollbar-width:thin}.call-hm{font-size:12.5px;line-height:1.5;color:var(--text)}.call-hm-who{display:block;margin-bottom:2px;font-size:10.5px;letter-spacing:.08em;color:var(--text-dim);opacity:.7}.call-hm.meta,.call-hm.tool{font-size:11.5px;font-style:italic;color:var(--text-dim)}.call-hm.current{border-left:2px solid var(--call-tone, #38bdf8);margin-left:-12px;padding-left:10px}.call-hm .code{margin:4px 0;padding:6px 8px;font-size:11.5px;color:var(--text)}.call-hist-back{align-self:center;margin:0 0 10px;min-height:32px;padding:0 12px;border-radius:999px;border:1px solid var(--line);background:#ffffff0f;color:var(--text);font-size:12px;cursor:pointer}.call-hist-back:hover{background:var(--bg-raised)}.call-modes{display:inline-flex;align-items:center;gap:2px;margin-top:6px;padding:2px;border:1px solid var(--line);border-radius:999px;background:#ffffff0a}.call-mode-btn{min-height:28px;padding:0 11px;border:0;border-radius:999px;cursor:pointer;background:transparent;color:var(--text-dim);font-size:12px;letter-spacing:.02em}.call-mode-btn:hover{color:var(--text)}.call-mode-btn.on{background:var(--call-tone, #38bdf8);color:#0b1220;font-weight:600;box-shadow:0 0 12px color-mix(in srgb,var(--call-tone, #38bdf8) 40%,transparent)}.call-controls{display:flex;align-items:center;gap:16px;margin-top:2px}.call-btn{width:52px;height:52px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);background:var(--bg-panel);color:var(--text);cursor:pointer}.call-btn:hover{background:var(--bg-raised);border-color:var(--text-dim)}.call-btn.on{background:var(--accent);color:var(--on-accent);border-color:transparent}.call-btn.hangup{width:60px;height:60px;background:var(--err);border-color:transparent;color:#fff}.call-btn.hangup:hover{background:var(--err);filter:brightness(1.1)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.call-gear{position:absolute;z-index:2;top:max(14px,env(safe-area-inset-top));right:14px;width:38px;height:38px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);background:var(--bg-panel);color:var(--text-dim);cursor:pointer}.call-gear:hover{color:var(--text);background:var(--bg-raised)}.call-sheet{position:absolute;top:0;right:0;bottom:0;left:0;z-index:3;display:flex;align-items:center;justify-content:center;padding:16px;background:#04060cbd;animation:call-in .16s ease-out}.call-sheet-card{width:min(460px,100%);max-height:88%;overflow-y:auto;display:flex;flex-direction:column;gap:14px;padding:16px;border:1px solid var(--line);border-radius:18px;background:#0d1220;box-shadow:0 24px 60px #0000008c}.call-sheet-head{display:flex;align-items:center;justify-content:space-between;font-size:15px;font-weight:600}.call-sheet-x{width:30px;height:30px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);background:transparent;color:var(--text-dim);cursor:pointer}.call-sheet-note{margin:0;font-size:11.5px;line-height:1.5;color:var(--text-dim)}.call-knob{display:flex;flex-direction:column;gap:4px}.call-knob-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}.call-knob-name{font-size:13.5px}.call-knob-val{font-size:13px;font-variant-numeric:tabular-nums;color:var(--call-tone, #38bdf8)}.call-knob input[type=range]{width:100%;height:30px;accent-color:var(--call-tone, #38bdf8);background:transparent;cursor:pointer}.call-knob-ends{display:flex;justify-content:space-between;font-size:10.5px;color:var(--text-dim)}.call-knob-hint{font-size:11px;line-height:1.45;color:var(--text-dim)}.call-knob.off{opacity:.45}.call-knob.off input[type=range]{cursor:not-allowed}.call-sheet-warn{margin:0;padding:9px 11px;border-radius:10px;font-size:11.5px;line-height:1.5;border:1px solid color-mix(in srgb,var(--call-tone, #38bdf8) 35%,transparent);background:color-mix(in srgb,var(--call-tone, #38bdf8) 12%,transparent);color:var(--text)}.call-sheet-foot{display:flex;gap:10px;justify-content:flex-end;margin-top:2px}.call-sheet-btn{min-height:40px;padding:0 14px;border-radius:10px;font-size:13px;border:1px solid var(--line);background:transparent;color:var(--text);cursor:pointer}.call-sheet-btn:hover{background:var(--bg-raised)}.call-sheet-btn.primary{background:var(--call-tone, #38bdf8);border-color:transparent;color:#0b1220;font-weight:600}@media (max-width: 720px){.call-mode{gap:8px}.call-sheet{align-items:flex-end;padding:0}.call-sheet-card{width:100%;max-height:84%;border-radius:20px 20px 0 0;padding-bottom:calc(16px + env(safe-area-inset-bottom))}.call-gear{width:42px;height:42px}.call-knob input[type=range]{height:34px}.call-orb{height:min(42vh,72vw,300px)}.call-lines{min-height:88px}.call-reply{max-height:20vh}.call-hist-list{max-height:min(30vh,240px)}.call-hist-peek{display:none}.call-btn{width:56px;height:56px}.call-btn.hangup{width:64px;height:64px}}@media (prefers-reduced-motion: reduce){.call-mode{animation:none}}.be-list{display:flex;flex-direction:column;gap:8px;margin-top:12px}.be-row{display:flex;gap:12px;align-items:flex-start;justify-content:space-between;background:var(--bg-raised);border:1px solid var(--line);border-radius:10px;padding:10px 12px}.be-row-main{min-width:0;display:flex;flex-direction:column;gap:3px}.be-row-title{display:flex;gap:8px;align-items:center;flex-wrap:wrap;font-size:13px}.be-row-sub{font-size:11.5px;color:var(--text-dim);font-family:var(--mono);word-break:break-all}.be-row-note{font-size:11.5px;color:var(--text-dim)}.be-kind-help{display:block;margin:6px 0 0;padding:8px 10px;border-left:2px solid var(--accent-dim);background:var(--chip-bg);border-radius:0 8px 8px 0;line-height:1.75}.be-kind-help b{color:var(--text)}.be-kind-help code{font-size:11px}.be-row-actions{display:flex;gap:6px;flex-shrink:0;flex-wrap:wrap}.be-badge{font-size:10.5px;padding:1px 6px;border-radius:999px;border:1px solid var(--line);color:var(--text-dim);background:var(--chip-bg)}.be-badge.be-warn{color:var(--accent);border-color:var(--accent-dim)}.be-badge.be-danger,.be-danger{color:var(--err)}.be-badge.be-dim{opacity:.75}.be-badge.be-ok{color:var(--ok, #3fb950);border-color:var(--ok, #3fb950)}.be-health{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:5px;font-size:11.5px}.be-code{font-family:var(--mono);font-size:10.5px;padding:0 4px;border:1px solid var(--line);border-radius:4px;color:var(--text-dim)}.be-guidance{flex-basis:100%;color:var(--text-dim);font-size:11.5px}.be-handshake{margin-top:4px;font-size:11.5px;color:var(--text-dim)}.be-handshake code{font-family:var(--mono)}.be-dim{color:var(--text-dim);font-size:11.5px}.hint-warn{color:var(--accent);font-size:11.5px;margin-top:4px}.be-hint{display:block}.be-hint code,.be-inspect code,.be-inspect-out{font-family:var(--mono)}.be-hint code{word-break:break-all}.be-inspect{margin-top:12px;border:1px dashed var(--line);border-radius:10px;padding:10px 12px;font-size:12px;background:var(--bg-raised)}.be-inspect-head{display:flex;justify-content:space-between;align-items:center;gap:8px}.be-inspect ul{margin:8px 0 0;padding-left:18px;display:flex;flex-direction:column;gap:4px}.be-inspect-out{margin-top:4px;font-size:11px;color:var(--text-dim);white-space:pre-wrap;word-break:break-all}.be-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:60;background:#00000073;display:flex;align-items:center;justify-content:center;padding:20px}.be-modal{background:var(--bg-panel);border:1px solid var(--line);border-radius:14px;width:min(560px,100%);max-height:min(86vh,780px);display:flex;flex-direction:column;box-shadow:0 18px 48px #00000080}.be-modal-head{display:flex;align-items:center;gap:8px;padding:12px 16px;border-bottom:1px solid var(--line);font-size:13.5px}.be-modal-head b{font-size:13.5px}.be-modal-head code{font-family:var(--mono);font-size:11.5px;color:var(--text-dim)}.be-modal-x{margin-left:auto}.be-modal-body{overflow:auto;overscroll-behavior:contain;padding:2px 16px 14px}.be-modal-foot{display:flex;align-items:center;gap:8px;padding:12px 16px;border-top:1px solid var(--line)}.be-modal-foot button{flex:0 0 auto;white-space:nowrap}.be-modal-foot .set-mini{margin-left:auto}.be-modal-err{flex:1 1 auto;min-width:0;font-size:11.5px;color:var(--err);border:none;padding:0;background:none}@media (max-width: 720px){.be-backdrop{padding:0;align-items:flex-end}.be-modal{width:100%;max-height:92vh;border-radius:14px 14px 0 0}}@media (max-width: 720px){.be-row{flex-direction:column}}
|