handmux 0.6.0 → 0.8.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.
package/README.md CHANGED
@@ -153,10 +153,6 @@ hook events in `~/.claude/settings.json` (idempotent; leaves your own hooks alon
153
153
  this too, and you can turn it on from the phone the first time you open the inbox. `handmux hooks uninstall`
154
154
  removes it. If you don't use Claude Code, this is skipped — nothing touches `~/.claude`.
155
155
 
156
- After installing the hooks it also offers (opt-in) to add a small block to `~/.tmux.conf` so each tmux
157
- window tab shows a live Claude status dot (working / needs you / done) — the same signal as the inbox, on
158
- your terminal. Decline it and nothing is changed; the block is marked and easy to remove later.
159
-
160
156
  ### start flags
161
157
 
162
158
  Flags override the config file for **one run** and never persist — handy for a quick try
package/README.zh-CN.md CHANGED
@@ -141,10 +141,6 @@ Agent 收件箱和「需要你就推给你」靠的是 Claude Code 的生命周
141
141
  注册六个 hook 事件(幂等;不动你自己的 hook)。`handmux setup` 也会问一句,首次在手机上打开收件箱时
142
142
  还能一键开启。`handmux hooks uninstall` 移除它。不用 Claude Code 的话直接跳过——绝不碰 `~/.claude`。
143
143
 
144
- 装完 hook 后,它还会(opt-in)问一句要不要往 `~/.tmux.conf` 加一小段配置,让每个 tmux 窗页签也显示一个
145
- 实时的 Claude 状态点(进行中 / 需要你 / 已完成)——和收件箱同一个信号,直接画在你的终端上。拒绝则什么都不改;
146
- 这段配置带标记,以后想删很容易。
147
-
148
144
  ### start 参数
149
145
 
150
146
  参数只对**这一次运行**覆盖配置文件、绝不落盘——适合不动已存配置就快速试一下
package/bin/handmux.js CHANGED
@@ -32,7 +32,8 @@ import { readState, clearState, isAlive, pocketHome, logPath, configPath, claude
32
32
  import { runSetup } from '../src/cli/setupWizard.js';
33
33
  import { hooksStatus, installHooks, uninstallHooks } from '../src/cli/claudeHooks.js';
34
34
  import { codexHooksStatus, installCodexHooks, uninstallCodexHooks } from '../src/cli/codexHooks.js';
35
- import { tmuxDotStatus, installTmuxDot, tmuxConfPath } from '../src/cli/tmuxConf.js';
35
+ import { statusLineStatus, installStatusLine, uninstallStatusLine, composeHint } from '../src/cli/statusLine.js';
36
+ import { claudeUsagePath } from '../src/usage.js';
36
37
  import { probe } from '../src/cli/probe.js';
37
38
  import { notifyUpdate, runUpdateCheck, PKG_NAME } from '../src/cli/updateCheck.js';
38
39
  import { t, initLocale, setLocale } from '../src/cli/i18n/index.js';
@@ -319,33 +320,38 @@ async function setupCmd() {
319
320
  const offerHooks = hooksStatus(HOME) === 'absent' || codexHooksStatus(HOME) === 'absent';
320
321
  if (offerHooks && await confirm(t('hooks.confirmEnable'))) {
321
322
  installAgentHooks();
322
- await maybeOfferTmuxDot();
323
323
  }
324
+ await maybeOfferStatusLine();
324
325
  if (await confirm(t('setup.confirmStart'))) { Object.assign(flags, cfg); return start(); }
325
326
  console.log(t('setup.later'));
326
327
  }
327
328
 
328
- // The per-window tmux status dot is the natural companion to the inbox hooks: the hook already writes a
329
- // colour into each window's `@claude_dot` on every Claude event, but tmux only SHOWS it if
330
- // `window-status-format` references it — otherwise it's a silent no-op. Offer to add that display block to
331
- // ~/.tmux.conf (opt-in, idempotent). Skip when it's already wired (ours or hand-rolled). Non-TTY: just hint.
332
- async function maybeOfferTmuxDot() {
333
- if (tmuxDotStatus(HOME) !== 'absent') return;
334
- if (!process.stdin.isTTY) {
335
- console.log(t('tmuxdot.tip', { conf: tmuxConfPath(HOME) }));
329
+ // Offer to enable the Claude statusLine usage capturer it feeds the phone Usage page's 5h/weekly bars
330
+ // (Claude Code's statusLine stdin is the only documented local source of those %). Opt-in and NON-
331
+ // DESTRUCTIVE: auto-installs only when there's no statusLine yet; if the user already has one we print a
332
+ // one-line compose snippet and change nothing. Codex needs no capturer its rollout already carries the
333
+ // quota. No-op when Claude Code isn't installed or ours is already in place.
334
+ async function maybeOfferStatusLine() {
335
+ const st = statusLineStatus(HOME);
336
+ if (st === 'no-claude' || st === 'ours') return;
337
+ if (st === 'foreign') {
338
+ // Deploy the capturer script (doesn't touch their statusLine) so the compose one-liner is runnable.
339
+ installStatusLine(HOME, { srcDir: HOOKS_SRC, usageFile: claudeUsagePath(HOME) });
340
+ console.log(t('statusline.foreignHint'));
341
+ console.log(' ' + composeHint(HOME, { usageFile: claudeUsagePath(HOME) }));
336
342
  return;
337
343
  }
338
- if (await confirm(t('tmuxdot.confirm'))) {
339
- installTmuxDot(HOME);
340
- console.log(t('tmuxdot.added', { path: tmuxConfPath(HOME) }));
341
- console.log(t('tmuxdot.apply'));
344
+ if (await confirm(t('statusline.confirmEnable'))) {
345
+ installStatusLine(HOME, { srcDir: HOOKS_SRC, usageFile: claudeUsagePath(HOME) });
346
+ console.log(t('statusline.installed'));
347
+ console.log(t('statusline.reload'));
342
348
  }
343
349
  }
344
350
 
345
351
  // Install the inbox hooks for every coding agent present on this host (Claude Code, Codex — the state file
346
352
  // is shared, entries are agent-tagged). Each is opt-in by the mere presence of its config dir. Prints a
347
- // per-agent line and returns how many were wired, so callers can gate the tmux-dot offer / the "reload"
348
- // hint. Codex's single `notify` slot may already hold the user's OWN program — we never clobber it, we warn.
353
+ // per-agent line and returns how many were wired, so callers can gate the "reload" hint. Codex's single
354
+ // `notify` slot may already hold the user's OWN program — we never clobber it, we warn.
349
355
  function installAgentHooks() {
350
356
  let installed = 0;
351
357
  if (hooksStatus(HOME) !== 'no-claude') {
@@ -371,12 +377,13 @@ async function hooksCmd() {
371
377
  return;
372
378
  }
373
379
  if (installAgentHooks() > 0) console.log(t('hooks.installedHint'));
374
- await maybeOfferTmuxDot();
380
+ await maybeOfferStatusLine();
375
381
  return;
376
382
  }
377
383
  if (sub === 'uninstall') {
378
384
  uninstallHooks(HOME);
379
385
  uninstallCodexHooks(HOME);
386
+ uninstallStatusLine(HOME);
380
387
  console.log(t('hooks.removed'));
381
388
  return;
382
389
  }
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ // handmux statusLine capturer. Claude Code pipes a JSON blob to its `statusLine` command on stdin — the
3
+ // ONLY officially-documented local source of the 5-hour / weekly rate-limit percentages (the same numbers
4
+ // `/usage` shows). See https://code.claude.com/docs/en/statusline ("Available data": rate_limits.five_hour
5
+ // / seven_day, context_window, model). We snapshot those fields to a file the handmux server serves to the
6
+ // phone's Usage page, then produce stdout so the terminal statusline still works:
7
+ //
8
+ // node handmux-statusline.cjs <usageFile> # snapshot + print a compact status line
9
+ // HANDMUX_STATUS_TEE=1 node handmux-statusline.cjs <usageFile> # snapshot + re-emit stdin verbatim
10
+ //
11
+ // TEE mode is for a user who ALREADY has a statusline: they pipe `... | handmux-statusline.cjs <f> | their
12
+ // renderer`, so their renderer downstream receives the exact same JSON and their display is unchanged.
13
+ //
14
+ // .cjs so it runs standalone via `node <file>` regardless of any surrounding package.json "type". Best-
15
+ // effort and silent throughout — a statusLine command must never fail Claude.
16
+ const fs = require('node:fs');
17
+ const path = require('node:path');
18
+
19
+ const file = process.argv[2];
20
+ const raw = (() => { try { return fs.readFileSync(0, 'utf8'); } catch { return ''; } })();
21
+ let j = {};
22
+ try { j = JSON.parse(raw || '{}'); } catch { /* not JSON → leave j = {} */ }
23
+
24
+ // One rate-limit window → our shape, or undefined if the field is absent (rate_limits only appears for
25
+ // Pro/Max plans, and only after a session's first API response).
26
+ function win(o) {
27
+ if (!o || typeof o.used_percentage !== 'number') return undefined;
28
+ const w = { usedPercent: o.used_percentage };
29
+ if (typeof o.resets_at === 'number') w.resetsAt = o.resets_at;
30
+ return w;
31
+ }
32
+
33
+ if (file) {
34
+ try {
35
+ const rl = j.rate_limits || {};
36
+ const cw = j.context_window || {};
37
+ const rateLimits = {
38
+ fiveHour: win(rl.five_hour),
39
+ sevenDay: win(rl.seven_day),
40
+ sevenDayOpus: win(rl.seven_day_opus),
41
+ sevenDaySonnet: win(rl.seven_day_sonnet),
42
+ };
43
+ for (const k of Object.keys(rateLimits)) if (rateLimits[k] === undefined) delete rateLimits[k];
44
+ const snap = {
45
+ updatedAt: Date.now(),
46
+ model: (j.model && (j.model.display_name || j.model.id)) || null,
47
+ context: (typeof cw.used_percentage === 'number') ? { usedPercent: cw.used_percentage } : undefined,
48
+ rateLimits,
49
+ };
50
+ if (snap.context === undefined) delete snap.context;
51
+ fs.mkdirSync(path.dirname(file), { recursive: true });
52
+ const tmp = `${file}.${process.pid}.tmp`;
53
+ fs.writeFileSync(tmp, JSON.stringify(snap));
54
+ fs.renameSync(tmp, file); // atomic: concurrent statuslines (multiple sessions) can't tear the snapshot
55
+ } catch { /* best effort — never fail the statusline */ }
56
+ }
57
+
58
+ // Output. TEE → re-emit stdin so a downstream renderer is unaffected. Otherwise render a compact line from
59
+ // whatever fields are present (a plain default statusline for users who had none).
60
+ if (process.env.HANDMUX_STATUS_TEE === '1') {
61
+ process.stdout.write(raw);
62
+ } else {
63
+ try {
64
+ const seg = [];
65
+ const dir = j.workspace && j.workspace.current_dir;
66
+ if (dir) seg.push(path.basename(dir));
67
+ if (j.model && j.model.display_name) seg.push(j.model.display_name);
68
+ const cw = j.context_window || {};
69
+ if (typeof cw.used_percentage === 'number') seg.push(`Ctx ${Math.round(cw.used_percentage)}%`);
70
+ const rl = j.rate_limits || {};
71
+ if (rl.five_hour && typeof rl.five_hour.used_percentage === 'number') seg.push(`5h ${Math.round(rl.five_hour.used_percentage)}%`);
72
+ if (rl.seven_day && typeof rl.seven_day.used_percentage === 'number') seg.push(`Wk ${Math.round(rl.seven_day.used_percentage)}%`);
73
+ if (seg.length) process.stdout.write(seg.join(' · '));
74
+ } catch { /* silent */ }
75
+ }
@@ -27,8 +27,6 @@ try { payload = JSON.parse(fs.readFileSync(0, 'utf8') || '{}'); } catch { /* unr
27
27
  // terminates an ESC-interrupted working turn (→ clear the stuck 进行中). Flag it here; the read-modify-
28
28
  // write under the lock — the only place we can read the prior state safely — makes the call.
29
29
  const isIdle = src === 'notify' && payload && payload.notification_type === 'idle_prompt';
30
- let cleared = false; // set by update() when idle cleared an interrupted 进行中 → also clear @claude_dot below
31
- let noop = false; // set when a codex PostToolUse resume had nothing to un-stick → skip the state + dot write
32
30
 
33
31
  // Synchronous nap without busy-spinning (the hook runs async, so a few ms is free). SharedArrayBuffer
34
32
  // may be unavailable in odd runtimes — fall back to a tiny busy loop so the lock retry still paces.
@@ -48,21 +46,21 @@ function update() {
48
46
  // idle after a resting state (done/needs/nothing) is just the "still waiting" reminder → drop and
49
47
  // leave the file as it was (recording it would bump ts and re-surface an already-cleared 已完成).
50
48
  // idle after a WORKING turn (prompt/resume) that never got a Stop = an ESC interrupt / walk-away —
51
- // no Stop hook fires there, so idle is the only signal the turn ended. Without this the 进行中 dot
52
- // sticks forever; treat it as a soft end and clear the pane (and its @claude_dot, below).
53
- if (prevSrc === 'prompt' || prevSrc === 'resume') { delete obj[pane]; cleared = true; }
49
+ // no Stop hook fires there, so idle is the only signal the turn ended. Without this the pane would
50
+ // stay latched at 进行中 forever; treat it as a soft end and clear the pane.
51
+ if (prevSrc === 'prompt' || prevSrc === 'resume') { delete obj[pane]; }
54
52
  else return; // resting → drop without writing
55
53
  } else if (src === 'end') {
56
54
  delete obj[pane]; // SessionEnd (clean exit) → drop the pane
57
55
  } else if (src === 'resume' && agent === 'codex') {
58
56
  // Codex fires PostToolUse on EVERY tool call, so its resume exists purely to un-stick a pane from 需要你
59
57
  // back to 进行中 after the user approved a PermissionRequest. Apply it ONLY as that transition — a mid-
60
- // turn tool call (pane already 进行中 / 已完成) is a no-op, so we don't rewrite the entry or repaint the
61
- // dot on every command (the load Claude's matcher avoids). Claude's resume — no agent arg — is unaffected.
58
+ // turn tool call (pane already 进行中 / 已完成) is a no-op, so we don't rewrite the entry on every
59
+ // command (the load Claude's matcher avoids). Claude's resume — no agent arg — is unaffected.
62
60
  const prev = obj[pane];
63
61
  const prevPerm = prev && (prev.src === 'permreq'
64
62
  || (prev.src === 'notify' && (prev.payload || {}).notification_type === 'permission_prompt'));
65
- if (!prevPerm) { noop = true; return; }
63
+ if (!prevPerm) { return; }
66
64
  obj[pane] = { ts: Number(ts) || 0, src, host, payload, agent };
67
65
  } else {
68
66
  // agent tag lets the server dispatch classify + liveness per agent (Codex passes 'codex'); omitted for
@@ -85,21 +83,3 @@ for (let i = 0; i < 60 && !held; i++) { // ~0.9s budget, t
85
83
  }
86
84
  try { update(); } catch { /* best effort */ }
87
85
  if (held) { try { fs.unlinkSync(lock); } catch { /* ignore */ } }
88
-
89
- // tmux 页签状态色点(事件驱动):把本次事件的状态色 markup 写进该 pane 所在窗的 @claude_dot 选项。
90
- // tmux 的 window-status-format 只读 #{@claude_dot}(纯查表、不跑任何 shell),所以稳态零重绘——只有
91
- // 状态真变化(即本 hook 触发的这一刻)才写一次、才重绘一次,不轮询、不卡。详见 tmux/README.md。
92
- // best-effort + 1s 超时:不在 tmux / tmux 不可达都静默忽略,永不阻塞或失败 Claude。
93
- function claudeDot(s, p) {
94
- if (s === 'stop') return '#[fg=#2e7d46]●#[default] '; // 已完成 绿
95
- if (s === 'prompt' || s === 'resume') return '#[fg=#2f6fed,blink]●#[default] '; // 进行中 蓝闪
96
- if (s === 'permreq') return '#[fg=#e0a020]●#[default] '; // 需要你 橙
97
- if (s === 'notify' && p && p.notification_type === 'permission_prompt') return '#[fg=#e0a020]●#[default] ';
98
- return null; // 其它无法分类 → 不动该窗的点(end 在下方单独清空)
99
- }
100
- try {
101
- const dot = (src === 'end' || cleared) ? '' : claudeDot(src, payload);
102
- if (dot !== null && !noop) {
103
- require('node:child_process').execFileSync('tmux', ['set-option', '-w', '-t', pane, '@claude_dot', dot], { stdio: 'ignore', timeout: 1000 });
104
- }
105
- } catch { /* 不在 tmux / tmux 不可达 → 忽略 */ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "handmux",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Mobile vibe coding — drive your real tmux session (and Claude Code) from your phone.",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -24,7 +24,6 @@
24
24
  "bin",
25
25
  "src",
26
26
  "hooks",
27
- "tmux",
28
27
  "public",
29
28
  "README.zh-CN.md"
30
29
  ],
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Copyright (c) 2014 The xterm.js authors. All rights reserved.
3
+ * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
4
+ * https://github.com/chjj/term.js
5
+ * @license MIT
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ *
25
+ * Originally forked from (with the author's permission):
26
+ * Fabrice Bellard's javascript vt100 for jslinux:
27
+ * http://bellard.org/jslinux/
28
+ * Copyright (c) 2011 Fabrice Bellard
29
+ * The original design remains. The terminal itself
30
+ * has been extended to include xterm CSI codes, among
31
+ * other features.
32
+ */.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}*{box-sizing:border-box}:root{--blue: #0a84ff;--blue-press: #0a6fd8;--blue-rgb: 10,132,255;--green: #34c759;--green-rgb: 52,199,89;--red: #ff453a}@font-face{font-family:JetBrainsMono Nerd Font;src:url(/fonts/JetBrainsMonoNerdFontMono-Regular.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:TW Unifont;src:url(/fonts/TWUnifont.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap;unicode-range:U+2190-21FF,U+2300-23FF,U+2400-243F,U+2500-257F,U+2580-259F,U+25A0-25FF,U+2600-26FF,U+2700-27BF,U+2800-28FF,U+2B00-2BFF}html,body,#root{height:100%;margin:0;overscroll-behavior:none}body{font-family:-apple-system,system-ui,sans-serif;background:#1a1b1e;color:#e6e6e6}.app{display:flex;flex-direction:column;height:100%;overflow:hidden}.topbar{display:flex;align-items:center;gap:6px;padding:4px 8px;background:#2a2b2e}.hamburger{font-size:20px;background:none;border:none;color:#e6e6e6;width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;padding:0;margin-left:-4px;touch-action:manipulation}.session-name{font-weight:600;margin-right:auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fontbtn{min-width:36px;padding:4px 10px;border:none;border-radius:8px;background:#33353a;color:#e6e6e6;font-size:14px;touch-action:manipulation}.fontbtn[aria-pressed=true]{background:#2a4060;color:#7ab4f5}.topbar-icon{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border:none;background:none;color:#e6e6e6;touch-action:manipulation}.topbar-icon:active{color:var(--blue)}.topbar-icon svg{width:21px;height:21px;display:block}.settings-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;z-index:19}.settings-card{position:fixed;z-index:20;left:50%;top:50%;transform:translate(-50%,-50%);width:calc(100% - 48px);max-width:360px;background:#232427;border-radius:12px;padding:16px;box-shadow:0 10px 40px #00000080}.settings-head{display:flex;align-items:center;margin-bottom:12px}.settings-title{font-size:16px;font-weight:600;margin-right:auto}.settings-close{flex:none;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:50%;background:#78788029;color:#ebebf58c;font-size:15px;line-height:1;touch-action:manipulation}.settings-close:active{background:#7878804d;color:#fff}.settings-close svg{width:14px;height:14px;display:block}.settings-section{padding:10px 0;border-top:1px solid #33353a}.settings-label{font-size:12px;color:#888;letter-spacing:1px;margin-bottom:8px}.settings-btns{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.lang-drop{position:relative;display:inline-block}.lang-drop-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1}.lang-trigger{display:flex;align-items:center;gap:8px;padding:5px 10px;background:#33353a;border:none;border-radius:8px;color:#e6e6e6;font-size:14px;touch-action:manipulation;cursor:pointer}.lang-chevron{font-size:11px;color:#888}.lang-menu{position:absolute;top:calc(100% + 4px);left:0;min-width:100%;background:#2a2c30;border-radius:8px;box-shadow:0 4px 20px #00000080;z-index:2;overflow:hidden}.lang-option{display:block;width:100%;padding:9px 14px;border:none;background:none;color:#e6e6e6;font-size:14px;text-align:left;touch-action:manipulation;white-space:nowrap}.lang-option:active{background:#33353a}.lang-option.active{color:#7ab4f5}.settings-value{min-width:56px;text-align:center;font-size:14px;color:#e6e6e6}.cols-btns{flex-wrap:nowrap;gap:5px}.col-step{min-width:40px;padding:4px 6px;letter-spacing:.3px}.col-fine{color:#aaa}.settings-note{font-size:13px;color:#9aa0a6;flex:1 1 auto;min-width:0}.settings-hint{font-size:12px;color:#7c8088;line-height:1.5;margin-top:8px}.settings-update{margin-top:10px;padding:8px 10px;border-radius:8px;background:rgba(var(--blue-rgb),.12);border:.5px solid rgba(var(--blue-rgb),.35)}.settings-update-title{font-size:14px;color:var(--blue);font-weight:600}.settings-update-how{font-size:12px;color:#9aa0a8;line-height:1.5;margin-top:3px}.settings-update-how code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:#e6e8ec;background:#78788038;padding:1px 5px;border-radius:5px}.settings-hint.preview-dynamic-disabled{color:#6b6f77;border-left:2px solid #34373d;padding-left:8px;margin-top:6px}@keyframes tw-spin{to{transform:rotate(360deg)}}.spinner{display:inline-block;width:14px;height:14px;flex:none;border:2px solid #4a4d52;border-top-color:#e6e6e6;border-radius:50%;animation:tw-spin .7s linear infinite}.bind-input{width:100%;padding:10px;border-radius:8px;border:1px solid #444;background:#1a1b1e;color:#fff;font-size:14px}.startup-custom{margin-top:6px}.opt+.opt{margin-top:14px}.field{width:100%;box-sizing:border-box;display:flex;align-items:center;gap:8px;padding:10px;border-radius:8px;border:1px solid #444;background:#1a1b1e;color:#fff;font-size:14px;text-align:left;touch-action:manipulation}.field:active{border-color:#555}.cwd-field{justify-content:space-between}.cwd-path{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px;opacity:.9}.cwd-action{flex:none;color:var(--blue);font-size:13px}.cwd-reset{margin-top:6px;background:none;border:none;color:#888;font-size:12px;padding:2px 0;touch-action:manipulation}.dd{position:relative}.dd-trigger{justify-content:space-between}.dd-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dd-caret{flex:none;color:#8a8f98;font-size:12px;transition:transform .15s ease}.dd-caret.open{transform:rotate(180deg)}.dd-menu{position:absolute;top:calc(100% + 6px);left:0;right:0;z-index:30;background:#26282c;border:1px solid #3a3c42;border-radius:8px;padding:4px;box-shadow:0 10px 30px #0000008c;transform-origin:top;animation:dd-pop .12s ease}@keyframes dd-pop{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}.dd-option{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:10px;border:none;border-radius:8px;background:none;color:#e6e6e6;font-size:14px;text-align:left;touch-action:manipulation}.dd-option:active{background:#33353a}.dd-option.is-selected{color:var(--green)}.dd-check{flex:none;color:var(--green);font-size:13px}.bind-error{margin-top:8px;color:var(--red);font-size:13px}.bind-hint{margin-top:8px;color:#888;font-size:13px}.bind-actions{margin-top:12px;justify-content:flex-end}.bind-confirm{background:var(--blue);color:#fff}.bind-confirm:disabled{opacity:.6}.windowbar{display:flex;gap:8px;align-items:center;padding:6px 8px;background:#222}.windowbar-scroll{flex:1;min-width:0;display:flex;gap:4px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;touch-action:pan-x;scrollbar-width:none}.windowbar-scroll::-webkit-scrollbar{display:none}.win-tab{white-space:nowrap;padding:4px 10px;border:none;border-radius:8px;background:#33353a;color:#bbb;font-size:13px;touch-action:manipulation}.win-tab.active{background:var(--blue);color:#fff}.win-new{border:1px dashed #555;color:#8aa;font-weight:700;background:transparent}.win-panes{margin-left:5px;font-size:11px;color:#889}.win-tab.active .win-panes{color:#d6e4ff}.wt-dd{position:relative;flex:none}.wt-trigger{display:inline-flex;align-items:center;gap:4px}.wt-trigger .agent-mark{margin-right:0}.wt-sep{margin:0 -1px;color:#cfe0ff;opacity:.4;font-weight:400}.wt-name,.wt-pane{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wt-name{max-width:9ch}.wt-pane{font-weight:600;max-width:11ch}.wt-caret{flex:none;font-size:11px;color:#d6e4ff;transition:transform .15s ease}.wt-caret.open{transform:rotate(180deg)}.wt-menu{position:fixed;top:auto;right:auto;min-width:160px;max-width:240px}.terminal-wrap{position:relative;flex:1;min-height:0;overflow:hidden}.terminal{height:100%;overflow-x:auto;overflow-y:hidden;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;touch-action:pan-x pan-y}.terminal--loading{opacity:0}.terminal .xterm{display:flex;flex-direction:column;justify-content:flex-end;height:100%;width:max-content;min-width:100%}.terminal .xterm-screen{flex:none}.terminal .xterm-viewport{touch-action:pan-x pan-y;overscroll-behavior:contain}.terminal .xterm-helper-textarea{pointer-events:none;opacity:0}.new-output{position:absolute;right:12px;bottom:12px;z-index:5;touch-action:manipulation;padding:8px 14px;border:none;border-radius:16px;background:var(--blue);color:#fff;box-shadow:0 2px 8px #0006}.dbg{position:absolute;left:6px;top:6px;z-index:6;font:12px/1.4 monospace;color:#9fe;background:#0009;padding:2px 6px;border-radius:4px;pointer-events:none}.term-banner{position:absolute;left:0;right:0;top:0;z-index:6;font:12px/1.7 -apple-system,system-ui,sans-serif;text-align:center;padding:2px 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none}.term-banner--hist{background:#e0a800;color:#1a1400}.term-banner--err{background:#d32f2f;color:#fff}.copy-bubble{position:absolute;z-index:7;padding:7px 16px;border:none;border-radius:16px;background:var(--blue);color:#fff;font-size:14px;font-weight:600;box-shadow:0 2px 10px #00000080;touch-action:manipulation}.sel-hint{position:absolute;left:50%;top:12px;transform:translate(-50%);z-index:8;max-width:92%;padding:7px 14px;border-radius:16px;background:rgba(var(--blue-rgb),.96);color:#fff;font-size:13px;font-weight:600;white-space:nowrap;box-shadow:0 2px 10px #00000080;pointer-events:none}.input-text{flex:1;min-width:0;padding:7px 6px 7px 11px;border:none;background:transparent;color:#fff;font-family:inherit;font-size:16px;line-height:22px;max-height:156px;resize:none;overflow-y:auto;display:block}.input-text:focus{outline:none}.input-text::placeholder{color:#6b7280}.token-prompt button{padding:8px 14px;border:none;border-radius:8px;background:var(--blue);color:#fff}.drawer{position:fixed;top:0;left:0;width:78%;max-width:320px;height:100%;background:#232427;transform:translate(-100%);transition:transform .2s;z-index:10;padding:12px;display:flex;flex-direction:column;overflow:hidden}.drawer.open{transform:translate(0)}.drawer-list{flex:1;min-height:0;overflow-y:auto}.drawer-logout{flex:none;margin-top:8px;padding:10px;border:none;border-radius:8px;background:#2e2a2c;color:var(--red);font-size:14px;touch-action:manipulation}.drawer-logout:active{background:#4a2f33}.drawer-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#0006;z-index:9}.drawer-title{font-size:12px;color:#888;letter-spacing:1px;margin-bottom:8px}.drawer-row{display:flex;align-items:center;gap:6px;border-radius:8px}.drawer-name{flex:1;min-width:0;padding:8px 4px;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.drawer-session.active{background:var(--blue);color:#fff}.drawer-unbind{flex:none;background:none;border:none;color:#888;font-size:14px;padding:6px 8px;touch-action:manipulation;display:inline-flex;align-items:center;justify-content:center;min-width:40px;min-height:44px}.drawer-session.active .drawer-unbind{color:#d6e4ff}.drawer-empty{padding:12px 4px;color:#888;font-size:13px}.drawer-bind{width:100%;margin-top:8px;padding:10px;border:none;border-radius:8px;background:#2b3550;color:#cdddff;font-size:14px;touch-action:manipulation}.drawer-bind:active{background:#344168}.token-prompt{max-width:360px;margin:80px auto;display:flex;flex-direction:column;gap:12px;padding:0 16px}.token-prompt input{padding:10px;border-radius:8px;border:1px solid #444;background:#1a1b1e;color:#fff}.loading{padding:40px;text-align:center;color:#888}.empty-cta{margin:auto;display:flex;flex-direction:column;gap:6px;align-items:center;padding:28px 32px;background:none;border:1px dashed #44464c;border-radius:12px;color:#aab;font-size:15px;touch-action:manipulation}.empty-cta span{font-size:13px;color:var(--blue)}.empty-cta:active{background:#232427}.bottom-dock{display:flex;gap:8px;padding:8px;background:#2a2b2e;align-items:stretch}.dock-left{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}.dock-dots{position:relative;display:flex;justify-content:center;align-items:center;gap:8px;padding:3px 0 4px;width:100%;border:none;background:transparent;-webkit-tap-highlight-color:transparent}.dock-dots:active .dock-dot{background:#5a5e66}.dock-dots:active .dock-dot.on{background:#6a93ff}.dock-dot{width:6px;height:6px;border-radius:50%;background:#4a4d54}.dock-dot.on{background:var(--blue)}.dock-mode-label{position:absolute;left:2px;top:50%;transform:translateY(-50%);font-size:10px;line-height:1;color:#8a93a0;white-space:nowrap;pointer-events:none}.dock-pager{overflow:hidden;min-width:0;contain:paint}.dock-track{display:flex;align-items:flex-start;width:200%;will-change:transform;transform:translateZ(0);transition:transform .3s cubic-bezier(.22,.61,.36,1)}.dock-track.at-chat{transform:translate3d(-50%,0,0)}.dock-track>.dock-page{flex:0 0 50%;width:50%;min-width:0}.dock-page.command{position:relative}.keybar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;min-width:0}.keybar-key{min-width:0;min-height:40px;padding:0 2px;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:8px;white-space:nowrap;background:#33353a;color:#e6e6e6;font:14px/1 ui-monospace,SF Mono,Menlo,monospace;touch-action:manipulation;-webkit-user-select:none;user-select:none}.keybar-key:active{background:var(--blue);color:#fff}.keybar-key svg{width:20px;height:20px;display:block}.keybar-mod.armed{background:var(--blue);color:#fff}.keybar-mod.locked{background:var(--blue);color:#fff;box-shadow:inset 0 -3px #ffd24a}.dock-input-row{display:flex;gap:6px;align-items:stretch}.input-wrap{position:relative;flex:1;min-width:0;display:flex;align-items:flex-end;gap:4px;padding:5px 6px 5px 5px;border:1px solid #3a3d44;border-radius:20px;background:#202227;box-shadow:0 1px 6px #00000059;transition:border-color .15s,box-shadow .15s}.input-wrap:focus-within{border-color:var(--green);box-shadow:0 0 0 1px rgba(var(--green-rgb),.4),0 2px 12px #0006}.input-wrap>.input-history,.input-wrap>.input-mic,.input-wrap>.input-send{margin-bottom:2px}.cmd-capture{position:absolute;left:0;bottom:0;width:2px;height:2px;padding:0;margin:0;border:0;opacity:0;background:transparent;color:transparent}.quick-bar{display:flex;align-items:stretch;gap:6px;padding:0 2px 6px}.quick-fixed{flex:none;display:flex;gap:6px;padding-right:7px;border-right:1px solid #33363d}.quick-fix{flex:none;display:inline-flex;align-items:center;gap:5px;border:1px solid #4a4f59;border-radius:9px;background:#383c44;color:#eaedf2;font:inherit;font-size:13.5px;font-weight:600;padding:7px 11px;line-height:1;touch-action:manipulation;-webkit-user-select:none;user-select:none}.quick-fix svg{width:15px;height:15px;display:block;color:#aeb6c2}.quick-fix:active{background:#454a54}.quick-fix:disabled{opacity:.4}.quick-scroll{flex:1;min-width:0;display:flex;align-items:stretch;gap:5px;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}.quick-scroll::-webkit-scrollbar{display:none}.quick-cmd{flex:none;display:inline-flex;align-items:center;white-space:nowrap;border:1px solid;border-radius:12px;color:rgb(var(--rgb));border-color:rgba(var(--rgb),.5);background:rgba(var(--rgb),.13);font:inherit;font-size:13.5px;padding:7px 12px;line-height:1;touch-action:manipulation;-webkit-user-select:none;user-select:none}.quick-cmd:active{background:rgba(var(--rgb),.26);border-color:rgb(var(--rgb))}.quick-cmd-add{--rgb: 150,157,167;border-style:dashed;padding:7px 11px}.quick-cmd-add svg{width:15px;height:15px;display:block}.qc-enter{margin-left:5px;opacity:.7;font-size:12px}.qc-esc{--rgb: 150,157,167}.qc-reply{--rgb: 95,208,138}.qc-cmd{--rgb: 110,168,255}.quick-cmd-plain{--rgb: 150,157,167}.quick-cmd-win{--rgb: 95,208,138}.dock-upload{padding:6px 4px 2px}.dock-upload-label{display:block;color:#9fb6d0;font-size:12px;margin-bottom:4px;font-variant-numeric:tabular-nums}.dock-upload.error .dock-upload-label{color:var(--red)}.dock-upload-track{display:block;height:4px;border-radius:2px;background:#1c2b3a;overflow:hidden}.dock-upload-fill{display:block;height:100%;background:#3a5a7e;transition:width .1s linear}.upload-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:200;display:grid;place-items:center;background:#0000009e;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);padding:24px;padding-bottom:calc(24px + env(safe-area-inset-bottom))}.upload-card{width:min(340px,86vw);background:#141b24;border:1px solid #24303d;border-radius:14px;padding:22px 20px 18px;box-shadow:0 24px 70px #0009;text-align:center}.upload-card-label{color:#e6edf3;font-size:14px;margin-bottom:16px;word-break:break-all;font-variant-numeric:tabular-nums}.upload-bar{height:6px;border-radius:3px;background:#1c2b3a;overflow:hidden}.upload-bar-fill{height:100%;background:var(--green);transition:width .12s linear}.upload-card-sub{color:#9fb6d0;font-size:12px;margin-top:10px;font-variant-numeric:tabular-nums}.upload-spinner{width:34px;height:34px;margin:4px auto 0;border-radius:50%;border:3px solid #24303d;border-top-color:var(--green);animation:upload-spin .8s linear infinite}@keyframes upload-spin{to{transform:rotate(360deg)}}.upload-cancel{margin-top:18px;width:100%;height:40px;border:1px solid #33424f;border-radius:10px;background:#1c2530;color:#e6edf3;font-size:14px}.upload-cancel:active{background:#243040}@media (prefers-reduced-motion: reduce){.upload-spinner{animation-duration:1.6s}}.input-send{flex:none;width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:var(--blue);color:#fff;padding:0;box-shadow:0 1px 4px rgba(var(--blue-rgb),.45);touch-action:manipulation;-webkit-user-select:none;user-select:none}.input-send:active{background:var(--blue-press)}.input-send:disabled{background:#00000040;color:#b6c0cc;box-shadow:none}.input-send svg{width:20px;height:20px;display:block}.input-history{flex:none;width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:8px;background:transparent;color:#8a93a0;padding:0;touch-action:manipulation;-webkit-user-select:none;user-select:none}.input-history svg{width:20px;height:20px;display:block}.input-history:active{color:var(--blue)}.input-wrap.recording{background:rgba(var(--green-rgb),.14);border:2px solid var(--green);animation:rec-breathe 1.3s ease-in-out infinite}.input-wrap.recording .input-text{color:#eafff3}@keyframes rec-breathe{0%,to{box-shadow:0 0 5px rgba(var(--green-rgb),.3);border-color:#2fd07e}50%{box-shadow:0 0 16px 4px rgba(var(--green-rgb),.8);border-color:var(--green)}}.input-mic{flex:none;width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:#00000040;color:#b6c0cc;padding:0;touch-action:manipulation;-webkit-user-select:none;user-select:none}.input-mic.on{color:#fff;background:var(--green)}.input-mic:disabled{opacity:.5}.input-mic svg{width:21px;height:21px;display:block}.cmd-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;z-index:21}.cmd-panel{position:fixed;left:0;right:0;bottom:0;z-index:22;max-height:72vh;display:flex;flex-direction:column;background:#232427;border-radius:16px 16px 0 0;box-shadow:0 -8px 30px #00000080}.cmd-panel.history{min-height:40vh}.cmd-head{display:flex;align-items:center;gap:8px;padding:12px 14px;border-bottom:1px solid #33353a}.cmd-title{font-size:16px;font-weight:600;margin-right:auto;display:flex;align-items:center;gap:7px}.idea-head-count{font-size:11px;font-weight:600;color:#a8c4e0;background:#3d5068;border-radius:8px;padding:1px 6px}.cmd-close{flex:none;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:50%;background:#78788029;color:#ebebf58c;font-size:15px;line-height:1;touch-action:manipulation}.cmd-close:active{background:#7878804d;color:#fff}.cmd-close svg{width:14px;height:14px;display:block}.cmd-add-open{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border:none;border-radius:9px;background:var(--blue);color:#fff;padding:0;touch-action:manipulation;box-shadow:0 1px 4px rgba(var(--blue-rgb),.4)}.cmd-add-open:active{background:var(--blue-press)}.cmd-add-open svg{width:18px;height:18px;display:block}.cmd-list{overflow-y:auto;-webkit-overflow-scrolling:touch;padding:6px 0 10px}.cmd-editor .cmd-list{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;padding:0}.cmd-editor .cmd-esection{flex:1 1 0;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column}.cmd-editor .cmd-esection .cmd-section{position:sticky;top:0;z-index:1;background:#1c1c1e}.cmd-editor .cmd-empty{flex:1;display:flex;align-items:center;justify-content:center;font-size:15px}.cmd-panel.cmd-editor{background:#1c1c1e}.cmd-editor .cmd-section{padding:12px 16px 6px}.cmd-editor .cmd-section-name{font-size:13px;letter-spacing:.4px}.cmd-editor .cmd-row{padding:0 10px 0 16px}.cmd-editor .cmd-row:not(:last-child){box-shadow:inset 0 -.5px #54545857}.cmd-editor .cmd-text{font-size:14px;padding:12px 0;color:#f2f2f7}.cmd-editor .cmd-enter{font-size:14px}.cmd-editor .cmd-move svg{width:18px;height:18px}.cmd-editor .cmd-del svg{width:16px;height:16px}.cmd-section{display:flex;align-items:baseline;gap:8px;padding:9px 14px 5px}.cmd-section.recent{margin-top:6px;border-top:1px solid #2c2e33;padding-top:12px}.cmd-section-name{font-size:12px;font-weight:700;letter-spacing:1px}.cmd-section.fav .cmd-section-name{color:#ffd27a}.cmd-section.recent .cmd-section-name{color:#9db8ff}.cmd-scope{margin-left:auto;font-size:10px;color:#9a9a9a;background:#2c2e33;padding:2px 8px;border-radius:10px;white-space:nowrap}.cmd-row{display:flex;align-items:center;gap:6px;padding:0 8px 0 14px}.cmd-text{flex:1;min-width:0;padding:9px 0;font:13px/1.3 ui-monospace,SF Mono,Menlo,monospace;color:#e6e6e6;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;touch-action:manipulation}button.cmd-text{background:none;border:none;text-align:left}.cmd-text:active{color:#9db8ff}.cmd-star{flex:none;background:none;border:none;color:#667;padding:6px 8px;touch-action:manipulation;display:inline-flex;align-items:center;justify-content:center;min-width:40px;min-height:44px}.cmd-star svg{width:16px;height:16px;display:block}.cmd-star.on{color:#ffd27a}.cmd-star.on svg{fill:currentColor}.cmd-copy{flex:none;background:none;border:none;color:#8a93a0;padding:6px 8px;touch-action:manipulation;display:inline-flex;align-items:center;justify-content:center;min-width:40px;min-height:44px}.cmd-copy svg{width:15px;height:15px;display:block}.cmd-copy:active{color:#9db8ff}.cmd-del{flex:none;background:none;border:none;color:#888;padding:6px 8px;touch-action:manipulation;display:inline-flex;align-items:center;justify-content:center;min-width:40px;min-height:44px}.cmd-del svg{width:14px;height:14px;display:block}.cmd-empty{padding:20px 14px;color:#888;font-size:13px;text-align:center}.cmd-hint{padding:2px 14px 8px;color:#7f8794;font-size:11px}.fav-chips{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}.fav-chip{background:#2a3a2e;border:1px solid #3d5a44;color:#9fe0af;border-radius:16px;padding:8px 14px;font-size:14px}.fav-add{display:flex;gap:8px;margin-top:8px}.fav-add-input{flex:1;min-width:0;background:#16171c;border:1px solid #444;border-radius:8px;color:#fff;padding:8px;font-size:16px}.fav-add-btn{border:none;border-radius:8px;background:var(--blue);color:#fff;padding:0 14px}.cmd-panel.cmd-editor{min-height:58vh}.cmd-esection{padding-bottom:6px}.cmd-esection.win{margin-top:4px;border-top:1px solid #2c2e33}.cmd-section.global .cmd-section-name{color:#aab0ba}.cmd-section.win .cmd-section-name{color:#5fd08a}.cmd-fav-text{flex:1}.cmd-enter{margin-left:7px;opacity:.65;font-size:12px}.cmd-move{flex:none;background:none;border:none;color:#8a93a0;padding:6px 5px;touch-action:manipulation;display:inline-flex;align-items:center;justify-content:center;min-width:36px;min-height:44px}.cmd-move svg{width:16px;height:16px;display:block}.cmd-move.up svg{transform:rotate(180deg)}.cmd-move:active{color:#9db8ff}.cmd-move:disabled{opacity:.28}.cmd-add-backdrop{z-index:23;background:#0009}.cmd-addcard{position:fixed;left:50%;top:50%;z-index:24;width:min(360px,calc(100vw - 32px));display:flex;flex-direction:column;gap:16px;background:#1c1c1e;border-radius:20px;padding:18px 18px 20px;box-shadow:0 24px 60px #000000a8;-webkit-font-smoothing:antialiased}.cmd-addcard-head{display:flex;align-items:center}.cmd-addcard-head .cmd-title{margin-right:auto;font-size:17px;font-weight:700;letter-spacing:.2px}.cmd-modetabs{display:flex;gap:24px;border-bottom:1px solid rgba(84,84,88,.5);padding:0 2px}.cmd-modetab{position:relative;border:none;background:none;padding:2px 0 12px;font:inherit;font-size:17px;font-weight:600;color:#ebebf580;touch-action:manipulation;transition:color .15s}.cmd-modetab.on{color:#fff}.cmd-modetab.on:after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2.5px;border-radius:2px;background:var(--blue)}.cmd-seg{display:flex;gap:2px;background:#76768038;border-radius:9px;padding:2px}.cmd-seg-btn{flex:1;border:none;background:transparent;color:#ebebf59e;font:inherit;font-size:14px;font-weight:600;padding:8px 0;border-radius:7px;touch-action:manipulation;transition:color .15s}.cmd-seg-btn.on{background:#48484a;color:#fff;box-shadow:0 1px 3px #00000059,0 0 0 .5px #0003}.cmd-seg-btn.win.on{background:#2f6f4a;color:#d6f5e2}.cmd-seg-btn:active:not(.on){color:#fff}.cmd-seg-btn:disabled{opacity:.38}.cmd-field{display:flex;flex-direction:column;gap:8px}.cmd-field-label{font-size:12px;font-weight:600;color:#ebebf599;padding-left:2px}.cmd-add-input{width:100%;box-sizing:border-box;background:#2c2c2e;border:none;border-radius:10px;color:#f2f2f7;padding:12px 13px;font:16px/1.2 ui-monospace,SF Mono,Menlo,monospace;box-shadow:0 0 0 1px transparent;transition:box-shadow .15s}.cmd-add-input::placeholder{color:#ebebf54d}.cmd-add-input:focus{outline:none;box-shadow:0 0 0 2px var(--blue)}.cmd-chord-preview{align-self:flex-start;color:#64d2ff;font-size:13px;font-weight:700;letter-spacing:.3px}.cmd-toggle-row{display:flex;align-items:center;justify-content:space-between;gap:8px;background:#2c2c2e;border-radius:10px;padding:11px 13px;color:#f2f2f7;font-size:15px;touch-action:manipulation}.cmd-switch{position:relative;flex:none;width:51px;height:31px}.cmd-switch input{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;margin:0;opacity:0;z-index:1}.cmd-switch-track{position:absolute;top:0;right:0;bottom:0;left:0;background:#39393d;border-radius:16px;transition:background .22s ease}.cmd-switch input:checked~.cmd-switch-track{background:var(--green)}.cmd-switch-knob{position:absolute;top:2px;left:2px;width:27px;height:27px;border-radius:50%;background:#fff;box-shadow:0 2px 5px #00000059;transition:transform .22s ease}.cmd-switch input:checked~.cmd-switch-knob{transform:translate(20px)}.cmd-submit{border:none;border-radius:13px;background:var(--blue);color:#fff;font:inherit;font-size:17px;font-weight:600;padding:13px 0;margin-top:2px;touch-action:manipulation;transition:background .12s}.cmd-submit:active{background:var(--blue-press)}.cmd-submit:disabled{background:#2c2c2e;color:#ebebf54d}.cmd-dd{position:relative}.cmd-dd-btn{display:flex;align-items:center;justify-content:space-between;width:100%;box-sizing:border-box;background:#2c2c2e;border:none;border-radius:10px;color:#f2f2f7;font:inherit;font-size:16px;padding:12px 13px;box-shadow:0 0 0 2px transparent;transition:box-shadow .15s;touch-action:manipulation}.cmd-dd-btn.open{box-shadow:0 0 0 2px var(--blue)}.cmd-dd-btn svg{width:17px;height:17px;color:#ebebf580;transition:transform .18s}.cmd-dd-btn.open svg{transform:rotate(180deg)}.cmd-dd-ph{color:#ebebf54d}.cmd-dd-scrim{position:fixed;top:0;right:0;bottom:0;left:0;z-index:24}.cmd-dd-menu{position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:25;background:#2c2c2e;border-radius:12px;padding:5px;max-height:216px;overflow-y:auto;-webkit-overflow-scrolling:touch;box-shadow:0 14px 36px #0009,0 0 0 .5px #0006}.cmd-dd-opt{display:flex;align-items:center;justify-content:space-between;width:100%;border:none;background:transparent;color:#f2f2f7;font:inherit;font-size:16px;text-align:left;padding:11px 12px;border-radius:8px;touch-action:manipulation}.cmd-dd-opt.on{color:var(--blue);font-weight:600}.cmd-dd-opt:active{background:#3a3a3c}.cmd-dd-opt svg{width:16px;height:16px}.idea-panel{position:fixed;left:0;right:0;bottom:0;z-index:22;min-height:50vh;max-height:80vh;display:flex;flex-direction:column;background:#232427;border-radius:16px 16px 0 0;box-shadow:0 -8px 30px #00000080}.idea-compose{display:flex;align-items:flex-end;gap:8px;padding:10px 14px;border-bottom:1px solid #33353a}.idea-input{flex:1;min-width:0;resize:none;max-height:96px;padding:8px 10px;border:1px solid #3a3c42;border-radius:8px;background:#1b1c1f;color:#e6e6e6;font:14px/1.4 -apple-system,system-ui,sans-serif}.idea-input:focus{outline:none;border-color:var(--blue)}.idea-compose .input-mic{position:static;right:auto;bottom:auto;flex:none}.idea-act{flex:none;width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:var(--blue);color:#fff;padding:0;touch-action:manipulation}.idea-act:disabled{background:#00000040;color:#b6c0cc;opacity:.55}.idea-act svg{width:20px;height:20px;display:block}.idea-cancel{flex:none;background:none;border:none;color:#aaa;font-size:13px;padding:9px 4px;touch-action:manipulation}.idea-list{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:6px 0 12px}.idea-list:has(.cmd-empty){display:flex;align-items:center;justify-content:center}.idea-row{display:flex;align-items:center;gap:6px;padding:0 8px 0 4px;background:#232427}.idea-row.editing{background:#262a31}.idea-row.dragging{background:#2c2f36;border-radius:8px;box-shadow:0 2px 12px #00000073}.idea-handle{flex:none;background:none;border:none;color:#777;font-size:20px;line-height:1;padding:11px 16px;cursor:grab;touch-action:none;-webkit-user-select:none;user-select:none}.idea-text{flex:1;min-width:0;padding:11px 0;font-size:14px;line-height:1.35;color:#e6e6e6;white-space:pre-wrap;overflow-wrap:anywhere;touch-action:manipulation}.idea-text:active{color:#9db8ff}.idea-send{flex:none;background:#2c2e33;color:#9db8ff;border:none;border-radius:8px;padding:6px 10px;font-size:13px;touch-action:manipulation}.idea-del{flex:none;background:none;border:none;color:#888;font-size:14px;padding:6px 8px;touch-action:manipulation;display:inline-flex;align-items:center;justify-content:center;min-width:40px;min-height:44px}.changelog-panel{position:fixed;left:0;right:0;bottom:0;z-index:22;max-height:80vh;display:flex;flex-direction:column;background:#232427;border-radius:16px 16px 0 0;box-shadow:0 -8px 30px #00000080}.changelog-list{overflow-y:auto;-webkit-overflow-scrolling:touch;padding:6px 16px 16px}.rel{padding:12px 0;border-bottom:1px solid #2c2e33}.rel:last-child{border-bottom:none}.rel-date{font-size:12px;font-weight:700;letter-spacing:.5px;color:#9db8ff;margin-bottom:6px}.rel-items{margin:0;padding-left:18px}.rel-items li{font-size:13px;line-height:1.5;color:#e6e6e6;margin:3px 0}.topbar-icon{position:relative}.topbar-dot{position:absolute;top:7px;right:7px;width:7px;height:7px;border-radius:50%;background:var(--red);box-shadow:0 0 0 2px #1b1c1f}.idea-badge{position:absolute;top:5px;right:4px;min-width:14px;height:14px;border-radius:7px;padding:0 3px;box-sizing:border-box;background:#3d5068;color:#a8c4e0;font-size:9px;font-weight:700;line-height:14px;text-align:center;pointer-events:none}.settings-dot{display:inline-block;width:7px;height:7px;margin-left:6px;border-radius:50%;background:var(--red);vertical-align:middle}.sheet-actions{display:flex;flex-direction:column;gap:8px}.sheet-action{width:100%;padding:12px;border:1px solid #33353a;border-radius:8px;background:#2a2c31;color:#ddd;font-size:15px;text-align:center;touch-action:manipulation}.sheet-action.danger{color:var(--red)}.sheet-action.armed{background:var(--red);color:#fff;border-color:var(--red)}.sheet-action:disabled{opacity:.4}.sheet-row{display:flex;gap:8px}.sheet-row .sheet-action{flex:1}.sheet-cancel{margin-top:4px}.win-tab,.session-name{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}.file-sheet{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;display:flex;flex-direction:column;background:#0b0f14;transform:translateY(100%);transition:transform .28s cubic-bezier(.22,.61,.36,1);pointer-events:none}.file-sheet.open{transform:translateY(0);pointer-events:auto}.file-tabs{display:flex;align-items:stretch;border-bottom:1px solid #1d2630;background:#11161d}.file-tabs-scroll{display:flex;overflow-x:auto;flex:1;-webkit-overflow-scrolling:touch}.file-tab{display:inline-flex;align-items:center;white-space:nowrap;border-right:1px solid #1d2630}.file-tab.active{background:#0b0f14;box-shadow:inset 0 -2px 0 var(--blue)}.file-tab-label{display:inline-flex;align-items:center;gap:5px;padding:10px 8px 10px 12px;background:transparent;border:none;color:#9fb0c0;font-size:13px}.file-tab-label svg{width:15px;height:15px}.file-tab.active .file-tab-label{color:#e6edf3}.file-tab-x{background:transparent;border:none;color:#6b7a89;font-size:11px;padding:0 10px 0 2px}.file-min{flex:0 0 auto;width:44px;display:inline-flex;align-items:center;justify-content:center;background:transparent;color:#9fb0c0;border:none;border-left:1px solid #1d2630}.file-min svg{width:20px;height:20px}.file-body{flex:1;overflow:hidden;display:flex}.preview-frame{flex:1;width:100%;border:0;background:#fff}.preview-body.pc{display:block;position:relative;overflow:auto;-webkit-overflow-scrolling:touch}.preview-scaler{position:relative}.preview-body.pc .preview-frame{position:absolute;top:0;left:0;flex:none}.preview-zoom{position:absolute;bottom:14px;left:50%;transform:translate(-50%);z-index:2;display:flex;align-items:center;gap:2px;padding:4px;background:#1c1e22eb;border:1px solid #3a3c42;border-radius:999px;box-shadow:0 6px 20px #00000073}.preview-zoom-btn{width:34px;height:30px;display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;color:#e6edf3;font-size:20px;line-height:1;border-radius:999px;touch-action:manipulation}.preview-zoom-btn:disabled{color:#5a626b}.preview-zoom-val{min-width:46px;text-align:center;color:#9fb0c0;font-size:13px;font-variant-numeric:tabular-nums}.preview-head{position:relative;align-items:center;gap:4px;min-height:44px;padding-left:10px}.preview-status{display:inline-flex;align-items:center;gap:5px;min-width:0;color:#e6edf3;font-size:12px}.preview-status svg{width:15px;height:15px;flex:0 0 auto}.preview-state{color:var(--green);font-weight:600;flex:0 0 auto}.preview-name{color:#9fb0c0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.preview-detail{color:#6e7d8c;margin-left:6px}.preview-remain{margin-left:auto;flex:0 0 auto;font-variant-numeric:tabular-nums;color:#9fb0c0;font-size:12px;padding:4px 8px;background:transparent;border:1px solid #33353a;border-radius:8px;touch-action:manipulation}.preview-remain:active{color:var(--blue);border-color:var(--blue)}.preview-pop-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:5}.preview-pop{position:absolute;top:46px;right:8px;z-index:6;min-width:168px;display:flex;flex-direction:column;gap:2px;padding:6px;background:#232427;border:1px solid #33353a;border-radius:10px;box-shadow:0 10px 30px #00000080}.preview-pop-item{background:transparent;border:none;color:#e6edf3;text-align:left;padding:10px 12px;border-radius:8px;font-size:14px}.preview-pop-item:active{background:#2f3338}.preview-pop-danger{color:var(--red)}.preview-iconbtn{flex:0 0 auto;width:32px;display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;color:#9fb0c0;touch-action:manipulation}.preview-iconbtn svg{width:17px;height:17px}.preview-iconbtn:active{color:var(--blue)}.preview-head .file-min{width:34px}.preview-head .file-min svg{width:18px;height:18px}.preview-confirm-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;display:flex;align-items:center;justify-content:center;background:#00000080}.preview-confirm{width:min(86vw,320px);background:#232427;border-radius:12px;padding:16px;box-shadow:0 10px 40px #00000080}.preview-confirm-title{font-size:16px;font-weight:600;color:#e6edf3;margin-bottom:8px}.preview-confirm-text{font-size:13px;color:#9aa3ad;line-height:1.5;margin-bottom:14px}.preview-confirm-btns{display:flex;justify-content:flex-end;gap:8px}.preview-confirm-danger{background:#5a1f1f;color:var(--red)}.settings-group{margin:16px -16px 0;padding:7px 16px;background:#1b1c1f;color:#9aa3ad;font-size:11px;font-weight:700;letter-spacing:1.2px;border-top:1px solid #33353a;border-bottom:1px solid #33353a}.settings-head+.settings-group{margin-top:0}.settings-group+.settings-section{border-top:none}.preview-running{display:inline-flex;align-items:center;gap:6px;color:var(--green);font-weight:600;font-size:13px}.live-dot{width:8px;height:8px;border-radius:50%;background:var(--green)}.preview-port{width:9em;padding:6px 10px;font-size:15px;color:#e8e8ea;background:#1b1c1f;border:1px solid #3a3c42;border-radius:8px}.preview-seg{display:inline-flex;align-self:flex-start;gap:2px;background:#76768038;border-radius:9px;padding:2px}.preview-seg button{background:transparent;border:none;color:#ebebf599;padding:7px 18px;min-width:60px;font-size:14px;font-weight:600;border-radius:7px;touch-action:manipulation;transition:color .15s}.preview-seg button.on{background:#48484a;color:#fff;box-shadow:0 1px 3px #00000059,0 0 0 .5px #0003}.preview-seg button:active:not(.on){color:#fff}.preview-start{display:flex;flex-direction:column;gap:12px}.preview-active{display:flex;flex-direction:column;gap:10px}.preview-active-head{display:flex;align-items:center;gap:10px}.preview-remain-s{margin-left:auto;font-variant-numeric:tabular-nums;color:#9aa3ad;font-size:13px}.settings-err{color:var(--red)}.preview-live{color:var(--green)}.home-pane{flex:1;display:flex;flex-direction:column;min-width:0}.file-seg{display:flex;gap:2px;margin:10px 12px;padding:2px;background:#76768033;border-radius:9px}.file-seg-btn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:7px;border:none;border-radius:7px;background:transparent;color:#ebebf599;font-size:14px;font-weight:600;touch-action:manipulation;transition:color .15s}.file-seg-btn.on{background:#48484a;color:#fff;box-shadow:0 1px 3px #00000059,0 0 0 .5px #0003}.file-seg-btn:active:not(.on){color:#cfe0f2}.file-seg-btn svg{width:16px;height:16px}.git-head{align-items:stretch;min-height:42px}.git-back{flex:0 0 auto;width:40px;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;color:#9fb0c0;font-size:26px;line-height:1}.git-drill-head{flex:1;min-width:0;display:flex;align-items:center;gap:4px;overflow:hidden}.git-drill-title{display:inline-flex;align-items:center;gap:7px;min-width:0;color:#e6edf3;font-size:14px}.git-drill-title svg{width:16px;height:16px;color:#6b86a3;flex:0 0 auto}.git-title-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.git-tabs-scroll{display:flex;align-items:stretch;overflow-x:auto;flex:1;-webkit-overflow-scrolling:touch}.git-tab-add{flex:0 0 auto;width:40px;display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;border-right:1px solid #1d2630;color:#8fb2dc;font-size:20px;line-height:1}.git-tab{flex:0 0 auto;display:inline-flex;align-items:center;white-space:nowrap;border-right:1px solid #1d2630}.git-tab.active{background:#0b0f14;box-shadow:inset 0 -2px 0 var(--blue)}.git-tab-label{display:inline-flex;align-items:center;padding:10px 4px 10px 12px;background:transparent;border:none;color:#9fb0c0;font-size:13px}.git-tab.active .git-tab-label{color:#e6edf3}.git-tab-x{background:transparent;border:none;color:#6b7a89;font-size:11px;padding:0 10px 0 4px;align-self:stretch}.git-branch-bar{display:flex;align-items:center;gap:10px;padding:7px 12px 7px 14px;border-bottom:1px solid #1d2630;background:#0b0f14;font-size:13px}.git-branch-bar-name{flex:1;min-width:0;color:#cfe0f2;font-weight:600;display:flex;align-items:center;gap:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.git-branch-glyph{color:#8fb2dc}.git-branch-cur-tag{flex:0 0 auto;font-size:11px;font-weight:600;color:var(--green);background:rgba(var(--green-rgb),.12);border:1px solid rgba(var(--green-rgb),.4);border-radius:999px;padding:1px 7px}.git-branch-bar-track{flex:0 0 auto;font-size:12px;font-variant-numeric:tabular-nums;display:flex;gap:5px}.git-branch-dd{position:relative;flex:0 0 auto}.git-branch-trigger{max-width:46vw;display:flex;align-items:center;gap:5px;background:#11161d;border:1px solid #1d2630;border-radius:8px;color:#9fb0c0;font-size:12px;padding:5px 9px}.git-branch-trigger.other{border-color:#2f6fc0;background:#15212f;color:#cfe0f2}.git-branch-trigger-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.git-branch-caret{flex:0 0 auto;display:inline-flex;color:#6b7a89}.git-branch-caret svg{width:13px;height:13px}.git-dd-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:40}.git-dd-menu{position:absolute;top:calc(100% + 6px);right:0;z-index:41;min-width:56vw;max-width:calc(100vw - 24px);max-height:56vh;overflow:auto;-webkit-overflow-scrolling:touch;background:#0e141b;border:1px solid #243040;border-radius:10px;box-shadow:0 10px 28px #00000080;padding:4px}.git-dd-item{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:transparent;border:none;color:#e6edf3;padding:10px;font-size:13px;border-radius:7px}.git-dd-item:active{background:#15212f}.git-dd-item.viewing{background:#15212f;box-shadow:inset 3px 0 #2f6fc0}.git-dd-item.current .git-row-path{color:#cfe0f2;font-weight:600}.git-section{display:flex;flex-direction:column;min-height:0;border-bottom:1px solid #161d26}.git-section:not(.open){flex:0 0 auto}.git-section.open.git-section--top{flex:0 1 auto;min-height:25%;max-height:50%}.git-section.open.git-section--mid{flex:1 1 0;min-height:96px}.git-section-head{flex:0 0 auto;display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:#0b0f14;border:none;color:#9fb0c0;padding:10px 14px;font-size:13px;font-weight:600}.git-section-head:active{background:#11161d}.git-section-caret{flex:0 0 auto;display:inline-flex;color:#6b7a89;transition:transform .15s;transform:rotate(-90deg)}.git-section.open .git-section-caret{transform:rotate(0)}.git-section-caret svg{width:14px;height:14px}.git-section-title{flex:0 0 auto}.git-section-sub{flex:1;min-width:0;color:#6b7a89;font-weight:400;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.git-section-count{flex:0 0 auto;margin-left:auto;color:#6b7a89;font-weight:400;font-size:12px;font-variant-numeric:tabular-nums}.git-section-sub+.git-section-count{margin-left:8px}.git-section-body{flex:1;min-height:0;overflow:auto;-webkit-overflow-scrolling:touch}.git-more{text-align:center;color:#6b7a89;font-size:12px;padding:12px}.git-body{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;padding-bottom:var(--kb-inset, 0px)}.git-scroll{flex:1;min-height:0;overflow:auto;-webkit-overflow-scrolling:touch}.git-error{color:var(--red);font-size:13px;padding:14px 16px}.git-loading,.git-empty{color:#6b7a89;font-size:13px;padding:16px}.git-notice{color:#8b97a5;font-size:13px;line-height:1.5;padding:14px 16px}.git-list{display:flex;flex-direction:column}.git-row{display:flex;align-items:center;gap:9px;width:100%;text-align:left;background:transparent;border:none;border-bottom:1px solid #161d26;color:#e6edf3;padding:11px 14px;font-size:13px}.git-row:active{background:#11161d}.git-row-path{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;flex:1}.git-badge{flex:0 0 auto;width:20px;text-align:center;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;color:#9aa3ad}.git-badge-m{color:#d8a13a}.git-badge-a{color:var(--green)}.git-badge-d{color:#f06b6b}.git-badge-r{color:#8fb2dc}.git-badge-q{color:#6b7a89}.git-commit-row{align-items:flex-start}.git-hash{flex:0 0 auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:#8fb2dc;font-size:12px;padding-top:1px}.git-commit-main{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}.git-commit-meta{color:#6b7a89;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.git-branch{gap:8px}.git-branch.current .git-row-path{color:#cfe0f2;font-weight:600}.git-branch.viewing{background:#11161d;box-shadow:inset 3px 0 #2f6fc0}.git-branch-dot{flex:0 0 auto;width:12px;text-align:center;color:var(--green);font-size:11px}.git-branch-up{flex:0 0 auto;color:#6b7a89;font-size:11px;font-variant-numeric:tabular-nums}.git-ahead{color:var(--green)}.git-behind{color:#f06b6b}.git-commit-detail{display:flex;flex-direction:column}.git-commit-msg{white-space:pre-wrap;word-break:break-word;margin:0;padding:14px 16px;color:#c9d6e2;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:1.5;border-bottom:1px solid #161d26;background:#0e131a}.git-diff-wrap{display:flex;flex-direction:column}.git-diff-zoom{position:sticky;top:0;z-index:2;display:flex;gap:6px;justify-content:flex-end;padding:8px 12px}.git-diff-trunc{position:sticky;top:0;z-index:1;background:#3a2a12;color:#f0c674;font-size:12px;padding:8px 14px;border-bottom:1px solid #5a4318}.git-diff-fname{padding:10px 14px 6px;color:#9fb0c0;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.git-diff{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:inherit;line-height:1.5;white-space:pre;overflow-x:auto;-webkit-overflow-scrolling:touch}.git-diff-line{padding:0 14px;min-width:max-content}.git-diff-hunk{color:#6b86a3;background:#0e131a}.git-diff-add{background:#3fb95029;color:#c7f0cf}.git-diff-del{background:#f06b6b29;color:#f3cccc}.git-diff-ctx{color:#c9d6e2}.home-view{flex:1;overflow:auto;-webkit-overflow-scrolling:touch;padding:12px;color:#c9d6e2}.home-empty{color:#6b7a89;font-size:13px;display:flex;flex-direction:column;gap:4px;padding:16px 4px}.home-empty span{color:#4a5663;font-size:12px}.home-recent-row{display:flex;align-items:center;width:100%}.home-recent{flex:1;display:flex;flex-direction:column;align-items:flex-start;background:#11161d;border:1px solid #1d2630;border-radius:8px;padding:8px 10px;margin-bottom:6px;color:#e6edf3;text-align:left}.home-path{font-size:11px;color:#6b7a89;overflow:hidden;text-overflow:ellipsis;max-width:80vw}.home-x{background:transparent;border:none;color:#6b7a89;padding:0 8px}.browse-view{flex:1;display:flex;flex-direction:column;min-height:0;position:relative}.browse-bar{display:flex;align-items:center;gap:6px;padding:6px 8px;border-bottom:1px solid #1d2630;background:#0e131a}.browse-root-dd{flex:0 0 auto}.browse-root{display:inline-flex;align-items:center;gap:3px;padding:9px 4px 9px 10px;background:transparent;border:none;color:#6b86a3;font-size:13px}.browse-root .dd-caret{font-size:10px}.browse-root-dd .dd-menu{left:0;right:auto;min-width:120px}.browse-up{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;background:#11161d;border:1px solid #1d2630;border-radius:8px;color:#9fb0c0}.browse-up:disabled{opacity:.4}.browse-up svg{width:18px;height:18px}.browse-cwd{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;background:#11161d;border:1px solid #1d2630;border-radius:8px;color:#9fb0c0}.browse-cwd svg{width:18px;height:18px}.browse-path{flex:1;min-width:0;display:flex;align-items:center;border-radius:8px;border:1px solid #243446;background:#11161d}.browse-path:focus-within{border-color:#3a5a7e}.browse-input:focus{outline:none}.browse-home{flex:0 0 auto;padding:9px 2px 9px 10px;color:#6b86a3;font-size:13px;-webkit-user-select:none;user-select:none}.browse-input{flex:1;min-width:0;padding:9px 10px 9px 0;border:none;border-radius:8px;background:transparent;color:#e6edf3;font-size:13px}.browse-err{padding:8px 12px 0}.browse-notice{position:absolute;left:50%;bottom:16px;transform:translate(-50%);z-index:6;max-width:88%;width:max-content;padding:9px 14px;border-radius:10px;background:#1c1e22f7;color:#d3dbe4;font-size:13px;line-height:1.4;box-shadow:0 6px 24px #00000080;pointer-events:none;word-break:break-all}.browse-saved{display:flex;align-items:center;gap:10px;margin:8px 12px 0;padding:8px 10px;border:1px solid #2a3f56;border-radius:8px;background:#15212e}.browse-saved-text{flex:1;min-width:0;color:#cfe0f0;font-size:13px}.browse-saved-close{flex:0 0 auto;width:32px;height:32px;border:none;border-radius:8px;background:transparent;color:#8aa0b6;font-size:20px;line-height:1}.browse-pending{display:flex;align-items:center;gap:10px;margin:8px 12px 0;padding:8px 10px;border:1px solid #2a3f56;border-radius:8px;background:#15212e}.browse-pending-text{flex:1;min-width:0;color:#cfe0f0;font-size:13px;overflow:hidden;text-overflow:ellipsis}.browse-pending-hint{color:#8aa0b6;font-style:normal;font-size:12px}.browse-pending-btn{flex:0 0 auto;height:32px;padding:0 14px;border:none;border-radius:8px;background:#2f5fa0;color:#fff;font-size:13px}.browse-pending-btn:disabled{opacity:.4}.browse-list{flex:1;overflow:auto;-webkit-overflow-scrolling:touch;padding:4px 12px 16px}.browse-empty{color:#6b7a89;font-size:13px;padding:16px 4px}.browse-overflow{color:#6b7a89;font-size:12px;padding:12px 4px 16px;text-align:center}.browse-entry{display:flex;align-items:center;gap:9px;width:100%;background:transparent;border:none;border-bottom:1px solid #161d26;color:#e6edf3;padding:11px 4px;text-align:left}.browse-entry-icon{flex:0 0 auto;display:inline-flex;color:#6b86a3}.browse-entry-icon svg{width:17px;height:17px}.browse-entry-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.browse-upload{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;background:#11161d;border:1px solid #1d2630;border-radius:8px;color:#9fb0c0}.browse-upload:disabled{opacity:.4}.browse-upload svg{width:18px;height:18px}.browse-file-input{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}.browse-mkdir{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;background:#11161d;border:1px solid #1d2630;border-radius:8px;color:#9fb0c0}.browse-mkdir:disabled{opacity:.4}.browse-mkdir svg{width:18px;height:18px}.browse-newfolder{display:flex;align-items:center;gap:8px;padding:8px 12px}.browse-newfolder-input{flex:1;min-width:0;padding:9px 10px;border-radius:8px;border:1px solid #243446;background:#11161d;color:#e6edf3;font-size:13px}.browse-newfolder-input:focus{outline:none;border-color:#3a5a7e}.browse-newfolder-ok{flex:0 0 auto;height:36px;padding:0 14px;border:none;border-radius:8px;background:#2f5fa0;color:#fff;font-size:13px;white-space:nowrap}.browse-newfolder-x{flex:0 0 auto;width:36px;height:36px;border:1px solid #1d2630;border-radius:8px;background:#11161d;color:#9fb0c0;font-size:15px;line-height:1}.browse-progress{padding:8px 12px 0}.browse-progress-label{display:block;color:#9fb6d0;font-size:12px;margin-bottom:4px;font-variant-numeric:tabular-nums}.browse-progress-track{display:block;height:4px;border-radius:2px;background:#1c2b3a;overflow:hidden}.browse-progress-fill{display:block;height:100%;background:#3a5a7e;transition:width .1s linear}.browse-entry-row{display:flex;align-items:center}.browse-entry-row .browse-entry{flex:1;min-width:0}.browse-entry-size{flex:0 0 auto;margin-left:auto;padding-left:8px;color:#6b7a89;font-size:12px;font-variant-numeric:tabular-nums}.browse-dl,.browse-copy{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:40px;height:44px;border:none;background:none;color:#6b86a3;margin-left:4px}.browse-dl svg,.browse-copy svg{width:17px;height:17px}.browse-copy:active{color:#9db8ff}.browse-pick-bar{padding:8px;border-top:1px solid #1d2630}.browse-pick-confirm{width:100%;padding:10px;border:none;border-radius:8px;background:var(--blue);color:#fff;font-size:14px}.dirpick-backdrop{z-index:30;background:#0000009e}.dirpick-card{width:min(92vw,520px);max-width:none;z-index:31;max-height:min(80vh,calc(100vh - var(--kb-inset, 0px) - 32px));display:flex;flex-direction:column}.dirpick-card .browse-view{flex:1;min-height:0}.dirpick-hint{font-size:12px;color:#9a9a9a;line-height:1.5;margin-bottom:10px;word-break:break-all}.dirpick-hint code{color:#d8c08a;background:#2c2e33;padding:1px 5px;border-radius:4px}.doc-md-wrap{position:relative;flex:1;min-width:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch}.doc-zoom{position:sticky;top:0;z-index:1;display:flex;gap:6px;align-items:center;padding:8px 12px 0}.doc-tts{display:flex;gap:6px}.doc-fonts{display:flex;gap:6px;margin-left:auto}.doc-zoom-btn{display:inline-flex;align-items:center;justify-content:center;background:#11161d;border:1px solid #1d2630;color:#9fb0c0;border-radius:8px;padding:4px 12px;font-size:14px;touch-action:manipulation}.doc-zoom-btn:disabled{opacity:.4}.doc-zoom-icon{padding:4px 9px}.doc-zoom-icon svg{width:17px;height:17px;display:block}.tts-active{background:rgba(var(--blue-rgb),.3);border-radius:3px;box-decoration-break:clone;-webkit-box-decoration-break:clone}.doc-md{padding:16px;color:#e6edf3;line-height:1.6;word-wrap:break-word}.doc-md h1,.doc-md h2,.doc-md h3{border-bottom:1px solid #1d2630;padding-bottom:4px}.doc-md pre{background:#11161d;padding:12px;border-radius:8px;overflow:auto}.doc-md code{background:#11161d;padding:1px 4px;border-radius:4px}.doc-md a{color:var(--blue)}.doc-md img{max-width:100%}.doc-md table{display:block;max-width:100%;overflow-x:auto;border-collapse:collapse}.doc-text{margin:0;padding:16px;color:#e6edf3;line-height:1.5;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere}.doc-iframe{width:100%;height:100%;border:0;background:#fff}.doc-image-wrap{flex:1;min-height:0;overflow:hidden;position:relative;display:flex;align-items:center;justify-content:center;padding:8px;background:#1b1d22;touch-action:none;user-select:none;-webkit-user-select:none}.doc-image{max-width:100%;max-height:100%;object-fit:contain;display:block;will-change:transform;-webkit-touch-callout:none}.doc-image-msg{flex:1;display:flex;align-items:center;justify-content:center;color:#9fb0c0;font-size:14px}.doc-image-zoom{position:absolute;bottom:14px;left:50%;transform:translate(-50%);z-index:2;display:flex;align-items:center;gap:2px;padding:4px;background:#1c1e22eb;border:1px solid #3a3c42;border-radius:999px;box-shadow:0 6px 20px #00000073}.doc-image-zoom button{width:34px;height:30px;display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;color:#e6edf3;font-size:20px;line-height:1;border-radius:999px;touch-action:manipulation}.doc-image-zoom button:disabled{color:#5a626b}.doc-image-zoom-val{min-width:46px;text-align:center;color:#9fb0c0;font-size:13px;font-variant-numeric:tabular-nums}.doc-image-note{position:absolute;top:14px;left:50%;transform:translate(-50%);z-index:3;max-width:88%;padding:7px 14px;border-radius:999px;white-space:nowrap;background:#1c1e22f0;border:1px solid #3a3c42;color:#e6edf3;font-size:13px;box-shadow:0 6px 20px #00000073}.doclink-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:58}.doclink-pop{position:fixed;z-index:59;width:max-content;max-width:calc(100vw - 16px);background:#1b2330;border:1px solid #2c3a4e;border-radius:12px;padding:12px 14px;box-shadow:0 12px 32px #0000008c;color:#e6edf3}.doclink-name{display:flex;align-items:center;gap:7px;font-weight:600;font-size:14px}.doclink-name svg{width:17px;height:17px;color:#6cb4ff;flex:0 0 auto}.doclink-path{font-size:11px;color:#7d8da0;margin:5px 0 11px;word-break:break-all;max-width:72vw}.doclink-actions{display:flex;gap:8px;justify-content:flex-end}.doclink-actions button{border:1px solid #2c3a4e;background:#11161d;color:#c9d6e2;border-radius:8px;padding:7px 18px;font-size:14px}.doclink-open{background:#2563b0;border-color:#2f6fc0;color:#fff}.doc-deco{border-bottom:2px solid #6cb4ff;background:#4aa3ff38;border-radius:3px;box-sizing:border-box}.doc-toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%);z-index:60;max-width:86vw;background:#2a1518;color:#ffd7d7;border:1px solid #5a2a2a;padding:10px 14px;border-radius:10px;font-size:13px;box-shadow:0 6px 20px #0006}.inbox-btn{position:relative}.inbox-dot{position:absolute;top:4px;right:4px;width:9px;height:9px;border-radius:50%;border:1.5px solid #2a2b2e}.inbox-dot.needs{background:#e0a020}.inbox-dot.done{background:var(--green)}.inbox-dot.working{background:var(--blue);animation:tw-blink 1s ease-in-out infinite}@media (prefers-reduced-motion: reduce){.inbox-dot.working{animation:none}}.inbox-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;z-index:19}.inbox-panel{position:fixed;z-index:20;top:48px;right:8px;width:calc(100% - 32px);max-width:360px;max-height:70vh;overflow-y:auto;background:#232427;border-radius:12px;padding:8px;box-shadow:0 10px 40px #00000080}.inbox-group-title{font-size:12px;color:#888;letter-spacing:1px;padding:8px 8px 4px}.inbox-row{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;background:none;border:none;color:#e6e6e6;padding:8px;border-radius:8px;touch-action:manipulation}.inbox-row:active{background:#2f3034}.inbox-row-head{display:flex;align-items:center;gap:6px;min-width:0}.agent-mark{width:15px;height:15px;flex:none;display:inline-block}.agent-mark svg{display:block;width:100%;height:100%}.win-tab .agent-mark{vertical-align:-2px;margin-right:4px}.inbox-chip{font-size:11px;padding:1px 6px;border-radius:4px;flex:none}.inbox-chip.needs{background:#e0a020;color:#111}.inbox-chip.done{background:var(--green);color:#fff}.inbox-chip.working{background:var(--blue);color:#fff;animation:tw-blink 1s ease-in-out infinite}@keyframes tw-blink{50%{opacity:.4}}@media (prefers-reduced-motion: reduce){.inbox-chip.working{animation:none}}.inbox-head{display:flex;align-items:center;gap:8px;padding:2px 8px 8px;font-size:13px;color:#9aa0a6}.inbox-summary{display:flex;gap:4px;margin-left:auto}.inbox-summary .inbox-chip{animation:none;font-size:10px;padding:1px 5px}.inbox-readall{background:none;border:none;color:var(--blue);font-size:13px;padding:4px 6px;touch-action:manipulation}.inbox-loc{font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.inbox-time{margin-left:auto;font-size:11px;color:#888;flex:none}.inbox-msg{font-size:12px;color:#9aa0a6;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.inbox-empty{padding:24px 8px;text-align:center;color:#888;font-size:13px}.inbox-enable{display:flex;flex-direction:column;gap:8px;align-items:stretch;text-align:left}.inbox-enable-title{font-weight:600;color:#e8eaed;font-size:14px}.inbox-enable-hint{color:#9aa0a6;font-size:12px;line-height:1.4}.inbox-enable-btn{margin-top:2px;padding:8px 12px;border:none;border-radius:8px;background:var(--blue);color:#fff;font-size:13px;touch-action:manipulation}.inbox-enable-btn:disabled{opacity:.6}.inbox-enable-err{color:var(--red);font-size:12px}.drawer-orphans{border-top:1px solid #34353a;margin-top:10px;padding-top:6px}.drawer-orphans-head{display:flex;align-items:center;width:100%;gap:6px;background:none;border:none;color:#888;font-size:12px;letter-spacing:1px;padding:6px 4px;text-align:left;touch-action:manipulation}.drawer-orphans-caret{margin-left:auto}.drawer-orphans-hint{color:#777;font-size:11px;padding:0 4px 4px}.drawer-orphan-row{padding:6px 4px}.drawer-orphan-row+.drawer-orphan-row{border-top:1px solid #2a2b2f}.drawer-orphan-head{display:flex;align-items:center;gap:6px}.drawer-orphan-cwd{flex:1;min-width:0;color:#cdddff;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.drawer-orphan-btn{flex:none;padding:4px 10px;border:none;border-radius:8px;background:#2b3550;color:#cdddff;font-size:13px;touch-action:manipulation}.drawer-orphan-btn:active{background:#344168}.drawer-orphan-btn:disabled{opacity:.45}.drawer-orphan-meta{display:flex;align-items:center;gap:6px;margin-top:2px;min-width:0}.drawer-orphan-agent{flex:none;font-size:10px;padding:0 5px;border-radius:3px;background:#333a45;color:#c7ccd1}.drawer-orphan-state{flex:none;font-size:10px;padding:0 5px;border-radius:3px}.drawer-orphan-state.idle{background:var(--green);color:#fff}.drawer-orphan-state.busy{background:var(--blue);color:#fff}.drawer-orphan-time{flex:none;font-size:11px;color:#888}.drawer-orphan-msg{flex:1;min-width:0;font-size:11px;color:#9aa0a6;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.orphan-targets{display:flex;flex-wrap:wrap;gap:6px}.orphan-targets .fontbtn[aria-pressed=true]{background:var(--blue);color:#fff;border-color:var(--blue)}.orphan-reco{margin-left:6px;font-size:10px;color:#7ee0a0}.orphan-targets .fontbtn[aria-pressed=true] .orphan-reco{color:#d6f5e3}.orphan-help{font-size:11px;color:#9aa0a6;line-height:1.5;margin-top:6px}.usage-card{max-width:420px;max-height:80vh;overflow-y:auto}.usage-agent{padding:12px 0}.usage-agent+.usage-agent{border-top:1px solid #33353a}.usage-agent-head{display:flex;align-items:center;gap:8px;font-weight:600;font-size:14px;margin-bottom:8px}.usage-agent-head .agent-mark{width:18px;height:18px}.usage-row{margin:12px 0}.usage-row-head{display:flex;justify-content:space-between;align-items:baseline;font-size:13px;margin-bottom:5px}.usage-row-label{color:#ddd}.usage-row-sub{color:#888}.usage-row-pct{font-variant-numeric:tabular-nums;color:#ddd;font-weight:600}.usage-bar{position:relative;height:8px;background:#33353a;border-radius:5px;overflow:hidden}.usage-bar-time{position:absolute;top:-1px;bottom:-1px;width:2px;margin-left:-1px;background:#ffffffd9;box-shadow:0 0 2px #0009}.usage-bar-fill{height:100%;border-radius:5px;transition:width .3s ease}.usage-bar-fill.lvl-lo{background:#4ec98a}.usage-bar-fill.lvl-mid{background:#e0b341}.usage-bar-fill.lvl-hi{background:#ff6b6b}.usage-row-reset{margin-top:4px;font-size:11px;color:#888}.usage-empty{font-size:13px;color:#9aa0a6;padding:6px 0;line-height:1.5}.usage-code{display:inline-block;margin-top:6px;font-family:ui-monospace,SFMono-Regular,monospace;font-size:12px;background:#1a1b1e;color:#b7f0cd;padding:3px 8px;border-radius:8px}.usage-updated{margin-left:auto;font-size:11px;color:#777}.usage-card .settings-title{margin-right:8px}.usage-head-note{margin-right:auto;font-size:11px;color:#777}