symbio 0.4.0 → 0.5.0

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.
@@ -5,7 +5,7 @@ import { randomBytes } from "node:crypto";
5
5
  import { promises as fs } from "node:fs";
6
6
  import path from "node:path";
7
7
  import { AssetRegister } from "./assets.js";
8
- import { AGENT_PERMISSIONS, wildcardMatch } from "./guard.js";
8
+ import { AGENT_PERMISSIONS, imageReadRefusal, wildcardMatch } from "./guard.js";
9
9
  import { bus } from "./bus.js";
10
10
  import { privateDocsInstruction } from "./docs.js";
11
11
  import { parseModel } from "./opencode/client.js";
@@ -17,7 +17,7 @@ import { accountChildUsage, accountUsage, emptyUsage, sessionUsage } from "./cos
17
17
  import { AGENT_UPDATES, unseenUpdates, updatesNote } from "./updates.js";
18
18
  import { cleanBuildOutputs, dailyBackup, gb, helperFolders, lastBackup, unpushedWork } from "./housekeeping.js";
19
19
  import { coordinatorTools, workerTools } from "./tools.js";
20
- import { changedFiles, createWorkspace, inProjectFolder, isGitRepo, leaveWorkspace, mergeWorkspace, removeWorkspace, restoreWorkspace, syncWorkspace } from "./workspaces.js";
20
+ import { changedFiles, createWorkspace, inProjectFolder, isGitRepo, leaveWorkspace, mergeWorkspace, reattachWorkspace, removeWorkspace, restoreWorkspace, syncWorkspace } from "./workspaces.js";
21
21
  const STUCK_AFTER_MS = Number(process.env.SYMBIO_STUCK_MINUTES ?? 10) * 60_000;
22
22
  const WATCHDOG_INTERVAL_MS = 30_000;
23
23
  // Loop guard: max conversational messages between the same pair in the window (per
@@ -85,6 +85,8 @@ export class Team {
85
85
  limitNoticed = new Map(); // pair → when the human was last told
86
86
  failedModels = new Map(); // agentId → model → failedAt
87
87
  fallbackBusy = new Set();
88
+ /** When each agent last got a fresh session because its conversation was too large to send. */
89
+ oversizedAt = new Map();
88
90
  /** agentId → tool call id of an open interactive question. */
89
91
  pendingQuestion = new Map();
90
92
  /** Connection actions (SSH, git, GitHub API) and their approvals. Set at startup. */
@@ -268,6 +270,24 @@ export class Team {
268
270
  : "Symbio: the human set this project's helpers to work in their own copy (own branch) by default. Helpers already in the " +
269
271
  "project folder stay there.", false);
270
272
  }
273
+ /** The human turned the rules register on or off; every brief mentions it, and core is told. */
274
+ async setRulesRegister(project, on) {
275
+ if (!!project.rulesRegister === on)
276
+ return;
277
+ project.rulesRegister = on;
278
+ await this.store.update(project);
279
+ bus.publish({ type: "project.updated", projectId: project.id });
280
+ for (const agent of project.agents.filter(active))
281
+ await this.refreshInstructions(project, agent).catch(() => { });
282
+ const coordinator = this.coordinator(project);
283
+ if (!coordinator || coordinator.status === "stopped")
284
+ return;
285
+ await this.system(project, coordinator, on
286
+ ? "Symbio: the human turned on the rules register for this project. Your instructions now explain it (save_rule, list_rules…). " +
287
+ "Record rules as they come up in the work; if the project already has rules written down somewhere, offer the human to " +
288
+ "bring them into the register as a planned task."
289
+ : "Symbio: the human turned off the rules register for this project. Stop recording rules; what's recorded stays in the file.", false);
290
+ }
271
291
  /** Renames a helper. Its branch and folder keep their names; the old name keeps working. */
272
292
  async renameAgent(project, agent, newName) {
273
293
  if (agent.role === "coordinator")
@@ -954,6 +974,14 @@ export class Team {
954
974
  async onPermissionAsked(project, agent, req) {
955
975
  const action = String(req.action ?? "");
956
976
  const resources = Array.isArray(req.resources) ? req.resources.map(String) : [];
977
+ // Image files: refused at once, with what to use instead (never a question for the human).
978
+ const refusal = imageReadRefusal(action, resources);
979
+ if (refusal) {
980
+ await this.client()
981
+ .request("POST", `/api/session/${agent.sessionId}/permission/${req.id}/reply`, { decision: "reject", message: refusal })
982
+ .catch(() => { });
983
+ return;
984
+ }
957
985
  // Already answered "always" for this kind of request in this project?
958
986
  const allowed = resources.length > 0 && resources.every((r) => project.allowedPatterns.some((a) => a.action === action && wildcardMatch(a.pattern, r)));
959
987
  if (allowed) {
@@ -1236,11 +1264,29 @@ export class Team {
1236
1264
  }
1237
1265
  /** Before starting an agent's turn: make sure its tools and private docs are in place. */
1238
1266
  async prepare(project, agent) {
1267
+ await this.reattach(project, agent);
1239
1268
  await this.ensureTools(project, agent.directory);
1240
1269
  await this.syncPrivateDocs(project, agent);
1241
1270
  }
1271
+ /** A helper whose folder disappeared gets it back from its branch (see reattachWorkspace). */
1272
+ async reattach(project, agent) {
1273
+ if (agent.status === "stopped")
1274
+ return;
1275
+ const recreated = await reattachWorkspace(project, agent).catch((err) => {
1276
+ console.error(`[team] could not recreate ${agent.name}'s folder:`, err.message);
1277
+ return false;
1278
+ });
1279
+ if (!recreated)
1280
+ return;
1281
+ const text = `${agent.name}'s folder (${agent.directory}) had disappeared; Symbio recreated it from its branch ${agent.branch}. ` +
1282
+ "Everything it committed is there; changes it hadn't committed were in the folder and are gone.";
1283
+ await this.log(project, { from: "symbio", to: "human", kind: "system", text });
1284
+ await this.system(project, agent, `Symbio: ${text.replace(`${agent.name}'s folder`, "Your folder")} Check your state before continuing.`, false);
1285
+ }
1242
1286
  async refreshAll() {
1243
1287
  for (const project of this.store.list()) {
1288
+ for (const agent of project.agents.filter(active))
1289
+ await this.reattach(project, agent);
1244
1290
  const dirs = new Set(project.agents.filter(active).map((a) => a.directory));
1245
1291
  for (const dir of dirs) {
1246
1292
  await this.registerTools(project, dir).catch((err) => console.error(`[team] could not register tools for ${project.name} (${dir}):`, err.message));
@@ -1374,6 +1420,47 @@ export class Team {
1374
1420
  bus.publish({ type: "agent.stream", projectId: project.id, agentId: agent.id, event: { type: e.type, data: e.data } });
1375
1421
  }
1376
1422
  }
1423
+ /**
1424
+ * An agent whose conversation got too large to send continues in a fresh session (with the
1425
+ * usual handoff note) and is told why. Once per 15 minutes: if the fresh one fails the same
1426
+ * way, the human is told instead of looping.
1427
+ */
1428
+ async renewOversized(project, agent, message) {
1429
+ const last = this.oversizedAt.get(agent.id) ?? 0;
1430
+ if (Date.now() - last < 15 * 60_000) {
1431
+ if (agent.problem)
1432
+ return;
1433
+ agent.problem = `Its conversation is too large to send, even after a fresh session (${message}).`;
1434
+ this.setStatus(project, agent, "error");
1435
+ await this.store.update(project);
1436
+ bus.publish({ type: "project.updated", projectId: project.id });
1437
+ await this.log(project, { from: "symbio", to: "human", kind: "alert", text: `${agent.name} can't continue: ${agent.problem}` });
1438
+ return;
1439
+ }
1440
+ this.oversizedAt.set(agent.id, Date.now());
1441
+ this.fallbackBusy.add(agent.id);
1442
+ try {
1443
+ agent.problem = null;
1444
+ if (agent.status !== "idle")
1445
+ this.setStatus(project, agent, "idle");
1446
+ await this.renewSession(project, agent, "its conversation had grown too large to send");
1447
+ await this.system(project, agent, "Symbio: your previous conversation had grown too large to send to the model (the provider said: " +
1448
+ `"${message}"), so you continue in this fresh session; the handoff note above has what carries over. ` +
1449
+ "Usually it's images read in full: each one stays in the conversation and is sent again every turn. " +
1450
+ "To look at an image, read a small copy (scaled down to about 1000 px wide) or have a helper review it. " +
1451
+ "Continue where you left off.");
1452
+ }
1453
+ catch (err) {
1454
+ agent.problem = `Its conversation is too large to send (${message}), and a fresh session couldn't start: ${err.message}. Use New session in its chat.`;
1455
+ this.setStatus(project, agent, "error");
1456
+ await this.store.update(project);
1457
+ bus.publish({ type: "project.updated", projectId: project.id });
1458
+ await this.log(project, { from: "symbio", to: "human", kind: "alert", text: `${agent.name} can't continue: ${agent.problem}` });
1459
+ }
1460
+ finally {
1461
+ this.fallbackBusy.delete(agent.id);
1462
+ }
1463
+ }
1377
1464
  /**
1378
1465
  * When an agent's model fails for provider reasons (quota, outage, timeouts),
1379
1466
  * switch it to the next allowed model and tell it to continue.
@@ -1386,6 +1473,15 @@ export class Team {
1386
1473
  const status = Number(error?.status ?? 0);
1387
1474
  if (/interrupt|abort|cancel/i.test(`${type} ${message}`))
1388
1475
  return; // our own interrupts
1476
+ // The conversation itself is too big to send (seen with Copilot: "Timed out reading request
1477
+ // body", after an agent read several large images). Another model won't help; a fresh session will.
1478
+ if (status === 413 || /request body|request size|payload too large|request too large|request entity too large/i.test(message)) {
1479
+ // Still retrying the same oversized request: stop it before moving on.
1480
+ if (interruptFirst)
1481
+ await this.client().interrupt(agent.sessionId).catch(() => { });
1482
+ await this.renewOversized(project, agent, message);
1483
+ return;
1484
+ }
1389
1485
  const providerProblem = type.startsWith("provider") ||
1390
1486
  [401, 402, 403, 404, 408, 429].includes(status) ||
1391
1487
  status >= 500 ||
@@ -2,6 +2,8 @@
2
2
  // specific agent (identified by its session); coordinator-only tools refuse
3
3
  // other callers.
4
4
  import { describeTask, TASK_STATUSES } from "./plan.js";
5
+ import { CONFIRMATIONS, listRules, saveArea, saveRule, saveSource, STATUSES } from "./rules.js";
6
+ import { DEFAULT_IMAGE_SIZE, viewImage } from "./images.js";
5
7
  const str = (description) => ({ type: "string", description });
6
8
  function obj(properties, required = []) {
7
9
  return { type: "object", properties, required, additionalProperties: false };
@@ -357,7 +359,101 @@ const githubApi = {
357
359
  }, ["connection", "method", "path", "reason"]),
358
360
  run: ({ connection, method, path, body, reason }, { team, project, agent }) => team.remote.request(project, agent, { kind: "github_api", connectionId: String(connection), method: String(method), path: String(path), body }, String(reason)),
359
361
  };
362
+ // ---- rules register (only when the project keeps one)
363
+ function registerOn(project) {
364
+ if (!project.rulesRegister)
365
+ throw new Error("This project doesn't keep a rules register (the human can turn it on in the project's Settings).");
366
+ }
367
+ // ---- images
368
+ const viewImageTool = {
369
+ name: "view_image",
370
+ description: "Look at an image (png, jpg, gif, webp, bmp): returns a scaled-down copy, so it doesn't bloat your conversation. " +
371
+ "Reading image files directly is blocked: a full-size image stays in your conversation and is re-sent every turn. " +
372
+ "For details, ask for a crop: a region of the original, in its pixels, shown at full resolution.",
373
+ inputSchema: obj({
374
+ path: str("The image file (absolute, or relative to your folder)"),
375
+ max_size: { type: "integer", description: `Longest side of the copy in pixels (default ${DEFAULT_IMAGE_SIZE}, at most 2048)` },
376
+ crop: obj({ left: { type: "integer" }, top: { type: "integer" }, width: { type: "integer" }, height: { type: "integer" } }, ["left", "top", "width", "height"]),
377
+ }, ["path"]),
378
+ run: (args, { agent }) => viewImage(agent.directory, args),
379
+ };
380
+ const listRulesTool = {
381
+ name: "list_rules",
382
+ description: "The project's rules register: its areas, sources and rules (id, status, confirmation, text, sources). Filter to keep it short.",
383
+ inputSchema: obj({
384
+ query: str("Words to look for in the id, text, current state or citations"),
385
+ area: str("Only this area (its prefix, e.g. 'AP')"),
386
+ status: { type: "string", enum: [...STATUSES] },
387
+ }),
388
+ async run(args, { project }) {
389
+ registerOn(project);
390
+ return listRules(project, args);
391
+ },
392
+ };
393
+ const saveRuleTool = {
394
+ name: "save_rule",
395
+ description: "Add a rule to the register, or update one (give its id; only the fields you pass change). A new rule gets the next id in its " +
396
+ "area. State only what the sources say; if nothing backs it yet, add it without citations (it shows as unsourced) rather than " +
397
+ "inventing a source. Citations quote the source literally.",
398
+ inputSchema: obj({
399
+ id: str("To update an existing rule, e.g. 'AP-031'. Leave out to add a new one."),
400
+ area: str("Area prefix (define areas with save_rule_area)"),
401
+ stage: str("Stage id within the area (e.g. 'B')"),
402
+ text: str("What the rule says (Markdown)"),
403
+ action: str("What the work does about it, e.g. 'blocks submission', 'warning only', 'none'"),
404
+ citations: {
405
+ type: "array",
406
+ description: "Where it comes from. Each: source code (define sources with save_rule_source), location (p.20, l.10…), literal excerpt.",
407
+ items: obj({ source: str("Source code, e.g. 'MA'"), location: str("Where in the source"), excerpt: str("The source's words, copied literally") }, ["source"]),
408
+ },
409
+ imposed_by: str("Who imposes it (an authority code)"),
410
+ confirmation: { type: "string", enum: [...CONFIRMATIONS], description: "found = extracted, nobody checked; checked-by-agent; checked-by-human; contested" },
411
+ status: { type: "string", enum: [...STATUSES], description: "Is it met by the work today?" },
412
+ current: str("How things are today, especially where they differ from the rule"),
413
+ check: str("How to check that it's met"),
414
+ superseded_by: str("Id of the rule that replaced this one (the old rule stays for the record)"),
415
+ }, []),
416
+ async run(args, { project, agent }) {
417
+ registerOn(project);
418
+ return saveRule(project, args, agent.name);
419
+ },
420
+ };
421
+ const saveRuleAreaTool = {
422
+ name: "save_rule_area",
423
+ description: "Define or update an area of the rules register (a part of the project with its own rule ids) and its stages, in order.",
424
+ inputSchema: obj({
425
+ id: str("Short prefix for its rule ids, e.g. 'AP' → AP-001. Must differ from every source code."),
426
+ name: str("Name, e.g. 'Student — Submission'"),
427
+ group: str("Optional larger group it belongs to"),
428
+ description: str("What it covers"),
429
+ stages: { type: "array", items: obj({ id: str("e.g. 'A'"), name: str("e.g. 'Access'") }, ["name"]), description: "Its steps or sections, in order" },
430
+ }, ["id", "name"]),
431
+ async run(args, { project }) {
432
+ registerOn(project);
433
+ return saveArea(project, args);
434
+ },
435
+ };
436
+ const saveRuleSourceTool = {
437
+ name: "save_rule_source",
438
+ description: "Define or update a source rules are cited from (a document, a meeting, a decision), with the file when there is one.",
439
+ inputSchema: obj({
440
+ id: str("Short code used in citations, e.g. 'MA' or 'D38'. Must differ from every area prefix."),
441
+ name: str("e.g. 'Student manual 2026'"),
442
+ file: str("The file, relative to the project folder (so the human can open it at the cited place)"),
443
+ authority: str("Code of who stands behind it, e.g. 'EC'"),
444
+ authority_name: str("Name of that authority, the first time you use its code"),
445
+ }, ["id", "name"]),
446
+ async run(args, { project }) {
447
+ registerOn(project);
448
+ return saveSource(project, args);
449
+ },
450
+ };
360
451
  const COMMON = [
452
+ viewImageTool,
453
+ listRulesTool,
454
+ saveRuleTool,
455
+ saveRuleAreaTool,
456
+ saveRuleSourceTool,
361
457
  listConnections,
362
458
  remoteExec,
363
459
  remoteUpload,
@@ -416,12 +512,15 @@ function withInbox(tool) {
416
512
  }
417
513
  const arrived = await ctx.team.takeInbox(ctx.agent).catch(() => []);
418
514
  if (arrived.length === 0) {
419
- if (result.startsWith("Error: "))
515
+ if (typeof result === "string" && result.startsWith("Error: "))
420
516
  throw new Error(result.slice(7));
421
517
  return result;
422
518
  }
519
+ const inbox = `📬 Messages that arrived while you were working (already delivered — they won't be repeated):\n\n${arrived.join("\n\n---\n\n")}`;
520
+ if (typeof result !== "string")
521
+ return { content: [...result.content, { type: "text", text: inbox }] };
423
522
  const header = tool === checkMessages ? "" : `${result}\n\n`;
424
- return `${header}📬 Messages that arrived while you were working (already delivered — they won't be repeated):\n\n${arrived.join("\n\n---\n\n")}`;
523
+ return `${header}${inbox}`;
425
524
  },
426
525
  };
427
526
  }
@@ -58,6 +58,22 @@ export const AGENT_UPDATES = [
58
58
  "with search({ namespace: \"symbio\" }). Never conclude they're gone without calling one; if a call really fails, tell the " +
59
59
  "human what the error said.",
60
60
  },
61
+ {
62
+ id: "2026-11-05-rules-register",
63
+ text: "Rules register: a project can keep a register of its rules (requirements, decisions, constraints), each with its source, " +
64
+ "a literal excerpt, who imposes it, how confirmed it is and whether the work meets it; the human browses it in the Docs tab. " +
65
+ "It's on only when the human turns it on in the project's Settings (new projects have it on by default); then your " +
66
+ "instructions explain the tools (list_rules, save_rule, save_rule_area, save_rule_source). Until then, nothing changes.",
67
+ },
68
+ {
69
+ id: "2026-11-05-conversation-size",
70
+ text: "Keep conversations small: whatever an agent reads stays in its conversation and is sent to the model again every turn. " +
71
+ "Reading several full-size images made a coordinator's conversation too large to send at all (\"Timed out reading request " +
72
+ "body\"), whatever the model. So reading image files directly is now refused: look at images with the new view_image tool " +
73
+ "(a scaled-down copy; ask for a crop to see details at full resolution). Read only the part of a big file you need, and " +
74
+ "leave reviewing many images to a helper. If a conversation still becomes too large, Symbio moves that agent to a fresh " +
75
+ "session with a handoff note instead of trying other models.",
76
+ },
61
77
  ];
62
78
  /** Entries a project hasn't been told about yet. */
63
79
  export function unseenUpdates(seen) {
@@ -115,6 +115,20 @@ export async function restoreWorkspace(project, agent) {
115
115
  await git(project.directory, "worktree", "add", agent.directory, agent.branch);
116
116
  return { directory: agent.directory, branch: agent.branch, base, reset: true };
117
117
  }
118
+ /**
119
+ * An active helper's folder that disappeared (deleted outside Symbio): recreate it from its
120
+ * branch, which keeps everything it committed. Unlike restoreWorkspace, the branch is never
121
+ * moved. Returns false when there was nothing to do.
122
+ */
123
+ export async function reattachWorkspace(project, agent) {
124
+ if (!agent.branch || existsSync(agent.directory) || !(await isGitRepo(project.directory)))
125
+ return false;
126
+ await git(project.directory, "worktree", "prune").catch(() => { });
127
+ const branchExists = await git(project.directory, "rev-parse", "--verify", "--quiet", agent.branch).then(() => true, () => false);
128
+ await fs.mkdir(path.dirname(agent.directory), { recursive: true });
129
+ await git(project.directory, "worktree", "add", ...(branchExists ? [agent.directory, agent.branch] : ["-b", agent.branch, agent.directory, "HEAD"]));
130
+ return true;
131
+ }
118
132
  export async function removeWorkspace(project, agent) {
119
133
  if (!agent.branch)
120
134
  return;
@@ -1 +1 @@
1
- @font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2)format("woff2-variations");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2)format("woff2-variations");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2)format("woff2-variations");unicode-range:U+1F??}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-wght-normal-CkhJZR-_.woff2)format("woff2-variations");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-wght-normal-Dx4kXJAl.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--bg:#0b0c0e;--bg-sunken:#08090a;--panel:#101114;--surface:#15161a;--surface-2:#1b1c21;--surface-hover:#202127;--border:#23252b;--border-strong:#30323a;--text:#ededef;--text-2:#a0a1ab;--text-3:#6c6d78;--accent:#6d6af5;--accent-hover:#7e7bf7;--accent-soft:#6d6af524;--accent-text:#aaa8ff;--green:#3fb27f;--green-soft:#3fb27f24;--amber:#d4a03a;--amber-soft:#d4a03a24;--red:#e5534b;--red-soft:#e5534b24;--blue:#4c8df6;--blue-soft:#4c8df624;--r-sm:4px;--r:6px;--r-lg:10px;--shadow-pop:0 12px 32px #00000073, 0 0 0 1px var(--border-strong);--font:"Inter Variable", Inter, "Segoe UI", system-ui, sans-serif;--mono:"JetBrains Mono", "Cascadia Code", Consolas, ui-monospace, monospace;font-family:var(--font);color:var(--text);background:var(--bg);--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;font-feature-settings:"cv11", "ss01";-webkit-font-smoothing:antialiased;font-size:13px;line-height:1.5}*{box-sizing:border-box}body{margin:0}a{color:inherit;text-decoration:none}h1,h2,h3{letter-spacing:-.015em;margin:0;font-weight:600}h1{font-size:20px}h2{font-size:15px}h3{font-size:13px}p{margin:0}code,pre,.mono{font-family:var(--mono);font-size:12px}:focus-visible{outline:2px solid var(--accent);outline-offset:1px}::selection{background:var(--accent-soft)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:#2a2c33 padding-box content-box;border:3px solid #0000;border-radius:10px}::-webkit-scrollbar-thumb:hover{background:#3a3c45 padding-box content-box;border:3px solid #0000}.muted{color:var(--text-2)}.subtle{color:var(--text-3)}.small{font-size:12px}.tnum{font-variant-numeric:tabular-nums}.grow{flex:1;min-width:0}.row{align-items:center;gap:8px;display:flex}.stack{flex-direction:column;gap:8px;display:flex}.spacer{flex:1}.center{text-align:center}.ellipsis{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.error{color:var(--red);background:var(--red-soft);border-radius:var(--r);border:1px solid #e5534b4d;padding:8px 12px;font-size:13px}.notice{color:var(--amber);background:var(--amber-soft);border-radius:var(--r);border:1px solid #d4a03a4d;padding:8px 12px;font-size:13px}.btn{border-radius:var(--r);border:1px solid var(--border-strong);background:var(--surface-2);height:30px;color:var(--text);font:inherit;cursor:pointer;white-space:nowrap;justify-content:center;align-items:center;gap:6px;padding:0 12px;font-size:13px;font-weight:500;transition:background .12s,border-color .12s,color .12s;display:inline-flex}.btn:hover:not(:disabled){background:var(--surface-hover);border-color:#3a3d46}.btn:disabled{opacity:.45;cursor:not-allowed}.btn svg{flex:none}.btn.primary{background:var(--accent);color:#fff;border-color:#0000}.btn.primary:hover:not(:disabled){background:var(--accent-hover)}.btn.ghost{color:var(--text-2);background:0 0;border-color:#0000}.btn.ghost:hover:not(:disabled){background:var(--surface-2);color:var(--text)}.btn.danger{color:var(--red);background:0 0;border-color:#e5534b59}.btn.danger:hover:not(:disabled){background:var(--red-soft)}.btn.danger-solid{color:#fff;background:#c4392f;border-color:#0000}.btn.danger-solid:hover:not(:disabled){background:#d6453b}.btn.sm{height:26px;padding:0 9px;font-size:12px}.btn.icon{width:30px;padding:0}.btn.icon.sm{width:26px}.btn.icon.xs{width:20px;height:20px;color:var(--text-3)}.btn.icon.xs:hover{color:var(--text)}.title-input{max-width:260px;height:24px;padding:0 6px;font-weight:600}.btn.block{width:100%}.link{color:var(--accent-text);font:inherit;cursor:pointer;background:0 0;border:none;padding:0}.link:hover{text-decoration:underline}input,textarea,select{background:var(--bg-sunken);border:1px solid var(--border-strong);color:var(--text);border-radius:var(--r);font:inherit;outline:none;padding:7px 10px;font-size:13px;transition:border-color .12s,box-shadow .12s}input::placeholder,textarea::placeholder{color:var(--text-3)}input:focus,textarea:focus,select:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}textarea{resize:vertical;line-height:1.5}input[type=checkbox],input[type=radio]{accent-color:var(--accent);margin:0}.field{flex-direction:column;gap:6px;display:flex}.field>span{color:var(--text-2);font-size:12px;font-weight:500}.field .hint{color:var(--text-3);font-size:12px}.field>.input-row{font-size:inherit;font-weight:inherit;gap:8px;display:flex}.input-row>input{flex:1;min-width:0}.input-row>.btn{flex-shrink:0}.field>.seg{align-self:flex-start}.field-row{gap:12px;display:flex}.field-row>.field{flex:1}.check{color:var(--text-2);cursor:pointer;align-items:center;gap:6px;font-size:12px;display:inline-flex}.seg{background:var(--bg-sunken);border:1px solid var(--border-strong);border-radius:var(--r);gap:2px;padding:2px;display:inline-flex}.seg button{border-radius:var(--r-sm);height:24px;color:var(--text-2);font:inherit;cursor:pointer;background:0 0;border:none;padding:0 10px;font-size:12px;font-weight:500}.seg button:hover{color:var(--text)}.seg button.on{background:var(--surface-hover);color:var(--text);box-shadow:0 0 0 1px var(--border-strong)}.choice{border:1px solid var(--border-strong);border-radius:var(--r);cursor:pointer;align-items:flex-start;gap:10px;padding:10px 12px;transition:border-color .12s,background .12s;display:flex}.choice:hover{border-color:#3a3d46}.choice:has(input:checked){background:var(--accent-soft);border-color:#6d6af599}.choice input{margin-top:3px}.choice-body{flex-direction:column;gap:2px;display:flex}.choice-title{align-items:center;gap:6px;font-weight:500;display:flex}.choice-desc{color:var(--text-2);font-size:12px}.tag{border-radius:var(--r-sm);height:20px;color:var(--text-2);background:var(--surface-2);border:1px solid var(--border);white-space:nowrap;align-items:center;gap:4px;padding:0 7px;font-size:11px;font-weight:500;display:inline-flex}.tag svg{width:11px;height:11px}.tag.accent{color:var(--accent-text);background:var(--accent-soft);border-color:#0000}.tag.green{color:var(--green);background:var(--green-soft);border-color:#0000}.tag.amber{color:var(--amber);background:var(--amber-soft);border-color:#0000}.tag.red{color:var(--red);background:var(--red-soft);border-color:#0000}.tag.blue{color:var(--blue);background:var(--blue-soft);border-color:#0000}.dot{background:var(--text-3);border-radius:50%;flex:none;width:7px;height:7px;display:inline-block;position:relative}.dot.idle{background:var(--text-3)}.dot.busy{background:var(--green)}.dot.busy:after{content:"";border:1.5px solid var(--green);opacity:0;border-radius:50%;animation:1.8s ease-out infinite ping;position:absolute;inset:-3px}.dot.waiting{background:var(--amber)}.dot.stuck,.dot.error{background:var(--red)}.dot.stopped{border:1.5px solid var(--text-3);background:0 0}@keyframes ping{0%{opacity:.8;transform:scale(.6)}to{opacity:0;transform:scale(1.9)}}.avatar{color:#fff;text-transform:uppercase;letter-spacing:0;border-radius:6px;flex:none;justify-content:center;align-items:center;width:24px;height:24px;font-size:11px;font-weight:600;display:inline-flex;position:relative}.avatar.sm{border-radius:4px;width:18px;height:18px;font-size:9px}.avatar.lg{border-radius:8px;width:30px;height:30px;font-size:13px}.avatar .dot{width:9px;height:9px;box-shadow:0 0 0 2px var(--panel);position:absolute;bottom:-3px;right:-3px}.avatar.human,.avatar.system{background:var(--surface-hover);color:var(--text-2)}.kbd{font-family:var(--mono);border-radius:var(--r-sm);border:1px solid var(--border-strong);color:var(--text-2);padding:1px 5px;font-size:11px}.app{flex-direction:column;height:100vh;display:flex}.topbar{border-bottom:1px solid var(--border);background:var(--panel);flex:none;align-items:center;gap:12px;height:48px;padding:0 14px 0 16px;display:flex}.remote-banner{background:var(--amber-soft);color:var(--amber);border-bottom:1px solid #d4a03a59;flex:none;align-items:center;gap:10px;padding:7px 14px 7px 16px;font-size:13px;display:flex}.remote-banner a{color:inherit;text-decoration:underline}.remote-banner .spacer{flex:1}.remote-code{letter-spacing:.08em;font-family:ui-monospace,monospace;font-weight:600}.remote-code.big{color:var(--text);font-size:22px}.brand{letter-spacing:-.01em;align-items:center;gap:9px;font-size:14px;font-weight:600;display:flex}.brand-logo{flex:none;width:22px;height:22px}.crumbs{color:var(--text-3);align-items:center;gap:6px;min-width:0;font-size:13px;display:flex}.crumbs a{color:var(--text-2)}.crumbs a:hover{color:var(--text)}.crumbs .current{color:var(--text);font-weight:500}.topbar-actions{align-items:center;gap:6px;margin-left:auto;display:flex}.runtime{border:1px solid var(--border);height:26px;color:var(--text-2);border-radius:999px;align-items:center;gap:7px;padding:0 10px;font-size:12px;display:inline-flex}.runtime .dot.running{background:var(--green)}.runtime .dot.starting{background:var(--amber)}.runtime .dot.crashed,.runtime .dot.stopped{background:var(--red)}.page{flex:1;min-height:0;overflow:auto}.page-inner{flex-direction:column;gap:24px;max-width:1040px;margin:0 auto;padding:32px 32px 64px;display:flex}.page-head{justify-content:space-between;align-items:flex-end;gap:16px;display:flex}.page-head p{color:var(--text-2);margin-top:4px}.page-title{align-items:center;gap:10px;display:flex}.page-title svg{color:var(--text-2)}.back{color:var(--text-2);cursor:pointer;font-size:13px;font:inherit;background:0 0;border:none;align-items:center;gap:6px;margin-bottom:14px;padding:0;display:inline-flex}.back:hover{color:var(--text)}.section{background:var(--panel);border:1px solid var(--border);border-radius:var(--r-lg)}.section-head{border-bottom:1px solid var(--border);justify-content:space-between;align-items:flex-start;gap:16px;padding:16px 18px;display:flex}.section-head p{color:var(--text-2);max-width:640px;margin-top:3px;font-size:12px}.section-body{padding:8px}.section-empty{text-align:center;color:var(--text-3);padding:28px 18px;font-size:13px}.list-row{border-radius:var(--r);align-items:center;gap:12px;padding:10px 12px;display:flex}.list-row:hover{background:var(--surface)}.list-row+.list-row{border-top:1px solid var(--border);border-radius:0}.list-row:hover+.list-row{border-top-color:#0000}.list-title{font-weight:500}.list-sub{color:var(--text-2);font-size:12px}.project-list{border:1px solid var(--border);border-radius:var(--r-lg);background:var(--panel);flex-direction:column;display:flex;overflow:visible}.project-row{color:inherit;grid-template-columns:minmax(0,1fr) auto auto auto;align-items:center;gap:20px;padding:14px 16px;transition:background .12s;display:grid}.project-row:first-child{border-radius:var(--r-lg) var(--r-lg) 0 0}.project-row:last-child{border-radius:0 0 var(--r-lg) var(--r-lg)}.project-row:only-child{border-radius:var(--r-lg)}.project-row+.project-row{border-top:1px solid var(--border)}.project-row:hover{background:var(--surface)}.project-name{align-items:center;gap:8px;font-size:14px;font-weight:600;display:flex}.project-dir{color:var(--text-3);font-size:12px;font-family:var(--mono);margin-top:2px}.avatar-stack{gap:3px;display:flex}.project-meta{color:var(--text-2);align-items:center;gap:6px;min-width:120px;font-size:12px;display:flex}.progress-mini{background:var(--surface-hover);border-radius:4px;width:70px;height:4px;overflow:hidden}.progress-mini>div{background:var(--green);border-radius:4px;height:100%}.empty{text-align:center;color:var(--text-2);flex-direction:column;align-items:center;gap:10px;padding:56px 20px;display:flex}.empty-icon{background:var(--surface);border:1px solid var(--border);width:44px;height:44px;color:var(--text-2);border-radius:12px;justify-content:center;align-items:center;margin-bottom:4px;display:flex}.empty h3{color:var(--text);font-size:14px}.locked{justify-content:center;align-items:center;max-width:460px;min-height:100vh;margin:0 auto;display:flex}.empty p{max-width:380px;font-size:13px}.backdrop{z-index:60;background:#0000008c;justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}.dialog{background:var(--panel);border:1px solid var(--border-strong);border-radius:12px;flex-direction:column;width:min(560px,100%);max-height:calc(100vh - 48px);display:flex;box-shadow:0 24px 64px #0000008c}.dialog.wide{width:min(880px,100%)}.dialog-head{align-items:center;gap:10px;padding:16px 18px 12px;display:flex}.dialog-head h2{flex:1}.dialog-sub{color:var(--text-2);margin-top:-6px;margin-bottom:8px;padding:0 18px;font-size:12px}.dialog-body{flex-direction:column;gap:14px;padding:8px 18px 16px;display:flex;overflow:auto}.dialog-foot{border-top:1px solid var(--border);justify-content:flex-end;align-items:center;gap:8px;padding:12px 18px;display:flex}.steps{color:var(--text-3);align-items:center;gap:6px;padding:0 18px 10px;font-size:12px;display:flex}.steps .step{align-items:center;gap:6px;display:flex}.steps .step-num{border:1px solid var(--border-strong);border-radius:50%;justify-content:center;align-items:center;width:18px;height:18px;font-size:11px;font-weight:600;display:inline-flex}.steps .step.on{color:var(--text)}.steps .step.on .step-num{background:var(--accent);border-color:var(--accent);color:#fff}.steps .step.done .step-num{background:var(--surface-hover);color:var(--text-2)}.steps .sep{background:var(--border-strong);width:18px;height:1px}.drawer-backdrop{z-index:50;background:#0006;justify-content:flex-end;display:flex;position:fixed;inset:0}.drawer{background:var(--panel);border-left:1px solid var(--border-strong);flex-direction:column;width:440px;max-width:94vw;height:100%;display:flex;box-shadow:-24px 0 48px #0006}.drawer-head{border-bottom:1px solid var(--border);align-items:center;gap:10px;padding:14px 16px;display:flex}.drawer-head h2{flex:1}.drawer-body{flex-direction:column;flex:1;gap:12px;padding:14px 16px;display:flex;overflow:auto}.menu{flex:none;position:relative}.menu-list{z-index:40;background:var(--surface);min-width:200px;box-shadow:var(--shadow-pop);border-radius:8px;flex-direction:column;padding:4px;display:flex;position:absolute;top:calc(100% + 4px);right:0}.menu-list button{text-align:left;color:var(--text);font:inherit;border-radius:var(--r-sm);cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:7px 9px;font-size:13px;display:flex}.menu-list button:hover{background:var(--surface-hover)}.menu-list button.danger{color:var(--red)}.menu-list svg{color:var(--text-2)}.menu-list button.danger svg{color:var(--red)}.project-view{grid-template-columns:248px minmax(0,1fr);height:100%;display:grid}.side{border-right:1px solid var(--border);background:var(--panel);flex-direction:column;min-height:0;display:flex}.side-scroll{flex-direction:column;flex:1;gap:18px;padding:10px 8px;display:flex;overflow:auto}.side-group-title{color:var(--text-3);letter-spacing:.02em;justify-content:space-between;align-items:center;padding:0 8px 6px;font-size:11px;font-weight:600;display:flex}.side-foot{border-top:1px solid var(--border);flex-direction:column;gap:8px;padding:10px 12px;display:flex}.usage-line{color:var(--text-2);cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:6px;padding:2px 0;font-family:inherit;font-size:12px;display:flex}.usage-line:hover{color:var(--text)}.usage-line svg{color:var(--text-3)}.usage-total{white-space:nowrap;flex-direction:column;flex:none;align-items:flex-end;gap:2px;display:flex}.usage-total strong{font-size:18px}.usage-table{border-collapse:collapse;width:100%;font-size:12px}.usage-table th{text-align:left;color:var(--text-3);border-bottom:1px solid var(--border);white-space:nowrap;padding:6px 8px;font-weight:500}.usage-table td{border-bottom:1px solid var(--border);white-space:nowrap;padding:6px 8px}.usage-table .num{text-align:right}.usage-table tfoot td{border-bottom:none;font-weight:600}.usage-table tr.muted td{color:var(--text-3)}.price-row{flex-wrap:wrap;gap:8px}.price-row>.btn{justify-content:center;min-width:64px}.price-row .list-sub.warn{color:var(--amber)}.price-field{color:var(--text-3);flex-direction:column;gap:2px;font-size:11px;display:flex}.price-field input{width:84px;height:28px;padding:0 6px;font-size:12px}.agent-row{border-radius:var(--r);width:100%;color:var(--text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:10px;padding:6px 8px;display:flex}.agent-row:hover{background:var(--surface)}.agent-row.active{background:var(--surface-2)}.agent-row .avatar .dot{box-shadow:0 0 0 2px var(--panel)}.agent-row:hover .avatar .dot,.agent-row.active .avatar .dot{box-shadow:0 0 0 2px var(--surface-2)}.agent-name{align-items:center;gap:6px;font-weight:500;display:flex}.agent-sub{color:var(--text-3);font-size:12px}.agent-sub.working{color:var(--green)}.agent-sub.waiting{color:var(--amber)}.agent-sub.problem{color:var(--red)}.stopped-toggle{color:var(--text-3);cursor:pointer;font-size:12px;font:inherit;background:0 0;border:none;align-items:center;gap:6px;padding:4px 8px;display:flex}.stopped-toggle:hover{color:var(--text-2)}.asset-row{border-radius:var(--r);align-items:center;gap:8px;padding:5px 8px;font-size:12px;display:flex}.asset-row:hover{background:var(--surface)}.asset-row svg{color:var(--text-3);flex:none}.asset-row.held svg{color:var(--amber)}.asset-name{color:var(--text);font-size:12px;font-weight:500}.asset-sub{color:var(--text-3);font-size:11px}.main{flex-direction:column;min-width:0;min-height:0;display:flex}.main-head{border-bottom:1px solid var(--border);flex:none;align-items:center;gap:4px;height:46px;padding:0 12px 0 8px;display:flex}.tabs{align-items:center;gap:2px;height:100%;display:flex}.tab{height:100%;color:var(--text-2);font:inherit;cursor:pointer;background:0 0;border:none;align-items:center;gap:7px;padding:0 10px;font-weight:500;display:inline-flex;position:relative}.tab:hover,.tab.active{color:var(--text)}.tab svg{color:var(--text-3)}.tab.active svg{color:var(--text-2)}.tab-underline{background:var(--text);border-radius:2px;height:2px;position:absolute;bottom:-1px;left:8px;right:8px}.tab .count{color:var(--text-3);font-variant-numeric:tabular-nums;font-size:11px}.tab-alert{background:var(--amber);color:#1a1405;border-radius:9px;align-items:center;gap:5px;height:18px;padding:0 7px;font-size:11px;font-weight:600;display:inline-flex}.tab-alert-dot{background:#1a1405;border-radius:50%;width:6px;height:6px;position:relative}.tab-alert-dot:after{content:"";background:#1a1405;border-radius:50%;animation:1.6s ease-out infinite ping;position:absolute;inset:0}.main-actions{align-items:center;gap:6px;margin-left:auto;display:flex}.needs-you{background:var(--amber-soft);height:28px;color:var(--amber);font:inherit;cursor:pointer;border:1px solid #d4a03a66;border-radius:999px;align-items:center;gap:7px;padding:0 10px;font-size:12px;font-weight:600;display:inline-flex}.needs-you:hover{background:#d4a03a38}.needs-you .count{background:var(--amber);color:#1a1405;border-radius:9px;justify-content:center;align-items:center;min-width:18px;height:18px;padding:0 5px;font-size:11px;display:inline-flex}.main-body{flex-direction:column;flex:1;min-height:0;display:flex}.banner{border-bottom:1px solid var(--border);flex:none;align-items:center;gap:12px;padding:9px 16px;font-size:13px;display:flex}.banner svg{flex:none}.banner.red{background:var(--red-soft);color:var(--text)}.banner.red svg{color:var(--red)}.banner.blue{background:var(--blue-soft)}.banner.blue svg{color:var(--blue)}.banner .muted{font-size:12px}.inbox-item{border:1px solid var(--border-strong);border-radius:var(--r-lg);background:var(--surface);flex-direction:column;gap:10px;padding:12px;display:flex}.inbox-item-head{align-items:center;gap:8px;font-size:13px;display:flex}.inbox-item-head .when{color:var(--text-3);margin-left:auto;font-size:11px}.inbox-kind{color:var(--text-3);text-transform:uppercase;letter-spacing:.04em;font-size:11px;font-weight:600}.command{background:var(--bg-sunken);border:1px solid var(--border);border-radius:var(--r);font-family:var(--mono);white-space:pre-wrap;word-break:break-word;max-height:180px;margin:0;padding:8px 10px;font-size:12px;overflow:auto}.inbox-reason{color:var(--text-2);font-size:12px}.inbox-actions{flex-wrap:wrap;gap:6px;display:flex}.inbox-empty{text-align:center;color:var(--text-3);padding:40px 10px}.session-note{border:1px dashed var(--border-strong);border-radius:var(--r);max-width:760px;color:var(--text-2);justify-content:space-between;align-items:center;gap:12px;margin:0 auto;padding:12px 14px;font-size:13px;display:flex}.chat{flex-direction:column;height:100%;min-height:0;display:flex}.chat-head{border-bottom:1px solid var(--border);align-items:center;gap:10px;padding:10px 20px;display:flex}.chat-head .title{font-weight:600}.chat-head .sub{color:var(--text-3);font-size:12px}.inline-select{field-sizing:content;border-radius:var(--r-sm);width:auto;height:auto;color:inherit;font:inherit;cursor:pointer;background:0 0;border:none;padding:0 2px}.inline-select:hover{color:var(--text);background:var(--surface-hover)}.inline-select:focus{box-shadow:none}.inline-select option{background:var(--panel);color:var(--text)}.chat-scroll{flex:1;padding:24px 24px 12px;overflow:auto}.chat-col{flex-direction:column;gap:18px;max-width:760px;margin:0 auto;display:flex}.chat-col>.load-older{align-self:center}.list-compact{flex-direction:column;gap:4px;display:flex}.msg-user{background:var(--surface-2);border:1px solid var(--border);white-space:pre-wrap;border-radius:12px 12px 4px;align-self:flex-end;max-width:82%;padding:9px 13px;font-size:14px;line-height:1.55}.msg-assistant{flex-direction:column;gap:8px;font-size:14px;line-height:1.65;display:flex}.msg-note{color:var(--text-3);text-align:center;justify-content:center;font-size:12px;line-height:1.5;display:flex}.msg-note>span{background:var(--panel);border:1px solid var(--border);border-radius:999px;max-width:88%;padding:4px 10px}.msg-agent{border:1px solid var(--border);border-radius:var(--r-lg);background:var(--panel);overflow:hidden}.msg-agent-head{border-bottom:1px solid var(--border);align-items:center;gap:8px;padding:8px 12px;font-size:12px;display:flex}.msg-agent-head strong{font-weight:600}.msg-agent-body{padding:10px 12px;font-size:13.5px}.msg-failure{color:var(--red);background:var(--red-soft);border-radius:var(--r);align-items:flex-start;gap:8px;padding:8px 12px;font-size:13px;display:flex}.msg-failure svg{flex:none;margin-top:2px}.md>:first-child{margin-top:0}.md>:last-child{margin-bottom:0}.md p{margin:0 0 10px}.md h1,.md h2,.md h3{margin:18px 0 8px}.md h1{font-size:18px}.md h2{font-size:16px}.md h3{font-size:14px}.md code{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--r-sm);padding:0 4px;font-size:.86em}.md pre{background:var(--bg-sunken);border:1px solid var(--border);border-radius:var(--r);padding:12px;overflow:auto}.md pre code{background:0 0;border:none;padding:0}.md ul,.md ol{margin:0 0 10px;padding-left:22px}.md li{margin:2px 0}.md table{border-collapse:collapse;margin:0 0 10px}.md th,.md td{border:1px solid var(--border-strong);padding:5px 9px}.md a{color:var(--accent-text)}.md blockquote{border-left:2px solid var(--border-strong);color:var(--text-2);margin:0 0 10px;padding-left:12px}.reasoning{color:var(--text-3);font-size:13px}.reasoning summary{cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:6px;list-style:none;display:inline-flex}.reasoning summary::-webkit-details-marker{display:none}.reasoning summary:hover{color:var(--text-2)}.reasoning-body{white-space:pre-wrap;border-left:2px solid var(--border-strong);margin-top:6px;padding:4px 0 4px 12px}.tool{border:1px solid var(--border);border-radius:var(--r);background:var(--panel);font-size:12px}.tool summary{cursor:pointer;color:var(--text-2);align-items:center;gap:8px;padding:6px 10px;list-style:none;display:flex}.tool summary::-webkit-details-marker{display:none}.tool summary:hover{color:var(--text)}.tool-name{color:var(--text);font-weight:500}.tool-arg{font-family:var(--mono);color:var(--text-3);text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.tool-state{flex:none;display:inline-flex}.tool-state.done{color:var(--green)}.tool-state.failed{color:var(--red)}.tool-io{border-top:1px solid var(--border);max-height:260px;font-family:var(--mono);white-space:pre-wrap;color:var(--text-2);margin:0;padding:10px;font-size:12px;overflow:auto}.tool-io.out{background:var(--bg-sunken)}.spin{animation:.9s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}.thinking{color:var(--text-3);align-items:center;gap:8px;font-size:13px;display:flex}.thinking.retrying{color:var(--amber)}.typing{gap:3px;display:inline-flex}.typing i{background:currentColor;border-radius:50%;width:5px;height:5px;animation:1.2s ease-in-out infinite typing}.typing i:nth-child(2){animation-delay:.15s}.typing i:nth-child(3){animation-delay:.3s}@keyframes typing{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}.chat-empty{text-align:center;color:var(--text-2);padding:56px 20px}.chat-empty h2{color:var(--text);margin-bottom:6px;font-size:18px}.composer-wrap{padding:8px 24px 18px}.composer{border:1px solid var(--border-strong);background:var(--surface);border-radius:12px;max-width:760px;margin:0 auto;transition:border-color .12s,box-shadow .12s}.composer:focus-within{border-color:#44465a;box-shadow:0 0 0 3px #6d6af514}.composer textarea{resize:none;width:100%;box-shadow:none;background:0 0;border:none;padding:12px 14px 4px;font-size:14px}.composer textarea:focus{box-shadow:none}.composer-bar{align-items:center;gap:8px;padding:6px 8px 8px 14px;display:flex}.composer-hint{color:var(--text-3);font-size:11px}.form-card{border-radius:var(--r-lg);background:var(--panel);border:1px solid #d4a03a73;overflow:hidden}.form-card-head{border-bottom:1px solid var(--border);background:var(--amber-soft);align-items:center;gap:8px;padding:10px 14px;font-size:13px;font-weight:600;display:flex}.form-card-head svg{color:var(--amber)}.form-card-body{flex-direction:column;gap:14px;padding:12px 14px;display:flex}.form-field-title{margin-bottom:8px;font-size:13px;font-weight:500}.form-options{flex-direction:column;gap:6px;display:flex}.form-option{text-align:left;background:var(--surface);border:1px solid var(--border-strong);color:var(--text);font:inherit;border-radius:var(--r);cursor:pointer;flex-direction:column;gap:2px;padding:9px 12px;display:flex}.form-option:hover{border-color:#3a3d46}.form-option.on{border-color:var(--accent);background:var(--accent-soft)}.form-option:disabled{opacity:.45;cursor:not-allowed}.form-field-desc{color:var(--text-2);margin:-4px 0 8px;font-size:13px}.form-option span{color:var(--text-2);font-size:12px}.kanban{flex-direction:column;height:100%;min-height:0;display:flex}.kanban-head{border-bottom:1px solid var(--border);align-items:center;gap:16px;padding:14px 20px;display:flex}.kanban-goal{flex:1;min-width:0}.kanban-goal-text{font-size:14px;font-weight:500}.kanban-goal-meta{color:var(--text-3);align-items:center;gap:8px;margin-top:4px;font-size:12px;display:flex}.progress{color:var(--text-2);flex:none;align-items:center;gap:10px;font-size:12px;display:flex}.progress-track{background:var(--surface-hover);border-radius:6px;width:160px;height:6px;overflow:hidden}.progress-fill{background:var(--green);border-radius:6px;height:100%}.plan-banner{border:1px solid var(--border-strong);border-radius:var(--r-lg);background:var(--surface);flex-direction:column;gap:10px;margin:12px 20px 0;padding:12px 14px;display:flex}.plan-banner-row{align-items:center;gap:10px;display:flex}.plan-banner-row textarea{flex:1}.columns{flex:1;grid-template-columns:repeat(5,minmax(190px,1fr));gap:10px;min-height:0;padding:14px 20px 16px;display:grid;overflow-x:auto}.column{border-radius:var(--r-lg);background:var(--panel);border:1px solid var(--border);flex-direction:column;min-height:0;display:flex}.column-head{color:var(--text-2);align-items:center;gap:8px;padding:10px 12px;font-size:12px;font-weight:600;display:flex}.column-head svg{color:var(--text-3)}.col-in-progress .column-head svg{color:var(--green)}.col-blocked .column-head svg{color:var(--red)}.col-review .column-head svg{color:var(--amber)}.col-done .column-head svg{color:var(--accent-text)}.column-count{color:var(--text-3);font-variant-numeric:tabular-nums;margin-left:auto;font-size:11px}.column-body{flex-direction:column;flex:1;gap:6px;padding:0 8px 8px;display:flex;overflow-y:auto}.column-empty{text-align:center;color:var(--text-3);padding:14px 6px;font-size:12px}.task-card{text-align:left;font:inherit;color:var(--text);background:var(--surface);border:1px solid var(--border);border-radius:var(--r);cursor:pointer;flex-direction:column;gap:7px;padding:10px;transition:border-color .12s,background .12s;display:flex}.task-card:hover{border-color:var(--border-strong);background:var(--surface-2)}.task-card.ts-done .task-title{color:var(--text-2)}.task-top{color:var(--text-3);align-items:center;gap:6px;font-size:11px;display:flex}.task-id{font-family:var(--mono);color:var(--text-3);font-size:11px}.task-title{font-size:13px;font-weight:500;line-height:1.4}.task-meta{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.task-bottom{color:var(--text-2);align-items:center;gap:6px;font-size:12px;display:flex}.task-bottom .subtle{align-items:center;gap:3px;margin-left:auto;font-size:11px;display:inline-flex}.task-detail-meta{grid-template-columns:110px 1fr;gap:6px 12px;font-size:12px;display:grid}.task-detail-meta dt{color:var(--text-3)}.task-detail-meta dd{flex-wrap:wrap;align-items:center;gap:6px;margin:0;display:flex}.history{flex-direction:column;gap:10px;display:flex}.history-item{gap:10px;font-size:12px;display:flex}.history-item .when{color:var(--text-3);font-variant-numeric:tabular-nums;flex:none;width:54px}.history-item .what{color:var(--text-2);white-space:pre-wrap}.history-item .what strong{color:var(--text);font-weight:500}.timeline{flex:1;overflow:auto}.timeline-inner{max-width:820px;margin:0 auto;padding:16px 24px 32px}.timeline-toolbar{border-bottom:1px solid var(--border);color:var(--text-2);align-items:center;gap:10px;padding:10px 24px;font-size:12px;display:flex}.event{border-bottom:1px solid var(--border);grid-template-columns:28px minmax(0,1fr);gap:10px;padding:10px 0;display:grid}.event:last-child{border-bottom:none}.event-head{color:var(--text-2);flex-wrap:wrap;align-items:center;gap:6px;font-size:12px;display:flex}.event-head strong{color:var(--text);font-weight:600}.event-head .when{color:var(--text-3);font-variant-numeric:tabular-nums;margin-left:auto}.event-body{margin-top:4px;font-size:13px}.event.quiet .event-body{color:var(--text-2);font-size:12px}.event.open{background:linear-gradient(90deg, var(--amber-soft), transparent 70%);border-radius:var(--r);margin-left:-8px;padding-left:8px}.reply{align-items:flex-end;gap:8px;margin-top:8px;display:flex}.reply textarea{resize:none;flex:1}.docs{grid-template-columns:240px minmax(0,1fr);height:100%;min-height:0;display:grid}.docs-list{border-right:1px solid var(--border);flex-direction:column;gap:1px;padding:10px 8px;display:flex;overflow:auto}.docs-item{text-align:left;color:var(--text-2);font:inherit;border-radius:var(--r);cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.docs-item svg{color:var(--text-3);flex:none}.docs-item:hover{background:var(--surface);color:var(--text)}.docs-item.active{background:var(--surface-2);color:var(--text)}.docs-item .grow{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.docs-item-time{color:var(--text-3);flex:none;font-size:11px}.docs-view{flex-direction:column;min-width:0;min-height:0;display:flex}.docs-toolbar{border-bottom:1px solid var(--border);align-items:center;gap:8px;padding:8px 16px;display:flex}.docs-toolbar code{color:var(--text-2)}.docs-body{flex:1;padding:24px 32px 48px;overflow:auto}.docs-body .md{max-width:760px;font-size:14px;line-height:1.7}.docs-editor{resize:none;width:100%;height:100%;min-height:420px;font-family:var(--mono);font-size:13px;line-height:1.6}.settings-scroll{flex:1;overflow:auto}.settings-inner{flex-direction:column;gap:20px;max-width:780px;padding:24px 28px 64px;display:flex}.conn-icon{background:var(--surface-2);border:1px solid var(--border-strong);width:32px;height:32px;color:var(--text-2);border-radius:8px;flex:none;justify-content:center;align-items:center;display:inline-flex}.conn-icon.sm{border-radius:5px;width:22px;height:22px}.conn-test{align-items:center;gap:5px;margin-top:2px;font-size:12px;display:inline-flex}.conn-test.ok{color:var(--green)}.conn-test.bad{color:var(--red)}.pick-row{border:1px solid var(--border-strong);border-radius:var(--r);align-items:center;gap:10px;padding:8px 10px;display:flex}.pick-row+.pick-row{margin-top:6px}.pick-row.on{background:var(--accent-soft);border-color:#6d6af580}.pick-main{cursor:pointer;flex:1;align-items:center;gap:10px;min-width:0;display:flex}.danger-zone{border-color:#e5534b4d}.model-picker{border:1px solid var(--border-strong);border-radius:var(--r-lg);overflow:hidden}.model-picker-head{border-bottom:1px solid var(--border);background:var(--surface);align-items:center;gap:10px;padding:8px 10px;display:flex}.model-picker-head input{flex:1;height:28px;padding:4px 8px}.model-summary{border-bottom:1px solid var(--border);color:var(--text-2);flex-wrap:wrap;align-items:center;gap:6px;padding:8px 12px;font-size:12px;display:flex}.model-groups{max-height:300px;padding:4px;overflow:auto}.model-group-title{background:var(--panel);color:var(--text-3);z-index:1;padding:8px 8px 4px;font-size:11px;font-weight:600;position:sticky;top:0}.model-row{border-radius:var(--r-sm);cursor:pointer;align-items:center;gap:8px;padding:5px 8px;font-size:13px;display:flex}.model-row:hover{background:var(--surface)}.model-row.on{background:var(--accent-soft)}.model-row .check-box{border:1px solid var(--border-strong);color:#fff;border-radius:4px;flex:none;justify-content:center;align-items:center;width:15px;height:15px;display:inline-flex}.model-row.on .check-box{background:var(--accent);border-color:var(--accent)}.model-name{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lead-btn{color:var(--text-3);cursor:pointer;border-radius:var(--r-sm);background:0 0;border:none;padding:2px;display:inline-flex}.lead-btn:hover{color:var(--text);background:var(--surface-hover)}.lead-btn.on{color:var(--amber)}.folder-summary{border:1px solid var(--border-strong);border-radius:var(--r-lg);background:var(--surface);flex-direction:column;gap:10px;padding:12px 14px;display:flex}.folder-headline{flex-wrap:wrap;align-items:center;gap:8px;font-size:13px;display:flex}.folder-headline svg{color:var(--text-2)}.kind-bar{background:var(--surface-hover);border-radius:6px;gap:2px;height:6px;display:flex;overflow:hidden}.kind-seg{height:100%}.k0{background:#6d6af5}.k1{background:#3fb27f}.k2{background:#d4a03a}.k3{background:#c76bd6}.k4{background:#4c8df6}.k5{background:#6c6d78}.kind-legend{color:var(--text-2);flex-wrap:wrap;gap:4px 14px;font-size:12px;display:flex}.kind-legend i{border-radius:2px;width:8px;height:8px;margin-right:6px;display:inline-block}.top-level{color:var(--text-3);font-size:12px;font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.btn.ghost.active{color:var(--text);background:var(--surface-2)}.folder-browser{border:1px solid var(--border-strong);border-radius:var(--r);background:var(--bg-sunken);flex-direction:column;display:flex;overflow:hidden}.folder-browser-head{border-bottom:1px solid var(--border);align-items:center;gap:8px;padding:8px;display:flex}.folder-browser-path{min-width:0;color:var(--text);flex:1;font-size:12px}.folder-browser-places{border-bottom:1px solid var(--border);flex-wrap:wrap;gap:4px;padding:6px 8px;display:flex}.folder-browser-list{flex-direction:column;max-height:240px;padding:4px;display:flex;overflow:auto}.folder-browser-item{color:var(--text);font:inherit;text-align:left;border-radius:var(--r-sm);cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.folder-browser-item:hover{background:var(--surface-hover)}.folder-browser-item svg{color:var(--text-3);flex:none}.folder-browser-foot{border-top:1px solid var(--border);align-items:center;gap:8px;padding:8px;display:flex}.folder-browser-foot .spacer{flex:1}
1
+ @font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2)format("woff2-variations");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2)format("woff2-variations");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2)format("woff2-variations");unicode-range:U+1F??}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-wght-normal-CkhJZR-_.woff2)format("woff2-variations");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-wght-normal-Dx4kXJAl.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--bg:#0b0c0e;--bg-sunken:#08090a;--panel:#101114;--surface:#15161a;--surface-2:#1b1c21;--surface-hover:#202127;--border:#23252b;--border-strong:#30323a;--text:#ededef;--text-2:#a0a1ab;--text-3:#6c6d78;--accent:#6d6af5;--accent-hover:#7e7bf7;--accent-soft:#6d6af524;--accent-text:#aaa8ff;--green:#3fb27f;--green-soft:#3fb27f24;--amber:#d4a03a;--amber-soft:#d4a03a24;--red:#e5534b;--red-soft:#e5534b24;--blue:#4c8df6;--blue-soft:#4c8df624;--r-sm:4px;--r:6px;--r-lg:10px;--shadow-pop:0 12px 32px #00000073, 0 0 0 1px var(--border-strong);--font:"Inter Variable", Inter, "Segoe UI", system-ui, sans-serif;--mono:"JetBrains Mono", "Cascadia Code", Consolas, ui-monospace, monospace;font-family:var(--font);color:var(--text);background:var(--bg);--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;font-feature-settings:"cv11", "ss01";-webkit-font-smoothing:antialiased;font-size:13px;line-height:1.5}*{box-sizing:border-box}body{margin:0}a{color:inherit;text-decoration:none}h1,h2,h3{letter-spacing:-.015em;margin:0;font-weight:600}h1{font-size:20px}h2{font-size:15px}h3{font-size:13px}p{margin:0}code,pre,.mono{font-family:var(--mono);font-size:12px}:focus-visible{outline:2px solid var(--accent);outline-offset:1px}::selection{background:var(--accent-soft)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:#2a2c33 padding-box content-box;border:3px solid #0000;border-radius:10px}::-webkit-scrollbar-thumb:hover{background:#3a3c45 padding-box content-box;border:3px solid #0000}.muted{color:var(--text-2)}.subtle{color:var(--text-3)}.small{font-size:12px}.tnum{font-variant-numeric:tabular-nums}.grow{flex:1;min-width:0}.row{align-items:center;gap:8px;display:flex}.stack{flex-direction:column;gap:8px;display:flex}.spacer{flex:1}.center{text-align:center}.ellipsis{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.error{color:var(--red);background:var(--red-soft);border-radius:var(--r);border:1px solid #e5534b4d;padding:8px 12px;font-size:13px}.notice{color:var(--amber);background:var(--amber-soft);border-radius:var(--r);border:1px solid #d4a03a4d;padding:8px 12px;font-size:13px}.btn{border-radius:var(--r);border:1px solid var(--border-strong);background:var(--surface-2);height:30px;color:var(--text);font:inherit;cursor:pointer;white-space:nowrap;justify-content:center;align-items:center;gap:6px;padding:0 12px;font-size:13px;font-weight:500;transition:background .12s,border-color .12s,color .12s;display:inline-flex}.btn:hover:not(:disabled){background:var(--surface-hover);border-color:#3a3d46}.btn:disabled{opacity:.45;cursor:not-allowed}.btn svg{flex:none}.btn.primary{background:var(--accent);color:#fff;border-color:#0000}.btn.primary:hover:not(:disabled){background:var(--accent-hover)}.btn.ghost{color:var(--text-2);background:0 0;border-color:#0000}.btn.ghost:hover:not(:disabled){background:var(--surface-2);color:var(--text)}.btn.danger{color:var(--red);background:0 0;border-color:#e5534b59}.btn.danger:hover:not(:disabled){background:var(--red-soft)}.btn.danger-solid{color:#fff;background:#c4392f;border-color:#0000}.btn.danger-solid:hover:not(:disabled){background:#d6453b}.btn.sm{height:26px;padding:0 9px;font-size:12px}.btn.icon{width:30px;padding:0}.btn.icon.sm{width:26px}.btn.icon.xs{width:20px;height:20px;color:var(--text-3)}.btn.icon.xs:hover{color:var(--text)}.title-input{max-width:260px;height:24px;padding:0 6px;font-weight:600}.btn.block{width:100%}.link{color:var(--accent-text);font:inherit;cursor:pointer;background:0 0;border:none;padding:0}.link:hover{text-decoration:underline}input,textarea,select{background:var(--bg-sunken);border:1px solid var(--border-strong);color:var(--text);border-radius:var(--r);font:inherit;outline:none;padding:7px 10px;font-size:13px;transition:border-color .12s,box-shadow .12s}input::placeholder,textarea::placeholder{color:var(--text-3)}input:focus,textarea:focus,select:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}textarea{resize:vertical;line-height:1.5}input[type=checkbox],input[type=radio]{accent-color:var(--accent);margin:0}.field{flex-direction:column;gap:6px;display:flex}.field>span{color:var(--text-2);font-size:12px;font-weight:500}.field .hint{color:var(--text-3);font-size:12px}.field>.input-row{font-size:inherit;font-weight:inherit;gap:8px;display:flex}.input-row>input{flex:1;min-width:0}.input-row>.btn{flex-shrink:0}.field>.seg{align-self:flex-start}.field-row{gap:12px;display:flex}.field-row>.field{flex:1}.check{color:var(--text-2);cursor:pointer;align-items:center;gap:6px;font-size:12px;display:inline-flex}.seg{background:var(--bg-sunken);border:1px solid var(--border-strong);border-radius:var(--r);gap:2px;padding:2px;display:inline-flex}.seg button{border-radius:var(--r-sm);height:24px;color:var(--text-2);font:inherit;cursor:pointer;background:0 0;border:none;padding:0 10px;font-size:12px;font-weight:500}.seg button:hover{color:var(--text)}.seg button.on{background:var(--surface-hover);color:var(--text);box-shadow:0 0 0 1px var(--border-strong)}.choice{border:1px solid var(--border-strong);border-radius:var(--r);cursor:pointer;align-items:flex-start;gap:10px;padding:10px 12px;transition:border-color .12s,background .12s;display:flex}.choice:hover{border-color:#3a3d46}.choice:has(input:checked){background:var(--accent-soft);border-color:#6d6af599}.choice input{margin-top:3px}.choice-body{flex-direction:column;gap:2px;display:flex}.choice-title{align-items:center;gap:6px;font-weight:500;display:flex}.choice-desc{color:var(--text-2);font-size:12px}.tag{border-radius:var(--r-sm);height:20px;color:var(--text-2);background:var(--surface-2);border:1px solid var(--border);white-space:nowrap;align-items:center;gap:4px;padding:0 7px;font-size:11px;font-weight:500;display:inline-flex}.tag svg{width:11px;height:11px}.tag.accent{color:var(--accent-text);background:var(--accent-soft);border-color:#0000}.tag.green{color:var(--green);background:var(--green-soft);border-color:#0000}.tag.amber{color:var(--amber);background:var(--amber-soft);border-color:#0000}.tag.red{color:var(--red);background:var(--red-soft);border-color:#0000}.tag.blue{color:var(--blue);background:var(--blue-soft);border-color:#0000}.dot{background:var(--text-3);border-radius:50%;flex:none;width:7px;height:7px;display:inline-block;position:relative}.dot.idle{background:var(--text-3)}.dot.busy{background:var(--green)}.dot.busy:after{content:"";border:1.5px solid var(--green);opacity:0;border-radius:50%;animation:1.8s ease-out infinite ping;position:absolute;inset:-3px}.dot.waiting{background:var(--amber)}.dot.stuck,.dot.error{background:var(--red)}.dot.stopped{border:1.5px solid var(--text-3);background:0 0}@keyframes ping{0%{opacity:.8;transform:scale(.6)}to{opacity:0;transform:scale(1.9)}}.avatar{color:#fff;text-transform:uppercase;letter-spacing:0;border-radius:6px;flex:none;justify-content:center;align-items:center;width:24px;height:24px;font-size:11px;font-weight:600;display:inline-flex;position:relative}.avatar.sm{border-radius:4px;width:18px;height:18px;font-size:9px}.avatar.lg{border-radius:8px;width:30px;height:30px;font-size:13px}.avatar .dot{width:9px;height:9px;box-shadow:0 0 0 2px var(--panel);position:absolute;bottom:-3px;right:-3px}.avatar.human,.avatar.system{background:var(--surface-hover);color:var(--text-2)}.kbd{font-family:var(--mono);border-radius:var(--r-sm);border:1px solid var(--border-strong);color:var(--text-2);padding:1px 5px;font-size:11px}.app{flex-direction:column;height:100vh;display:flex}.topbar{border-bottom:1px solid var(--border);background:var(--panel);flex:none;align-items:center;gap:12px;height:48px;padding:0 14px 0 16px;display:flex}.remote-banner{background:var(--amber-soft);color:var(--amber);border-bottom:1px solid #d4a03a59;flex:none;align-items:center;gap:10px;padding:7px 14px 7px 16px;font-size:13px;display:flex}.remote-banner a{color:inherit;text-decoration:underline}.remote-banner .spacer{flex:1}.remote-code{letter-spacing:.08em;font-family:ui-monospace,monospace;font-weight:600}.remote-code.big{color:var(--text);font-size:22px}.brand{letter-spacing:-.01em;align-items:center;gap:9px;font-size:14px;font-weight:600;display:flex}.brand-logo{flex:none;width:22px;height:22px}.crumbs{color:var(--text-3);align-items:center;gap:6px;min-width:0;font-size:13px;display:flex}.crumbs a{color:var(--text-2)}.crumbs a:hover{color:var(--text)}.crumbs .current{color:var(--text);font-weight:500}.topbar-actions{align-items:center;gap:6px;margin-left:auto;display:flex}.runtime{border:1px solid var(--border);height:26px;color:var(--text-2);border-radius:999px;align-items:center;gap:7px;padding:0 10px;font-size:12px;display:inline-flex}.runtime .dot.running{background:var(--green)}.runtime .dot.starting{background:var(--amber)}.runtime .dot.crashed,.runtime .dot.stopped{background:var(--red)}.page{flex:1;min-height:0;overflow:auto}.page-inner{flex-direction:column;gap:24px;max-width:1040px;margin:0 auto;padding:32px 32px 64px;display:flex}.page-head{justify-content:space-between;align-items:flex-end;gap:16px;display:flex}.page-head p{color:var(--text-2);margin-top:4px}.page-title{align-items:center;gap:10px;display:flex}.page-title svg{color:var(--text-2)}.back{color:var(--text-2);cursor:pointer;font-size:13px;font:inherit;background:0 0;border:none;align-items:center;gap:6px;margin-bottom:14px;padding:0;display:inline-flex}.back:hover{color:var(--text)}.section{background:var(--panel);border:1px solid var(--border);border-radius:var(--r-lg)}.section-head{border-bottom:1px solid var(--border);justify-content:space-between;align-items:flex-start;gap:16px;padding:16px 18px;display:flex}.section-head p{color:var(--text-2);max-width:640px;margin-top:3px;font-size:12px}.section-body{padding:8px}.section-empty{text-align:center;color:var(--text-3);padding:28px 18px;font-size:13px}.list-row{border-radius:var(--r);align-items:center;gap:12px;padding:10px 12px;display:flex}.list-row:hover{background:var(--surface)}.list-row+.list-row{border-top:1px solid var(--border);border-radius:0}.list-row:hover+.list-row{border-top-color:#0000}.list-title{font-weight:500}.list-sub{color:var(--text-2);font-size:12px}.project-list{border:1px solid var(--border);border-radius:var(--r-lg);background:var(--panel);flex-direction:column;display:flex;overflow:visible}.project-row{color:inherit;grid-template-columns:minmax(0,1fr) auto auto auto;align-items:center;gap:20px;padding:14px 16px;transition:background .12s;display:grid}.project-row:first-child{border-radius:var(--r-lg) var(--r-lg) 0 0}.project-row:last-child{border-radius:0 0 var(--r-lg) var(--r-lg)}.project-row:only-child{border-radius:var(--r-lg)}.project-row+.project-row{border-top:1px solid var(--border)}.project-row:hover{background:var(--surface)}.project-name{align-items:center;gap:8px;font-size:14px;font-weight:600;display:flex}.project-dir{color:var(--text-3);font-size:12px;font-family:var(--mono);margin-top:2px}.avatar-stack{gap:3px;display:flex}.project-meta{color:var(--text-2);align-items:center;gap:6px;min-width:120px;font-size:12px;display:flex}.progress-mini{background:var(--surface-hover);border-radius:4px;width:70px;height:4px;overflow:hidden}.progress-mini>div{background:var(--green);border-radius:4px;height:100%}.empty{text-align:center;color:var(--text-2);flex-direction:column;align-items:center;gap:10px;padding:56px 20px;display:flex}.empty-icon{background:var(--surface);border:1px solid var(--border);width:44px;height:44px;color:var(--text-2);border-radius:12px;justify-content:center;align-items:center;margin-bottom:4px;display:flex}.empty h3{color:var(--text);font-size:14px}.locked{justify-content:center;align-items:center;max-width:460px;min-height:100vh;margin:0 auto;display:flex}.empty p{max-width:380px;font-size:13px}.backdrop{z-index:60;background:#0000008c;justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}.dialog{background:var(--panel);border:1px solid var(--border-strong);border-radius:12px;flex-direction:column;width:min(560px,100%);max-height:calc(100vh - 48px);display:flex;box-shadow:0 24px 64px #0000008c}.dialog.wide{width:min(880px,100%)}.dialog-head{align-items:center;gap:10px;padding:16px 18px 12px;display:flex}.dialog-head h2{flex:1}.dialog-sub{color:var(--text-2);margin-top:-6px;margin-bottom:8px;padding:0 18px;font-size:12px}.dialog-body{flex-direction:column;gap:14px;padding:8px 18px 16px;display:flex;overflow:auto}.dialog-foot{border-top:1px solid var(--border);justify-content:flex-end;align-items:center;gap:8px;padding:12px 18px;display:flex}.steps{color:var(--text-3);align-items:center;gap:6px;padding:0 18px 10px;font-size:12px;display:flex}.steps .step{align-items:center;gap:6px;display:flex}.steps .step-num{border:1px solid var(--border-strong);border-radius:50%;justify-content:center;align-items:center;width:18px;height:18px;font-size:11px;font-weight:600;display:inline-flex}.steps .step.on{color:var(--text)}.steps .step.on .step-num{background:var(--accent);border-color:var(--accent);color:#fff}.steps .step.done .step-num{background:var(--surface-hover);color:var(--text-2)}.steps .sep{background:var(--border-strong);width:18px;height:1px}.drawer-backdrop{z-index:50;background:#0006;justify-content:flex-end;display:flex;position:fixed;inset:0}.drawer{background:var(--panel);border-left:1px solid var(--border-strong);flex-direction:column;width:440px;max-width:94vw;height:100%;display:flex;box-shadow:-24px 0 48px #0006}.drawer-head{border-bottom:1px solid var(--border);align-items:center;gap:10px;padding:14px 16px;display:flex}.drawer-head h2{flex:1}.drawer-body{flex-direction:column;flex:1;gap:12px;padding:14px 16px;display:flex;overflow:auto}.menu{flex:none;position:relative}.menu-list{z-index:40;background:var(--surface);min-width:200px;box-shadow:var(--shadow-pop);border-radius:8px;flex-direction:column;padding:4px;display:flex;position:absolute;top:calc(100% + 4px);right:0}.menu-list button{text-align:left;color:var(--text);font:inherit;border-radius:var(--r-sm);cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:7px 9px;font-size:13px;display:flex}.menu-list button:hover{background:var(--surface-hover)}.menu-list button.danger{color:var(--red)}.menu-list svg{color:var(--text-2)}.menu-list button.danger svg{color:var(--red)}.project-view{grid-template-columns:248px minmax(0,1fr);height:100%;display:grid}.side{border-right:1px solid var(--border);background:var(--panel);flex-direction:column;min-height:0;display:flex}.side-scroll{flex-direction:column;flex:1;gap:18px;padding:10px 8px;display:flex;overflow:auto}.side-group-title{color:var(--text-3);letter-spacing:.02em;justify-content:space-between;align-items:center;padding:0 8px 6px;font-size:11px;font-weight:600;display:flex}.side-foot{border-top:1px solid var(--border);flex-direction:column;gap:8px;padding:10px 12px;display:flex}.usage-line{color:var(--text-2);cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:6px;padding:2px 0;font-family:inherit;font-size:12px;display:flex}.usage-line:hover{color:var(--text)}.usage-line svg{color:var(--text-3)}.usage-total{white-space:nowrap;flex-direction:column;flex:none;align-items:flex-end;gap:2px;display:flex}.usage-total strong{font-size:18px}.usage-table{border-collapse:collapse;width:100%;font-size:12px}.usage-table th{text-align:left;color:var(--text-3);border-bottom:1px solid var(--border);white-space:nowrap;padding:6px 8px;font-weight:500}.usage-table td{border-bottom:1px solid var(--border);white-space:nowrap;padding:6px 8px}.usage-table .num{text-align:right}.usage-table tfoot td{border-bottom:none;font-weight:600}.usage-table tr.muted td{color:var(--text-3)}.price-row{flex-wrap:wrap;gap:8px}.price-row>.btn{justify-content:center;min-width:64px}.price-row .list-sub.warn{color:var(--amber)}.price-field{color:var(--text-3);flex-direction:column;gap:2px;font-size:11px;display:flex}.price-field input{width:84px;height:28px;padding:0 6px;font-size:12px}.agent-row{border-radius:var(--r);width:100%;color:var(--text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:10px;padding:6px 8px;display:flex}.agent-row:hover{background:var(--surface)}.agent-row.active{background:var(--surface-2)}.agent-row .avatar .dot{box-shadow:0 0 0 2px var(--panel)}.agent-row:hover .avatar .dot,.agent-row.active .avatar .dot{box-shadow:0 0 0 2px var(--surface-2)}.agent-name{align-items:center;gap:6px;font-weight:500;display:flex}.agent-sub{color:var(--text-3);font-size:12px}.agent-sub.working{color:var(--green)}.agent-sub.waiting{color:var(--amber)}.agent-sub.problem{color:var(--red)}.stopped-toggle{color:var(--text-3);cursor:pointer;font-size:12px;font:inherit;background:0 0;border:none;align-items:center;gap:6px;padding:4px 8px;display:flex}.stopped-toggle:hover{color:var(--text-2)}.asset-row{border-radius:var(--r);align-items:center;gap:8px;padding:5px 8px;font-size:12px;display:flex}.asset-row:hover{background:var(--surface)}.asset-row svg{color:var(--text-3);flex:none}.asset-row.held svg{color:var(--amber)}.asset-name{color:var(--text);font-size:12px;font-weight:500}.asset-sub{color:var(--text-3);font-size:11px}.main{flex-direction:column;min-width:0;min-height:0;display:flex}.main-head{border-bottom:1px solid var(--border);flex:none;align-items:center;gap:4px;height:46px;padding:0 12px 0 8px;display:flex}.tabs{align-items:center;gap:2px;height:100%;display:flex}.tab{height:100%;color:var(--text-2);font:inherit;cursor:pointer;background:0 0;border:none;align-items:center;gap:7px;padding:0 10px;font-weight:500;display:inline-flex;position:relative}.tab:hover,.tab.active{color:var(--text)}.tab svg{color:var(--text-3)}.tab.active svg{color:var(--text-2)}.tab-underline{background:var(--text);border-radius:2px;height:2px;position:absolute;bottom:-1px;left:8px;right:8px}.tab .count{color:var(--text-3);font-variant-numeric:tabular-nums;font-size:11px}.tab-alert{background:var(--amber);color:#1a1405;border-radius:9px;align-items:center;gap:5px;height:18px;padding:0 7px;font-size:11px;font-weight:600;display:inline-flex}.tab-alert-dot{background:#1a1405;border-radius:50%;width:6px;height:6px;position:relative}.tab-alert-dot:after{content:"";background:#1a1405;border-radius:50%;animation:1.6s ease-out infinite ping;position:absolute;inset:0}.main-actions{align-items:center;gap:6px;margin-left:auto;display:flex}.needs-you{background:var(--amber-soft);height:28px;color:var(--amber);font:inherit;cursor:pointer;border:1px solid #d4a03a66;border-radius:999px;align-items:center;gap:7px;padding:0 10px;font-size:12px;font-weight:600;display:inline-flex}.needs-you:hover{background:#d4a03a38}.needs-you .count{background:var(--amber);color:#1a1405;border-radius:9px;justify-content:center;align-items:center;min-width:18px;height:18px;padding:0 5px;font-size:11px;display:inline-flex}.main-body{flex-direction:column;flex:1;min-height:0;display:flex}.banner{border-bottom:1px solid var(--border);flex:none;align-items:center;gap:12px;padding:9px 16px;font-size:13px;display:flex}.banner svg{flex:none}.banner.red{background:var(--red-soft);color:var(--text)}.banner.red svg{color:var(--red)}.banner.blue{background:var(--blue-soft)}.banner.blue svg{color:var(--blue)}.banner .muted{font-size:12px}.inbox-item{border:1px solid var(--border-strong);border-radius:var(--r-lg);background:var(--surface);flex-direction:column;gap:10px;padding:12px;display:flex}.inbox-item-head{align-items:center;gap:8px;font-size:13px;display:flex}.inbox-item-head .when{color:var(--text-3);margin-left:auto;font-size:11px}.inbox-kind{color:var(--text-3);text-transform:uppercase;letter-spacing:.04em;font-size:11px;font-weight:600}.command{background:var(--bg-sunken);border:1px solid var(--border);border-radius:var(--r);font-family:var(--mono);white-space:pre-wrap;word-break:break-word;max-height:180px;margin:0;padding:8px 10px;font-size:12px;overflow:auto}.inbox-reason{color:var(--text-2);font-size:12px}.inbox-actions{flex-wrap:wrap;gap:6px;display:flex}.inbox-empty{text-align:center;color:var(--text-3);padding:40px 10px}.session-note{border:1px dashed var(--border-strong);border-radius:var(--r);max-width:760px;color:var(--text-2);justify-content:space-between;align-items:center;gap:12px;margin:0 auto;padding:12px 14px;font-size:13px;display:flex}.chat{flex-direction:column;height:100%;min-height:0;display:flex}.chat-head{border-bottom:1px solid var(--border);align-items:center;gap:10px;padding:10px 20px;display:flex}.chat-head .title{font-weight:600}.chat-head .sub{color:var(--text-3);font-size:12px}.inline-select{field-sizing:content;border-radius:var(--r-sm);width:auto;height:auto;color:inherit;font:inherit;cursor:pointer;background:0 0;border:none;padding:0 2px}.inline-select:hover{color:var(--text);background:var(--surface-hover)}.inline-select:focus{box-shadow:none}.inline-select option{background:var(--panel);color:var(--text)}.chat-scroll{flex:1;padding:24px 24px 12px;overflow:auto}.chat-col{flex-direction:column;gap:18px;max-width:760px;margin:0 auto;display:flex}.chat-col>.load-older{align-self:center}.list-compact{flex-direction:column;gap:4px;display:flex}.msg-user{background:var(--surface-2);border:1px solid var(--border);white-space:pre-wrap;border-radius:12px 12px 4px;align-self:flex-end;max-width:82%;padding:9px 13px;font-size:14px;line-height:1.55}.msg-assistant{flex-direction:column;gap:8px;font-size:14px;line-height:1.65;display:flex}.msg-note{color:var(--text-3);text-align:center;justify-content:center;font-size:12px;line-height:1.5;display:flex}.msg-note>span{background:var(--panel);border:1px solid var(--border);border-radius:999px;max-width:88%;padding:4px 10px}.msg-agent{border:1px solid var(--border);border-radius:var(--r-lg);background:var(--panel);overflow:hidden}.msg-agent-head{border-bottom:1px solid var(--border);align-items:center;gap:8px;padding:8px 12px;font-size:12px;display:flex}.msg-agent-head strong{font-weight:600}.msg-agent-body{padding:10px 12px;font-size:13.5px}.msg-failure{color:var(--red);background:var(--red-soft);border-radius:var(--r);align-items:flex-start;gap:8px;padding:8px 12px;font-size:13px;display:flex}.msg-failure svg{flex:none;margin-top:2px}.md>:first-child{margin-top:0}.md>:last-child{margin-bottom:0}.md p{margin:0 0 10px}.md h1,.md h2,.md h3{margin:18px 0 8px}.md h1{font-size:18px}.md h2{font-size:16px}.md h3{font-size:14px}.md code{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--r-sm);padding:0 4px;font-size:.86em}.md pre{background:var(--bg-sunken);border:1px solid var(--border);border-radius:var(--r);padding:12px;overflow:auto}.md pre code{background:0 0;border:none;padding:0}.md ul,.md ol{margin:0 0 10px;padding-left:22px}.md li{margin:2px 0}.md table{border-collapse:collapse;margin:0 0 10px}.md th,.md td{border:1px solid var(--border-strong);padding:5px 9px}.md a{color:var(--accent-text)}.md blockquote{border-left:2px solid var(--border-strong);color:var(--text-2);margin:0 0 10px;padding-left:12px}.reasoning{color:var(--text-3);font-size:13px}.reasoning summary{cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:6px;list-style:none;display:inline-flex}.reasoning summary::-webkit-details-marker{display:none}.reasoning summary:hover{color:var(--text-2)}.reasoning-body{white-space:pre-wrap;border-left:2px solid var(--border-strong);margin-top:6px;padding:4px 0 4px 12px}.tool{border:1px solid var(--border);border-radius:var(--r);background:var(--panel);font-size:12px}.tool summary{cursor:pointer;color:var(--text-2);align-items:center;gap:8px;padding:6px 10px;list-style:none;display:flex}.tool summary::-webkit-details-marker{display:none}.tool summary:hover{color:var(--text)}.tool-name{color:var(--text);font-weight:500}.tool-arg{font-family:var(--mono);color:var(--text-3);text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.tool-state{flex:none;display:inline-flex}.tool-state.done{color:var(--green)}.tool-state.failed{color:var(--red)}.tool-io{border-top:1px solid var(--border);max-height:260px;font-family:var(--mono);white-space:pre-wrap;color:var(--text-2);margin:0;padding:10px;font-size:12px;overflow:auto}.tool-io.out{background:var(--bg-sunken)}.spin{animation:.9s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}.thinking{color:var(--text-3);align-items:center;gap:8px;font-size:13px;display:flex}.thinking.retrying{color:var(--amber)}.typing{gap:3px;display:inline-flex}.typing i{background:currentColor;border-radius:50%;width:5px;height:5px;animation:1.2s ease-in-out infinite typing}.typing i:nth-child(2){animation-delay:.15s}.typing i:nth-child(3){animation-delay:.3s}@keyframes typing{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}.chat-empty{text-align:center;color:var(--text-2);padding:56px 20px}.chat-empty h2{color:var(--text);margin-bottom:6px;font-size:18px}.composer-wrap{padding:8px 24px 18px}.composer{border:1px solid var(--border-strong);background:var(--surface);border-radius:12px;max-width:760px;margin:0 auto;transition:border-color .12s,box-shadow .12s}.composer:focus-within{border-color:#44465a;box-shadow:0 0 0 3px #6d6af514}.composer textarea{resize:none;width:100%;box-shadow:none;background:0 0;border:none;padding:12px 14px 4px;font-size:14px}.composer textarea:focus{box-shadow:none}.composer-bar{align-items:center;gap:8px;padding:6px 8px 8px 14px;display:flex}.composer-hint{color:var(--text-3);font-size:11px}.form-card{border-radius:var(--r-lg);background:var(--panel);border:1px solid #d4a03a73;overflow:hidden}.form-card-head{border-bottom:1px solid var(--border);background:var(--amber-soft);align-items:center;gap:8px;padding:10px 14px;font-size:13px;font-weight:600;display:flex}.form-card-head svg{color:var(--amber)}.form-card-body{flex-direction:column;gap:14px;padding:12px 14px;display:flex}.form-field-title{margin-bottom:8px;font-size:13px;font-weight:500}.form-options{flex-direction:column;gap:6px;display:flex}.form-option{text-align:left;background:var(--surface);border:1px solid var(--border-strong);color:var(--text);font:inherit;border-radius:var(--r);cursor:pointer;flex-direction:column;gap:2px;padding:9px 12px;display:flex}.form-option:hover{border-color:#3a3d46}.form-option.on{border-color:var(--accent);background:var(--accent-soft)}.form-option:disabled{opacity:.45;cursor:not-allowed}.form-field-desc{color:var(--text-2);margin:-4px 0 8px;font-size:13px}.form-option span{color:var(--text-2);font-size:12px}.kanban{flex-direction:column;height:100%;min-height:0;display:flex}.kanban-head{border-bottom:1px solid var(--border);align-items:center;gap:16px;padding:14px 20px;display:flex}.kanban-goal{flex:1;min-width:0}.kanban-goal-text{font-size:14px;font-weight:500}.kanban-goal-meta{color:var(--text-3);align-items:center;gap:8px;margin-top:4px;font-size:12px;display:flex}.progress{color:var(--text-2);flex:none;align-items:center;gap:10px;font-size:12px;display:flex}.progress-track{background:var(--surface-hover);border-radius:6px;width:160px;height:6px;overflow:hidden}.progress-fill{background:var(--green);border-radius:6px;height:100%}.plan-banner{border:1px solid var(--border-strong);border-radius:var(--r-lg);background:var(--surface);flex-direction:column;gap:10px;margin:12px 20px 0;padding:12px 14px;display:flex}.plan-banner-row{align-items:center;gap:10px;display:flex}.plan-banner-row textarea{flex:1}.columns{flex:1;grid-template-columns:repeat(5,minmax(190px,1fr));gap:10px;min-height:0;padding:14px 20px 16px;display:grid;overflow-x:auto}.column{border-radius:var(--r-lg);background:var(--panel);border:1px solid var(--border);flex-direction:column;min-height:0;display:flex}.column-head{color:var(--text-2);align-items:center;gap:8px;padding:10px 12px;font-size:12px;font-weight:600;display:flex}.column-head svg{color:var(--text-3)}.col-in-progress .column-head svg{color:var(--green)}.col-blocked .column-head svg{color:var(--red)}.col-review .column-head svg{color:var(--amber)}.col-done .column-head svg{color:var(--accent-text)}.column-count{color:var(--text-3);font-variant-numeric:tabular-nums;margin-left:auto;font-size:11px}.column-body{flex-direction:column;flex:1;gap:6px;padding:0 8px 8px;display:flex;overflow-y:auto}.column-empty{text-align:center;color:var(--text-3);padding:14px 6px;font-size:12px}.task-card{text-align:left;font:inherit;color:var(--text);background:var(--surface);border:1px solid var(--border);border-radius:var(--r);cursor:pointer;flex-direction:column;gap:7px;padding:10px;transition:border-color .12s,background .12s;display:flex}.task-card:hover{border-color:var(--border-strong);background:var(--surface-2)}.task-card.ts-done .task-title{color:var(--text-2)}.task-top{color:var(--text-3);align-items:center;gap:6px;font-size:11px;display:flex}.task-id{font-family:var(--mono);color:var(--text-3);font-size:11px}.task-title{font-size:13px;font-weight:500;line-height:1.4}.task-meta{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.task-bottom{color:var(--text-2);align-items:center;gap:6px;font-size:12px;display:flex}.task-bottom .subtle{align-items:center;gap:3px;margin-left:auto;font-size:11px;display:inline-flex}.task-detail-meta{grid-template-columns:110px 1fr;gap:6px 12px;font-size:12px;display:grid}.task-detail-meta dt{color:var(--text-3)}.task-detail-meta dd{flex-wrap:wrap;align-items:center;gap:6px;margin:0;display:flex}.history{flex-direction:column;gap:10px;display:flex}.history-item{gap:10px;font-size:12px;display:flex}.history-item .when{color:var(--text-3);font-variant-numeric:tabular-nums;flex:none;width:54px}.history-item .what{color:var(--text-2);white-space:pre-wrap}.history-item .what strong{color:var(--text);font-weight:500}.timeline{flex:1;overflow:auto}.timeline-inner{max-width:820px;margin:0 auto;padding:16px 24px 32px}.timeline-toolbar{border-bottom:1px solid var(--border);color:var(--text-2);align-items:center;gap:10px;padding:10px 24px;font-size:12px;display:flex}.event{border-bottom:1px solid var(--border);grid-template-columns:28px minmax(0,1fr);gap:10px;padding:10px 0;display:grid}.event:last-child{border-bottom:none}.event-head{color:var(--text-2);flex-wrap:wrap;align-items:center;gap:6px;font-size:12px;display:flex}.event-head strong{color:var(--text);font-weight:600}.event-head .when{color:var(--text-3);font-variant-numeric:tabular-nums;margin-left:auto}.event-body{margin-top:4px;font-size:13px}.event.quiet .event-body{color:var(--text-2);font-size:12px}.event.open{background:linear-gradient(90deg, var(--amber-soft), transparent 70%);border-radius:var(--r);margin-left:-8px;padding-left:8px}.reply{align-items:flex-end;gap:8px;margin-top:8px;display:flex}.reply textarea{resize:none;flex:1}.docs{grid-template-columns:280px minmax(0,1fr);height:100%;min-height:0;display:grid}.docs-list{border-right:1px solid var(--border);flex-direction:column;gap:1px;padding:10px 8px;display:flex;overflow:auto}.docs-tree-folder{flex-direction:column;gap:1px;display:flex}.docs-search{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);color:var(--text-3);flex:none;align-items:center;gap:6px;margin-bottom:8px;padding:0 4px 0 9px;display:flex}.docs-search:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}.docs-search input,.docs-search input:focus{box-shadow:none;background:0 0;border:none;border-radius:0}.docs-search input{min-width:0;color:var(--text);background:0 0;border:none;outline:none;flex:1;padding:7px 0;font-size:13px}.docs-folder{color:var(--text-2)}.docs-results{flex-direction:column;gap:10px;display:flex}.docs-result-file{flex-direction:column;gap:1px;display:flex}.docs-result-path{color:var(--text-2);align-items:center;gap:6px;padding:2px 8px;font-size:12px;display:flex}.docs-result-path svg{color:var(--text-3);flex:none}.docs-result-path .ellipsis{flex:1}.docs-result{text-align:left;font:inherit;border-radius:var(--r);cursor:pointer;color:var(--text-2);background:0 0;border:none;gap:8px;padding:5px 8px;font-size:12px;line-height:1.45;display:flex}.docs-result:hover{background:var(--surface);color:var(--text)}.docs-result-line{color:var(--text-3);font-family:var(--mono);text-align:right;flex:none;min-width:28px;padding-top:1px;font-size:11px}.docs-result-text{-webkit-line-clamp:3;word-break:break-word;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.docs-result mark{background:var(--accent-soft);color:var(--accent-text);border-radius:2px}.docs-result-more{color:var(--text-3);padding:2px 8px 0 44px;font-size:11px}.docs-page{align-items:flex-start;gap:40px;display:flex}.docs-page .md{flex:1;min-width:0}.docs-toc{flex-direction:column;flex:none;gap:1px;width:220px;max-height:calc(100vh - 200px);display:flex;position:sticky;top:0;overflow:auto}.docs-toc-title{text-transform:uppercase;letter-spacing:.04em;color:var(--text-3);padding:0 8px 6px;font-size:11px;font-weight:600}.docs-toc-item{text-align:left;font:inherit;color:var(--text-2);border-radius:var(--r-sm);cursor:pointer;text-overflow:ellipsis;white-space:nowrap;background:0 0;border:none;padding:3px 8px;font-size:12px;overflow:hidden}.docs-toc-item:hover{background:var(--surface);color:var(--text)}.docs-toc-item.level-1{color:var(--text);font-weight:500}.docs-toc-item.level-3{padding-left:20px}@media (width<=1280px){.docs-toc{display:none}}.md a.doc-path{text-decoration:none}.md a.doc-path code{color:var(--accent-text);border-color:var(--accent-soft)}.md a.doc-path:hover code{background:var(--accent-soft)}.docs-text{font-family:var(--mono);font-size:12.5px;line-height:1.6}.docs-text-line{border-radius:var(--r-sm);gap:14px;display:flex}.docs-text-no{color:var(--text-3);text-align:right;-webkit-user-select:none;user-select:none;flex:none;min-width:40px}.docs-text-content{white-space:pre-wrap;word-break:break-word}.docs-body .flash{animation:1.6s ease-out flash}@keyframes flash{0%,30%{background:var(--accent-soft)}to{background:0 0}}.docs-item{text-align:left;color:var(--text-2);font:inherit;border-radius:var(--r);cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.docs-item svg{color:var(--text-3);flex:none}.docs-item:hover{background:var(--surface);color:var(--text)}.docs-item.active{background:var(--surface-2);color:var(--text)}.docs-item .grow{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.docs-item-time{color:var(--text-3);flex:none;font-size:11px}.docs-view{flex-direction:column;min-width:0;min-height:0;display:flex}.docs-toolbar{border-bottom:1px solid var(--border);align-items:center;gap:8px;padding:8px 16px;display:flex}.docs-toolbar code{color:var(--text-2)}.docs-body{flex:1;padding:24px 32px 48px;overflow:auto}.docs-body .md{max-width:760px;font-size:14px;line-height:1.7}.docs-editor{resize:none;width:100%;height:100%;min-height:420px;font-family:var(--mono);font-size:13px;line-height:1.6}.settings-scroll{flex:1;overflow:auto}.settings-inner{flex-direction:column;gap:20px;max-width:780px;padding:24px 28px 64px;display:flex}.conn-icon{background:var(--surface-2);border:1px solid var(--border-strong);width:32px;height:32px;color:var(--text-2);border-radius:8px;flex:none;justify-content:center;align-items:center;display:inline-flex}.conn-icon.sm{border-radius:5px;width:22px;height:22px}.conn-test{align-items:center;gap:5px;margin-top:2px;font-size:12px;display:inline-flex}.conn-test.ok{color:var(--green)}.conn-test.bad{color:var(--red)}.pick-row{border:1px solid var(--border-strong);border-radius:var(--r);align-items:center;gap:10px;padding:8px 10px;display:flex}.pick-row+.pick-row{margin-top:6px}.pick-row.on{background:var(--accent-soft);border-color:#6d6af580}.pick-main{cursor:pointer;flex:1;align-items:center;gap:10px;min-width:0;display:flex}.danger-zone{border-color:#e5534b4d}.model-picker{border:1px solid var(--border-strong);border-radius:var(--r-lg);overflow:hidden}.model-picker-head{border-bottom:1px solid var(--border);background:var(--surface);align-items:center;gap:10px;padding:8px 10px;display:flex}.model-picker-head input{flex:1;height:28px;padding:4px 8px}.model-summary{border-bottom:1px solid var(--border);color:var(--text-2);flex-wrap:wrap;align-items:center;gap:6px;padding:8px 12px;font-size:12px;display:flex}.model-groups{max-height:300px;padding:4px;overflow:auto}.model-group-title{background:var(--panel);color:var(--text-3);z-index:1;padding:8px 8px 4px;font-size:11px;font-weight:600;position:sticky;top:0}.model-row{border-radius:var(--r-sm);cursor:pointer;align-items:center;gap:8px;padding:5px 8px;font-size:13px;display:flex}.model-row:hover{background:var(--surface)}.model-row.on{background:var(--accent-soft)}.model-row .check-box{border:1px solid var(--border-strong);color:#fff;border-radius:4px;flex:none;justify-content:center;align-items:center;width:15px;height:15px;display:inline-flex}.model-row.on .check-box{background:var(--accent);border-color:var(--accent)}.model-name{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lead-btn{color:var(--text-3);cursor:pointer;border-radius:var(--r-sm);background:0 0;border:none;padding:2px;display:inline-flex}.lead-btn:hover{color:var(--text);background:var(--surface-hover)}.lead-btn.on{color:var(--amber)}.folder-summary{border:1px solid var(--border-strong);border-radius:var(--r-lg);background:var(--surface);flex-direction:column;gap:10px;padding:12px 14px;display:flex}.folder-headline{flex-wrap:wrap;align-items:center;gap:8px;font-size:13px;display:flex}.folder-headline svg{color:var(--text-2)}.kind-bar{background:var(--surface-hover);border-radius:6px;gap:2px;height:6px;display:flex;overflow:hidden}.kind-seg{height:100%}.k0{background:#6d6af5}.k1{background:#3fb27f}.k2{background:#d4a03a}.k3{background:#c76bd6}.k4{background:#4c8df6}.k5{background:#6c6d78}.kind-legend{color:var(--text-2);flex-wrap:wrap;gap:4px 14px;font-size:12px;display:flex}.kind-legend i{border-radius:2px;width:8px;height:8px;margin-right:6px;display:inline-block}.top-level{color:var(--text-3);font-size:12px;font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.btn.ghost.active{color:var(--text);background:var(--surface-2)}.folder-browser{border:1px solid var(--border-strong);border-radius:var(--r);background:var(--bg-sunken);flex-direction:column;display:flex;overflow:hidden}.folder-browser-head{border-bottom:1px solid var(--border);align-items:center;gap:8px;padding:8px;display:flex}.folder-browser-path{min-width:0;color:var(--text);flex:1;font-size:12px}.folder-browser-places{border-bottom:1px solid var(--border);flex-wrap:wrap;gap:4px;padding:6px 8px;display:flex}.folder-browser-list{flex-direction:column;max-height:240px;padding:4px;display:flex;overflow:auto}.folder-browser-item{color:var(--text);font:inherit;text-align:left;border-radius:var(--r-sm);cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.folder-browser-item:hover{background:var(--surface-hover)}.folder-browser-item svg{color:var(--text-3);flex:none}.folder-browser-foot{border-top:1px solid var(--border);align-items:center;gap:8px;padding:8px;display:flex}.folder-browser-foot .spacer{flex:1}.docs-rules{color:var(--text);margin-bottom:6px;font-weight:500}.docs-rules svg{color:var(--accent-text)}.rules{flex-direction:column;gap:20px;font-size:13px;display:flex}.rules-filters{background:var(--panel);border:1px solid var(--border);border-radius:var(--r-lg);grid-template-columns:minmax(200px,1.4fr) repeat(5,minmax(120px,1fr));gap:12px;padding:14px 16px;display:grid}.rules-filters select:disabled{opacity:.5}.rules-filters-foot{grid-column:1/-1;align-items:center;gap:12px;display:flex}.rules-check{color:var(--text-2);cursor:pointer;align-items:center;gap:7px;font-size:13px;display:inline-flex}.rules-area h2{margin:4px 0 6px;font-size:16px}.rules-prefix{font-family:var(--mono);color:var(--text-3);margin-left:4px;font-size:12px;font-weight:400}.rules-stages{color:var(--text-3);flex-wrap:wrap;gap:4px 14px;margin:0 0 10px;display:flex}.rules-stages a{color:var(--accent-text);text-decoration:none}.rules-stages a:hover{text-decoration:underline}.rules-stage h3{margin:16px 0 8px;scroll-margin-top:12px;font-size:14px}.rules-table-wrap{border:1px solid var(--border);border-radius:var(--r-lg);overflow-x:auto}.rules-table{border-collapse:collapse;table-layout:fixed;width:100%;min-width:1000px}.rules-table th{text-align:left;text-transform:uppercase;letter-spacing:.04em;color:var(--text-3);background:var(--panel);border-bottom:1px solid var(--border);padding:9px 10px;font-size:11px;font-weight:600}.rules-table td{vertical-align:top;border-top:1px solid var(--border);color:var(--text-2);overflow-wrap:anywhere;padding:10px;line-height:1.5}.rules-table tr:first-child td{border-top:none}.rules-table tr.superseded td{opacity:.55}.rules-table tr{scroll-margin-top:12px}.rules-id{font-family:var(--mono);font-size:12px;font-weight:600;color:var(--accent-text)!important}.rules-superseded{font-family:var(--font);color:var(--text-3);margin-top:4px;font-size:11px;font-weight:400}.rules-md{color:var(--text)!important}.rules-md p{margin:0 0 6px}.rules-md p:last-child{margin:0}.rules-md ul,.rules-md ol{margin:0 0 6px;padding-left:18px}.rules-md code{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--r-sm);padding:0 4px;font-size:.86em}.rules-md a,.rules-cites a{color:var(--accent-text)}.rules-check-how{color:var(--text-3);margin-top:6px;font-size:12px}.rules-cites{color:var(--text)}.rules-cite{-webkit-text-decoration:underline dotted var(--text-3);text-decoration:underline dotted var(--text-3);text-underline-offset:3px}.rules-excerpt-toggle{font:inherit;color:var(--accent-text);cursor:pointer;background:0 0;border:none;align-items:center;gap:3px;margin-top:6px;padding:0;font-size:12px;display:inline-flex}.rules-excerpt{background:var(--accent-soft);border-left:2px solid var(--accent);border-radius:var(--r-sm);color:var(--text);margin:6px 0 0;padding:8px 10px;font-size:12.5px;font-style:italic}.rules-excerpt-src{color:var(--accent-text);margin-bottom:3px;font-size:11px;font-style:normal;font-weight:600}.rules-status{white-space:nowrap;align-items:center;gap:6px;font-weight:500;display:inline-flex}.rules-status.done{color:var(--green)}.rules-status.partial{color:var(--amber)}.rules-status.missing{color:var(--red)}.rules-status.na{color:var(--text-3)}.rule-dot{background:var(--amber);border-radius:50%;width:9px;height:9px;display:inline-block}.docs-body .rules~*{padding-right:24px}.docs-body:has(.rules){padding-right:24px}