ai-cli-online 3.0.17 → 3.0.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-cli-online",
3
- "version": "3.0.17",
3
+ "version": "3.0.20",
4
4
  "description": "AI-Cli Online - Web Terminal for Claude Code via xterm.js + tmux",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -10,4 +10,33 @@ export declare function getAnnotation(sessionName: string, filePath: string): {
10
10
  } | null;
11
11
  export declare function saveAnnotation(sessionName: string, filePath: string, content: string, updatedAt: number): void;
12
12
  export declare function cleanupOldAnnotations(maxAgeDays?: number): number;
13
+ export interface AutoSession {
14
+ session_name: string;
15
+ task_dir: string;
16
+ status: string;
17
+ max_iterations: number;
18
+ timeout_minutes: number;
19
+ started_at: string;
20
+ }
21
+ export interface AutoStep {
22
+ id: number;
23
+ session_name: string;
24
+ step: string;
25
+ result: string;
26
+ next: string;
27
+ checkpoint: string;
28
+ iteration: number;
29
+ started_at: string;
30
+ ended_at: string | null;
31
+ }
32
+ export declare function createAutoSession(sessionName: string, taskDir: string, maxIterations: number, timeoutMinutes: number): void;
33
+ export declare function getAutoSession(sessionName: string): AutoSession | null;
34
+ export declare function getAllRunningAutoSessions(): AutoSession[];
35
+ export declare function updateAutoStatus(sessionName: string, status: string): void;
36
+ export declare function deleteAutoSession(sessionName: string): void;
37
+ export declare function insertAutoStep(sessionName: string, step: string, result: string, next: string, checkpoint: string, iteration: number): number;
38
+ export declare function endAutoStep(stepId: number): void;
39
+ export declare function getAutoSteps(sessionName: string): AutoStep[];
40
+ export declare function getLastAutoStep(sessionName: string): AutoStep | null;
41
+ export declare function deleteAutoSteps(sessionName: string): void;
13
42
  export declare function closeDb(): void;
package/server/dist/db.js CHANGED
@@ -106,6 +106,79 @@ export function cleanupOldAnnotations(maxAgeDays = 7) {
106
106
  const result = stmtAnnCleanup.run(cutoff);
107
107
  return result.changes;
108
108
  }
109
+ // --- Auto mode tables ---
110
+ db.exec(`
111
+ CREATE TABLE IF NOT EXISTS task_auto (
112
+ session_name TEXT PRIMARY KEY,
113
+ task_dir TEXT NOT NULL UNIQUE,
114
+ status TEXT DEFAULT 'running',
115
+ max_iterations INTEGER DEFAULT 20,
116
+ timeout_minutes INTEGER DEFAULT 30,
117
+ started_at TEXT NOT NULL
118
+ )
119
+ `);
120
+ db.exec(`
121
+ CREATE TABLE IF NOT EXISTS task_auto_steps (
122
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
123
+ session_name TEXT NOT NULL,
124
+ step TEXT NOT NULL,
125
+ result TEXT DEFAULT '',
126
+ next TEXT DEFAULT '',
127
+ checkpoint TEXT DEFAULT '',
128
+ iteration INTEGER DEFAULT 0,
129
+ started_at TEXT NOT NULL,
130
+ ended_at TEXT
131
+ )
132
+ `);
133
+ db.exec('CREATE INDEX IF NOT EXISTS idx_auto_steps_session ON task_auto_steps(session_name)');
134
+ // --- Auto mode statements ---
135
+ const stmtAutoInsert = db.prepare(`
136
+ INSERT INTO task_auto (session_name, task_dir, status, max_iterations, timeout_minutes, started_at)
137
+ VALUES (?, ?, 'running', ?, ?, ?)
138
+ `);
139
+ const stmtAutoGet = db.prepare('SELECT * FROM task_auto WHERE session_name = ?');
140
+ const stmtAutoGetAll = db.prepare("SELECT * FROM task_auto WHERE status = 'running'");
141
+ const stmtAutoUpdateStatus = db.prepare('UPDATE task_auto SET status = ? WHERE session_name = ?');
142
+ const stmtAutoDelete = db.prepare('DELETE FROM task_auto WHERE session_name = ?');
143
+ const stmtAutoStepInsert = db.prepare(`
144
+ INSERT INTO task_auto_steps (session_name, step, result, next, checkpoint, iteration, started_at)
145
+ VALUES (?, ?, ?, ?, ?, ?, ?)
146
+ `);
147
+ const stmtAutoStepEnd = db.prepare('UPDATE task_auto_steps SET ended_at = ? WHERE id = ?');
148
+ const stmtAutoStepGetAll = db.prepare('SELECT * FROM task_auto_steps WHERE session_name = ? ORDER BY id ASC');
149
+ const stmtAutoStepGetLast = db.prepare('SELECT * FROM task_auto_steps WHERE session_name = ? ORDER BY id DESC LIMIT 1');
150
+ const stmtAutoStepsDelete = db.prepare('DELETE FROM task_auto_steps WHERE session_name = ?');
151
+ export function createAutoSession(sessionName, taskDir, maxIterations, timeoutMinutes) {
152
+ stmtAutoInsert.run(sessionName, taskDir, maxIterations, timeoutMinutes, new Date().toISOString());
153
+ }
154
+ export function getAutoSession(sessionName) {
155
+ return stmtAutoGet.get(sessionName) ?? null;
156
+ }
157
+ export function getAllRunningAutoSessions() {
158
+ return stmtAutoGetAll.all();
159
+ }
160
+ export function updateAutoStatus(sessionName, status) {
161
+ stmtAutoUpdateStatus.run(status, sessionName);
162
+ }
163
+ export function deleteAutoSession(sessionName) {
164
+ stmtAutoDelete.run(sessionName);
165
+ }
166
+ export function insertAutoStep(sessionName, step, result, next, checkpoint, iteration) {
167
+ const info = stmtAutoStepInsert.run(sessionName, step, result, next, checkpoint, iteration, new Date().toISOString());
168
+ return Number(info.lastInsertRowid);
169
+ }
170
+ export function endAutoStep(stepId) {
171
+ stmtAutoStepEnd.run(new Date().toISOString(), stepId);
172
+ }
173
+ export function getAutoSteps(sessionName) {
174
+ return stmtAutoStepGetAll.all(sessionName);
175
+ }
176
+ export function getLastAutoStep(sessionName) {
177
+ return stmtAutoStepGetLast.get(sessionName) ?? null;
178
+ }
179
+ export function deleteAutoSteps(sessionName) {
180
+ stmtAutoStepsDelete.run(sessionName);
181
+ }
109
182
  export function closeDb() {
110
183
  db.close();
111
184
  }
@@ -19,6 +19,7 @@ import filesRouter from './routes/files.js';
19
19
  import editorRouter from './routes/editor.js';
20
20
  import settingsRouter from './routes/settings.js';
21
21
  import gitRouter from './routes/git.js';
22
+ import taskAutoRouter, { recoverAutoSessions, stopAllWatchers } from './routes/taskAuto.js';
22
23
  const __dirname = dirname(fileURLToPath(import.meta.url));
23
24
  config();
24
25
  const PORT = process.env.PORT || 3001;
@@ -101,6 +102,7 @@ async function main() {
101
102
  app.use(editorRouter);
102
103
  app.use(settingsRouter);
103
104
  app.use(gitRouter);
105
+ app.use(taskAutoRouter);
104
106
  // --- Static files ---
105
107
  const webDistPath = join(__dirname, '../../web/dist');
106
108
  if (existsSync(webDistPath)) {
@@ -175,6 +177,12 @@ async function main() {
175
177
  catch (e) {
176
178
  console.error('[startup:drafts]', e);
177
179
  }
180
+ try {
181
+ recoverAutoSessions();
182
+ }
183
+ catch (e) {
184
+ console.error('[startup:auto-recover]', e);
185
+ }
178
186
  const CLEANUP_INTERVAL = 60 * 60 * 1000;
179
187
  const cleanupTimer = setInterval(async () => {
180
188
  try {
@@ -201,6 +209,7 @@ async function main() {
201
209
  const shutdown = () => {
202
210
  console.log('\n[shutdown] Closing server...');
203
211
  clearWsIntervals();
212
+ stopAllWatchers();
204
213
  if (cleanupTimer)
205
214
  clearInterval(cleanupTimer);
206
215
  wss.clients.forEach((client) => {
@@ -1,6 +1,6 @@
1
1
  import { Router } from 'express';
2
2
  import { extractToken, checkAuth, resolveSession } from '../middleware/auth.js';
3
- import { listSessions, killSession, buildSessionName, getCwd, getPaneCommand } from '../tmux.js';
3
+ import { listSessions, killSession, buildSessionName, getCwd, getPaneCommand, captureScrollback } from '../tmux.js';
4
4
  import { getActiveSessionNames } from '../websocket.js';
5
5
  import { deleteDraft } from '../db.js';
6
6
  const router = Router();
@@ -61,4 +61,18 @@ router.get('/api/sessions/:sessionId/pane-command', async (req, res) => {
61
61
  res.json({ command: '' });
62
62
  }
63
63
  });
64
+ // Capture pane scrollback content (for live terminal popup)
65
+ router.get('/api/sessions/:sessionId/capture-pane', async (req, res) => {
66
+ const sessionName = resolveSession(req, res);
67
+ if (!sessionName)
68
+ return;
69
+ try {
70
+ const content = await captureScrollback(sessionName);
71
+ res.json({ content });
72
+ }
73
+ catch (err) {
74
+ console.error(`[api:capture-pane] ${sessionName}:`, err);
75
+ res.status(500).json({ error: 'Failed to capture pane content' });
76
+ }
77
+ });
64
78
  export default router;
@@ -0,0 +1,4 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export declare function recoverAutoSessions(): void;
3
+ export declare function stopAllWatchers(): void;
4
+ export default router;
@@ -0,0 +1,302 @@
1
+ import { Router } from 'express';
2
+ import { resolveSession } from '../middleware/auth.js';
3
+ import { createAutoSession, getAutoSession, getAllRunningAutoSessions, updateAutoStatus, deleteAutoSession, insertAutoStep, endAutoStep, getAutoSteps, getLastAutoStep, deleteAutoSteps, } from '../db.js';
4
+ import { watch, readFileSync, writeFileSync, existsSync } from 'fs';
5
+ import { join } from 'path';
6
+ const router = Router();
7
+ // In-memory watcher map: sessionName → FSWatcher
8
+ const watchers = new Map();
9
+ function parseSignalFile(taskDir) {
10
+ const signalPath = join(taskDir, '.auto-signal');
11
+ try {
12
+ if (!existsSync(signalPath))
13
+ return null;
14
+ const raw = readFileSync(signalPath, 'utf-8').trim();
15
+ if (!raw)
16
+ return null;
17
+ return JSON.parse(raw);
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ function formatDuration(startedAt, endedAt) {
24
+ const start = new Date(startedAt).getTime();
25
+ const end = endedAt ? new Date(endedAt).getTime() : Date.now();
26
+ const sec = Math.round((end - start) / 1000);
27
+ if (sec < 60)
28
+ return `${sec}s`;
29
+ const min = Math.floor(sec / 60);
30
+ const rem = sec % 60;
31
+ if (min < 60)
32
+ return rem > 0 ? `${min}m ${rem}s` : `${min}m`;
33
+ const hr = Math.floor(min / 60);
34
+ const mrem = min % 60;
35
+ return mrem > 0 ? `${hr}h ${mrem}m` : `${hr}h`;
36
+ }
37
+ function formatTime(iso) {
38
+ return iso.replace('T', ' ').replace(/\.\d+Z$/, '').replace('Z', '');
39
+ }
40
+ /** Write .auto-timeline.md to the task directory with the full step history */
41
+ function writeTimelineFile(sessionName, taskDir) {
42
+ const session = getAutoSession(sessionName);
43
+ if (!session)
44
+ return;
45
+ const steps = getAutoSteps(sessionName);
46
+ if (steps.length === 0)
47
+ return;
48
+ const totalDuration = formatDuration(session.started_at, steps[steps.length - 1].ended_at ?? new Date().toISOString());
49
+ const endTime = steps[steps.length - 1].ended_at ?? new Date().toISOString();
50
+ const lines = [];
51
+ lines.push(`## Execution Timeline`);
52
+ lines.push(``);
53
+ lines.push(`- **Status**: ${session.status}`);
54
+ lines.push(`- **Total Duration**: ${totalDuration} (${formatTime(session.started_at)} → ${formatTime(endTime)})`);
55
+ const maxIter = Math.max(...steps.map(s => s.iteration));
56
+ if (maxIter > 0)
57
+ lines.push(`- **Iterations**: ${maxIter}`);
58
+ lines.push(``);
59
+ // Table
60
+ lines.push(`| # | Phase | Result | Checkpoint | Duration | Started | Ended |`);
61
+ lines.push(`|---|-------|--------|------------|----------|---------|-------|`);
62
+ for (let i = 0; i < steps.length; i++) {
63
+ const s = steps[i];
64
+ const dur = s.ended_at ? formatDuration(s.started_at, s.ended_at) : 'running';
65
+ const cp = s.checkpoint || '';
66
+ const started = formatTime(s.started_at).split(' ')[1] || '';
67
+ const ended = s.ended_at ? (formatTime(s.ended_at).split(' ')[1] || '') : '—';
68
+ lines.push(`| ${i + 1} | ${s.step} | ${s.result} | ${cp} | ${dur} | ${started} | ${ended} |`);
69
+ }
70
+ lines.push(``);
71
+ // Visual flow — show result only for decision steps (check, merge)
72
+ const flow = steps.map(s => {
73
+ const dur = s.ended_at ? formatDuration(s.started_at, s.ended_at) : '...';
74
+ const showResult = s.step === 'check' || s.step === 'merge';
75
+ const label = showResult ? `${s.step}:${s.result}` : s.step;
76
+ return `${label}(${dur})`;
77
+ }).join(' → ');
78
+ lines.push(`**Flow**: ${flow}`);
79
+ lines.push(``);
80
+ try {
81
+ writeFileSync(join(taskDir, '.auto-timeline.md'), lines.join('\n'));
82
+ }
83
+ catch (err) {
84
+ console.error(`[taskAuto] Failed to write .auto-timeline.md:`, err);
85
+ }
86
+ }
87
+ function processSignal(sessionName, signal) {
88
+ const lastStep = getLastAutoStep(sessionName);
89
+ // If same step+result+checkpoint as last, skip (no transition)
90
+ if (lastStep &&
91
+ lastStep.step === signal.step &&
92
+ lastStep.result === (signal.result || '') &&
93
+ lastStep.checkpoint === (signal.checkpoint || '')) {
94
+ return;
95
+ }
96
+ // End previous step if it has no ended_at
97
+ if (lastStep && !lastStep.ended_at) {
98
+ endAutoStep(lastStep.id);
99
+ }
100
+ // Insert new step
101
+ insertAutoStep(sessionName, signal.step, signal.result || '', signal.next || '', signal.checkpoint || '', signal.iteration ?? 0);
102
+ // If next is "(stop)" or "(done)", mark auto session as completed
103
+ if (signal.next === '(stop)' || signal.next === '(done)') {
104
+ // End the just-inserted step
105
+ const newLast = getLastAutoStep(sessionName);
106
+ if (newLast && !newLast.ended_at) {
107
+ endAutoStep(newLast.id);
108
+ }
109
+ updateAutoStatus(sessionName, 'completed');
110
+ // Write timeline file before stopping
111
+ const session = getAutoSession(sessionName);
112
+ if (session)
113
+ writeTimelineFile(sessionName, session.task_dir);
114
+ stopWatcher(sessionName);
115
+ }
116
+ }
117
+ function startWatcher(sessionName, taskDir) {
118
+ stopWatcher(sessionName);
119
+ try {
120
+ const watcher = watch(taskDir, (_eventType, filename) => {
121
+ if (filename === '.auto-signal') {
122
+ const signal = parseSignalFile(taskDir);
123
+ if (signal) {
124
+ try {
125
+ processSignal(sessionName, signal);
126
+ }
127
+ catch (err) {
128
+ console.error(`[taskAuto:watcher] Error processing signal for ${sessionName}:`, err);
129
+ }
130
+ }
131
+ }
132
+ // Detect .auto-stop written by the auto skill itself
133
+ if (filename === '.auto-stop') {
134
+ const session = getAutoSession(sessionName);
135
+ if (session && session.status === 'running') {
136
+ const lastStep = getLastAutoStep(sessionName);
137
+ if (lastStep && !lastStep.ended_at) {
138
+ endAutoStep(lastStep.id);
139
+ }
140
+ updateAutoStatus(sessionName, 'stopped');
141
+ writeTimelineFile(sessionName, session.task_dir);
142
+ stopWatcher(sessionName);
143
+ }
144
+ }
145
+ });
146
+ watchers.set(sessionName, watcher);
147
+ }
148
+ catch (err) {
149
+ console.error(`[taskAuto] Failed to watch ${taskDir}:`, err);
150
+ }
151
+ }
152
+ function stopWatcher(sessionName) {
153
+ const watcher = watchers.get(sessionName);
154
+ if (watcher) {
155
+ try {
156
+ watcher.close();
157
+ }
158
+ catch { /* ignore */ }
159
+ watchers.delete(sessionName);
160
+ }
161
+ }
162
+ // --- REST endpoints ---
163
+ // POST: Start auto tracking
164
+ router.post('/api/sessions/:sessionId/task-auto', (req, res) => {
165
+ const sessionName = resolveSession(req, res);
166
+ if (!sessionName)
167
+ return;
168
+ const { taskDir, maxIterations = 20, timeoutMinutes = 1440 } = req.body || {};
169
+ if (!taskDir || typeof taskDir !== 'string') {
170
+ res.status(400).json({ error: 'taskDir is required' });
171
+ return;
172
+ }
173
+ // Check if already tracking
174
+ const existing = getAutoSession(sessionName);
175
+ if (existing && existing.status === 'running') {
176
+ res.status(409).json({ error: 'Auto already running for this session' });
177
+ return;
178
+ }
179
+ // Clean up any old data
180
+ if (existing) {
181
+ deleteAutoSteps(sessionName);
182
+ deleteAutoSession(sessionName);
183
+ }
184
+ try {
185
+ createAutoSession(sessionName, taskDir, maxIterations, timeoutMinutes);
186
+ // Read initial signal if exists
187
+ const signal = parseSignalFile(taskDir);
188
+ if (signal) {
189
+ processSignal(sessionName, signal);
190
+ }
191
+ startWatcher(sessionName, taskDir);
192
+ res.json({ ok: true });
193
+ }
194
+ catch (err) {
195
+ console.error('[taskAuto:start]', err);
196
+ res.status(500).json({ error: 'Failed to start auto tracking' });
197
+ }
198
+ });
199
+ // GET: Get auto status + step history
200
+ router.get('/api/sessions/:sessionId/task-auto', (req, res) => {
201
+ const sessionName = resolveSession(req, res);
202
+ if (!sessionName)
203
+ return;
204
+ const session = getAutoSession(sessionName);
205
+ if (!session) {
206
+ res.json(null);
207
+ return;
208
+ }
209
+ const steps = getAutoSteps(sessionName);
210
+ const startedAt = new Date(session.started_at);
211
+ const elapsedMinutes = (Date.now() - startedAt.getTime()) / 60000;
212
+ res.json({
213
+ status: session.status,
214
+ taskDir: session.task_dir,
215
+ maxIterations: session.max_iterations,
216
+ timeoutMinutes: session.timeout_minutes,
217
+ startedAt: session.started_at,
218
+ elapsedMinutes: Math.round(elapsedMinutes * 10) / 10,
219
+ steps: steps.map((s) => ({
220
+ id: s.id,
221
+ step: s.step,
222
+ result: s.result,
223
+ next: s.next,
224
+ checkpoint: s.checkpoint,
225
+ iteration: s.iteration,
226
+ startedAt: s.started_at,
227
+ endedAt: s.ended_at,
228
+ })),
229
+ });
230
+ });
231
+ // DELETE: Stop auto tracking
232
+ router.delete('/api/sessions/:sessionId/task-auto', (req, res) => {
233
+ const sessionName = resolveSession(req, res);
234
+ if (!sessionName)
235
+ return;
236
+ const session = getAutoSession(sessionName);
237
+ if (!session) {
238
+ res.status(404).json({ error: 'No auto session found' });
239
+ return;
240
+ }
241
+ // If already finished (completed/cancelled/stopped), just clean up records
242
+ if (session.status !== 'running') {
243
+ deleteAutoSteps(sessionName);
244
+ deleteAutoSession(sessionName);
245
+ res.json({ ok: true });
246
+ return;
247
+ }
248
+ // Write .auto-stop to signal the auto subprocess to halt
249
+ try {
250
+ const stopPath = join(session.task_dir, '.auto-stop');
251
+ writeFileSync(stopPath, JSON.stringify({ reason: 'user_stop', timestamp: new Date().toISOString() }));
252
+ }
253
+ catch (err) {
254
+ console.error('[taskAuto:stop] Failed to write .auto-stop:', err);
255
+ }
256
+ // End last step
257
+ const lastStep = getLastAutoStep(sessionName);
258
+ if (lastStep && !lastStep.ended_at) {
259
+ endAutoStep(lastStep.id);
260
+ }
261
+ updateAutoStatus(sessionName, 'cancelled');
262
+ writeTimelineFile(sessionName, session.task_dir);
263
+ stopWatcher(sessionName);
264
+ res.json({ ok: true });
265
+ });
266
+ // --- Server restart recovery ---
267
+ export function recoverAutoSessions() {
268
+ const sessions = getAllRunningAutoSessions();
269
+ for (const session of sessions) {
270
+ if (existsSync(session.task_dir)) {
271
+ console.log(`[taskAuto:recover] Resuming watcher for ${session.session_name}`);
272
+ // Process any signals that arrived while server was down
273
+ const signal = parseSignalFile(session.task_dir);
274
+ if (signal) {
275
+ try {
276
+ processSignal(session.session_name, signal);
277
+ }
278
+ catch { /* ignore */ }
279
+ }
280
+ // Check if still running after processing
281
+ const updated = getAutoSession(session.session_name);
282
+ if (updated && updated.status === 'running') {
283
+ startWatcher(session.session_name, session.task_dir);
284
+ }
285
+ }
286
+ else {
287
+ console.log(`[taskAuto:recover] Task dir gone for ${session.session_name}, cleaning up`);
288
+ deleteAutoSteps(session.session_name);
289
+ deleteAutoSession(session.session_name);
290
+ }
291
+ }
292
+ }
293
+ export function stopAllWatchers() {
294
+ for (const [, watcher] of watchers) {
295
+ try {
296
+ watcher.close();
297
+ }
298
+ catch { /* ignore */ }
299
+ }
300
+ watchers.clear();
301
+ }
302
+ export default router;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-cli-online-server",
3
- "version": "3.0.17",
3
+ "version": "3.0.20",
4
4
  "description": "CLI-Online Backend Server",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-cli-online-shared",
3
- "version": "3.0.17",
3
+ "version": "3.0.20",
4
4
  "description": "Shared types for CLI-Online",
5
5
  "type": "module",
6
6
  "main": "dist/types.js",
@@ -29,4 +29,4 @@
29
29
  * The original design remains. The terminal itself
30
30
  * has been extended to include xterm CSI codes, among
31
31
  * other features.
32
- */.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}@font-face{font-family:JetBrains Mono;src:url(/fonts/JetBrainsMono-Regular.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:JetBrains Mono;src:url(/fonts/JetBrainsMono-Bold.woff2) format("woff2");font-weight:700;font-style:normal;font-display:swap}:root,[data-theme=dark]{--bg-primary: #000000;--bg-secondary: #0c0c0c;--bg-tertiary: #171717;--bg-hover: #1c1c1c;--border: #2d2d2d;--text-primary: #cccccc;--text-secondary: #858585;--text-bright: #e8e8e8;--accent-blue: #569cd6;--accent-purple: #c586c0;--accent-cyan: #4ec9b0;--accent-green: #89d185;--accent-yellow: #cca700;--accent-red: #f44747;--accent-orange: #ce9178;--scrollbar-thumb: rgba(121, 121, 121, .4);--scrollbar-thumb-hover: rgba(121, 121, 121, .7);--selection-bg: rgba(38, 79, 120, .5)}[data-theme=light]{--bg-primary: #ffffff;--bg-secondary: #f6f8fa;--bg-tertiary: #ffffff;--bg-hover: #eff2f5;--border: #d1d9e0;--text-primary: #1f2328;--text-secondary: #59636e;--text-bright: #1f2328;--accent-blue: #0969da;--accent-purple: #8250df;--accent-cyan: #1b7c83;--accent-green: #1a7f37;--accent-yellow: #9a6700;--accent-red: #d1242f;--accent-orange: #bc4c00;--scrollbar-thumb: rgba(31, 35, 40, .15);--scrollbar-thumb-hover: rgba(31, 35, 40, .3);--selection-bg: rgba(9, 105, 218, .2)}*{margin:0;padding:0;box-sizing:border-box}html,body,#root{width:100%;height:100%;overflow:hidden;background-color:var(--bg-primary);font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}body.resizing-panes,body.resizing-panes *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.session-sidebar{transition:width .2s ease;overflow:hidden;flex-shrink:0;z-index:10;position:relative}body.resizing-panes-v,body.resizing-panes-v *{cursor:row-resize!important;-webkit-user-select:none!important;user-select:none!important}button{transition:all .15s ease;font-family:inherit}button:hover{filter:brightness(1.2)}button:active{transform:scale(.97)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}::selection{background:var(--selection-bg);color:var(--text-bright)}input:focus-visible,button:focus-visible{outline:1px solid var(--accent-blue);outline-offset:1px}.header-btn{background:none;border:1px solid var(--border);color:var(--accent-blue);padding:3px 10px;border-radius:5px;cursor:pointer;font-size:13px;line-height:1.4;transition:all .15s ease}.header-btn:hover{background:#7aa2f71f;border-color:var(--accent-blue);box-shadow:0 0 8px #7aa2f726}.header-btn--muted{color:var(--text-secondary);font-size:12px}.header-btn--muted:hover{color:var(--text-primary);border-color:var(--text-secondary);background:#565f891a}.pane-btn{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:12px;line-height:1;padding:2px 5px;border-radius:4px;transition:all .15s ease}.pane-btn:hover{color:var(--accent-blue);background:#7aa2f71f}.pane-btn--danger:hover{color:var(--accent-red);background:#f7768e1f}.login-input{transition:border-color .2s ease,box-shadow .2s ease}.login-input:focus{border-color:var(--accent-blue)!important;box-shadow:0 0 0 3px #7aa2f726}.login-card{box-shadow:0 8px 32px #0006,0 0 0 1px #7aa2f714;transition:box-shadow .3s ease}.login-submit{transition:all .2s ease}.login-submit:not(:disabled):hover{filter:brightness(1.1);box-shadow:0 4px 12px #7aa2f74d}.md-editor-textarea{flex:1;min-width:0;resize:none;border:none;outline:none;padding:8px 12px;font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;font-size:13px;line-height:1.5;color:var(--text-primary);background-color:var(--bg-primary);-moz-tab-size:2;tab-size:2}.md-editor-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.md-editor-divider{height:3px;background:var(--border);cursor:row-resize;flex-shrink:0;transition:background .15s ease,box-shadow .15s ease}.md-editor-divider:hover{background:var(--accent-blue);box-shadow:0 0 6px #7aa2f766}.pane-btn--active{color:var(--accent-blue)}.plan-panel-body{display:flex;flex-direction:row;flex:1;min-height:0;overflow:hidden}.plan-renderer{position:relative;overflow:hidden;padding:0;min-width:0;-webkit-user-select:text;user-select:text}.plan-divider-h{width:2px;background:var(--border);cursor:col-resize;flex-shrink:0;transition:background .15s ease,box-shadow .15s ease}.plan-divider-h:hover{background:var(--accent-blue);box-shadow:0 0 6px #7aa2f766}.plan-editor-wrap{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}.plan-filename-input{background:var(--bg-primary);border:1px solid var(--border);color:var(--text-primary);padding:2px 6px;border-radius:3px;font-family:inherit;font-size:11px;width:120px;outline:none;transition:border-color .15s ease}.plan-filename-input:focus{border-color:var(--accent-blue)}body.resizing-panes-h,body.resizing-panes-h *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.md-preview{color:var(--text-primary);font-size:13px;line-height:1.6;word-wrap:break-word}.md-preview h1{color:var(--accent-blue);font-size:1.4em;margin:.6em 0 .3em;padding-bottom:.2em;border-bottom:1px solid var(--border)}.md-preview h2{color:var(--accent-purple);font-size:1.2em;margin:.5em 0 .3em}.md-preview h3{color:var(--accent-cyan);font-size:1.05em;margin:.4em 0 .2em}.md-preview p{margin:.4em 0}.md-preview code{background:var(--bg-tertiary);color:var(--text-bright);padding:1px 4px;border-radius:3px;font-size:.9em;font-family:JetBrains Mono,LXGW WenKai Mono,monospace}.md-preview pre{background:var(--bg-tertiary);border:1px solid var(--border);border-radius:4px;padding:10px 12px;overflow-x:auto;margin:.5em 0}.md-preview pre code{background:none;padding:0;border-radius:0}.md-preview blockquote{border-left:3px solid var(--accent-blue);padding:2px 12px;margin:.4em 0;color:var(--text-secondary)}.md-preview ul,.md-preview ol{padding-left:1.5em;margin:.3em 0}.md-preview li{margin:.15em 0}.md-preview table{border-collapse:collapse;width:100%;margin:.5em 0;font-size:12px}.md-preview th,.md-preview td{border:1px solid var(--border);padding:4px 8px;text-align:left}.md-preview th{background:var(--bg-tertiary);color:var(--accent-blue);font-weight:600}.md-preview a{color:var(--accent-blue);text-decoration:none}.md-preview a:hover{text-decoration:underline}.md-preview hr{border:none;border-top:1px solid var(--border);margin:.6em 0}.slash-dropdown{flex-shrink:0;max-height:200px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:13px}.slash-item{display:flex;align-items:center;gap:10px;padding:6px 12px;cursor:pointer;transition:background .12s ease}.slash-item:hover,.slash-item--active{background:var(--bg-hover)}.slash-cmd{color:var(--accent-blue);font-weight:600;min-width:180px;font-family:JetBrains Mono,LXGW WenKai Mono,monospace}.slash-desc{color:var(--accent-purple);font-size:11px}.file-dropdown{flex-shrink:0;max-height:180px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:12px}.file-item{display:flex;align-items:center;gap:8px;padding:5px 10px;cursor:pointer;transition:background .1s ease}.file-item:hover,.file-item--active{background:var(--bg-hover)}.file-loading{color:var(--text-secondary);cursor:default}.file-icon{flex-shrink:0;width:16px;text-align:center;font-size:13px}.file-name{color:var(--text-bright);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.history-dropdown{flex-shrink:0;max-height:260px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:12px}.history-item{display:flex;align-items:flex-start;gap:8px;padding:6px 10px;cursor:pointer;transition:background .1s ease;position:relative}.history-item:hover,.history-item--active{background:var(--bg-hover)}.history-empty{color:var(--text-secondary);cursor:default;justify-content:center;padding:12px}.history-text{flex:1;color:var(--text-bright);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;white-space:pre-wrap;overflow-wrap:break-word;line-height:1.4}.history-time{flex-shrink:0;color:var(--text-secondary);font-size:10px;white-space:nowrap;margin-top:2px}.history-delete{flex-shrink:0;background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:14px;padding:0 2px;line-height:1;opacity:0;transition:opacity .1s ease,color .1s ease}.history-item:hover .history-delete,.history-item--active .history-delete{opacity:1}.history-delete:hover{color:var(--accent-red)}.tab-bar{display:flex;align-items:center;padding:0 10px;height:32px;background:var(--bg-secondary);border-top:1px solid var(--border);flex-shrink:0;overflow-x:auto;gap:3px}.tab-bar::-webkit-scrollbar{height:0}.tab-item{display:flex;align-items:center;gap:6px;padding:4px 12px;font-size:13px;color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;white-space:nowrap;transition:color .15s ease,border-color .15s ease,background .15s ease,box-shadow .15s ease;border-radius:5px 5px 0 0;-webkit-user-select:none;user-select:none;flex-shrink:0}.tab-item:hover{color:var(--text-primary);background:#7aa2f70f}.tab-item--active{color:var(--text-bright);border-bottom-color:var(--accent-blue);background:#7aa2f71a;box-shadow:inset 0 -1px 0 var(--accent-blue)}.tab-item__name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.tab-item__count{font-size:10px;color:var(--scrollbar-thumb-hover)}.tab-item__close{font-size:14px;line-height:1;color:inherit;opacity:0;background:none;border:none;cursor:pointer;padding:0 2px;border-radius:3px;transition:opacity .1s ease}.tab-item:hover .tab-item__close{opacity:.5}.tab-item__close:hover{opacity:1!important;color:var(--accent-red);background:#f7768e1a}.tab-item__rename-input{background:transparent;border:1px solid var(--accent-blue);color:var(--text-bright);font-size:13px;font-family:inherit;padding:0 6px;border-radius:3px;outline:none;width:100px}.tab-bar-add{background:none;border:1px solid transparent;color:var(--text-secondary);font-size:18px;line-height:1;padding:2px 8px;border-radius:5px;cursor:pointer;margin-left:4px;flex-shrink:0}.tab-bar-add:hover{color:var(--accent-blue);border-color:var(--border);background:#7aa2f71a}.md-editor-actions{display:flex;align-items:center;gap:8px;padding:4px 8px;flex-shrink:0;background:var(--bg-secondary);border-top:1px solid var(--border)}.plan-anno-toolbar{display:flex;align-items:center;gap:6px;padding:3px 10px;height:28px;flex-shrink:0;background:var(--bg-secondary);border-bottom:1px solid var(--border)}.plan-anno-content{-webkit-user-select:text;user-select:text}.plan-insert-zone{position:relative;min-height:12px}.plan-insert-btn{display:none;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:20px;height:20px;border-radius:50%;border:1px solid var(--scrollbar-thumb-hover);background:var(--bg-secondary);color:var(--accent-blue);font-size:15px;line-height:1;cursor:pointer;padding:0 0 1px;z-index:2;transition:background .12s ease,border-color .12s ease,transform .12s ease;align-items:center;justify-content:center}.plan-insert-zone:hover .plan-insert-btn{display:flex}.plan-anno-content--editing .plan-insert-zone:hover .plan-insert-btn{display:none}.plan-empty-placeholder{display:flex;align-items:center;justify-content:center;min-height:120px;color:var(--text-secondary);font-size:13px;font-style:italic;cursor:pointer;-webkit-user-select:none;user-select:none;text-align:center;padding:16px}.plan-empty-placeholder:hover{color:var(--accent-blue)}.plan-insert-btn:hover{background:var(--bg-hover);border-color:var(--accent-blue);transform:translate(-50%,-50%) scale(1.15)}.plan-annotation-card{display:flex;align-items:flex-start;gap:6px;padding:6px 10px;margin:4px 0;background:#e0af681f;border-left:3px solid var(--accent-yellow);border-radius:0 4px 4px 0}.plan-annotation-card--editing{border-left-color:var(--accent-blue);background:#7aa2f70f}.plan-annotation-textarea{flex:1;min-height:36px;max-height:30em;field-sizing:content;resize:vertical;border:1px solid var(--border);border-radius:3px;background:var(--bg-primary);color:var(--text-primary);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;font-size:12px;padding:4px 6px;outline:none;transition:border-color .15s ease}.plan-annotation-textarea:focus{border-color:var(--accent-blue)}.plan-annotation-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.plan-deletion-card{display:flex;align-items:center;gap:6px;padding:2px 8px;margin:2px 0;background:#f7768e0f;border-left:3px solid var(--accent-red);border-radius:0 4px 4px 0;font-size:11px}.plan-selection-float{position:absolute;z-index:1000;display:flex;flex-direction:row;gap:2px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;padding:2px;box-shadow:0 2px 8px #0000004d}.plan-selection-float button{width:24px;height:24px;border-radius:4px;border:none;cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center;background:transparent;transition:background .15s,transform .1s}.plan-selection-float button:hover{transform:scale(1.1)}.plan-selection-float__delete{color:var(--accent-red)}.plan-selection-float__delete:hover{background:#f7768e33}.plan-selection-float__replace{color:var(--accent-blue)}.plan-selection-float__replace:hover{background:#7aa2f733}.plan-selection-float__comment{color:var(--accent-green)}.plan-selection-float__comment:hover{background:#9ece6a33}.plan-replace-card{display:flex;align-items:flex-start;gap:6px;padding:2px 8px;margin:2px 0;border-left:3px solid rgba(122,162,247,.6);background:#7aa2f70a;border-radius:0 4px 4px 0;font-size:11px}.plan-comment-card{display:flex;align-items:flex-start;gap:6px;padding:2px 8px;margin:2px 0;border-left:3px solid rgba(158,206,106,.6);background:#9ece6a0a;border-radius:0 4px 4px 0;font-size:11px}.plan-block--deleted{border-left:3px solid rgba(247,118,142,.5);padding-left:8px;border-radius:2px;position:relative}.plan-block--replaced{border-left:3px solid rgba(122,162,247,.5);padding-left:8px;border-radius:2px;position:relative}.plan-block--commented{border-left:3px solid rgba(158,206,106,.5);padding-left:8px;border-radius:2px;position:relative}.mermaid-diagram{margin:8px 0;padding:12px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;overflow-x:auto}.mermaid-diagram svg{display:block;margin:0 auto;max-width:100%;height:auto}.mermaid-error{border-left:3px solid var(--accent-red);padding-left:8px}.mermaid-error__msg{color:var(--accent-red);font-size:11px;margin-top:4px}.pane-btn--sm{font-size:11px;flex-shrink:0}.plan-file-browser{display:flex;flex-direction:column;height:100%;width:100%;background:var(--bg-secondary);overflow:hidden}.plan-file-browser__header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;height:28px;flex-shrink:0;border-bottom:1px solid var(--border)}.plan-file-browser__title{font-size:11px;color:var(--accent-blue);font-weight:600;letter-spacing:.3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;direction:rtl;text-align:left}.plan-file-browser__list{flex:1;overflow-y:auto;overflow-x:hidden;padding:2px 0}.plan-file-browser__status{padding:8px 10px;font-size:11px;color:var(--text-secondary);font-style:italic}.plan-file-browser__item{display:flex;align-items:center;padding:3px 8px;font-size:12px;cursor:pointer;gap:5px;transition:background .1s ease;border-left:2px solid transparent}.plan-file-browser__item:hover{background:var(--bg-tertiary)}.plan-file-browser__item--active{background:#7aa2f71a;border-left-color:var(--accent-blue)}.plan-file-browser__item--active .plan-file-browser__name{color:var(--text-bright)}.plan-file-browser__icon{flex-shrink:0;width:14px;font-size:10px;color:var(--text-secondary);text-align:center}.plan-file-browser__name{flex:1;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.plan-file-browser__size{flex-shrink:1;font-size:9px;color:var(--scrollbar-thumb-hover);white-space:nowrap;overflow:hidden;min-width:0}.plan-file-browser__create{display:flex;align-items:center;gap:4px;padding:4px 6px;border-top:1px solid var(--border);flex-shrink:0}.plan-file-browser__input{flex:1;min-width:0;background:var(--bg-primary);border:1px solid var(--border);color:var(--text-primary);padding:2px 6px;border-radius:3px;font-family:inherit;font-size:11px;outline:none;transition:border-color .15s ease}.plan-file-browser__input:focus{border-color:var(--accent-blue)}.plan-file-browser__input::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.plan-overlay-body{display:flex;flex:1;min-height:0;overflow:hidden}.plan-overlay-center{flex:1;min-width:0;overflow:hidden}.plan-anno-counts{display:inline-flex;align-items:center;gap:4px;font-size:10px;margin-left:4px}.plan-anno-counts__unsent{color:var(--accent-yellow)}.plan-anno-counts__sent{color:var(--accent-green)}.plan-anno-dropdown-trigger{display:flex;align-items:center;gap:4px;padding:2px 6px;border:1px solid var(--border);border-radius:3px;cursor:pointer;background:var(--bg-primary);transition:border-color .15s ease,background .15s ease;min-width:0}.plan-anno-dropdown-trigger:hover,.plan-anno-dropdown-trigger--active{border-color:var(--accent-blue);background:var(--bg-hover)}.plan-anno-dropdown-trigger__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;color:var(--text-secondary)}.plan-anno-dropdown-trigger__arrow{flex-shrink:0;font-size:9px;color:var(--text-secondary);transition:transform .15s ease}.plan-anno-dropdown-trigger--active .plan-anno-dropdown-trigger__arrow{transform:rotate(180deg)}.plan-anno-dropdown{position:absolute;top:100%;right:0;z-index:100;width:320px;max-height:300px;display:flex;flex-direction:column;background:var(--bg-secondary);border:1px solid var(--border);border-radius:4px;box-shadow:0 4px 12px #0000004d;overflow:hidden}.plan-anno-dropdown__header{display:flex;align-items:center;justify-content:center;padding:4px 6px;border-bottom:1px solid var(--border);flex-shrink:0}.plan-anno-dropdown__list{flex:1;overflow-y:auto;padding:2px 0}.plan-anno-dropdown__item{display:flex;align-items:center;gap:4px;padding:3px 6px;font-size:11px;border-bottom:1px solid var(--border-subtle, rgba(128,128,128,.1))}.plan-anno-dropdown__item:last-child{border-bottom:none}.plan-anno-dropdown__item--add{border-left:2px solid var(--accent-yellow)}.plan-anno-dropdown__item--del{border-left:2px solid var(--accent-red)}.plan-anno-dropdown__item--rep{border-left:2px solid var(--accent-blue)}.plan-anno-dropdown__item--com{border-left:2px solid var(--accent-green)}.plan-anno-dropdown__type{flex-shrink:0;width:14px;font-weight:700;text-align:center}.plan-anno-dropdown__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-primary)}.plan-anno-dropdown__badge{flex-shrink:0;font-size:9px;padding:0 4px;border-radius:3px;background:var(--accent-green);color:var(--bg-primary)}.plan-anno-dropdown__empty{padding:8px;text-align:center;font-size:11px;color:var(--text-secondary);font-style:italic}.plan-edit-textarea{width:100%;flex:1;resize:none;border:none;outline:none;padding:8px 12px;font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;line-height:1.6;background:var(--bg-primary);color:var(--text-primary);-moz-tab-size:2;tab-size:2}.plan-edit-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}
32
+ */.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}@font-face{font-family:JetBrains Mono;src:url(/fonts/JetBrainsMono-Regular.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:JetBrains Mono;src:url(/fonts/JetBrainsMono-Bold.woff2) format("woff2");font-weight:700;font-style:normal;font-display:swap}:root,[data-theme=dark]{--bg-primary: #000000;--bg-secondary: #0c0c0c;--bg-tertiary: #171717;--bg-hover: #1c1c1c;--border: #2d2d2d;--text-primary: #cccccc;--text-secondary: #858585;--text-bright: #e8e8e8;--accent-blue: #569cd6;--accent-purple: #c586c0;--accent-cyan: #4ec9b0;--accent-green: #89d185;--accent-yellow: #cca700;--accent-red: #f44747;--accent-orange: #ce9178;--scrollbar-thumb: rgba(121, 121, 121, .4);--scrollbar-thumb-hover: rgba(121, 121, 121, .7);--selection-bg: rgba(38, 79, 120, .5)}[data-theme=light]{--bg-primary: #ffffff;--bg-secondary: #f6f8fa;--bg-tertiary: #ffffff;--bg-hover: #eff2f5;--border: #d1d9e0;--text-primary: #1f2328;--text-secondary: #59636e;--text-bright: #1f2328;--accent-blue: #0969da;--accent-purple: #8250df;--accent-cyan: #1b7c83;--accent-green: #1a7f37;--accent-yellow: #9a6700;--accent-red: #d1242f;--accent-orange: #bc4c00;--scrollbar-thumb: rgba(31, 35, 40, .15);--scrollbar-thumb-hover: rgba(31, 35, 40, .3);--selection-bg: rgba(9, 105, 218, .2)}*{margin:0;padding:0;box-sizing:border-box}html,body,#root{width:100%;height:100%;overflow:hidden;background-color:var(--bg-primary);font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}body.resizing-panes,body.resizing-panes *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.session-sidebar{transition:width .2s ease;overflow:hidden;flex-shrink:0;z-index:10;position:relative}body.resizing-panes-v,body.resizing-panes-v *{cursor:row-resize!important;-webkit-user-select:none!important;user-select:none!important}button{transition:all .15s ease;font-family:inherit}button:hover{filter:brightness(1.2)}button:active{transform:scale(.97)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}::selection{background:var(--selection-bg);color:var(--text-bright)}input:focus-visible,button:focus-visible{outline:1px solid var(--accent-blue);outline-offset:1px}.header-btn{background:none;border:1px solid var(--border);color:var(--accent-blue);padding:3px 10px;border-radius:5px;cursor:pointer;font-size:13px;line-height:1.4;transition:all .15s ease}.header-btn:hover{background:#7aa2f71f;border-color:var(--accent-blue);box-shadow:0 0 8px #7aa2f726}.header-btn--muted{color:var(--text-secondary);font-size:12px}.header-btn--muted:hover{color:var(--text-primary);border-color:var(--text-secondary);background:#565f891a}.pane-btn{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:12px;line-height:1;padding:2px 5px;border-radius:4px;transition:all .15s ease}.pane-btn:hover{color:var(--accent-blue);background:#7aa2f71f}.pane-btn--danger:hover{color:var(--accent-red);background:#f7768e1f}.login-input{transition:border-color .2s ease,box-shadow .2s ease}.login-input:focus{border-color:var(--accent-blue)!important;box-shadow:0 0 0 3px #7aa2f726}.login-card{box-shadow:0 8px 32px #0006,0 0 0 1px #7aa2f714;transition:box-shadow .3s ease}.login-submit{transition:all .2s ease}.login-submit:not(:disabled):hover{filter:brightness(1.1);box-shadow:0 4px 12px #7aa2f74d}.md-editor-textarea{flex:1;min-width:0;resize:none;border:none;outline:none;padding:8px 12px;font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;font-size:13px;line-height:1.5;color:var(--text-primary);background-color:var(--bg-primary);-moz-tab-size:2;tab-size:2}.md-editor-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.md-editor-divider{height:3px;background:var(--border);cursor:row-resize;flex-shrink:0;transition:background .15s ease,box-shadow .15s ease}.md-editor-divider:hover{background:var(--accent-blue);box-shadow:0 0 6px #7aa2f766}.pane-btn--active{color:var(--accent-blue)}.plan-panel-body{display:flex;flex-direction:row;flex:1;min-height:0;overflow:hidden}.plan-renderer{position:relative;overflow:hidden;padding:0;min-width:0;-webkit-user-select:text;user-select:text}.plan-divider-h{width:2px;background:var(--border);cursor:col-resize;flex-shrink:0;transition:background .15s ease,box-shadow .15s ease}.plan-divider-h:hover{background:var(--accent-blue);box-shadow:0 0 6px #7aa2f766}.plan-editor-wrap{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}.plan-filename-input{background:var(--bg-primary);border:1px solid var(--border);color:var(--text-primary);padding:2px 6px;border-radius:3px;font-family:inherit;font-size:11px;width:120px;outline:none;transition:border-color .15s ease}.plan-filename-input:focus{border-color:var(--accent-blue)}body.resizing-panes-h,body.resizing-panes-h *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.md-preview{color:var(--text-primary);font-size:13px;line-height:1.6;word-wrap:break-word}.md-preview h1{color:var(--accent-blue);font-size:1.4em;margin:.6em 0 .3em;padding-bottom:.2em;border-bottom:1px solid var(--border)}.md-preview h2{color:var(--accent-purple);font-size:1.2em;margin:.5em 0 .3em}.md-preview h3{color:var(--accent-cyan);font-size:1.05em;margin:.4em 0 .2em}.md-preview p{margin:.4em 0}.md-preview code{background:var(--bg-tertiary);color:var(--text-bright);padding:1px 4px;border-radius:3px;font-size:.9em;font-family:JetBrains Mono,LXGW WenKai Mono,monospace}.md-preview pre{background:var(--bg-tertiary);border:1px solid var(--border);border-radius:4px;padding:10px 12px;overflow-x:auto;margin:.5em 0}.md-preview pre code{background:none;padding:0;border-radius:0}.md-preview blockquote{border-left:3px solid var(--accent-blue);padding:2px 12px;margin:.4em 0;color:var(--text-secondary)}.md-preview ul,.md-preview ol{padding-left:1.5em;margin:.3em 0}.md-preview li{margin:.15em 0}.md-preview table{border-collapse:collapse;width:100%;margin:.5em 0;font-size:12px}.md-preview th,.md-preview td{border:1px solid var(--border);padding:4px 8px;text-align:left}.md-preview th{background:var(--bg-tertiary);color:var(--accent-blue);font-weight:600}.md-preview a{color:var(--accent-blue);text-decoration:none}.md-preview a:hover{text-decoration:underline}.md-preview hr{border:none;border-top:1px solid var(--border);margin:.6em 0}.slash-dropdown{flex-shrink:0;max-height:200px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:13px}.slash-item{display:flex;align-items:center;gap:10px;padding:6px 12px;cursor:pointer;transition:background .12s ease}.slash-item:hover,.slash-item--active{background:var(--bg-hover)}.slash-cmd{color:var(--accent-blue);font-weight:600;min-width:180px;font-family:JetBrains Mono,LXGW WenKai Mono,monospace}.slash-desc{color:var(--accent-purple);font-size:11px}.file-dropdown{flex-shrink:0;max-height:180px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:12px}.file-item{display:flex;align-items:center;gap:8px;padding:5px 10px;cursor:pointer;transition:background .1s ease}.file-item:hover,.file-item--active{background:var(--bg-hover)}.file-loading{color:var(--text-secondary);cursor:default}.file-icon{flex-shrink:0;width:16px;text-align:center;font-size:13px}.file-name{color:var(--text-bright);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.history-dropdown{flex-shrink:0;max-height:260px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:12px}.history-item{display:flex;align-items:flex-start;gap:8px;padding:6px 10px;cursor:pointer;transition:background .1s ease;position:relative}.history-item:hover,.history-item--active{background:var(--bg-hover)}.history-empty{color:var(--text-secondary);cursor:default;justify-content:center;padding:12px}.history-text{flex:1;color:var(--text-bright);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;white-space:pre-wrap;overflow-wrap:break-word;line-height:1.4}.history-time{flex-shrink:0;color:var(--text-secondary);font-size:10px;white-space:nowrap;margin-top:2px}.history-delete{flex-shrink:0;background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:14px;padding:0 2px;line-height:1;opacity:0;transition:opacity .1s ease,color .1s ease}.history-item:hover .history-delete,.history-item--active .history-delete{opacity:1}.history-delete:hover{color:var(--accent-red)}.tab-bar{display:flex;align-items:center;padding:0 10px;height:32px;background:var(--bg-secondary);border-top:1px solid var(--border);flex-shrink:0;overflow-x:auto;gap:3px}.tab-bar::-webkit-scrollbar{height:0}.tab-item{display:flex;align-items:center;gap:6px;padding:4px 12px;font-size:13px;color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;white-space:nowrap;transition:color .15s ease,border-color .15s ease,background .15s ease,box-shadow .15s ease;border-radius:5px 5px 0 0;-webkit-user-select:none;user-select:none;flex-shrink:0}.tab-item:hover{color:var(--text-primary);background:#7aa2f70f}.tab-item--active{color:var(--text-bright);border-bottom-color:var(--accent-blue);background:#7aa2f71a;box-shadow:inset 0 -1px 0 var(--accent-blue)}.tab-item__name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.tab-item__count{font-size:10px;color:var(--scrollbar-thumb-hover)}.tab-item__close{font-size:14px;line-height:1;color:inherit;opacity:0;background:none;border:none;cursor:pointer;padding:0 2px;border-radius:3px;transition:opacity .1s ease}.tab-item:hover .tab-item__close{opacity:.5}.tab-item__close:hover{opacity:1!important;color:var(--accent-red);background:#f7768e1a}.tab-item__rename-input{background:transparent;border:1px solid var(--accent-blue);color:var(--text-bright);font-size:13px;font-family:inherit;padding:0 6px;border-radius:3px;outline:none;width:100px}.tab-bar-add{background:none;border:1px solid transparent;color:var(--text-secondary);font-size:18px;line-height:1;padding:2px 8px;border-radius:5px;cursor:pointer;margin-left:4px;flex-shrink:0}.tab-bar-add:hover{color:var(--accent-blue);border-color:var(--border);background:#7aa2f71a}.md-editor-actions{display:flex;align-items:center;gap:8px;padding:4px 8px;flex-shrink:0;background:var(--bg-secondary);border-top:1px solid var(--border)}.plan-anno-toolbar{display:flex;align-items:center;gap:6px;padding:3px 10px;height:28px;flex-shrink:0;background:var(--bg-secondary);border-bottom:1px solid var(--border)}.plan-anno-content{-webkit-user-select:text;user-select:text}.plan-insert-zone{position:relative;min-height:12px}.plan-insert-btn{display:none;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:20px;height:20px;border-radius:50%;border:1px solid var(--scrollbar-thumb-hover);background:var(--bg-secondary);color:var(--accent-blue);font-size:15px;line-height:1;cursor:pointer;padding:0 0 1px;z-index:2;transition:background .12s ease,border-color .12s ease,transform .12s ease;align-items:center;justify-content:center}.plan-insert-zone:hover .plan-insert-btn{display:flex}.plan-anno-content--editing .plan-insert-zone:hover .plan-insert-btn{display:none}.plan-empty-placeholder{display:flex;align-items:center;justify-content:center;min-height:120px;color:var(--text-secondary);font-size:13px;font-style:italic;cursor:pointer;-webkit-user-select:none;user-select:none;text-align:center;padding:16px}.plan-empty-placeholder:hover{color:var(--accent-blue)}.plan-insert-btn:hover{background:var(--bg-hover);border-color:var(--accent-blue);transform:translate(-50%,-50%) scale(1.15)}.plan-annotation-card{display:flex;align-items:flex-start;gap:6px;padding:6px 10px;margin:4px 0;background:#e0af681f;border-left:3px solid var(--accent-yellow);border-radius:0 4px 4px 0}.plan-annotation-card--editing{border-left-color:var(--accent-blue);background:#7aa2f70f}.plan-annotation-textarea{flex:1;min-height:36px;max-height:30em;field-sizing:content;resize:vertical;border:1px solid var(--border);border-radius:3px;background:var(--bg-primary);color:var(--text-primary);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;font-size:12px;padding:4px 6px;outline:none;transition:border-color .15s ease}.plan-annotation-textarea:focus{border-color:var(--accent-blue)}.plan-annotation-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.plan-deletion-card{display:flex;align-items:center;gap:6px;padding:2px 8px;margin:2px 0;background:#f7768e0f;border-left:3px solid var(--accent-red);border-radius:0 4px 4px 0;font-size:11px}.plan-selection-float{position:absolute;z-index:1000;display:flex;flex-direction:row;gap:2px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;padding:2px;box-shadow:0 2px 8px #0000004d}.plan-selection-float button{width:24px;height:24px;border-radius:4px;border:none;cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center;background:transparent;transition:background .15s,transform .1s}.plan-selection-float button:hover{transform:scale(1.1)}.plan-selection-float__delete{color:var(--accent-red)}.plan-selection-float__delete:hover{background:#f7768e33}.plan-selection-float__replace{color:var(--accent-blue)}.plan-selection-float__replace:hover{background:#7aa2f733}.plan-selection-float__comment{color:var(--accent-green)}.plan-selection-float__comment:hover{background:#9ece6a33}.plan-replace-card{display:flex;align-items:flex-start;gap:6px;padding:2px 8px;margin:2px 0;border-left:3px solid rgba(122,162,247,.6);background:#7aa2f70a;border-radius:0 4px 4px 0;font-size:11px}.plan-comment-card{display:flex;align-items:flex-start;gap:6px;padding:2px 8px;margin:2px 0;border-left:3px solid rgba(158,206,106,.6);background:#9ece6a0a;border-radius:0 4px 4px 0;font-size:11px}.plan-block--deleted{border-left:3px solid rgba(247,118,142,.5);padding-left:8px;border-radius:2px;position:relative}.plan-block--replaced{border-left:3px solid rgba(122,162,247,.5);padding-left:8px;border-radius:2px;position:relative}.plan-block--commented{border-left:3px solid rgba(158,206,106,.5);padding-left:8px;border-radius:2px;position:relative}.mermaid-diagram{margin:8px 0;padding:12px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;overflow-x:auto}.mermaid-diagram svg{display:block;margin:0 auto;max-width:100%;height:auto}.mermaid-error{border-left:3px solid var(--accent-red);padding-left:8px}.mermaid-error__msg{color:var(--accent-red);font-size:11px;margin-top:4px}.pane-btn--sm{font-size:11px;flex-shrink:0}.plan-file-browser{display:flex;flex-direction:column;height:100%;width:100%;background:var(--bg-secondary);overflow:hidden}.plan-file-browser__header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;height:28px;flex-shrink:0;border-bottom:1px solid var(--border)}.plan-file-browser__title{font-size:11px;color:var(--accent-blue);font-weight:600;letter-spacing:.3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;direction:rtl;text-align:left}.plan-file-browser__list{flex:1;overflow-y:auto;overflow-x:hidden;padding:2px 0}.plan-file-browser__status{padding:8px 10px;font-size:11px;color:var(--text-secondary);font-style:italic}.plan-file-browser__item{display:flex;align-items:center;padding:3px 8px;font-size:12px;cursor:pointer;gap:5px;transition:background .1s ease;border-left:2px solid transparent}.plan-file-browser__item:hover{background:var(--bg-tertiary)}.plan-file-browser__item--active{background:#7aa2f71a;border-left-color:var(--accent-blue)}.plan-file-browser__item--active .plan-file-browser__name{color:var(--text-bright)}.plan-file-browser__icon{flex-shrink:0;width:14px;font-size:10px;color:var(--text-secondary);text-align:center}.plan-file-browser__name{flex:1;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.plan-file-browser__size{flex-shrink:1;font-size:9px;color:var(--scrollbar-thumb-hover);white-space:nowrap;overflow:hidden;min-width:0}.plan-file-browser__create{display:flex;align-items:center;gap:4px;padding:4px 6px;border-top:1px solid var(--border);flex-shrink:0}.plan-file-browser__input{flex:1;min-width:0;background:var(--bg-primary);border:1px solid var(--border);color:var(--text-primary);padding:2px 6px;border-radius:3px;font-family:inherit;font-size:11px;outline:none;transition:border-color .15s ease}.plan-file-browser__input:focus{border-color:var(--accent-blue)}.plan-file-browser__input::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.plan-overlay-body{display:flex;flex:1;min-height:0;overflow:hidden}.plan-overlay-center{flex:1;min-width:0;overflow:hidden}.plan-anno-counts{display:inline-flex;align-items:center;gap:4px;font-size:10px;margin-left:4px}.plan-anno-counts__unsent{color:var(--accent-yellow)}.plan-anno-counts__sent{color:var(--accent-green)}.plan-anno-dropdown-trigger{display:flex;align-items:center;gap:4px;padding:2px 6px;border:1px solid var(--border);border-radius:3px;cursor:pointer;background:var(--bg-primary);transition:border-color .15s ease,background .15s ease;min-width:0}.plan-anno-dropdown-trigger:hover,.plan-anno-dropdown-trigger--active{border-color:var(--accent-blue);background:var(--bg-hover)}.plan-anno-dropdown-trigger__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;color:var(--text-secondary)}.plan-anno-dropdown-trigger__arrow{flex-shrink:0;font-size:9px;color:var(--text-secondary);transition:transform .15s ease}.plan-anno-dropdown-trigger--active .plan-anno-dropdown-trigger__arrow{transform:rotate(180deg)}.plan-anno-dropdown{position:absolute;top:100%;right:0;z-index:100;width:320px;max-height:300px;display:flex;flex-direction:column;background:var(--bg-secondary);border:1px solid var(--border);border-radius:4px;box-shadow:0 4px 12px #0000004d;overflow:hidden}.plan-anno-dropdown__header{display:flex;align-items:center;justify-content:center;padding:4px 6px;border-bottom:1px solid var(--border);flex-shrink:0}.plan-anno-dropdown__list{flex:1;overflow-y:auto;padding:2px 0}.plan-anno-dropdown__item{display:flex;align-items:center;gap:4px;padding:3px 6px;font-size:11px;border-bottom:1px solid var(--border-subtle, rgba(128,128,128,.1))}.plan-anno-dropdown__item:last-child{border-bottom:none}.plan-anno-dropdown__item--add{border-left:2px solid var(--accent-yellow)}.plan-anno-dropdown__item--del{border-left:2px solid var(--accent-red)}.plan-anno-dropdown__item--rep{border-left:2px solid var(--accent-blue)}.plan-anno-dropdown__item--com{border-left:2px solid var(--accent-green)}.plan-anno-dropdown__type{flex-shrink:0;width:14px;font-weight:700;text-align:center}.plan-anno-dropdown__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-primary)}.plan-anno-dropdown__badge{flex-shrink:0;font-size:9px;padding:0 4px;border-radius:3px;background:var(--accent-green);color:var(--bg-primary)}.plan-anno-dropdown__empty{padding:8px;text-align:center;font-size:11px;color:var(--text-secondary);font-style:italic}.plan-edit-textarea{width:100%;flex:1;resize:none;border:none;outline:none;padding:8px 12px;font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;line-height:1.6;background:var(--bg-primary);color:var(--text-primary);-moz-tab-size:2;tab-size:2}.plan-edit-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.auto-timeline{display:flex;align-items:center;gap:5px;padding:3px 8px;min-height:26px;overflow:hidden}.auto-divider{color:var(--border);font-size:11px;-webkit-user-select:none;user-select:none;flex-shrink:0}.auto-spin-input{display:inline-flex;align-items:center;height:18px;background:var(--bg-tertiary);border:1px solid var(--border);border-radius:3px;overflow:hidden;flex-shrink:0}.auto-spin-input input{width:100%;height:100%;padding:0 2px;font-size:10px;background:transparent;color:var(--text-primary);border:none;outline:none;text-align:left;-moz-appearance:textfield}.auto-spin-input input::-webkit-inner-spin-button,.auto-spin-input input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.auto-spin-btns{display:flex;flex-direction:column;flex-shrink:0;border-left:1px solid var(--border)}.auto-spin-btns button{display:flex;align-items:center;justify-content:center;width:14px;height:9px;font-size:5px;line-height:1;padding:0;background:var(--bg-secondary);color:var(--text-secondary);border:none;cursor:pointer}.auto-spin-btns button:hover{background:var(--bg-tertiary);color:var(--text-primary)}.auto-spin-btns button:first-child{border-bottom:1px solid var(--border)}.auto-step-node{display:flex;flex-direction:column;align-items:center;gap:1px;background:none;border:none;padding:2px 4px;cursor:pointer;min-width:40px;flex-shrink:0}.auto-step-node:disabled{cursor:default;opacity:.5}.auto-step-node:not(:disabled):hover .auto-step-circle{transform:scale(1.3)}.auto-step-circle{width:8px;height:8px;border-radius:50%;transition:transform .15s,background-color .2s;flex-shrink:0}.auto-step-node.completed .auto-step-circle{background-color:var(--accent-green)}.auto-step-node.active .auto-step-circle{background-color:var(--accent-blue);animation:auto-pulse 1.5s ease-in-out infinite}.auto-step-node.pending .auto-step-circle{background-color:var(--text-secondary);opacity:.4}@keyframes auto-pulse{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.4);opacity:.7}}.auto-step-label{font-size:9px;color:var(--text-primary);white-space:nowrap;max-width:50px;overflow:hidden;text-overflow:ellipsis}.auto-step-duration{font-size:8px;color:var(--text-secondary);white-space:nowrap}.auto-connector{width:12px;height:2px;background-color:var(--border);flex-shrink:0;transition:background-color .2s}.auto-connector.completed{background-color:var(--accent-green)}.auto-step-popup{position:absolute;left:0;right:0;bottom:0;top:0;z-index:10;background-color:var(--bg-primary);display:flex;flex-direction:column;border-top:2px solid var(--accent-blue)}