mulmoterminal 0.2.0 → 0.4.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 +135 -5
- package/dist/assets/index-BiacYhkj.css +1 -0
- package/dist/assets/index-Ctrr8pOx.js +296 -0
- package/dist/assets/{marp-B0qDHvVn.js → marp-BJeBr0yc.js} +1 -1
- package/dist/assets/material-symbols-outlined-gxDE5xnH.woff2 +0 -0
- package/dist/index.html +2 -2
- package/package.json +9 -10
- package/plugins/plugins.json +8 -1
- package/server/app-config.spec.ts +64 -0
- package/server/app-config.ts +45 -0
- package/server/config-routes.ts +33 -13
- package/server/gitRemote.spec.ts +157 -0
- package/server/gitRemote.ts +79 -0
- package/server/index.ts +160 -15
- package/server/pick-file.spec.ts +32 -0
- package/server/pick-file.ts +73 -0
- package/server/scripts.spec.ts +95 -0
- package/server/scripts.ts +63 -0
- package/server/transcript.spec.ts +65 -1
- package/server/transcript.ts +123 -7
- package/server/worktree-diff.spec.ts +83 -0
- package/server/worktree-diff.ts +71 -0
- package/server/worktree-pr.spec.ts +101 -0
- package/server/worktree-pr.ts +107 -0
- package/server/worktree-routes.spec.ts +252 -0
- package/server/worktree-routes.ts +89 -0
- package/server/worktrees.spec.ts +142 -0
- package/server/worktrees.ts +218 -0
- package/dist/assets/index-BQpDgtuh.js +0 -294
- package/dist/assets/index-BTYOl3Xg.css +0 -1
- package/dist/assets/material-symbols-outlined-CogVgFVS.woff2 +0 -0
package/README.md
CHANGED
|
@@ -10,6 +10,13 @@ WebSocket. A sidebar lists every Claude session for the project and reflects, in
|
|
|
10
10
|
real time, which sessions are **working** (Claude is thinking) and which **need
|
|
11
11
|
attention** (waiting for input, or finished with output you haven't seen).
|
|
12
12
|
|
|
13
|
+
**Inserting a file path** — like a native terminal, you can put a file's absolute
|
|
14
|
+
path into the prompt: **drag a file** onto the terminal (works where the browser
|
|
15
|
+
exposes the path via `file://` — Firefox/Safari), or click the **📎 file button**
|
|
16
|
+
in the terminal header, which asks the local server to open the OS file dialog and
|
|
17
|
+
inserts the chosen path (works in every browser, including Chrome). The path is
|
|
18
|
+
inserted at the cursor — it is not submitted, so you can review it first.
|
|
19
|
+
|
|
13
20
|
---
|
|
14
21
|
|
|
15
22
|
## Install & run
|
|
@@ -50,10 +57,13 @@ server, and opens the browser. For local development from a clone, see
|
|
|
50
57
|
- [Tech stack](#tech-stack)
|
|
51
58
|
- [Configuration](#configuration)
|
|
52
59
|
- [Running](#running)
|
|
60
|
+
- [Scripts (Run menu)](#scripts-run-menu)
|
|
53
61
|
- [Server API specification](#server-api-specification)
|
|
54
62
|
- [HTTP: `GET /api/sessions`](#http-get-apisessions)
|
|
63
|
+
- [HTTP: `GET /api/scripts`](#http-get-apiscripts)
|
|
55
64
|
- [HTTP: `POST /api/hook`](#http-post-apihook)
|
|
56
65
|
- [WebSocket: `/ws` (terminal)](#websocket-ws-terminal)
|
|
66
|
+
- [WebSocket: `/ws/run` (command terminal)](#websocket-wsrun-command-terminal)
|
|
57
67
|
- [Socket.IO: `/ws/pubsub` (activity pub/sub)](#socketio-wspubsub-activity-pubsub)
|
|
58
68
|
- [Session model](#session-model)
|
|
59
69
|
- [Session lifecycle](#session-lifecycle)
|
|
@@ -83,8 +93,11 @@ server, and opens the browser. For local development from a clone, see
|
|
|
83
93
|
- **Session list** is fetched over HTTP (`/api/sessions`).
|
|
84
94
|
- **Live activity** is pushed over a Socket.IO pub/sub channel (`/ws/pubsub`);
|
|
85
95
|
the server learns of activity from **Claude hooks** that POST to `/api/hook`.
|
|
86
|
-
-
|
|
87
|
-
in
|
|
96
|
+
- **Script commands** (`yarn dev`, tests, …), launched from a cell's directory
|
|
97
|
+
picker, run in their own ephemeral PTY over a separate WebSocket (`/ws/run`);
|
|
98
|
+
they are not Claude sessions. See [Scripts (Run menu)](#scripts-run-menu).
|
|
99
|
+
- The Vite dev server proxies `/ws` (covers `/ws/run`), `/ws/pubsub`, and `/api` to
|
|
100
|
+
the backend; in production the backend serves the built client from `dist/`.
|
|
88
101
|
|
|
89
102
|
---
|
|
90
103
|
|
|
@@ -136,6 +149,23 @@ Example `.env` (gitignored):
|
|
|
136
149
|
CLAUDE_CWD=/Users/you/my-project
|
|
137
150
|
```
|
|
138
151
|
|
|
152
|
+
### UI settings (`~/.mulmoterminal/config.json`)
|
|
153
|
+
|
|
154
|
+
The Settings modal (⚙) persists per-user UI choices to `~/.mulmoterminal/config.json`
|
|
155
|
+
(read/written via `GET`/`POST /api/config`):
|
|
156
|
+
|
|
157
|
+
| Field | Meaning |
|
|
158
|
+
| ------------ | ------- |
|
|
159
|
+
| `cwdPresets` | Quick-pick directories offered when launching a terminal. |
|
|
160
|
+
| `soundFile` | Absolute path to a custom **attention sound** (played when a session needs attention). Empty/unset uses the built-in synthesized chime. |
|
|
161
|
+
|
|
162
|
+
**Attention sound.** The default chime is generated with the Web Audio API — **no
|
|
163
|
+
audio file is bundled**, so the npm package stays light and has no media-licensing
|
|
164
|
+
concerns. To use your own sound, set `soundFile` in Settings (Browse / Test / Use
|
|
165
|
+
chime) or in the config file; the server streams that file at `GET /api/sound` and
|
|
166
|
+
the client decodes it (falling back to the chime if it's missing or not audio). It's
|
|
167
|
+
your own local file referenced by absolute path — nothing is added to the package.
|
|
168
|
+
|
|
139
169
|
---
|
|
140
170
|
|
|
141
171
|
## Running
|
|
@@ -164,6 +194,55 @@ In dev, open the Vite URL; its proxy forwards `/ws`, `/ws/pubsub`, and `/api` to
|
|
|
164
194
|
|
|
165
195
|
---
|
|
166
196
|
|
|
197
|
+
## Scripts (Run menu)
|
|
198
|
+
|
|
199
|
+
An empty grid cell's launcher (the directory picker) offers a **run a script** row
|
|
200
|
+
that launches project scripts (a dev server, tests, a build, …) **in that cell, in
|
|
201
|
+
the directory the cell is pointed at** — so a whole workflow lives in one window
|
|
202
|
+
alongside the Claude sessions. Scripts are **per-directory**: the cell reads the
|
|
203
|
+
`script.json` of whatever directory you select, so different cells can offer
|
|
204
|
+
different projects' scripts.
|
|
205
|
+
|
|
206
|
+
Every running terminal's header also has a **▶ Run ▾** dropdown (next to the
|
|
207
|
+
connection status), in both the single view and each grid cell — but **only when the
|
|
208
|
+
open project has scripts** (no `script.json`, no button). It lists the **open
|
|
209
|
+
project's** `script.json` — the directory that terminal runs in — and launches the
|
|
210
|
+
picked script in a **spare grid cell** (reusing an open launcher, else a new one),
|
|
211
|
+
switching to the grid from the single view so you can watch it. So you can start a
|
|
212
|
+
dev server or tests for the project you're working in without disturbing the
|
|
213
|
+
session that's running.
|
|
214
|
+
|
|
215
|
+
The list is populated from a **`script.json`** at the chosen directory's root. It's
|
|
216
|
+
optional; a directory without one simply shows no scripts.
|
|
217
|
+
|
|
218
|
+
```jsonc
|
|
219
|
+
// <dir>/script.json
|
|
220
|
+
{
|
|
221
|
+
"scripts": [
|
|
222
|
+
{ "label": "Dev server", "command": "yarn dev" },
|
|
223
|
+
{ "label": "Unit tests", "command": "yarn test" },
|
|
224
|
+
{ "label": "Build", "command": "yarn build" },
|
|
225
|
+
// optional per-script working dir (relative to this file, or absolute):
|
|
226
|
+
{ "label": "Sub server", "command": "yarn serve", "cwd": "packages/server" }
|
|
227
|
+
]
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| Field | Required | Meaning |
|
|
232
|
+
| --------- | -------- | ------- |
|
|
233
|
+
| `label` | yes | What the launcher shows. |
|
|
234
|
+
| `command` | yes | Shell command, run via the login shell (`$SHELL -lc "<command>"`). |
|
|
235
|
+
| `cwd` | no | Working dir, relative to `script.json` or absolute. Defaults to the cell's directory. |
|
|
236
|
+
|
|
237
|
+
A command terminal is **not** a Claude session: it has no session id, no hooks, no
|
|
238
|
+
transcript, and **isn't persisted** — it's ephemeral, so a page reload drops it and
|
|
239
|
+
closing the cell (or reloading) kills the process. When the command exits, the cell
|
|
240
|
+
offers a **↻ re-run**. The browser only ever sends the script's **index** + its
|
|
241
|
+
directory; the server reads that directory's `script.json` and resolves the
|
|
242
|
+
command, so the file is the allowlist of what can run.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
167
246
|
## Server API specification
|
|
168
247
|
|
|
169
248
|
Base URL: `http://localhost:$PORT` (default `http://localhost:3456`).
|
|
@@ -200,6 +279,28 @@ newest first, including freshly-created sessions that aren't yet written to disk
|
|
|
200
279
|
- `500 { "error": string }` on an unexpected filesystem error. A missing project
|
|
201
280
|
directory is **not** an error — it yields an empty `sessions` array.
|
|
202
281
|
|
|
282
|
+
### HTTP: `GET /api/scripts`
|
|
283
|
+
|
|
284
|
+
The runnable entries from `<cwd>/script.json` for a cell's chosen directory
|
|
285
|
+
(`?cwd=<dir>`, falling back to `CLAUDE_CWD`); see
|
|
286
|
+
[Scripts (Run menu)](#scripts-run-menu). The resolved `cwd` is echoed back (the
|
|
287
|
+
server may fall back from a bad path), and each entry carries its `index` (the
|
|
288
|
+
position the client sends back to `/ws/run`).
|
|
289
|
+
|
|
290
|
+
```jsonc
|
|
291
|
+
// GET /api/scripts?cwd=/Users/me/proj
|
|
292
|
+
{
|
|
293
|
+
"cwd": "/Users/me/proj",
|
|
294
|
+
"scripts": [
|
|
295
|
+
{ "index": 0, "label": "Dev server", "command": "yarn dev" },
|
|
296
|
+
{ "index": 1, "label": "Sub server", "command": "yarn serve", "cwd": "packages/server" }
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
A missing or invalid `script.json` is **not** an error — it yields an empty
|
|
302
|
+
`scripts` array.
|
|
303
|
+
|
|
203
304
|
### HTTP: `POST /api/hook`
|
|
204
305
|
|
|
205
306
|
**Internal endpoint.** Claude hooks (injected per session — see
|
|
@@ -262,6 +363,27 @@ A non-JSON frame is written to the PTY verbatim (fallback).
|
|
|
262
363
|
**kept alive** in the background; otherwise it's killed. See
|
|
263
364
|
[Session lifecycle](#session-lifecycle).
|
|
264
365
|
|
|
366
|
+
### WebSocket: `/ws/run` (command terminal)
|
|
367
|
+
|
|
368
|
+
A raw WebSocket carrying a one-off **Run-menu command** (see
|
|
369
|
+
[Scripts (Run menu)](#scripts-run-menu)) — a plain shell PTY, **not** a Claude
|
|
370
|
+
session, so there's no `session` message, no hooks, and no reattach.
|
|
371
|
+
|
|
372
|
+
**Connect**
|
|
373
|
+
|
|
374
|
+
- `ws://host/ws/run?index=<n>&cwd=<dir>` — run the script at position `<n>` in
|
|
375
|
+
`<dir>/script.json` (cwd falls back to `CLAUDE_CWD`). The server reads that
|
|
376
|
+
file and spawns `$SHELL -lc "<command>"` in the script's `cwd`. An out-of-range
|
|
377
|
+
index (or a missing/invalid `script.json`) yields
|
|
378
|
+
`{ "type": "error", "message": string }` and the socket closes.
|
|
379
|
+
|
|
380
|
+
The **output / input / resize / exit** frames are identical to `/ws`. There is no
|
|
381
|
+
`session` frame.
|
|
382
|
+
|
|
383
|
+
**Disconnect** — the terminal is **ephemeral**: when the socket closes (cell
|
|
384
|
+
closed, or page reloaded) the process is **killed**. There is no background
|
|
385
|
+
survival and no resume.
|
|
386
|
+
|
|
265
387
|
### Socket.IO: `/ws/pubsub` (activity pub/sub)
|
|
266
388
|
|
|
267
389
|
A minimal Socket.IO pub/sub for live session-activity updates. Channel names are
|
|
@@ -401,7 +523,9 @@ appears, at which point the on-disk title takes over.
|
|
|
401
523
|
```
|
|
402
524
|
server/
|
|
403
525
|
index.js Express app, /api routes, terminal WebSocket, PTY lifecycle,
|
|
404
|
-
session state, hook injection, session discovery
|
|
526
|
+
session state, hook injection, session discovery; also
|
|
527
|
+
/api/scripts + the /ws/run command-terminal relay
|
|
528
|
+
scripts.ts Loads/validates script.json; resolves a Run-menu command by index
|
|
405
529
|
pubsub.js createPubSub(server) — socket.io pub/sub at /ws/pubsub
|
|
406
530
|
fix-pty-perms.js postinstall: fixes node-pty prebuilt binary permissions
|
|
407
531
|
src/
|
|
@@ -409,10 +533,16 @@ src/
|
|
|
409
533
|
components/
|
|
410
534
|
Sidebar.vue Session list; working dot + waiting bold; pub/sub driven
|
|
411
535
|
Sidebar.spec.ts Vitest component tests
|
|
412
|
-
Terminal.vue xterm.js terminal; /ws
|
|
536
|
+
Terminal.vue xterm.js terminal; /ws (or /ws/run); single-view ▶ Run menu
|
|
537
|
+
GridView.vue Grid toolbar (auto-layout, + Terminal); runs handed-off scripts
|
|
538
|
+
RunMenu.vue ▶ Run dropdown: lists a dir's script.json, emits the pick
|
|
539
|
+
TerminalCell.vue A cell: Claude launcher (dir picker + resume + run-a-script)
|
|
540
|
+
TerminalGrid.vue Grid of cells; auto-sizes by count; zoom lines up every tab
|
|
541
|
+
CommandCell.vue A grid cell that runs a script.json command (ephemeral)
|
|
413
542
|
composables/
|
|
414
543
|
usePubSub.ts socket.io-client pub/sub composable (subscribe/unsubscribe)
|
|
415
|
-
|
|
544
|
+
usePendingScript.ts Hands a header-picked script to the grid to run
|
|
545
|
+
vite.config.ts Dev proxy for /ws (covers /ws/run), /ws/pubsub, /api
|
|
416
546
|
vitest.config.ts jsdom test environment
|
|
417
547
|
```
|
|
418
548
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@font-face{font-family:Material Symbols Outlined;font-style:normal;font-weight:100 700;font-display:block;src:url(/assets/material-symbols-outlined-gxDE5xnH.woff2)format("woff2")}.material-symbols-outlined{letter-spacing:normal;text-transform:none;white-space:nowrap;word-wrap:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizelegibility;font-feature-settings:"liga";direction:ltr;font-family:Material Symbols Outlined;font-size:24px;font-style:normal;font-weight:400;line-height:1;display:inline-block}:root,:root[data-theme=midnight]{--bg-base:#1a1a2e;--bg-deep:#11162a;--bg-panel:#16213e;--bg-subtle:#1d2b4e;--bg-elevated:#20203a;--bg-input:#11111f;--bg-hover:#2a3b66;--bg-selected:#1b3a6b;--bg-selected-hover:#224a86;--border:#2a2a4e;--accent:#4a8cff;--accent-bg:#2f5bd0;--accent-bg-hover:#3a6be0;--on-accent:#fff;--text:#e6e6f0;--text-secondary:#c7cdf0;--text-muted:#9aa5c4;--text-dim:#7c87a8;--term-fg:#e0e0e0;--term-selection:#3a3a5e}:root[data-theme=nord]{--bg-base:#2e3440;--bg-deep:#272b35;--bg-panel:#3b4252;--bg-subtle:#353c4a;--bg-elevated:#434c5e;--bg-input:#21252e;--bg-hover:#4c566a;--bg-selected:#3b4a63;--bg-selected-hover:#4c5d7d;--border:#434c5e;--accent:#88c0d0;--accent-bg:#5e81ac;--accent-bg-hover:#6b8fbb;--on-accent:#eceff4;--text:#eceff4;--text-secondary:#d8dee9;--text-muted:#abb4c4;--text-dim:#7e879b;--term-fg:#d8dee9;--term-selection:#434c5e}:root[data-theme=daylight]{--bg-base:#f4f6fb;--bg-deep:#e8edf6;--bg-panel:#fff;--bg-subtle:#eef2fa;--bg-elevated:#eef2fb;--bg-input:#fff;--bg-hover:#e2e9f6;--bg-selected:#d6e4fb;--bg-selected-hover:#c3d6f7;--border:#d4dbe8;--accent:#2563eb;--accent-bg:#2563eb;--accent-bg-hover:#1d4ed8;--on-accent:#fff;--text:#1b2430;--text-secondary:#38445a;--text-muted:#5d6b82;--text-dim:#8492a8;--term-fg:#1b2430;--term-selection:#cfe0ff}:root[data-theme=solarized]{--bg-base:#fdf6e3;--bg-deep:#ece5cf;--bg-panel:#eee8d5;--bg-subtle:#f4eed9;--bg-elevated:#f4eed9;--bg-input:#fffbf0;--bg-hover:#e3dcc4;--bg-selected:#d6e4ec;--bg-selected-hover:#c4d8e4;--border:#ded7c0;--accent:#268bd2;--accent-bg:#268bd2;--accent-bg-hover:#1f78ba;--on-accent:#fff;--text:#34474d;--text-secondary:#49595d;--text-muted:#657b83;--text-dim:#93a1a1;--term-fg:#586e75;--term-selection:#eee8d5}:root{--ok:#a5d6a7;--ok-bg:#1b5e20;--ok-bg-subtle:#14361c;--ok-border:#1c3a24;--warn:#ffcc80;--warn-bg:#e65100;--warn-bg-subtle:#4a3a10;--amber:#f5a623;--err:#ef9a9a;--err-text:#ff7b7b;--err-strong:#ef4444;--err-deep:#b71c1c;--err-bg:#4a1414;--err-hover-bg:#3a2030}:root[data-theme=daylight],:root[data-theme=solarized]{--ok:#1b7a2e;--ok-bg:#d7f0db;--ok-bg-subtle:#e6f4ea;--ok-border:#b7e0bf;--warn:#8a4b00;--warn-bg:#ffe0b2;--warn-bg-subtle:#fff0db;--amber:#b8860b;--err:#c0392b;--err-text:#c0392b;--err-strong:#d32f2f;--err-deep:#fadbd8;--err-bg:#fadbd8;--err-hover-bg:#f6d4d7}*{box-sizing:border-box;margin:0;padding:0}body{background:var(--bg-base);overflow:hidden}.material-symbols-outlined{font-size:inherit;vertical-align:middle;-webkit-user-select:none;user-select:none;font-variation-settings:"FILL" 0, "wght" 400, "GRAD" 0, "opsz" 20;line-height:1}.chip[data-v-4ea36656]{border:1px solid var(--border);background:var(--bg-subtle);color:var(--text-muted);cursor:pointer;border-radius:9999px;align-items:center;padding:2px 10px;font-size:11px;line-height:16px;transition:background .12s,color .12s,border-color .12s;display:inline-flex}.chip[data-v-4ea36656]:hover{background:var(--bg-selected-hover);color:var(--text-secondary)}.chip.active[data-v-4ea36656]{background:var(--accent-bg);border-color:var(--accent-bg);color:var(--on-accent)}.sidebar[data-v-8331149e]{background:var(--bg-panel);width:260px;color:var(--text);border-right:1px solid var(--border);flex-direction:column;flex-shrink:0;font-family:system-ui,sans-serif;display:flex;overflow:hidden}.sidebar-header[data-v-8331149e]{justify-content:space-between;align-items:center;padding:10px 14px;display:flex}.heading[data-v-8331149e]{letter-spacing:.05em;color:var(--text-muted);font-size:13px;font-weight:600}.icon-btn[data-v-8331149e]{color:var(--text-muted);cursor:pointer;background:0 0;border:none;font-size:16px;line-height:1}.icon-btn[data-v-8331149e]:hover{color:var(--text)}.new-btn[data-v-8331149e]{background:var(--bg-selected);color:var(--text-secondary);cursor:pointer;border:none;border-radius:6px;justify-content:center;align-items:center;gap:6px;margin:0 12px 8px;padding:8px;font-size:13px;display:flex}.new-btn .material-symbols-outlined[data-v-8331149e]{font-size:18px}.new-btn[data-v-8331149e]:hover{background:var(--bg-selected-hover)}.filters[data-v-8331149e]{align-items:center;gap:6px;padding:0 12px 8px;display:flex}.sort-btn[data-v-8331149e]{margin-left:auto;font-size:14px}.state[data-v-8331149e]{color:var(--text-muted);padding:12px 14px;font-size:13px}.state.error[data-v-8331149e]{color:var(--err)}.list[data-v-8331149e]{flex:1;margin:0;padding:0;list-style:none;overflow-y:auto}.item[data-v-8331149e]{cursor:pointer;border-left:3px solid #0000;flex-direction:column;gap:2px;padding:10px 14px;display:flex}.item[data-v-8331149e]:hover{background:var(--bg-subtle)}.item.active[data-v-8331149e]{background:var(--bg-subtle);border-left-color:var(--accent)}.item-title[data-v-8331149e]{white-space:nowrap;text-overflow:ellipsis;font-size:13px;overflow:hidden}.item.waiting .item-title[data-v-8331149e]{color:var(--text);font-weight:700}.spinner[data-v-8331149e]{border:2px solid color-mix(in srgb, var(--accent) 30%, transparent);border-top-color:var(--accent);vertical-align:middle;border-radius:50%;width:10px;height:10px;margin-right:5px;animation:.9s linear infinite sidebar-spin-8331149e;display:inline-block}@keyframes sidebar-spin-8331149e{to{transform:rotate(360deg)}}.item-time[data-v-8331149e]{color:var(--text-dim);font-size:11px}.tabbar[data-v-b1fd7a75]{background:var(--bg-panel);height:40px;color:var(--text);border-bottom:1px solid var(--border);flex-shrink:0;align-items:center;gap:8px;padding:0 10px;font-family:system-ui,sans-serif;display:flex;overflow:hidden}.new-btn[data-v-b1fd7a75]{background:var(--bg-selected);width:26px;height:26px;color:var(--text-secondary);cursor:pointer;border:none;border-radius:6px;flex-shrink:0;font-size:16px;line-height:1}.new-btn[data-v-b1fd7a75]:hover{background:var(--bg-selected-hover)}.filters[data-v-b1fd7a75]{flex-shrink:0;align-items:center;gap:6px;display:flex}.sort-btn[data-v-b1fd7a75]{font-size:14px}.tabs[data-v-b1fd7a75]{flex:1;gap:6px;min-width:0;display:flex;overflow:hidden}.tab[data-v-b1fd7a75]{min-width:0;max-width:200px;height:28px;color:var(--text-secondary);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;flex:1 1 0;align-items:center;gap:5px;padding:0 10px;font-size:12px;transition:background .12s;display:flex;position:relative}.tab[data-v-b1fd7a75]:hover{background:var(--bg-subtle)}.tab.active[data-v-b1fd7a75]{background:var(--bg-subtle);border-color:var(--accent)}.tab-title[data-v-b1fd7a75]{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.tab.waiting .tab-title[data-v-b1fd7a75]{color:var(--text);font-weight:700}.unread-dot[data-v-b1fd7a75]{background:var(--err-strong);width:7px;height:7px;box-shadow:0 0 0 2px var(--bg-panel);border-radius:50%;flex-shrink:0}.spinner[data-v-b1fd7a75]{border:2px solid color-mix(in srgb, var(--accent) 30%, transparent);border-top-color:var(--accent);border-radius:50%;flex-shrink:0;width:10px;height:10px;animation:.9s linear infinite tabbar-spin-b1fd7a75}@keyframes tabbar-spin-b1fd7a75{to{transform:rotate(360deg)}}.actions[data-v-b1fd7a75]{flex-shrink:0;align-items:center;gap:8px;display:flex}.icon-btn[data-v-b1fd7a75]{color:var(--text-muted);cursor:pointer;background:0 0;border:none;font-size:16px;line-height:1}.icon-btn[data-v-b1fd7a75]:hover{color:var(--text)}.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.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{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;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;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}.run-menu[data-v-fc0b7996]{display:inline-flex;position:relative}.run-trigger[data-v-fc0b7996]{border:1px solid var(--border);background:var(--bg-base);color:var(--text-secondary);cursor:pointer;border-radius:6px;padding:5px 10px;font-family:system-ui,sans-serif;font-size:12px;line-height:1}.run-trigger[data-v-fc0b7996]:hover,.run-trigger.active[data-v-fc0b7996]{background:var(--bg-hover);color:var(--text)}.run-pop[data-v-fc0b7996]{z-index:20;background:var(--bg-panel);border:1px solid var(--border);border-radius:6px;flex-direction:column;min-width:180px;max-height:320px;padding:4px;display:flex;position:absolute;top:calc(100% + 4px);left:0;overflow-y:auto;box-shadow:0 6px 20px #00000059}.run-item[data-v-fc0b7996]{text-align:left;color:var(--text-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-radius:4px;padding:6px 8px;font-family:ui-monospace,JetBrains Mono,monospace;font-size:12px}.run-item[data-v-fc0b7996]:hover{background:var(--bg-hover);color:var(--text)}.terminal-wrapper[data-v-00c9ad8f]{background:var(--bg-base);flex-direction:column;flex:1;min-width:0;height:100%;min-height:0;display:flex}.header[data-v-00c9ad8f]{background:var(--bg-panel);color:var(--text);align-items:center;gap:12px;padding:8px 16px;font-family:system-ui,sans-serif;font-size:14px;display:flex}.title[data-v-00c9ad8f]{font-weight:600}.pick-file[data-v-00c9ad8f]{color:var(--text-muted);cursor:pointer;background:0 0;border:none;border-radius:4px;align-items:center;margin-left:auto;padding:2px;display:inline-flex}.pick-file[data-v-00c9ad8f]:hover{background:var(--bg-selected);color:var(--text)}.pick-file .material-symbols-outlined[data-v-00c9ad8f]{font-size:18px}.status[data-v-00c9ad8f]{border-radius:4px;padding:2px 8px;font-size:12px}.status.connected[data-v-00c9ad8f]{background:var(--ok-bg);color:var(--ok)}.status.connecting[data-v-00c9ad8f]{background:var(--warn-bg);color:var(--warn)}.status.disconnected[data-v-00c9ad8f]{background:var(--err-deep);color:var(--err)}.terminal-container[data-v-00c9ad8f]{flex:1;min-height:0;padding:4px}.terminal-container.drag-over[data-v-00c9ad8f]{outline:2px dashed var(--accent);outline-offset:-2px}.plugin-frame-host[data-v-d65d6c36]{display:block}.gui-panel[data-v-c9a1ca5e]{background:var(--bg-deep);border-left:1px solid var(--border);flex-direction:column;flex:1;min-width:0;height:100%;display:flex}.header[data-v-c9a1ca5e]{background:var(--bg-panel);color:var(--text);justify-content:space-between;align-items:center;padding:8px 16px;font-family:system-ui,sans-serif;font-size:14px;display:flex}.title[data-v-c9a1ca5e]{font-weight:600}.gear[data-v-c9a1ca5e]{color:var(--text-dim);cursor:pointer;background:0 0;border:none;border-radius:4px;padding:2px 4px;font-size:15px;line-height:1}.gear[data-v-c9a1ca5e]:hover{color:var(--text)}.content[data-v-c9a1ca5e]{color:var(--text);flex:1;padding:12px 16px;font-family:system-ui,sans-serif;font-size:14px;line-height:1.5;overflow-y:auto}.empty[data-v-c9a1ca5e]{color:var(--text-dim);font-size:13px}.empty code[data-v-c9a1ca5e]{background:var(--bg-subtle);border-radius:4px;padding:1px 5px}.frame+.frame[data-v-c9a1ca5e]{border-top:1px solid var(--border);margin-top:16px;padding-top:16px}.tools-pane[data-v-a7ab181f]{background:var(--bg-deep);border-left:1px solid var(--border);flex-direction:column;flex-shrink:0;width:340px;height:100%;display:flex}.header[data-v-a7ab181f]{background:var(--bg-panel);color:var(--text);justify-content:space-between;align-items:center;padding:8px 16px;font-family:system-ui,sans-serif;font-size:14px;display:flex}.title[data-v-a7ab181f]{font-weight:600}.close-btn[data-v-a7ab181f]{color:var(--text-dim);cursor:pointer;background:0 0;border:none;border-radius:4px;padding:2px 4px;font-size:15px;line-height:1}.close-btn[data-v-a7ab181f]:hover{color:var(--text)}.content[data-v-a7ab181f]{color:var(--text);flex:1;font-family:system-ui,sans-serif;font-size:13px;overflow-y:auto}.section[data-v-a7ab181f]{border-bottom:1px solid var(--border);padding:10px 12px}.section-title[data-v-a7ab181f]{text-transform:uppercase;letter-spacing:.04em;color:var(--text-dim);margin-bottom:8px;font-size:11px;font-weight:700}.section-title--with-action[data-v-a7ab181f]{justify-content:space-between;align-items:center;gap:8px;display:flex}.copy-history[data-v-a7ab181f]{text-transform:none;letter-spacing:.02em;color:var(--text-muted);background:var(--bg-subtle);border:1px solid var(--border);cursor:pointer;border-radius:4px;align-items:center;gap:4px;padding:2px 8px;font-size:10px;font-weight:600;display:inline-flex}.copy-history .material-symbols-outlined[data-v-a7ab181f]{font-size:14px;transition:color .15s,background .15s}.copy-history[data-v-a7ab181f]:hover:not(:disabled){color:var(--text-secondary);background:var(--bg-selected-hover)}.copy-history[data-v-a7ab181f]:disabled{opacity:.4;cursor:not-allowed}.muted[data-v-a7ab181f]{color:var(--text-dim);font-size:12px}.italic[data-v-a7ab181f]{font-style:italic}.tool+.tool[data-v-a7ab181f]{margin-top:4px}.tool-head[data-v-a7ab181f],.call-head[data-v-a7ab181f]{cursor:pointer;text-align:left;width:100%;color:inherit;background:0 0;border:none;justify-content:space-between;align-items:center;gap:8px;padding:4px 0;display:flex}.tool-name[data-v-a7ab181f],.call-name[data-v-a7ab181f]{background:var(--bg-subtle);color:var(--text-secondary);word-break:break-all;border-radius:4px;padding:2px 6px;font-family:JetBrains Mono,monospace;font-size:12px}.caret[data-v-a7ab181f]{color:var(--text-dim);font-size:18px}.tool-desc[data-v-a7ab181f]{color:var(--text-muted);white-space:pre-wrap;margin:2px 0 6px;font-size:12px}.call[data-v-a7ab181f]{border:1px solid var(--border);background:var(--bg-deep);border-radius:6px;margin-top:6px;padding:6px 8px}.call-meta[data-v-a7ab181f]{flex-shrink:0;align-items:center;gap:8px;display:flex}.badge[data-v-a7ab181f]{border-radius:999px;padding:1px 6px;font-size:10px}.badge.running[data-v-a7ab181f]{background:var(--warn-bg-subtle);color:var(--warn)}.badge.done[data-v-a7ab181f]{background:var(--ok-bg-subtle);color:var(--ok)}.badge.failed[data-v-a7ab181f]{background:var(--err-bg);color:var(--err)}.time[data-v-a7ab181f]{color:var(--text-dim);font-variant-numeric:tabular-nums;font-size:11px}.call-body[data-v-a7ab181f]{margin-top:6px}.label[data-v-a7ab181f]{text-transform:uppercase;letter-spacing:.04em;color:var(--text-dim);margin:6px 0 2px;font-size:10px}.block[data-v-a7ab181f]{background:var(--bg-deep);border:1px solid var(--border);white-space:pre-wrap;word-break:break-word;border-radius:4px;max-height:220px;margin:0;padding:6px 8px;font-family:JetBrains Mono,monospace;font-size:11.5px;overflow:auto}.block.result[data-v-a7ab181f]{border-color:var(--ok-border)}.block.error[data-v-a7ab181f]{border-color:var(--err-bg);color:var(--err)}.browse-overlay[data-v-410cf95d]{z-index:50;background:var(--bg-deep);position:fixed;inset:40px 0 0}.cell[data-v-ae042951]{background:var(--bg-base);border:1px solid var(--border);border-radius:6px;flex-direction:column;min-width:0;min-height:0;display:flex;position:relative;overflow:hidden}.cell.is-working[data-v-ae042951]{border-color:var(--accent)}.cell.is-waiting[data-v-ae042951]{border-color:var(--amber);box-shadow:0 0 0 2px color-mix(in srgb, var(--amber) 55%, transparent)}.cell-header[data-v-ae042951]{background:var(--bg-panel);border-bottom:1px solid var(--border);flex:none;align-items:center;gap:8px;height:34px;padding:0 8px;display:flex}.cell-header.is-working[data-v-ae042951]{background:var(--bg-selected);border-bottom-color:var(--accent)}.cell-header.is-waiting[data-v-ae042951]{background:var(--warn-bg-subtle);color:var(--warn);border-bottom-color:var(--amber)}.cell-dot[data-v-ae042951]{background:var(--text-dim);border-radius:50%;flex:none;width:9px;height:9px}.cell-dot.is-working[data-v-ae042951]{background:var(--accent);animation:1.2s ease-in-out infinite pulse-ae042951}.cell-dot.is-waiting[data-v-ae042951]{background:var(--amber)}@keyframes pulse-ae042951{0%,to{opacity:1}50%{opacity:.35}}.cell-dir[data-v-ae042951]{text-align:left;cursor:pointer;min-width:16ch;max-width:60%;color:var(--text-dim);white-space:nowrap;text-overflow:ellipsis;direction:rtl;background:0 0;border:none;flex:0 auto;padding:0;font-family:ui-monospace,JetBrains Mono,monospace;font-size:11px;overflow:hidden}.cell-dir-path[data-v-ae042951]{unicode-bidi:plaintext}.cell-dir[data-v-ae042951]:hover{color:var(--text-muted);text-decoration:underline}.cell-gh-wrap[data-v-ae042951]{flex:none;display:inline-flex;position:relative}.cell-gh[data-v-ae042951]{width:20px;height:20px;color:var(--text-dim);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:0;display:inline-flex}.cell-gh[data-v-ae042951]:hover{background:var(--bg-hover);color:var(--text)}.cell-gh-icon[data-v-ae042951]{width:14px;height:14px;display:block}.cell-gh-menu[data-v-ae042951]{z-index:20;background:var(--bg-panel);border:1px solid var(--border);border-radius:6px;flex-direction:column;min-width:132px;margin-top:4px;padding:4px;display:flex;position:absolute;top:100%;left:0;box-shadow:0 6px 18px #00000059}.cell-gh-item[data-v-ae042951]{text-align:left;color:var(--text-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;padding:6px 8px;font-family:system-ui,sans-serif;font-size:12px}.cell-gh-item[data-v-ae042951]:hover{background:var(--bg-hover);color:var(--text)}.cell-prompt[data-v-ae042951]{min-width:0;color:var(--text-secondary);white-space:nowrap;text-overflow:ellipsis;flex:auto;font-family:system-ui,sans-serif;font-size:12px;overflow:hidden}.cell-actions[data-v-ae042951]{flex:none;gap:4px;display:flex}.cell-btn[data-v-ae042951]{width:28px;height:26px;color:var(--text-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;font-size:16px;line-height:1;display:inline-flex}.cell-btn[data-v-ae042951]:hover{background:var(--bg-hover);color:var(--text)}.cell-close[data-v-ae042951]:hover{background:var(--err-hover-bg);color:var(--err-text)}.cell-term[data-v-ae042951]{flex:1;min-height:0}.cell-launch[data-v-ae042951]{flex-direction:column;flex:1;justify-content:safe center;align-items:center;gap:8px;min-height:0;padding:16px;display:flex;overflow-y:auto}.cell-presets[data-v-ae042951]{flex-wrap:wrap;justify-content:center;gap:6px;max-width:360px;display:flex}.cell-preset[data-v-ae042951]{border:1px solid var(--border);background:var(--bg-elevated);color:var(--text-secondary);cursor:pointer;border-radius:14px;padding:4px 10px;font-family:system-ui,sans-serif;font-size:12px}.cell-preset[data-v-ae042951]:hover{background:var(--bg-hover);color:var(--text)}.cell-preset.active[data-v-ae042951]{background:var(--bg-hover);color:var(--text);border-color:var(--accent)}.cell-launch-label[data-v-ae042951]{flex-direction:column;align-items:center;gap:6px;width:100%;max-width:360px;display:flex}.cell-launch-caption[data-v-ae042951]{color:var(--text-dim);text-transform:uppercase;letter-spacing:.05em;font-family:system-ui,sans-serif;font-size:11px}.cell-dir-input[data-v-ae042951]{box-sizing:border-box;background:var(--bg-input);border:1px solid var(--border);width:100%;color:var(--text);border-radius:6px;padding:7px 10px;font-family:ui-monospace,JetBrains Mono,monospace;font-size:12px}.cell-dir-input[data-v-ae042951]:focus{border-color:var(--accent);outline:none}.cell-start[data-v-ae042951]{border:1px solid var(--border);background:var(--bg-elevated);color:var(--text-secondary);cursor:pointer;border-radius:6px;padding:7px 16px;font-family:system-ui,sans-serif;font-size:14px;font-weight:500}.cell-start[data-v-ae042951]:hover{background:var(--bg-hover);color:var(--text)}.cell-worktrees[data-v-ae042951]{flex-direction:column;align-items:stretch;gap:6px;width:100%;max-width:360px;display:flex}.wt-new[data-v-ae042951]{gap:6px;display:flex}.wt-task[data-v-ae042951]{flex:auto;width:auto;min-width:0}.wt-start[data-v-ae042951]{white-space:nowrap;flex:none}.wt-row[data-v-ae042951]{align-items:center;gap:6px;display:flex}.wt-reuse[data-v-ae042951]{text-align:left;border:1px solid var(--border);background:var(--bg-elevated);min-width:0;color:var(--text-secondary);cursor:pointer;white-space:nowrap;text-overflow:ellipsis;border-radius:6px;flex:auto;padding:5px 10px;font-family:ui-monospace,JetBrains Mono,monospace;font-size:12px;overflow:hidden}.wt-reuse[data-v-ae042951]:hover{background:var(--bg-hover);color:var(--text)}.wt-dirty[data-v-ae042951]{color:var(--warn-text,#e0a030);margin-left:6px}.wt-del[data-v-ae042951]{cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;padding:4px 6px;font-size:13px}.wt-del[data-v-ae042951]:hover{background:var(--err-hover-bg)}.cell-scripts[data-v-ae042951]{flex-direction:column;align-items:center;gap:6px;width:100%;max-width:360px;display:flex}.cell-script-list[data-v-ae042951]{flex-wrap:wrap;justify-content:center;gap:6px;width:100%;display:flex}.cell-script-item[data-v-ae042951]{color:#b6e3c7;cursor:pointer;background:#16271d;border:1px solid #2a4e3a;border-radius:14px;padding:4px 10px;font-family:system-ui,sans-serif;font-size:12px}.cell-script-item[data-v-ae042951]:hover{color:#fff;background:#1f3a2a;border-color:#3fae6b}.cell-resume[data-v-ae042951]{flex-direction:column;align-items:center;gap:6px;width:100%;max-width:360px;min-height:0;display:flex}.cell-resume-list[data-v-ae042951]{flex-direction:column;gap:4px;width:100%;display:flex}.cell-resume-item[data-v-ae042951]{border:1px solid var(--border);background:var(--bg-deep);color:var(--text-secondary);cursor:pointer;text-align:left;border-radius:6px;justify-content:space-between;align-items:baseline;gap:8px;padding:5px 10px;font-family:system-ui,sans-serif;font-size:12px;display:flex}.cell-resume-item[data-v-ae042951]:hover{background:var(--bg-elevated);border-color:var(--accent)}.ri-title[data-v-ae042951]{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.ri-time[data-v-ae042951]{color:var(--text-dim);flex:none;font-size:11px}.cell-wt-badge[data-v-ae042951]{border:1px solid var(--border);background:var(--bg-elevated);cursor:pointer;border-radius:10px;flex:none;align-items:center;gap:6px;padding:1px 7px;font-family:ui-monospace,JetBrains Mono,monospace;font-size:11px;display:inline-flex}.cell-wt-badge[data-v-ae042951]:hover{background:var(--bg-hover)}.wt-ahead[data-v-ae042951]{color:var(--accent)}.wt-dirty-count[data-v-ae042951]{color:var(--warn-text,#e0a030)}.cell-diff[data-v-ae042951]{z-index:15;background:var(--bg-base);border-top:1px solid var(--border);flex-direction:column;display:flex;position:absolute;inset:34px 0 0;overflow:hidden}.cell-diff-head[data-v-ae042951]{border-bottom:1px solid var(--border);background:var(--bg-panel);flex:none;align-items:center;gap:8px;padding:6px 8px;display:flex}.cell-diff-title[data-v-ae042951]{color:var(--text);font-family:system-ui,sans-serif;font-size:12px;font-weight:600}.cell-diff-sum[data-v-ae042951]{color:var(--text-dim);flex:auto;font-family:system-ui,sans-serif;font-size:11px}.cell-diff-files[data-v-ae042951]{border-bottom:1px solid var(--border);flex:none;max-height:35%;padding:4px 8px;overflow-y:auto}.cell-diff-file[data-v-ae042951]{align-items:baseline;gap:8px;padding:1px 0;font-family:ui-monospace,JetBrains Mono,monospace;font-size:11px;display:flex}.df-path[data-v-ae042951]{white-space:nowrap;text-overflow:ellipsis;min-width:0;color:var(--text-secondary);direction:rtl;flex:auto;overflow:hidden}.df-nums[data-v-ae042951]{flex:none}.df-add[data-v-ae042951]{color:#3fae6b}.df-del[data-v-ae042951]{color:var(--err-text,#e0556b)}.df-new[data-v-ae042951]{color:#3fae6b;flex:none}.cell-diff-patch[data-v-ae042951]{color:var(--text-secondary);white-space:pre;tab-size:2;flex:auto;margin:0;padding:8px;font-family:ui-monospace,JetBrains Mono,monospace;font-size:11px;line-height:1.45;overflow:auto}.cell-diff-note[data-v-ae042951],.cell-diff-empty[data-v-ae042951]{color:var(--text-dim);margin:0;padding:8px;font-family:system-ui,sans-serif;font-size:11px}.cell-diff-actions[data-v-ae042951]{border-top:1px solid var(--border);background:var(--bg-panel);flex:none;align-items:center;gap:8px;padding:6px 8px;display:flex}.cell-diff-btn[data-v-ae042951]{border:1px solid var(--border);background:var(--bg-elevated);color:var(--text-secondary);cursor:pointer;border-radius:6px;padding:4px 12px;font-family:system-ui,sans-serif;font-size:12px}.cell-diff-btn[data-v-ae042951]:hover:not(:disabled){background:var(--bg-hover);color:var(--text)}.cell-diff-btn[data-v-ae042951]:disabled{opacity:.5;cursor:not-allowed}.cell-diff-msg[data-v-ae042951]{white-space:nowrap;text-overflow:ellipsis;min-width:0;color:var(--text-dim);flex:auto;font-family:system-ui,sans-serif;font-size:11px;overflow:hidden}.cell-close-confirm[data-v-ae042951]{z-index:25;background:color-mix(in srgb, var(--bg-base) 82%, transparent);justify-content:center;align-items:center;padding:16px;display:flex;position:absolute;inset:0}.ccx-box[data-v-ae042951]{background:var(--bg-panel);border:1px solid var(--border);border-radius:8px;flex-direction:column;gap:10px;max-width:320px;padding:16px;display:flex;box-shadow:0 8px 24px #0006}.ccx-title[data-v-ae042951]{color:var(--text);margin:0;font-family:system-ui,sans-serif;font-size:13px;font-weight:600}.ccx-sub[data-v-ae042951]{color:var(--text-dim);margin:0;font-family:system-ui,sans-serif;font-size:12px}.ccx-warn[data-v-ae042951]{color:var(--warn-text,#e0a030);margin:0;font-family:system-ui,sans-serif;font-size:12px}.ccx-actions[data-v-ae042951]{flex-wrap:wrap;gap:6px;display:flex}.ccx-btn[data-v-ae042951]{border:1px solid var(--border);background:var(--bg-elevated);color:var(--text-secondary);cursor:pointer;border-radius:6px;padding:6px 12px;font-family:system-ui,sans-serif;font-size:12px}.ccx-btn[data-v-ae042951]:hover{background:var(--bg-hover);color:var(--text)}.ccx-keep[data-v-ae042951]{border-color:var(--accent);color:var(--text)}.ccx-remove[data-v-ae042951]:hover{background:var(--err-hover-bg);color:var(--err-text);border-color:var(--err-text,#e0556b)}.cell[data-v-ab5c82a0]{background:#1a1a2e;border:1px solid #2a2a4e;border-radius:6px;flex-direction:column;min-width:0;min-height:0;display:flex;overflow:hidden}.cell-header[data-v-ab5c82a0]{background:#16213e;border-bottom:1px solid #2a2a4e;flex:none;align-items:center;gap:8px;height:34px;padding:0 8px;display:flex}.cell-dot[data-v-ab5c82a0]{background:#4a5070;border-radius:50%;flex:none;width:9px;height:9px}.cell-dot.is-working[data-v-ab5c82a0]{background:#4a8cff;animation:1.2s ease-in-out infinite pulse-ab5c82a0}@keyframes pulse-ab5c82a0{0%,to{opacity:1}50%{opacity:.35}}.cell-dir[data-v-ab5c82a0]{color:#7f88ad;white-space:nowrap;text-overflow:ellipsis;text-align:left;direction:rtl;flex:0 auto;min-width:16ch;max-width:45%;font-family:ui-monospace,JetBrains Mono,monospace;font-size:11px;overflow:hidden}.cell-dir-path[data-v-ab5c82a0]{unicode-bidi:plaintext}.cell-cmd[data-v-ab5c82a0]{color:#c7cdf0;white-space:nowrap;text-overflow:ellipsis;flex:auto;min-width:0;font-family:ui-monospace,JetBrains Mono,monospace;font-size:12px;overflow:hidden}.cell-actions[data-v-ab5c82a0]{flex:none;gap:4px;display:flex}.cell-btn[data-v-ab5c82a0]{color:#c7cdf0;cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;width:28px;height:26px;font-size:16px;line-height:1;display:inline-flex}.cell-btn[data-v-ab5c82a0]:hover{color:#e6e6f0;background:#2a3b66}.cell-close[data-v-ab5c82a0]:hover{color:#ff6b6b;background:#3a2030}.cell-term[data-v-ab5c82a0]{flex:1;min-height:0}.stage[data-v-5c1e257f]{background:var(--bg-deep);flex-direction:column;width:100%;min-width:0;height:100%;min-height:0;display:flex}.grid[data-v-5c1e257f]{box-sizing:border-box;flex:1;min-height:0;padding:6px;display:grid}.zoom-main[data-v-5c1e257f]{display:none}.stage.zoomed .zoom-main[data-v-5c1e257f]{flex:1;min-width:0;min-height:0;padding:6px 6px 0;display:flex}.zoom-main[data-v-5c1e257f]>*{flex:1;min-width:0;min-height:0}.stage.zoomed .grid[data-v-5c1e257f]{flex:0 0 150px;gap:6px;display:flex;overflow:auto hidden}.stage.zoomed .grid[data-v-5c1e257f]>*{flex:0 0 260px;min-width:0;height:100%}.overlay[data-v-07e065af]{z-index:100;background:#0000008c;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.modal[data-v-07e065af]{background:var(--bg-base);border:1px solid var(--border);width:min(560px,92vw);max-height:80vh;color:var(--text);border-radius:10px;flex-direction:column;padding:16px;font-family:system-ui,sans-serif;display:flex}.modal-head[data-v-07e065af]{justify-content:space-between;align-items:center;display:flex}.modal-title[data-v-07e065af]{margin:0;font-size:15px;font-weight:600}.section-title[data-v-07e065af]{text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted);margin:14px 0 8px;font-size:12px;font-weight:600}.themes[data-v-07e065af]{flex-wrap:wrap;gap:8px;display:flex}.theme-card[data-v-07e065af]{background:var(--bg-elevated);border:1px solid var(--border);width:84px;color:var(--text-muted);cursor:pointer;border-radius:8px;flex-direction:column;align-items:center;gap:6px;padding:8px;display:flex}.theme-card[data-v-07e065af]:hover{background:var(--bg-hover);color:var(--text)}.theme-card.active[data-v-07e065af]{border-color:var(--accent);color:var(--text)}.swatch[data-v-07e065af]{border:1px solid var(--border);border-radius:6px;width:100%;height:34px;position:relative;overflow:hidden}.swatch-dot[data-v-07e065af]{border-radius:50%;width:12px;height:12px;position:absolute;bottom:6px}.swatch-dot[data-v-07e065af]:first-child{left:8px}.swatch-dot[data-v-07e065af]:nth-child(2){left:24px}.theme-label[data-v-07e065af]{font-size:12px}.hint[data-v-07e065af]{color:var(--text-dim);margin:6px 0 12px;font-size:12px}.rows[data-v-07e065af]{flex-direction:column;gap:8px;display:flex;overflow-y:auto}.row[data-v-07e065af]{align-items:center;gap:8px;display:flex}.field[data-v-07e065af]{box-sizing:border-box;background:var(--bg-input);border:1px solid var(--border);color:var(--text);border-radius:6px;padding:7px 10px;font-size:12px}.field[data-v-07e065af]:focus{border-color:var(--accent);outline:none}.label-field[data-v-07e065af]{flex:0 0 30%}.path-field[data-v-07e065af]{flex:auto;font-family:ui-monospace,JetBrains Mono,monospace}.empty[data-v-07e065af]{color:var(--text-dim);font-size:12px}.sound-row[data-v-07e065af]{align-items:center;gap:8px;display:flex}.sound-field[data-v-07e065af]{flex:auto;font-family:ui-monospace,JetBrains Mono,monospace}.sound-actions[data-v-07e065af]{gap:8px;margin-top:8px;display:flex}.error[data-v-07e065af]{color:var(--err-text);margin:12px 0 0;font-size:12px}.modal-foot[data-v-07e065af]{align-items:center;gap:8px;margin-top:16px;display:flex}.btn[data-v-07e065af]:disabled{opacity:.6;cursor:default}.spacer[data-v-07e065af]{flex:1}.icon-btn[data-v-07e065af]{color:var(--text-muted);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:4px 6px;font-size:14px}.icon-btn[data-v-07e065af]:hover{background:var(--err-hover-bg);color:var(--err-text)}.btn[data-v-07e065af]{border:1px solid var(--border);background:var(--bg-elevated);color:var(--text-secondary);cursor:pointer;border-radius:6px;padding:6px 14px;font-size:13px}.btn[data-v-07e065af]:hover{background:var(--bg-hover);color:var(--text)}.btn-primary[data-v-07e065af]{background:var(--accent-bg);border-color:var(--accent);color:var(--on-accent)}.btn-primary[data-v-07e065af]:hover{background:var(--accent-bg-hover)}.shell[data-v-127db71b]{flex-direction:column;width:100vw;height:100vh;display:flex;overflow:hidden}.toolbar[data-v-127db71b]{background:var(--bg-panel);border-bottom:1px solid var(--border);flex:none;align-items:center;gap:16px;height:40px;padding:0 16px;display:flex}.toolbar-title[data-v-127db71b]{color:var(--text);letter-spacing:.02em;font-family:system-ui,sans-serif;font-size:14px;font-weight:600}.tb-add[data-v-127db71b]{margin-left:auto}.tb-add.active[data-v-127db71b]{background:var(--bg-hover);color:var(--text);border-color:var(--accent)}.tb-btn[data-v-127db71b]{border:1px solid var(--border);background:var(--bg-base);color:var(--text-secondary);cursor:pointer;border-radius:6px;padding:5px 10px;font-family:system-ui,sans-serif;font-size:12px;line-height:1}.tb-btn[data-v-127db71b]:hover{background:var(--bg-hover);color:var(--text)}.tabbar[data-v-127db71b]{background:var(--bg-panel);border-bottom:1px solid var(--border);flex:none;align-items:center;gap:4px;height:30px;padding:0 16px;display:flex}.tab[data-v-127db71b]{border:1px solid var(--border);background:var(--bg-base);color:var(--text-muted);cursor:pointer;border-radius:6px;min-width:28px;padding:3px 8px;font-family:ui-monospace,monospace;font-size:12px}.tab[data-v-127db71b]:hover{background:var(--bg-hover);color:var(--text)}.tab.active[data-v-127db71b]{background:var(--bg-hover);color:var(--text);border-color:var(--accent)}.main[data-v-127db71b]{flex:1;min-width:0;min-height:0}.shell[data-v-7f5b07f4]{flex-direction:column;width:100vw;height:100vh;display:flex;overflow:hidden}.toolbar[data-v-7f5b07f4]{background:var(--bg-panel);border-bottom:1px solid var(--border);flex:none;align-items:center;height:40px;padding:0 16px;display:flex}.toolbar-title[data-v-7f5b07f4]{color:var(--text);letter-spacing:.02em;font-family:system-ui,sans-serif;font-size:14px;font-weight:600}.launcher[data-v-7f5b07f4]{align-items:center;gap:3px;min-width:0;margin-left:16px;display:flex;overflow-x:auto}.launcher-btn[data-v-7f5b07f4]{width:30px;height:30px;color:var(--text-muted);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.launcher-btn[data-v-7f5b07f4]:hover{background:var(--bg-hover);color:var(--text)}.launcher-btn.active[data-v-7f5b07f4]{background:var(--accent-bg);color:var(--on-accent)}.sound-toggle[data-v-7f5b07f4]{margin-left:auto}.launcher-btn .material-symbols-outlined[data-v-7f5b07f4]{font-size:19px;line-height:1}.app[data-v-7f5b07f4]{flex:1;width:100%;min-height:0;display:flex;overflow:hidden}.app-vertical[data-v-7f5b07f4]{flex-direction:row}.app-horizontal[data-v-7f5b07f4]{flex-direction:column}.main[data-v-7f5b07f4]{flex:1;min-width:0;min-height:0;display:flex}.terminal-pane[data-v-7f5b07f4]{min-width:0}.splitter[data-v-7f5b07f4]{cursor:col-resize;background:var(--bg-panel);border-left:1px solid var(--border);border-right:1px solid var(--border);flex:0 0 5px}.splitter[data-v-7f5b07f4]:hover{background:var(--bg-hover)}.splitter[data-v-7f5b07f4]:focus-visible{background:var(--accent);outline:none}
|