deckide 3.5.40 → 3.5.42
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/dist/config.js +28 -0
- package/dist/routes/codeserver.js +79 -0
- package/dist/routes/files.js +72 -0
- package/dist/server.js +22 -2
- package/dist/utils/agent-browser.js +63 -11
- package/dist/utils/browser-maintenance.js +145 -0
- package/dist/utils/browser-webrtc.js +471 -0
- package/dist/utils/code-server.js +291 -0
- package/dist/websocket.js +54 -2
- package/package.json +5 -2
- package/web/dist/assets/index-C1OzsVds.css +32 -0
- package/web/dist/assets/index-DFNjEZYB.js +178 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-CdzOg4rb.css +0 -32
- package/web/dist/assets/index-D2wX1H1J.js +0 -178
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import net from 'node:net';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { dataDir } from '../config.js';
|
|
6
|
+
const IDLE_TIMEOUT_MS = 20 * 60 * 1000;
|
|
7
|
+
const START_TIMEOUT_MS = 30_000;
|
|
8
|
+
const REAP_INTERVAL_MS = 60_000;
|
|
9
|
+
function sleep(ms) {
|
|
10
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11
|
+
}
|
|
12
|
+
async function pathExists(filePath) {
|
|
13
|
+
try {
|
|
14
|
+
await fs.access(filePath);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function findInPath(name) {
|
|
22
|
+
for (const dir of (process.env.PATH || '').split(path.delimiter)) {
|
|
23
|
+
if (!dir)
|
|
24
|
+
continue;
|
|
25
|
+
const candidate = path.join(dir, name);
|
|
26
|
+
if (await pathExists(candidate)) {
|
|
27
|
+
return candidate;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function getFreePort() {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const srv = net.createServer();
|
|
35
|
+
srv.once('error', reject);
|
|
36
|
+
srv.listen(0, '127.0.0.1', () => {
|
|
37
|
+
const addr = srv.address();
|
|
38
|
+
const port = typeof addr === 'object' && addr ? addr.port : 0;
|
|
39
|
+
srv.close(() => (port ? resolve(port) : reject(new Error('Could not get a free port'))));
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Manages per-workspace code-server child processes — the "power editor" surface.
|
|
45
|
+
* Mirrors AgentBrowserService: spawn on demand, supervise, poll readiness, and
|
|
46
|
+
* idle-reap (auto-stop, not auto-restart). One instance per workspace id.
|
|
47
|
+
*/
|
|
48
|
+
export class CodeServerService {
|
|
49
|
+
workspaces;
|
|
50
|
+
instances = new Map();
|
|
51
|
+
reaper = null;
|
|
52
|
+
// Directory layout under ~/.deckide/code-server (set by config.dataDir).
|
|
53
|
+
root = path.join(dataDir, 'code-server');
|
|
54
|
+
constructor(workspaces) {
|
|
55
|
+
this.workspaces = workspaces;
|
|
56
|
+
}
|
|
57
|
+
// Resolve the code-server executable: explicit env → standalone install under
|
|
58
|
+
// dataDir → PATH. Returns null when not acquired.
|
|
59
|
+
async resolveBin() {
|
|
60
|
+
const configured = process.env.DECKIDE_CODE_SERVER_BIN;
|
|
61
|
+
if (configured) {
|
|
62
|
+
return (await pathExists(configured)) ? configured : null;
|
|
63
|
+
}
|
|
64
|
+
const standalone = path.join(this.root, 'bin', 'code-server');
|
|
65
|
+
if (await pathExists(standalone)) {
|
|
66
|
+
return standalone;
|
|
67
|
+
}
|
|
68
|
+
return findInPath('code-server');
|
|
69
|
+
}
|
|
70
|
+
async isAcquired() {
|
|
71
|
+
return (await this.resolveBin()) !== null;
|
|
72
|
+
}
|
|
73
|
+
async getStatus(wsId) {
|
|
74
|
+
const bin = await this.resolveBin();
|
|
75
|
+
const instance = wsId ? this.instances.get(wsId) : undefined;
|
|
76
|
+
return {
|
|
77
|
+
available: bin !== null,
|
|
78
|
+
acquired: bin !== null,
|
|
79
|
+
binPath: bin,
|
|
80
|
+
running: instance ? instance.proc.exitCode == null : false,
|
|
81
|
+
instances: this.instances.size,
|
|
82
|
+
wsId: wsId ?? null,
|
|
83
|
+
reason: bin ? undefined : 'code-server is not installed (run: deckide codeserver install)',
|
|
84
|
+
error: instance?.error,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Ensure an instance for this workspace is running and ready; return its port.
|
|
88
|
+
async ensure(wsId) {
|
|
89
|
+
const existing = this.instances.get(wsId);
|
|
90
|
+
if (existing && existing.proc.exitCode == null) {
|
|
91
|
+
existing.lastActive = Date.now();
|
|
92
|
+
await existing.ready;
|
|
93
|
+
return existing.port;
|
|
94
|
+
}
|
|
95
|
+
if (existing) {
|
|
96
|
+
this.instances.delete(wsId);
|
|
97
|
+
}
|
|
98
|
+
const workspace = this.workspaces.get(wsId);
|
|
99
|
+
if (!workspace) {
|
|
100
|
+
throw new Error(`Unknown workspace: ${wsId}`);
|
|
101
|
+
}
|
|
102
|
+
const bin = await this.resolveBin();
|
|
103
|
+
if (!bin) {
|
|
104
|
+
throw new Error('code-server is not installed (run: deckide codeserver install)');
|
|
105
|
+
}
|
|
106
|
+
const port = await getFreePort();
|
|
107
|
+
const userDataDir = path.join(this.root, 'user', wsId);
|
|
108
|
+
const extensionsDir = path.join(this.root, 'ext');
|
|
109
|
+
await fs.mkdir(userDataDir, { recursive: true });
|
|
110
|
+
await fs.mkdir(extensionsDir, { recursive: true });
|
|
111
|
+
// Per-instance config file so the user's global ~/.config/code-server/config.yaml
|
|
112
|
+
// (which may set auth/bind-addr) can never override our flags.
|
|
113
|
+
const configPath = path.join(userDataDir, 'config.yaml');
|
|
114
|
+
await fs.writeFile(configPath, `bind-addr: 127.0.0.1:${port}\nauth: none\ncert: false\n`, 'utf8');
|
|
115
|
+
// code-server honors the PORT env var ahead of --bind-addr, so strip it
|
|
116
|
+
// (Deck IDE's own PORT would otherwise collide).
|
|
117
|
+
const childEnv = { ...process.env };
|
|
118
|
+
delete childEnv.PORT;
|
|
119
|
+
const proc = spawn(bin, [
|
|
120
|
+
'--config', configPath,
|
|
121
|
+
'--auth', 'none', // Deck IDE owns auth at the same-origin proxy.
|
|
122
|
+
'--disable-telemetry',
|
|
123
|
+
'--disable-update-check',
|
|
124
|
+
'--bind-addr', `127.0.0.1:${port}`,
|
|
125
|
+
'--user-data-dir', userDataDir,
|
|
126
|
+
'--extensions-dir', extensionsDir,
|
|
127
|
+
workspace.path,
|
|
128
|
+
], { stdio: ['ignore', 'pipe', 'pipe'], env: childEnv });
|
|
129
|
+
let stderrTail = '';
|
|
130
|
+
proc.stderr.setEncoding('utf8');
|
|
131
|
+
proc.stderr.on('data', (chunk) => {
|
|
132
|
+
stderrTail = (stderrTail + chunk).slice(-2000);
|
|
133
|
+
});
|
|
134
|
+
proc.stdout.resume();
|
|
135
|
+
const instance = {
|
|
136
|
+
wsId,
|
|
137
|
+
proc,
|
|
138
|
+
port,
|
|
139
|
+
lastActive: Date.now(),
|
|
140
|
+
startedAt: Date.now(),
|
|
141
|
+
ready: this.waitForReady(port, proc, () => stderrTail),
|
|
142
|
+
};
|
|
143
|
+
this.instances.set(wsId, instance);
|
|
144
|
+
proc.once('exit', (code, signal) => {
|
|
145
|
+
const current = this.instances.get(wsId);
|
|
146
|
+
if (current === instance) {
|
|
147
|
+
this.instances.delete(wsId);
|
|
148
|
+
}
|
|
149
|
+
if (code !== 0 && code != null) {
|
|
150
|
+
console.error(`[code-server] ${wsId} exited (${signal ?? code}): ${stderrTail.trim()}`);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
proc.once('error', (error) => {
|
|
154
|
+
instance.error = error.message;
|
|
155
|
+
});
|
|
156
|
+
this.ensureReaper();
|
|
157
|
+
try {
|
|
158
|
+
await instance.ready;
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
await this.stop(wsId);
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
return port;
|
|
165
|
+
}
|
|
166
|
+
async waitForReady(port, proc, tail) {
|
|
167
|
+
const deadline = Date.now() + START_TIMEOUT_MS;
|
|
168
|
+
while (Date.now() < deadline) {
|
|
169
|
+
if (proc.exitCode != null) {
|
|
170
|
+
throw new Error(`code-server exited before becoming ready: ${tail().trim()}`);
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const res = await fetch(`http://127.0.0.1:${port}/healthz`, {
|
|
174
|
+
signal: AbortSignal.timeout(2000),
|
|
175
|
+
});
|
|
176
|
+
if (res.ok) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// not up yet
|
|
182
|
+
}
|
|
183
|
+
await sleep(250);
|
|
184
|
+
}
|
|
185
|
+
throw new Error('Timed out waiting for code-server to become ready');
|
|
186
|
+
}
|
|
187
|
+
// Returns the running port for a ready instance (for the HTTP proxy), bumping
|
|
188
|
+
// its idle timer. Starts the instance if needed.
|
|
189
|
+
async portFor(wsId) {
|
|
190
|
+
return this.ensure(wsId);
|
|
191
|
+
}
|
|
192
|
+
touch(wsId) {
|
|
193
|
+
const instance = this.instances.get(wsId);
|
|
194
|
+
if (instance) {
|
|
195
|
+
instance.lastActive = Date.now();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Proxy a WebSocket upgrade for a ready instance to its loopback port. The
|
|
199
|
+
// prefix /codeserver/:wsId has already been stripped from req.url by the caller.
|
|
200
|
+
proxyUpgrade(wsId, req, clientSocket, head) {
|
|
201
|
+
const instance = this.instances.get(wsId);
|
|
202
|
+
if (!instance || instance.proc.exitCode != null) {
|
|
203
|
+
clientSocket.destroy();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
instance.lastActive = Date.now();
|
|
207
|
+
const upstream = net.connect(instance.port, '127.0.0.1', () => {
|
|
208
|
+
const headerLines = [`${req.method} ${req.url} HTTP/1.1`];
|
|
209
|
+
const headers = req.headers;
|
|
210
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
211
|
+
if (value === undefined)
|
|
212
|
+
continue;
|
|
213
|
+
if (Array.isArray(value)) {
|
|
214
|
+
for (const v of value)
|
|
215
|
+
headerLines.push(`${key}: ${v}`);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
headerLines.push(`${key}: ${value}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
upstream.write(headerLines.join('\r\n') + '\r\n\r\n');
|
|
222
|
+
if (head && head.length) {
|
|
223
|
+
upstream.write(head);
|
|
224
|
+
}
|
|
225
|
+
upstream.pipe(clientSocket);
|
|
226
|
+
clientSocket.pipe(upstream);
|
|
227
|
+
});
|
|
228
|
+
const teardown = () => {
|
|
229
|
+
try {
|
|
230
|
+
upstream.destroy();
|
|
231
|
+
}
|
|
232
|
+
catch { /* ignore */ }
|
|
233
|
+
try {
|
|
234
|
+
clientSocket.destroy();
|
|
235
|
+
}
|
|
236
|
+
catch { /* ignore */ }
|
|
237
|
+
};
|
|
238
|
+
upstream.on('error', teardown);
|
|
239
|
+
clientSocket.on('error', teardown);
|
|
240
|
+
}
|
|
241
|
+
async stop(wsId) {
|
|
242
|
+
const instance = this.instances.get(wsId);
|
|
243
|
+
if (!instance)
|
|
244
|
+
return;
|
|
245
|
+
this.instances.delete(wsId);
|
|
246
|
+
const proc = instance.proc;
|
|
247
|
+
if (proc.exitCode == null && proc.signalCode == null) {
|
|
248
|
+
await new Promise((resolve) => {
|
|
249
|
+
const killTimer = setTimeout(() => {
|
|
250
|
+
try {
|
|
251
|
+
proc.kill('SIGKILL');
|
|
252
|
+
}
|
|
253
|
+
catch { /* ignore */ }
|
|
254
|
+
}, 3000);
|
|
255
|
+
killTimer.unref?.();
|
|
256
|
+
proc.once('exit', () => { clearTimeout(killTimer); resolve(); });
|
|
257
|
+
try {
|
|
258
|
+
proc.kill('SIGTERM');
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
clearTimeout(killTimer);
|
|
262
|
+
resolve();
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async stopAll() {
|
|
268
|
+
if (this.reaper) {
|
|
269
|
+
clearInterval(this.reaper);
|
|
270
|
+
this.reaper = null;
|
|
271
|
+
}
|
|
272
|
+
await Promise.all([...this.instances.keys()].map((wsId) => this.stop(wsId)));
|
|
273
|
+
}
|
|
274
|
+
ensureReaper() {
|
|
275
|
+
if (this.reaper)
|
|
276
|
+
return;
|
|
277
|
+
this.reaper = setInterval(() => {
|
|
278
|
+
const now = Date.now();
|
|
279
|
+
for (const [wsId, instance] of this.instances) {
|
|
280
|
+
if (now - instance.lastActive > IDLE_TIMEOUT_MS) {
|
|
281
|
+
void this.stop(wsId);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (this.instances.size === 0 && this.reaper) {
|
|
285
|
+
clearInterval(this.reaper);
|
|
286
|
+
this.reaper = null;
|
|
287
|
+
}
|
|
288
|
+
}, REAP_INTERVAL_MS);
|
|
289
|
+
this.reaper.unref?.();
|
|
290
|
+
}
|
|
291
|
+
}
|
package/dist/websocket.js
CHANGED
|
@@ -196,8 +196,47 @@ function readBufferedRange(session, startOffset, endOffset) {
|
|
|
196
196
|
}
|
|
197
197
|
return Buffer.from(raw.subarray(alignedStart, alignedEnd));
|
|
198
198
|
}
|
|
199
|
-
export function setupWebSocketServer(server, terminals, browserService) {
|
|
200
|
-
|
|
199
|
+
export function setupWebSocketServer(server, terminals, browserService, codeServerService) {
|
|
200
|
+
// noServer mode: we own the HTTP 'upgrade' event so code-server's WebSocket can
|
|
201
|
+
// be reverse-proxied alongside the app's own sockets. Everything that isn't a
|
|
202
|
+
// /codeserver/ upgrade is handed to wss exactly as before.
|
|
203
|
+
const wss = new WebSocketServer({ noServer: true, maxPayload: MAX_MESSAGE_SIZE });
|
|
204
|
+
server.on('upgrade', (req, socket, head) => {
|
|
205
|
+
let pathname;
|
|
206
|
+
try {
|
|
207
|
+
pathname = new URL(req.url || '', `http://localhost:${PORT}`).pathname;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
socket.destroy();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (codeServerService && pathname.startsWith('/codeserver/')) {
|
|
214
|
+
if (!verifyWebSocketAuth(req)) {
|
|
215
|
+
socket.destroy();
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const rest = pathname.slice('/codeserver/'.length);
|
|
219
|
+
const slash = rest.indexOf('/');
|
|
220
|
+
const wsId = slash === -1 ? rest : rest.slice(0, slash);
|
|
221
|
+
const prefix = `/codeserver/${wsId}`;
|
|
222
|
+
const original = req.url || '';
|
|
223
|
+
req.url = original.slice(prefix.length) || '/';
|
|
224
|
+
if (!req.url.startsWith('/')) {
|
|
225
|
+
req.url = `/${req.url}`;
|
|
226
|
+
}
|
|
227
|
+
codeServerService
|
|
228
|
+
.ensure(wsId)
|
|
229
|
+
.then(() => codeServerService.proxyUpgrade(wsId, req, socket, head))
|
|
230
|
+
.catch(() => {
|
|
231
|
+
try {
|
|
232
|
+
socket.destroy();
|
|
233
|
+
}
|
|
234
|
+
catch { /* ignore */ }
|
|
235
|
+
});
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
wss.handleUpgrade(req, socket, head, (ws) => wss.emit('connection', ws, req));
|
|
239
|
+
});
|
|
201
240
|
const heartbeatState = new WeakMap();
|
|
202
241
|
const heartbeatInterval = setInterval(() => {
|
|
203
242
|
for (const socket of wss.clients) {
|
|
@@ -298,6 +337,19 @@ export function setupWebSocketServer(server, terminals, browserService) {
|
|
|
298
337
|
browserService.attachAudioWebSocket(socket);
|
|
299
338
|
return;
|
|
300
339
|
}
|
|
340
|
+
if (url.pathname === '/api/browser/webrtc/ws') {
|
|
341
|
+
if (!browserService) {
|
|
342
|
+
untrackConnection(clientIP, socket);
|
|
343
|
+
socket.close(1011, 'Browser service unavailable');
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
socket.on('close', () => {
|
|
347
|
+
heartbeatState.delete(socket);
|
|
348
|
+
untrackConnection(clientIP, socket);
|
|
349
|
+
});
|
|
350
|
+
browserService.attachWebRtcWebSocket(socket);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
301
353
|
const match = url.pathname.match(/\/api\/terminals\/(.+)/);
|
|
302
354
|
if (!match) {
|
|
303
355
|
untrackConnection(clientIP, socket);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deckide",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.42",
|
|
4
4
|
"description": "Deck IDE - Browser-based IDE with terminal, file explorer, and git integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -66,5 +66,8 @@
|
|
|
66
66
|
"developer-tools"
|
|
67
67
|
],
|
|
68
68
|
"author": "tako0614",
|
|
69
|
-
"license": "MIT"
|
|
69
|
+
"license": "MIT",
|
|
70
|
+
"optionalDependencies": {
|
|
71
|
+
"werift": "^0.23.0"
|
|
72
|
+
}
|
|
70
73
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Noto+Sans+JP:wght@400;500;600&display=swap";/**
|
|
2
|
+
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
+
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
+
* https://github.com/chjj/term.js
|
|
5
|
+
* @license MIT
|
|
6
|
+
*
|
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
*
|
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
|
15
|
+
* all copies or substantial portions of the Software.
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
* THE SOFTWARE.
|
|
24
|
+
*
|
|
25
|
+
* Originally forked from (with the author's permission):
|
|
26
|
+
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
+
* http://bellard.org/jslinux/
|
|
28
|
+
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
+
* The original design remains. The terminal itself
|
|
30
|
+
* has been extended to include xterm CSI codes, among
|
|
31
|
+
* other features.
|
|
32
|
+
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:"JetBrains Mono", monospace;--color-red-400:oklch(70.4% .191 22.216);--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-bg:#f3f3f3;--color-bg-soft:#e8e8e8;--color-panel:#fff;--color-sidebar:#f3f3f3;--color-activitybar:#2c2c2c;--color-activitybar-fg:#fff;--color-activitybar-inactive:#fff9;--color-border:#e5e5e5;--color-ink:#333;--color-ink-muted:#6e6e6e;--color-muted:#717171;--color-accent:#007acc;--color-statusbar:#007acc;--color-statusbar-fg:#fff;--color-list-hover:#0000000a;--color-list-active:#0078d41a;--color-focus:#0090f1;--color-title-bar:#ddd;--color-git-modified:#cca700;--color-git-untracked:#4ec9b0;--color-git-deleted:#f14c4c;--color-git-staged:#73c991;--color-git-renamed:#4fc1ff;--color-git-conflicted:#ff6b6b;--font-ui:"Noto Sans JP", sans-serif}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*,:before,:after{box-sizing:border-box}html,body,#root{height:100%;min-height:100%;margin:0}body{font-family:var(--font-ui);background:var(--color-bg);color:var(--color-ink);font-size:13px;line-height:1.4;overflow:hidden}button,input,select,textarea{color:inherit;font-family:inherit}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:2px solid var(--color-focus);outline-offset:2px}@supports (height:100dvh){html,body,#root{height:100dvh;min-height:100dvh}}html,body,#root{height:var(--viewport-height,100dvh);min-height:var(--viewport-height,100dvh)}*{scrollbar-width:thin;scrollbar-color:#8080804d transparent}:root[data-theme=dark] *{scrollbar-color:#ffffff26 transparent}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:#8080804d;border-radius:3px}::-webkit-scrollbar-thumb:hover{background:#80808080}:root[data-theme=dark] ::-webkit-scrollbar-thumb{background:#ffffff26}:root[data-theme=dark] ::-webkit-scrollbar-thumb:hover{background:#ffffff4d}::-webkit-scrollbar-corner{background:0 0}}@layer components{.activity-bar-item.active:before{content:"";background:var(--color-activitybar-fg);width:2px;position:absolute;top:0;bottom:0;left:0}.workspace-editor-grid .activity-bar-item.active:before{background:var(--color-accent)}.app>nav.activity-bar .activity-bar-item.active:before{width:auto;height:2px;inset:0 0 auto}.git-tab.active:after{content:"";background:var(--color-accent);height:2px;position:absolute;bottom:0;left:0;right:0}.editor-tab:hover .editor-tab-close,.editor-tab.active .editor-tab-close{opacity:1}.editor-tab.dirty .editor-tab-close{opacity:0}.editor-tab.dirty:hover .editor-tab-close{opacity:1}.editor-tab.dirty:hover .editor-tab-dirty{display:none}.deck-tab:hover .deck-tab-close,.deck-tab.active .deck-tab-close{opacity:.5}.deck-tab-close:hover{color:var(--color-ink);background:#ffffff1f;opacity:1!important}.git-file-row:hover .git-file-actions{opacity:1}.tree-row.is-open .tree-chevron-icon{transform:rotate(90deg)}.terminal-split-container.is-drop-target:after{content:"デッキをここにドロップして分割";border:2px dashed var(--color-accent);color:var(--color-ink-muted);pointer-events:none;z-index:2;background:#0078d414;border-radius:6px;justify-content:center;align-items:center;font-size:12px;font-weight:600;display:flex;position:absolute;top:10px;right:10px;bottom:10px;left:10px}.git-tree-modified .tree-label{color:var(--color-git-modified)}.git-tree-untracked .tree-label{color:var(--color-git-untracked)}.git-tree-deleted .tree-label{color:var(--color-git-deleted)}.git-tree-staged .tree-label{color:var(--color-git-staged)}.git-tree-renamed .tree-label{color:var(--color-git-renamed)}.git-tree-conflicted .tree-label{color:var(--color-git-conflicted)}.sidebar-content .panel{box-shadow:none;background:0 0;border:none;border-radius:0}.sidebar-content .panel-header{background:var(--color-sidebar);z-index:1;margin-bottom:0;padding:8px 12px;position:sticky;top:0}.sidebar-content .panel-body{padding:0}}@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-1{top:calc(var(--spacing) * 1)}.right-1{right:calc(var(--spacing) * 1)}.z-50{z-index:50}.z-\[500\]{z-index:500}.z-\[999\]{z-index:999}.z-\[1000\]{z-index:1000}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing) * 0)}.my-1{margin-block:calc(var(--spacing) * 1)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-7{height:calc(var(--spacing) * 7)}.h-\[22px\]{height:22px}.h-full{height:100%}.h-px{height:1px}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-\[28px\]{min-height:28px}.min-h-\[36px\]{min-height:36px}.min-h-\[40px\]{min-height:40px}.min-h-\[44px\]{min-height:44px}.min-h-\[50px\]{min-height:50px}.min-h-screen{min-height:100vh}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-7{width:calc(var(--spacing) * 7)}.w-\[22px\]{width:22px}.w-\[220px\]{width:220px}.w-\[500px\]{width:500px}.w-full{width:100%}.max-w-\[160px\]{max-width:160px}.max-w-\[180px\]{max-width:180px}.max-w-\[500px\]{max-width:500px}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[44px\]{min-width:44px}.min-w-\[140px\]{min-width:140px}.min-w-\[160px\]{min-width:160px}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-y{resize:vertical}.grid-rows-\[35px_minmax\(0\,1fr\)\]{grid-template-rows:35px minmax(0,1fr)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.\!overflow-hidden{overflow:hidden!important}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-\[2px\]{border-radius:2px}.rounded-\[3px\]{border-radius:3px}.rounded-\[6px\]{border-radius:6px}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-accent{border-color:var(--color-accent)}.border-border{border-color:var(--color-border)}.bg-\[\#f14c4c\]{background-color:#f14c4c}.bg-accent{background-color:var(--color-accent)}.bg-accent\/20{background-color:#007acc33}@supports (color:color-mix(in lab,red,red)){.bg-accent\/20{background-color:color-mix(in oklab,var(--color-accent) 20%,transparent)}}.bg-bg{background-color:var(--color-bg)}.bg-bg-soft{background-color:var(--color-bg-soft)}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black) 50%,transparent)}}.bg-border{background-color:var(--color-border)}.bg-list-active{background-color:var(--color-list-active)}.bg-list-hover{background-color:var(--color-list-hover)}.bg-panel{background-color:var(--color-panel)}.bg-sidebar{background-color:var(--color-sidebar)}.bg-title-bar{background-color:var(--color-title-bar)}.bg-transparent{background-color:#0000}.fill-current{fill:currentColor}.p-0{padding:calc(var(--spacing) * 0)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-\[inherit\]{font-family:inherit}.font-mono{font-family:var(--font-mono)}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.75rem\]{font-size:.75rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[32px\]{font-size:32px}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.5px\]{--tw-tracking:.5px;letter-spacing:.5px}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-words{overflow-wrap:break-word}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[\#f14c4c\]{color:#f14c4c}.text-accent{color:var(--color-accent)}.text-ink{color:var(--color-ink)}.text-ink-muted{color:var(--color-ink-muted)}.text-muted{color:var(--color-muted)}.text-red-400{color:var(--color-red-400)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.shadow-\[0_4px_12px_rgba\(0\,0\,0\,0\.15\)\]{--tw-shadow:0 4px 12px var(--tw-shadow-color,#00000026);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media(hover:hover){.group-hover\:flex:is(:where(.group):hover *){display:flex}.hover\:bg-\[rgba\(0\,0\,0\,0\.08\)\]:hover{background-color:#00000014}.hover\:bg-\[rgba\(241\,76\,76\,0\.1\)\]:hover{background-color:#f14c4c1a}.hover\:bg-list-hover:hover{background-color:var(--color-list-hover)}.hover\:bg-red-400\/10:hover{background-color:#ff65681a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-400\/10:hover{background-color:color-mix(in oklab,var(--color-red-400) 10%,transparent)}}.hover\:text-ink:hover{color:var(--color-ink)}.hover\:text-red-400:hover{color:var(--color-red-400)}.hover\:opacity-90:hover{opacity:.9}}.focus\:border-focus:focus{border-color:var(--color-focus)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-default:disabled{cursor:default}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}@media(hover:hover){.dark\:hover\:bg-\[rgba\(255\,255\,255\,0\.08\)\]:where([data-theme=dark],[data-theme=dark] *):hover{background-color:#ffffff14}}.scrollbar-none{scrollbar-width:none}.scrollbar-none::-webkit-scrollbar{display:none}.spin{animation:1s linear infinite spin}.slide-in{animation:.2s slideIn}}:root[data-theme=dark]{--color-bg:#1e1e1e;--color-bg-soft:#252526;--color-panel:#1e1e1e;--color-sidebar:#252526;--color-activitybar:#333;--color-activitybar-inactive:#fff6;--color-border:#3c3c3c;--color-ink:#ccc;--color-ink-muted:#9e9e9e;--color-muted:#8b8b8b;--color-accent:#0078d4;--color-list-hover:#ffffff0a;--color-list-active:#0078d433;--color-focus:#007fd4;--color-title-bar:#3c3c3c}@keyframes spin{to{transform:rotate(360deg)}}@keyframes slideIn{0%{transform:translate(-100%)}to{transform:translate(0)}}.app{grid-template-rows:minmax(0,1fr) 22px;grid-template-columns:48px minmax(0,1fr);height:100%;display:grid;overflow:hidden}.activity-bar{background:var(--color-activitybar);flex-direction:column;grid-row:1/3;width:48px;display:flex}.activity-bar-top{flex-direction:column;display:flex}.activity-bar-bottom{flex-direction:column;margin-top:auto;display:flex}.activity-bar-item{width:48px;height:48px;color:var(--color-activitybar-inactive);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;transition:color .15s;display:flex;position:relative}.activity-bar-item:hover,.activity-bar-item.active{color:var(--color-activitybar-fg)}.activity-bar-item svg{width:24px;height:24px}.activity-bar-badge{text-align:center;background:var(--color-accent);color:#fff;border-radius:8px;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:600;line-height:16px;position:absolute;top:8px;right:6px}.main{background:var(--color-bg);flex-direction:column;min-height:0;display:flex}.workspace-editor-overlay{background:var(--color-bg);z-index:30;grid-template-rows:35px minmax(0,1fr);display:grid;position:fixed;top:0;right:0;bottom:0;left:0}.workspace-editor-header{background:var(--color-title-bar);border-bottom:1px solid var(--color-border);align-items:center;gap:12px;padding:0 12px;display:flex}.workspace-meta{color:var(--color-muted);font-size:12px;font-family:var(--font-mono);text-overflow:ellipsis;white-space:nowrap;text-align:center;flex:1;overflow:hidden}.workspace-editor-grid{grid-template-rows:minmax(0,1fr);grid-template-columns:48px 220px minmax(0,1fr);height:100%;min-height:0;display:grid}.sidebar-panel{background:var(--color-sidebar);border-right:1px solid var(--color-border);flex-direction:column;height:100%;min-height:0;display:flex}.sidebar-content{flex:1;min-height:0;overflow:auto}.workspace-editor-grid>.activity-bar{background:var(--color-activitybar);border-right:1px solid var(--color-border);grid-row:unset;flex-direction:column;width:48px;display:flex}.workspace-editor-grid .activity-bar-item{color:var(--color-activitybar-fg);opacity:.6;transition:opacity .15s}.workspace-editor-grid .activity-bar-item:hover,.workspace-editor-grid .activity-bar-item.active{opacity:1}.panel{background:var(--color-panel);border:1px solid var(--color-border);border-radius:0;flex-direction:column;min-height:0;padding:0;display:flex}.panel-header{border-bottom:1px solid var(--color-border);background:var(--color-sidebar);justify-content:space-between;align-items:center;gap:8px;padding:8px 12px;display:flex}.panel-title{text-transform:uppercase;letter-spacing:.5px;color:var(--color-ink-muted);font-size:11px;font-weight:600}.panel-subtitle{color:var(--color-muted);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.panel-body{flex:1;min-height:0;overflow:auto}.modal{background:var(--color-panel);border:1px solid var(--color-border);border-radius:4px;width:480px;max-width:96vw;max-height:90dvh;padding:16px;overflow-y:auto;box-shadow:0 8px 32px #0000004d}.modal-close-btn{color:var(--color-muted);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;width:32px;height:32px;padding:0;font-size:24px;line-height:1;display:flex}.modal-close-btn:hover{color:var(--color-ink);background:var(--color-list-hover)}.tree-body{padding:4px 0}.tree-row{color:var(--color-ink);text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:4px;width:100%;min-height:22px;padding:2px 8px 2px 4px;font-size:13px;transition:background .1s;display:flex}.tree-row:hover{background:var(--color-list-hover)}.tree-row:focus-visible{outline:2px solid var(--color-focus);outline-offset:-2px}.tree-chevron{width:16px;height:16px;color:var(--color-ink-muted);flex-shrink:0;justify-content:center;align-items:center;display:flex}.tree-chevron-icon{width:12px;height:12px;transition:transform .1s}.tree-icon{flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;display:flex}.tree-svg{width:16px;height:16px}.tree-label{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.tree-meta{color:var(--color-muted);font-size:11px;font-family:var(--font-mono);margin-left:auto}.tree-state{color:var(--color-muted);padding:8px 12px;font-size:12px}.tree-actions{align-items:center;gap:4px;display:flex}.tree-input-row{align-items:center;gap:4px;min-height:22px;padding:2px 8px 2px 4px;display:flex}.tree-input{border:1px solid var(--color-accent);background:var(--color-panel);min-width:0;color:var(--color-ink);border-radius:2px;outline:none;flex:1;padding:2px 6px;font-size:13px}.tree-input::placeholder{color:var(--color-muted)}.editor-container{background:var(--color-panel);flex-direction:column;height:100%;display:flex;overflow:hidden}.editor-container.editor-empty{justify-content:center;align-items:center;display:flex}.editor-welcome{color:var(--color-ink-muted);text-align:center;flex-direction:column;align-items:center;gap:16px;padding:60px 40px;display:flex}.editor-welcome-icon{opacity:.2;width:80px;height:80px}.editor-welcome-icon svg{width:100%;height:100%;stroke:var(--color-ink)}.editor-welcome-text{color:var(--color-ink-muted);font-size:18px;font-weight:400}.editor-welcome-hint{opacity:.6;font-size:13px}.editor-tabs{background:var(--color-bg-soft);border-bottom:1px solid var(--color-border);flex-shrink:0;align-items:stretch;min-height:35px;display:flex}.editor-tabs-list{scrollbar-width:none;display:flex;overflow-x:auto}.editor-tabs-list::-webkit-scrollbar{display:none}.editor-tab{background:var(--color-bg-soft);border:none;border-right:1px solid var(--color-border);min-width:100px;max-width:180px;height:35px;color:var(--color-ink-muted);cursor:pointer;align-items:center;gap:6px;padding:0 10px;font-size:13px;transition:background .1s,color .1s;display:flex;position:relative}.editor-tab:hover{background:var(--color-panel);color:var(--color-ink)}.editor-tab.active{background:var(--color-panel);color:var(--color-ink);border-bottom:1px solid var(--color-panel);margin-bottom:-1px}.editor-tab-icon{font-size:10px;font-weight:600;font-family:var(--font-mono);flex-shrink:0}.editor-tab-name{text-overflow:ellipsis;white-space:nowrap;text-align:left;flex:1;overflow:hidden}.editor-tab-dirty{color:var(--color-ink);flex-shrink:0;font-size:18px;line-height:1}.editor-tab-saving{flex-shrink:0;width:14px;height:14px}.editor-tab-saving svg{width:100%;height:100%;stroke:var(--color-ink-muted)}.editor-tab-close{width:20px;height:20px;color:var(--color-ink-muted);cursor:pointer;opacity:0;background:0 0;border:none;border-radius:3px;flex-shrink:0;justify-content:center;align-items:center;padding:0;transition:opacity .1s,background .1s;display:flex}.editor-tab-close svg{width:16px;height:16px}.editor-tab-close:hover{background:var(--color-list-hover);color:var(--color-ink)}.editor-breadcrumb{background:var(--color-panel);border-bottom:1px solid var(--color-border);color:var(--color-ink-muted);flex-shrink:0;align-items:center;height:22px;padding:0 12px;font-size:12px;display:flex}.editor-breadcrumb-path{text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-mono);overflow:hidden}.editor-content{flex:1;min-height:0;position:relative}.editor-no-file{height:100%;color:var(--color-ink-muted);justify-content:center;align-items:center;display:flex}.editor-statusbar{background:var(--color-statusbar);height:22px;color:var(--color-statusbar-fg);flex-shrink:0;justify-content:space-between;align-items:center;padding:0 12px;font-size:12px;display:flex}.editor-statusbar-left,.editor-statusbar-right{align-items:center;gap:14px;display:flex}.editor-status-item{cursor:default;align-items:center;gap:4px;display:flex}.editor-status-item svg{width:14px;height:14px}.terminal-layout{overflow-anchor:none;flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden}.terminal-topbar{background:var(--color-sidebar);border-bottom:1px solid var(--color-border);flex-shrink:0;align-items:stretch;min-width:0;display:flex;overflow:hidden}.topbar-left{flex:1;align-items:stretch;min-width:0;display:flex;overflow:hidden}.deck-tabs{scrollbar-width:none;flex:1;align-items:stretch;min-width:0;display:flex;overflow-x:auto}.deck-tabs::-webkit-scrollbar{display:none}.deck-tab{border:none;border-top:2px solid #0000;border-right:1px solid var(--color-border);min-width:80px;max-width:200px;color:var(--color-muted);cursor:pointer;white-space:nowrap;background:0 0;flex-shrink:0;align-items:center;gap:4px;padding:0 8px 0 12px;font-size:12px;font-weight:500;transition:background .12s,color .12s;display:flex}.deck-tab[draggable=true]{cursor:grab}.deck-tab.is-dragging{opacity:.5}.deck-tab.is-drag-over{background:var(--color-list-active);color:var(--color-ink)}.deck-tab:hover{background:var(--color-list-hover);color:var(--color-ink)}.deck-tab.active{background:var(--color-panel);color:var(--color-ink);border-top-color:var(--color-accent)}.deck-tab-name{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.deck-tab-close{opacity:0;width:16px;height:16px;color:var(--color-muted);border-radius:3px;flex-shrink:0;justify-content:center;align-items:center;font-size:13px;line-height:1;transition:opacity .12s,background .12s;display:flex}.deck-tab-add{border-top:none;justify-content:center;min-width:35px;max-width:35px;padding:0;font-size:16px;font-weight:300}.deck-tab-add:hover{background:var(--color-list-hover);color:var(--color-ink)}.terminal-split-container{flex:1;grid-auto-rows:minmax(0,1fr);gap:4px;width:100%;min-width:0;max-width:100%;min-height:0;padding:4px;display:grid;position:relative}.deck-split-pane{border:1px solid var(--color-border);border-radius:4px;flex-direction:column;min-width:0;min-height:0;display:flex;overflow:hidden}.topbar-btn-sm{border:1px solid var(--color-border);color:var(--color-muted);cursor:pointer;background:0 0;border-radius:3px;padding:2px 6px;font-size:11px;font-weight:600;transition:all .15s}.topbar-btn-sm:hover{background:var(--color-list-hover);color:var(--color-ink);border-color:var(--color-accent)}.topbar-btn-sm.topbar-btn-claude{color:#d97757}.topbar-btn-sm.topbar-btn-claude:hover{background:#d9775726;border-color:#d97757}.topbar-btn-sm.topbar-btn-codex{color:#00a86b}.topbar-btn-sm.topbar-btn-codex:hover{background:#00a86b26;border-color:#00a86b}.drive-mini-btn{color:var(--color-muted);cursor:pointer;background:0 0;border:0;border-radius:3px;padding:1px 5px;font-size:11px;line-height:1.4}.drive-mini-btn:hover{background:var(--color-list-hover);color:var(--color-ink)}.drive-body.drive-drag-active{outline:2px dashed var(--color-accent);outline-offset:-6px;background:var(--color-list-hover)}.drive-tab{cursor:pointer;background:0 0;border:0;border-bottom:2px solid #0000}.code-server-frame{background:#1e1e1e;border:0;width:100%;height:100%;display:block}.terminal-pane{overflow-anchor:none;flex-direction:column;flex:1;min-width:0;min-height:0;padding:4px;display:flex}.terminal-grid{flex:1;gap:4px;width:100%;min-width:0;min-height:0;display:grid;overflow:hidden}.terminal-tile-slot{display:contents}.terminal-switcher{display:none}.terminal-empty{background:var(--color-bg-soft);border:1px dashed var(--color-border);color:var(--color-muted);border-radius:4px;flex:1;justify-content:center;align-items:center;font-size:12px;display:flex}.terminal-tile{border:1px solid var(--color-border);color:#d4d4d4;background:#1e1e1e;border-radius:4px;flex-direction:column;min-width:0;min-height:0;transition:background .15s ease-out,box-shadow .15s ease-out;display:flex;overflow:hidden}.terminal-tile.bell-flash{background:#2a2a3a;transition:none;box-shadow:inset 0 0 0 2px #78aaffb3}.terminal-tile-header{background:#2d2d2d;border-bottom:1px solid #404040;justify-content:space-between;align-items:center;gap:8px;padding:6px 10px;font-size:12px;display:flex}.terminal-tile-header span{text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-mono);flex:1;overflow:hidden}.terminal-close-btn{color:#858585;cursor:pointer;background:0 0;border:none;border-radius:3px;flex-shrink:0;justify-content:center;align-items:center;width:20px;height:20px;transition:background .1s,color .1s;display:flex}.terminal-close-btn:hover{color:#fff;background:#404040}.terminal-tile-body{overflow-anchor:none;overscroll-behavior:contain;touch-action:pan-y;flex:1;min-height:0;overflow:hidden}.terminal-tile-body .xterm,.terminal-tile-body .xterm-viewport,.terminal-tile-body .xterm-screen{overflow-anchor:none}.terminal-tile-body .xterm-helper-textarea{z-index:0!important}.terminal-tile-body .xterm-viewport{overscroll-behavior-y:contain;-webkit-overflow-scrolling:touch;touch-action:pan-y}.browser-layout{background:var(--color-panel);flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden}.browser-toolbar{background:var(--color-sidebar);border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;gap:10px;min-height:38px;padding:4px 8px;display:flex}.browser-address-group{flex:1;align-items:center;gap:6px;min-width:0;display:flex}.browser-toolbar-button,.browser-go-button{border:1px solid var(--color-border);background:var(--color-bg-soft);width:28px;height:28px;color:var(--color-ink);cursor:pointer;border-radius:4px;justify-content:center;align-items:center;font-size:12px;line-height:1;display:flex}.browser-toolbar-button:hover,.browser-go-button:hover{background:var(--color-list-hover)}.browser-toolbar-button-active{border-color:var(--color-accent);color:var(--color-accent)}.browser-toolbar-button svg{width:16px;height:16px}.browser-toolbar-button:disabled,.browser-go-button:disabled{opacity:.45;cursor:not-allowed}.browser-address-form{flex:1;align-items:center;gap:6px;min-width:0;display:flex}.browser-address-input{border:1px solid var(--color-border);background:var(--color-panel);min-width:0;height:28px;color:var(--color-ink);font-family:var(--font-mono);border-radius:4px;flex:1;padding:0 9px;font-size:12px}.browser-status-line{color:var(--color-ink-muted);font-size:11px;font-family:var(--font-mono);text-overflow:ellipsis;white-space:nowrap;flex-shrink:0;align-items:center;gap:6px;max-width:180px;display:flex;overflow:hidden}.browser-dot{background:var(--color-muted);border-radius:50%;width:8px;height:8px}.browser-dot-running{background:var(--color-git-staged)}.browser-error{border-bottom:1px solid var(--color-border);color:var(--color-git-deleted);text-overflow:ellipsis;white-space:nowrap;background:#f14c4c1f;flex-shrink:0;padding:6px 10px;font-size:12px;overflow:hidden}.browser-tabs{background:var(--color-sidebar);border-bottom:1px solid var(--color-border);scrollbar-width:thin;flex-shrink:0;align-items:stretch;gap:4px;padding:4px 6px;display:flex;overflow-x:auto}.browser-tab{border:1px solid var(--color-border);background:var(--color-bg-soft);min-width:92px;max-width:180px;color:var(--color-ink-muted);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:6px;align-items:center;gap:6px;padding:4px 6px 4px 10px;font-size:12px;display:flex}.browser-tab:hover{background:var(--color-list-hover)}.browser-tab-active{background:var(--color-panel);color:var(--color-ink);border-color:var(--color-accent)}.browser-tab-title{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.browser-tab-close{width:16px;height:16px;color:inherit;cursor:pointer;opacity:.6;background:0 0;border:none;border-radius:4px;flex-shrink:0;justify-content:center;align-items:center;font-size:13px;line-height:1;display:flex}.browser-tab-close:hover{background:var(--color-list-hover);opacity:1}.browser-tab-new{border:1px solid var(--color-border);background:var(--color-bg-soft);width:28px;color:var(--color-ink);cursor:pointer;border-radius:6px;flex-shrink:0;font-size:16px;line-height:1}.browser-tab-new:hover{background:var(--color-list-hover)}.browser-audio{display:none}.browser-viewport{background:#111;outline:none;flex:1;justify-content:center;align-items:center;min-width:0;min-height:0;display:flex;overflow:hidden}.browser-viewport:focus-visible{box-shadow:inset 0 0 0 2px var(--color-focus)}.browser-frame{object-fit:contain;-webkit-user-select:none;user-select:none;cursor:default;width:100%;height:100%;display:block}.browser-state{text-align:center;color:#c8c8c8;font-family:var(--font-mono);flex-direction:column;align-items:center;gap:12px;padding:24px;display:flex}.browser-state-title{color:#e6e6e6;font-size:13px}.browser-state-hint{color:#9a9a9a;max-width:280px;font-size:12px;line-height:1.5}.browser-state-action{border:1px solid var(--color-border);background:var(--color-bg-soft);color:var(--color-ink);cursor:pointer;font-size:12px;font-family:var(--font-mono);border-radius:4px;padding:6px 16px}.browser-state-action:hover:not(:disabled){background:var(--color-list-hover)}.browser-state-action:disabled{opacity:.45;cursor:not-allowed}.browser-spinner{border:2px solid #ffffff2e;border-top-color:var(--color-accent);border-radius:50%;width:22px;height:22px;animation:.8s linear infinite browser-spin}@keyframes browser-spin{to{transform:rotate(360deg)}}.git-modified{color:var(--color-git-modified)}.git-untracked{color:var(--color-git-untracked)}.git-deleted{color:var(--color-git-deleted)}.git-staged{color:var(--color-git-staged)}.git-renamed{color:var(--color-git-renamed)}.git-conflicted{color:var(--color-git-conflicted)}.git-tabs{border-bottom:1px solid var(--color-border);background:var(--color-sidebar);flex-shrink:0;display:flex}.git-tab{color:var(--color-ink-muted);cursor:pointer;background:0 0;border:none;align-items:center;gap:6px;padding:6px 12px;font-size:12px;transition:color .1s,background .1s;display:flex;position:relative}.git-tab:hover{color:var(--color-ink);background:var(--color-list-hover)}.git-tab.active{color:var(--color-ink)}.git-file-row{align-items:center;gap:4px;transition:background .1s;display:flex}.git-file-row:hover{background:var(--color-list-hover)}.git-file-main{color:var(--color-ink);cursor:pointer;text-align:left;background:0 0;border:none;flex:1;align-items:center;gap:6px;min-width:0;min-height:22px;padding:4px 12px;display:flex}.git-status-badge{width:16px;height:16px;font-size:11px;font-weight:600;font-family:var(--font-mono);flex-shrink:0;justify-content:center;align-items:center;display:flex}.git-file-path{text-overflow:ellipsis;white-space:nowrap;font-size:13px;overflow:hidden}.git-file-actions{opacity:0;gap:2px;padding-right:8px;transition:opacity .1s;display:flex}.git-action-btn{width:22px;height:22px;color:var(--color-ink-muted);cursor:pointer;background:0 0;border:none;border-radius:3px;justify-content:center;align-items:center;padding:0;transition:background .1s,color .1s;display:flex}.git-action-btn:hover{background:var(--color-list-hover);color:var(--color-ink)}.git-action-btn svg{fill:currentColor;width:14px;height:14px}.status-float{right:20px;bottom:calc(40px + env(safe-area-inset-bottom,0px));background:var(--color-panel);border:1px solid var(--color-border);color:var(--color-ink);border-radius:4px;max-width:min(400px,100vw - 40px);padding:8px 14px;font-size:12px;position:fixed;box-shadow:0 4px 16px #0003}.sidebar-toggle-btn,.sidebar-overlay{display:none}@media(max-width:1024px){.workspace-editor-grid{grid-template-rows:200px minmax(0,1fr);grid-template-columns:48px 1fr}.workspace-editor-grid>.activity-bar{grid-row:1/-1}.sidebar-panel{border-right:none;border-bottom:1px solid var(--color-border)}}@media(max-width:720px){.app{padding-bottom:env(safe-area-inset-bottom);grid-template-rows:minmax(0,1fr) 48px 22px;grid-template-columns:1fr}.app>nav.activity-bar{width:auto;height:48px;padding:0 max(8px,env(safe-area-inset-right,0px)) 0 max(8px,env(safe-area-inset-left,0px));border-top:1px solid var(--color-border);flex-direction:row;grid-row:2;justify-content:space-between;gap:8px}.activity-bar-top,.activity-bar-bottom{flex-direction:row;align-items:center;gap:4px}.activity-bar-bottom{margin-top:0;margin-left:0}.main{grid-row:1;min-width:0;overflow:hidden}.sidebar-toggle-btn{justify-content:center;align-items:center;display:flex}.activity-bar-item{min-width:44px;min-height:44px}.deck-tab{min-height:40px;padding:0 8px 0 14px;font-size:13px}.topbar-btn-sm{min-width:44px;min-height:40px;padding:0 10px}.tree-row,.editor-tab{min-height:36px}.modal-close-btn{min-width:44px;min-height:44px}.modal{border-radius:8px;max-width:calc(100vw - 16px);max-height:90dvh;margin:8px}.deck-tabs{-webkit-overflow-scrolling:touch;scrollbar-width:none;flex-wrap:nowrap;overflow-x:auto}.deck-tabs::-webkit-scrollbar{display:none}.terminal-split-container{scroll-snap-type:none;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;touch-action:auto;scrollbar-width:none;width:100%;max-width:100%;overflow:scroll hidden;flex-direction:row!important;gap:0!important;padding:0!important;display:flex!important}.terminal-split-container::-webkit-scrollbar{display:none}.deck-split-pane{scroll-snap-align:start;border-left:none;border-right:none;border-radius:0;flex:0 0 100%;width:100%;max-width:100%;overflow:hidden}.terminal-pane{flex:auto;width:100%;max-width:100%;min-height:0;overflow:hidden;padding:0!important}.terminal-grid-mobile{flex-direction:column!important;flex:1!important;gap:0!important;min-height:0!important;padding:0!important;display:flex!important;overflow:hidden!important}.terminal-tile-slot-mobile-active{flex-direction:column;flex:1;min-height:0;overflow:hidden;display:flex!important}.terminal-tile-slot-mobile-active .terminal-tile{border:none;border-radius:0;flex:1;height:auto!important;min-height:0!important}.terminal-tile-slot-mobile-hidden{display:none!important}.terminal-switcher{background:var(--color-bg-soft);min-width:0;max-width:60%;height:28px;color:var(--color-ink);border:1px solid var(--color-border);font-size:12px;font-family:var(--font-mono);border-radius:4px;flex:auto;padding:0 8px;display:block}.status-float{right:12px;bottom:calc(78px + env(safe-area-inset-bottom,0px));max-width:calc(100vw - 24px)}html.keyboard-open .app{grid-template-rows:minmax(0,1fr);padding-bottom:0}html.keyboard-open .app>nav.activity-bar{display:none}html.keyboard-open .status-float{bottom:calc(env(safe-area-inset-bottom,0px) + 8px)}.workspace-editor-grid{grid-template-rows:minmax(0,1fr);grid-template-columns:1fr;position:relative}.workspace-editor-grid>.activity-bar{z-index:101;border-right:1px solid var(--color-border);border-top:none;flex-direction:column;width:48px;height:auto;transition:transform .2s;position:absolute;top:0;bottom:0;left:0;transform:translate(-100%)}.sidebar-panel{z-index:100;border-bottom:none;border-right:1px solid var(--color-border);width:260px;transition:transform .2s;position:absolute;top:0;bottom:0;left:48px;overflow-y:auto;transform:translate(calc(-100% - 48px))}.drawer-open .workspace-editor-grid>.activity-bar,.drawer-open .sidebar-panel{transform:translate(0)}.sidebar-overlay{z-index:99;background:#0006;display:none;position:absolute;top:0;right:0;bottom:0;left:0}.drawer-open .sidebar-overlay{display:block}.workspace-editor-header{gap:8px;padding:0 8px}.workspace-editor-header .sidebar-toggle-btn{order:3;margin-left:auto}.workspace-editor-header .workspace-meta{text-align:left;min-width:0}}@media(pointer:coarse){.modal-close-btn:hover,.tree-row:hover,.editor-tab:hover,.deck-tab:hover,.deck-tab-add:hover,.topbar-btn-sm:hover,.terminal-close-btn:hover,.git-file-row:hover,.git-action-btn:hover,.git-tab:hover{border-color:inherit;color:inherit;opacity:1;background:0 0}.editor-tab:hover{color:var(--color-ink-muted);background:0 0}.git-file-actions{opacity:1}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
|