tide-commander 1.160.0 → 1.162.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/assets/{BossLogsModal-COg0RBw_.js → BossLogsModal-DrYF13xp.js} +1 -1
  3. package/dist/assets/{BossSpawnModal-Bvkk2uFi.js → BossSpawnModal-2ZgbW8Iy.js} +1 -1
  4. package/dist/assets/{ControlsModal-BWcWGs2x.js → ControlsModal-CRdNNTEo.js} +1 -1
  5. package/dist/assets/{DockerLogsModal-C4tJ59Pf.js → DockerLogsModal-BGPZP9_V.js} +1 -1
  6. package/dist/assets/{EmbeddedEditor-DiDm5EvF.js → EmbeddedEditor-B99bT-bl.js} +1 -1
  7. package/dist/assets/{GmailOAuthSetup-GkYs6wUs.js → GmailOAuthSetup-DmMCxdUW.js} +1 -1
  8. package/dist/assets/{GoogleOAuthSetup-KKwp2gEQ.js → GoogleOAuthSetup-BZqit-mW.js} +1 -1
  9. package/dist/assets/{IframeModal-D0iTkxZB.js → IframeModal-vMY7XxHP.js} +1 -1
  10. package/dist/assets/{IntegrationsPanel-CCKoizJa.js → IntegrationsPanel-DVmqPRTs.js} +2 -2
  11. package/dist/assets/{LogViewerModal-CSGEkyhZ.js → LogViewerModal-rYC6IVPV.js} +1 -1
  12. package/dist/assets/{MonitoringModal-Be6uEd7K.js → MonitoringModal-C-QXpZkE.js} +1 -1
  13. package/dist/assets/{PM2LogsModal-DZG7Tcw7.js → PM2LogsModal-C3A_ohFv.js} +1 -1
  14. package/dist/assets/{RestoreArchivedAreaModal-CigBbBB_.js → RestoreArchivedAreaModal-Dx94NzSz.js} +1 -1
  15. package/dist/assets/{Scene2DCanvas-sJig3vJ4.js → Scene2DCanvas-BxOqJ0IB.js} +1 -1
  16. package/dist/assets/{SceneManager-BG_0UVJc.js → SceneManager-CxcXfq_u.js} +1 -1
  17. package/dist/assets/{SkillsPanel-BnAf8uyn.js → SkillsPanel-Fu5sfG7Q.js} +1 -1
  18. package/dist/assets/{SlackMultiInstanceSetup-DGuexHRz.js → SlackMultiInstanceSetup-jnGMesoq.js} +1 -1
  19. package/dist/assets/{SpawnModal-FjDJZlIm.js → SpawnModal-CGYg4uTC.js} +1 -1
  20. package/dist/assets/{StatisticsModal-CbbdwSF0.js → StatisticsModal-BOV6Juts.js} +1 -1
  21. package/dist/assets/{SubordinateAssignmentModal-Dn2uuOcT.js → SubordinateAssignmentModal-Bhgj9FvT.js} +1 -1
  22. package/dist/assets/{TriggerManagerPanel-Cj9pqf-r.js → TriggerManagerPanel-Qkw4ajmL.js} +1 -1
  23. package/dist/assets/{WorkflowEditorPanel-nucrx_0v.js → WorkflowEditorPanel-DTIBRGz4.js} +1 -1
  24. package/dist/assets/{area-logos-C93KZk3h.js → area-logos-uM2FM0I2.js} +1 -1
  25. package/dist/assets/{index-Gjc7NXlZ.js → index-3y5Ajiyr.js} +1 -1
  26. package/dist/assets/{index-iX9jPnEp.js → index-5tz2e3op.js} +1 -1
  27. package/dist/assets/{index-ojmo-Cva.js → index-B03BKiDN.js} +1 -1
  28. package/dist/assets/index-BFJWNGpT.js +19 -0
  29. package/dist/assets/{index-BkbKu66S.js → index-BvD1v4JH.js} +1 -1
  30. package/dist/assets/{index-D7YoMagO.js → index-BvOgm4yp.js} +1 -1
  31. package/dist/assets/{index-CmmI2kZf.js → index-CpQeaxZ7.js} +2 -2
  32. package/dist/assets/index-CrBXvs1w.css +1 -0
  33. package/dist/assets/{index-fh53j_4E.js → index-DzQxMm67.js} +1 -1
  34. package/dist/assets/index-cA0kPNUq.js +2 -0
  35. package/dist/assets/{main-BZcOdtO_.css → main-B-jhtDyZ.css} +1 -1
  36. package/dist/assets/main-rX2ghMIV.js +297 -0
  37. package/dist/assets/{web-8gl2noUE.js → web-ClQyiX7L.js} +1 -1
  38. package/dist/assets/{web-M9cLwTrs.js → web-NCIGsXXA.js} +1 -1
  39. package/dist/assets/{web-D0uiHhnA.js → web-ml-7D2g7.js} +1 -1
  40. package/dist/build-info.json +1 -1
  41. package/dist/index.html +2 -2
  42. package/dist/locales/en/terminal.json +4 -0
  43. package/dist/locales/es/terminal.json +1 -0
  44. package/dist/src/packages/server/claude/backend.js +4 -0
  45. package/dist/src/packages/server/claude/session-loader.js +116 -0
  46. package/dist/src/packages/server/codex/generated-image.js +35 -0
  47. package/dist/src/packages/server/codex/json-event-parser.js +122 -0
  48. package/dist/src/packages/server/index.js +4 -0
  49. package/dist/src/packages/server/routes/agents.js +9 -6
  50. package/dist/src/packages/server/services/claude-credentials-service.js +172 -13
  51. package/dist/src/packages/server/services/claude-usage-service.js +5 -1
  52. package/dist/src/packages/server/services/codex-usage-service.js +93 -0
  53. package/package.json +1 -1
  54. package/dist/assets/index-BIxFr4P2.css +0 -1
  55. package/dist/assets/index-DIOhr3im.js +0 -19
  56. package/dist/assets/index-DqM0QltS.js +0 -2
  57. package/dist/assets/main-BFW0rGXU.js +0 -297
@@ -162,6 +162,13 @@ export function listClaudeCredentialProfiles() {
162
162
  const OAUTH_TOKEN_URL = 'https://console.anthropic.com/v1/oauth/token';
163
163
  const OAUTH_CLIENT_ID = '9d1c250a-e61b-44d9-88ed-5944d1962f5e';
164
164
  const OAUTH_REFRESH_TIMEOUT_MS = 10_000;
165
+ // Claude Code refreshes an access token when it is within five minutes of
166
+ // expiry. Tide goes a little earlier so it normally owns token rotation for
167
+ // every saved account (including the active one) and can persist the rotated
168
+ // grant to all duplicate profile files before a CLI process needs it.
169
+ const KEEP_ALIVE_INTERVAL_MS = 5 * 60 * 1000;
170
+ const KEEP_ALIVE_REFRESH_WINDOW_MS = 15 * 60 * 1000;
171
+ const KEEP_ALIVE_REFRESH_TOKEN_WINDOW_MS = 24 * 60 * 60 * 1000;
165
172
  const GRANT_USAGE_TTL_OK_MS = 2 * 60 * 1000;
166
173
  const GRANT_USAGE_TTL_ERR_MS = 45 * 1000;
167
174
  // After a failed refresh, leave the grant alone for a while — retrying a
@@ -183,22 +190,36 @@ function readProfileTokens(filePath) {
183
190
  expiresAt: typeof oauth?.expiresAt === 'number' ? oauth.expiresAt : null,
184
191
  refreshToken: typeof oauth?.refreshToken === 'string' && oauth.refreshToken ? oauth.refreshToken : null,
185
192
  refreshTokenExpiresAt: typeof oauth?.refreshTokenExpiresAt === 'number' ? oauth.refreshTokenExpiresAt : null,
193
+ scopes: Array.isArray(oauth?.scopes)
194
+ ? oauth.scopes.filter((scope) => typeof scope === 'string')
195
+ : [],
196
+ clientId: typeof oauth?.clientId === 'string' && oauth.clientId ? oauth.clientId : null,
186
197
  };
187
198
  }
188
199
  catch {
189
- return { accessToken: null, expiresAt: null, refreshToken: null, refreshTokenExpiresAt: null };
200
+ return {
201
+ accessToken: null,
202
+ expiresAt: null,
203
+ refreshToken: null,
204
+ refreshTokenExpiresAt: null,
205
+ scopes: [],
206
+ clientId: null,
207
+ };
190
208
  }
191
209
  }
192
210
  /** Refresh an OAuth grant the way the CLI does. Returns tokens or an error string. */
193
- async function refreshOAuthGrant(refreshToken) {
211
+ async function refreshOAuthGrant(tokens) {
212
+ if (!tokens.refreshToken)
213
+ return { error: 'No refresh token stored' };
194
214
  try {
195
215
  const response = await fetch(OAUTH_TOKEN_URL, {
196
216
  method: 'POST',
197
217
  headers: { 'Content-Type': 'application/json' },
198
218
  body: JSON.stringify({
199
219
  grant_type: 'refresh_token',
200
- refresh_token: refreshToken,
201
- client_id: OAUTH_CLIENT_ID,
220
+ refresh_token: tokens.refreshToken,
221
+ client_id: tokens.clientId ?? OAUTH_CLIENT_ID,
222
+ ...(tokens.scopes.length > 0 ? { scope: tokens.scopes.join(' ') } : {}),
202
223
  }),
203
224
  signal: AbortSignal.timeout(OAUTH_REFRESH_TIMEOUT_MS),
204
225
  });
@@ -210,10 +231,19 @@ async function refreshOAuthGrant(refreshToken) {
210
231
  if (!accessToken)
211
232
  return { error: 'Token refresh returned no access token' };
212
233
  const expiresIn = typeof body.expires_in === 'number' ? body.expires_in : 3600;
234
+ const refreshTokenExpiresIn = typeof body.refresh_token_expires_in === 'number'
235
+ ? body.refresh_token_expires_in
236
+ : null;
213
237
  return {
214
238
  accessToken,
215
239
  refreshToken: typeof body.refresh_token === 'string' && body.refresh_token ? body.refresh_token : null,
216
240
  expiresAt: Date.now() + expiresIn * 1000,
241
+ refreshTokenExpiresAt: refreshTokenExpiresIn == null
242
+ ? null
243
+ : Date.now() + refreshTokenExpiresIn * 1000,
244
+ scopes: typeof body.scope === 'string'
245
+ ? body.scope.split(' ').filter(Boolean)
246
+ : null,
217
247
  };
218
248
  }
219
249
  catch (err) {
@@ -229,9 +259,36 @@ function writeRefreshedTokens(filePath, refreshed) {
229
259
  oauth.expiresAt = refreshed.expiresAt;
230
260
  if (refreshed.refreshToken)
231
261
  oauth.refreshToken = refreshed.refreshToken;
262
+ if (refreshed.refreshTokenExpiresAt != null) {
263
+ oauth.refreshTokenExpiresAt = refreshed.refreshTokenExpiresAt;
264
+ }
265
+ if (refreshed.scopes)
266
+ oauth.scopes = refreshed.scopes;
232
267
  data.claudeAiOauth = oauth;
233
268
  writeCredentialsAtomic(filePath, JSON.stringify(data));
234
269
  }
270
+ /**
271
+ * Persist one rotated grant to all of its copies. If another process (usually
272
+ * Claude Code) changed any refresh token while our request was in flight, do
273
+ * not overwrite its newer credentials with our response.
274
+ */
275
+ function persistRefreshedGrant(group, refreshed) {
276
+ const expectedRefreshToken = group.tokens.refreshToken;
277
+ const changedPath = group.paths.find((filePath) => readProfileTokens(filePath).refreshToken !== expectedRefreshToken);
278
+ if (changedPath) {
279
+ log.warn(`Claude credentials changed during refresh; leaving newer on-disk grant untouched (${group.ids.join(', ')})`);
280
+ return false;
281
+ }
282
+ for (const filePath of group.paths) {
283
+ try {
284
+ writeRefreshedTokens(filePath, refreshed);
285
+ }
286
+ catch (err) {
287
+ log.warn(`Refreshed grant but failed to persist to ${filePath}: ${err}`);
288
+ }
289
+ }
290
+ return true;
291
+ }
235
292
  function grantCacheKey(token) {
236
293
  return crypto.createHash('sha256').update(token).digest('hex').slice(0, 12);
237
294
  }
@@ -267,7 +324,7 @@ function fetchUsageForGrant(cacheKey, group) {
267
324
  error = 'Session expired — sign in to this account again';
268
325
  }
269
326
  else {
270
- const refreshed = await refreshOAuthGrant(tokens.refreshToken);
327
+ const refreshed = await refreshOAuthGrant(tokens);
271
328
  if ('error' in refreshed) {
272
329
  accessToken = null;
273
330
  error = refreshed.error;
@@ -280,14 +337,7 @@ function fetchUsageForGrant(cacheKey, group) {
280
337
  grantUsageCache.set(cacheKey, entry);
281
338
  return entry;
282
339
  }
283
- for (const filePath of group.paths) {
284
- try {
285
- writeRefreshedTokens(filePath, refreshed);
286
- }
287
- catch (err) {
288
- log.warn(`Refreshed grant but failed to persist to ${filePath}: ${err}`);
289
- }
290
- }
340
+ persistRefreshedGrant(group, refreshed);
291
341
  log.log(`Refreshed dormant Claude credentials for profile(s): ${group.ids.join(', ')}`);
292
342
  accessToken = refreshed.accessToken;
293
343
  }
@@ -364,6 +414,115 @@ export async function getClaudeCredentialProfilesUsage() {
364
414
  }));
365
415
  return { usage };
366
416
  }
417
+ let keepAliveTimer = null;
418
+ let keepAliveInFlight = null;
419
+ const keepAliveFailureCooldown = new Map();
420
+ /** Run one keepalive pass. Exported to make the credential lifecycle testable. */
421
+ export function runClaudeCredentialKeepAliveNow() {
422
+ if (keepAliveInFlight)
423
+ return keepAliveInFlight;
424
+ keepAliveInFlight = (async () => {
425
+ const now = Date.now();
426
+ const list = listClaudeCredentialProfiles();
427
+ const candidates = [...(list.active ? [list.active] : []), ...list.profiles];
428
+ const groups = new Map();
429
+ for (const meta of candidates) {
430
+ if (!meta.valid)
431
+ continue;
432
+ const tokens = readProfileTokens(meta.path);
433
+ if (!tokens.refreshToken)
434
+ continue;
435
+ const key = grantCacheKey(tokens.refreshToken);
436
+ const existing = groups.get(key);
437
+ if (existing) {
438
+ existing.ids.push(meta.id);
439
+ if (!existing.paths.includes(meta.path))
440
+ existing.paths.push(meta.path);
441
+ existing.includesActive = existing.includesActive || meta.id === 'active';
442
+ // Copies can have different access-token expiries even while they still
443
+ // share a refresh grant. Refresh according to the freshest copy.
444
+ if ((tokens.expiresAt ?? 0) > (existing.tokens.expiresAt ?? 0))
445
+ existing.tokens = tokens;
446
+ }
447
+ else {
448
+ groups.set(key, {
449
+ ids: [meta.id],
450
+ paths: [meta.path],
451
+ includesActive: meta.id === 'active',
452
+ tokens,
453
+ });
454
+ }
455
+ }
456
+ const result = {
457
+ checkedGrants: groups.size,
458
+ refreshedGrants: 0,
459
+ skippedGrants: 0,
460
+ failedGrants: 0,
461
+ };
462
+ await Promise.all(Array.from(groups.entries()).map(async ([key, group]) => {
463
+ const { tokens } = group;
464
+ const refreshExpired = tokens.refreshTokenExpiresAt != null
465
+ && tokens.refreshTokenExpiresAt <= now;
466
+ const refreshDue = tokens.expiresAt == null
467
+ || tokens.expiresAt <= now + KEEP_ALIVE_REFRESH_WINDOW_MS
468
+ || (tokens.refreshTokenExpiresAt != null
469
+ && tokens.refreshTokenExpiresAt <= now + KEEP_ALIVE_REFRESH_TOKEN_WINDOW_MS);
470
+ const retryAfter = keepAliveFailureCooldown.get(key) ?? 0;
471
+ if (refreshExpired || !refreshDue || retryAfter > now) {
472
+ result.skippedGrants += 1;
473
+ return;
474
+ }
475
+ const refreshed = await refreshOAuthGrant(tokens);
476
+ if ('error' in refreshed) {
477
+ keepAliveFailureCooldown.set(key, Date.now() + GRANT_REFRESH_FAIL_COOLDOWN_MS);
478
+ result.failedGrants += 1;
479
+ log.warn(`Claude credential keepalive failed for ${group.ids.join(', ')}: ${refreshed.error}`);
480
+ return;
481
+ }
482
+ if (persistRefreshedGrant(group, refreshed)) {
483
+ result.refreshedGrants += 1;
484
+ keepAliveFailureCooldown.delete(key);
485
+ // Cached gauges contain the previous access token/fingerprint.
486
+ grantUsageCache.delete(key);
487
+ resetClaudeRateLimitCache();
488
+ log.log(`Kept Claude account session alive: ${group.ids.join(', ')}`);
489
+ }
490
+ else {
491
+ result.skippedGrants += 1;
492
+ }
493
+ }));
494
+ return result;
495
+ })().finally(() => {
496
+ keepAliveInFlight = null;
497
+ });
498
+ return keepAliveInFlight;
499
+ }
500
+ /** Start refreshing saved Claude account sessions for the server lifetime. */
501
+ export function initClaudeCredentialKeepAlive() {
502
+ if (keepAliveTimer || process.env.CLAUDE_CREDENTIAL_KEEPALIVE === '0')
503
+ return;
504
+ void runClaudeCredentialKeepAliveNow().catch((err) => {
505
+ log.warn(`Initial Claude credential keepalive failed: ${err}`);
506
+ });
507
+ keepAliveTimer = setInterval(() => {
508
+ void runClaudeCredentialKeepAliveNow().catch((err) => {
509
+ log.warn(`Claude credential keepalive pass failed: ${err}`);
510
+ });
511
+ }, KEEP_ALIVE_INTERVAL_MS);
512
+ keepAliveTimer.unref?.();
513
+ log.log('Claude credential keepalive started');
514
+ }
515
+ /** Stop the keepalive scheduler during graceful shutdown. */
516
+ export function shutdownClaudeCredentialKeepAlive() {
517
+ if (keepAliveTimer)
518
+ clearInterval(keepAliveTimer);
519
+ keepAliveTimer = null;
520
+ }
521
+ export function resetClaudeCredentialKeepAliveForTests() {
522
+ shutdownClaudeCredentialKeepAlive();
523
+ keepAliveFailureCooldown.clear();
524
+ keepAliveInFlight = null;
525
+ }
367
526
  function assertValidName(name) {
368
527
  if (!isValidProfileName(name)) {
369
528
  throw new Error(`Invalid profile name "${name}". Use 1–64 chars: letters, digits, dot, underscore, hyphen; must start with alphanumeric.`);
@@ -328,12 +328,16 @@ export async function fetchClaudeRateLimitsForToken(accessToken) {
328
328
  };
329
329
  }
330
330
  const body = await response.json();
331
+ // Claude Code 2.1.207 labels this allowance "Fable", although the live
332
+ // endpoint still exposes it under the legacy seven_day_sonnet key.
333
+ const sevenDayFable = parseRateLimitWindow(body.seven_day_fable ?? body.seven_day_sonnet);
331
334
  return {
332
335
  rateLimits: {
333
336
  fiveHour: parseRateLimitWindow(body.five_hour),
334
337
  sevenDay: parseRateLimitWindow(body.seven_day),
335
338
  sevenDayOpus: parseRateLimitWindow(body.seven_day_opus),
336
- sevenDaySonnet: parseRateLimitWindow(body.seven_day_sonnet),
339
+ sevenDayFable,
340
+ sevenDaySonnet: sevenDayFable,
337
341
  },
338
342
  error: null,
339
343
  status: response.status,
@@ -0,0 +1,93 @@
1
+ import { spawn } from 'child_process';
2
+ import { getCodexBinaryPath } from './system-prompt-service.js';
3
+ export function classifyCodexRateLimits(raw) {
4
+ const result = { daily: null, weekly: null };
5
+ for (const value of [raw?.primary, raw?.secondary]) {
6
+ if (!value || typeof value.usedPercent !== 'number')
7
+ continue;
8
+ const mins = typeof value.windowDurationMins === 'number' ? value.windowDurationMins : null;
9
+ const resetsAtSeconds = typeof value.resetsAt === 'number' ? value.resetsAt : 0;
10
+ const window = {
11
+ utilization: Math.max(0, Math.min(100, value.usedPercent)),
12
+ resetsAt: resetsAtSeconds > 0 ? new Date(resetsAtSeconds * 1000).toISOString() : '',
13
+ windowDurationMins: mins,
14
+ };
15
+ // App-server identifies windows by duration rather than by name. Anything
16
+ // up to two days is the daily allowance; longer periods are weekly.
17
+ if (mins !== null && mins <= 2 * 24 * 60)
18
+ result.daily = window;
19
+ else
20
+ result.weekly = window;
21
+ }
22
+ return result;
23
+ }
24
+ function readNativeRateLimits() {
25
+ return new Promise((resolve, reject) => {
26
+ const child = spawn(getCodexBinaryPath(), ['app-server'], { stdio: ['pipe', 'pipe', 'pipe'], env: process.env });
27
+ let stdout = '';
28
+ let stderr = '';
29
+ let settled = false;
30
+ const finish = (err, value) => {
31
+ if (settled)
32
+ return;
33
+ settled = true;
34
+ clearTimeout(timer);
35
+ child.kill('SIGTERM');
36
+ if (err)
37
+ reject(err);
38
+ else
39
+ resolve(value ?? {});
40
+ };
41
+ const timer = setTimeout(() => finish(new Error('Codex usage request timed out')), 10_000);
42
+ child.on('error', (err) => finish(err));
43
+ child.stderr?.on('data', (chunk) => { stderr += chunk.toString(); });
44
+ child.stdout?.on('data', (chunk) => {
45
+ stdout += chunk.toString();
46
+ const lines = stdout.split('\n');
47
+ stdout = lines.pop() ?? '';
48
+ for (const line of lines) {
49
+ if (!line.trim())
50
+ continue;
51
+ try {
52
+ const message = JSON.parse(line);
53
+ if (message.id === 1 && message.result) {
54
+ child.stdin?.write(`${JSON.stringify({ method: 'initialized', params: {} })}\n`);
55
+ child.stdin?.write(`${JSON.stringify({ id: 2, method: 'account/rateLimits/read', params: {} })}\n`);
56
+ }
57
+ else if (message.id === 2) {
58
+ if (message.error)
59
+ finish(new Error(message.error.message || 'Codex rejected the usage request'));
60
+ else
61
+ finish(undefined, message.result?.rateLimits ?? {});
62
+ }
63
+ }
64
+ catch { /* wait for the next complete JSON line */ }
65
+ }
66
+ });
67
+ child.on('close', (code) => {
68
+ if (!settled)
69
+ finish(new Error(stderr.trim() || `Codex app-server exited with code ${code}`));
70
+ });
71
+ child.stdin?.write(`${JSON.stringify({
72
+ id: 1,
73
+ method: 'initialize',
74
+ params: { clientInfo: { name: 'tide-commander', title: 'Tide Commander', version: '1.0.0' }, capabilities: { experimentalApi: true } },
75
+ })}\n`);
76
+ });
77
+ }
78
+ let cache = null;
79
+ export async function buildCodexUsageSnapshot(_agent) {
80
+ if (cache && cache.expiresAt > Date.now())
81
+ return cache.snapshot;
82
+ let snapshot;
83
+ try {
84
+ const rateLimits = classifyCodexRateLimits(await readNativeRateLimits());
85
+ snapshot = { provider: 'codex', fetchedAt: Date.now(), rateLimits, rateLimitsError: null, cliHint: 'Run /status in Codex to see current usage limits.' };
86
+ }
87
+ catch (err) {
88
+ const message = err instanceof Error ? err.message : String(err);
89
+ snapshot = { provider: 'codex', fetchedAt: Date.now(), rateLimits: null, rateLimitsError: message, cliHint: 'Run /status in Codex to see current usage limits.' };
90
+ }
91
+ cache = { expiresAt: Date.now() + 60_000, snapshot };
92
+ return snapshot;
93
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tide-commander",
3
- "version": "1.160.0",
3
+ "version": "1.162.0",
4
4
  "description": "Visual multi-agent orchestrator and manager for Claude Code with 3D/2D interface",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1 +0,0 @@
1
- :root{--bg-primary: #0d0d14;--bg-secondary: #14141e;--bg-tertiary: #1c1c28;--border-color: #2a2a3a;--text-primary: #d0d0d8;--text-secondary: #8a8a98;--text-muted: #606070;--accent-blue: #5a8fd4;--accent-green: #5cb88a;--accent-orange: #d4a05a;--accent-red: #d45a5a;--accent-purple: #8a6fbf;--accent-cyan: #5ab8c8;--accent-claude: #a06848;--accent-claude-light: #c8896a;--accent-pink: #5a8fd4;--accent-yellow: #d0d0d8;--font-size-base: 14px;--line-height-base: 1.5;--msg-user-bg: color-mix(in srgb, #5ab8c8 8%, transparent);--msg-user-highlight-bg: var(--msg-user-bg);--msg-user-border: #5ab8c8;--msg-user-text: #d0d0d8;--msg-assistant-bg: color-mix(in srgb, #5cb88a 8%, transparent);--msg-assistant-border: #5cb88a;--msg-assistant-text: #d0d0d8;--tool-use-bg: color-mix(in srgb, #d4a05a 8%, transparent);--tool-use-border: #d4a05a;--tool-use-text: #d4a05a;--tool-use-name: #d4a05a;--tool-result-bg: color-mix(in srgb, #8a6fbf 6%, transparent);--tool-result-border: #8a6fbf;--tool-result-text: #5cb88a;--context-bar-bg: #1c1c28;--context-bar-fill: #8a6fbf;--output-line-bg: transparent;--task-label-color: #5ab8c8}.view-mode-toggle{display:flex;gap:2px;position:relative;background:#0009;border-radius:6px;padding:3px;border:1px solid #2a2a3a}.view-mode-toggle__indicator{position:absolute;top:3px;bottom:3px;background:#d4a05a2e;border-radius:4px;transition:left .2s cubic-bezier(.4,0,.2,1),width .2s cubic-bezier(.4,0,.2,1);pointer-events:none;z-index:0}.view-mode-toggle__btn{display:flex;align-items:center;gap:5px;padding:5px 10px;border:none;border-radius:4px;background:transparent;color:#8a8a98;font-size:11px;font-weight:600;font-family:JetBrains Mono,SF Mono,Fira Code,Consolas,monospace;cursor:pointer;transition:color .15s ease,background .15s ease;white-space:nowrap;position:relative;z-index:1}.view-mode-toggle__btn:hover:not(.view-mode-toggle__btn--active){background:#ffffff14;color:#d0d0d8}.view-mode-toggle__btn--active{color:#d4a05a}.view-mode-toggle__btn--active svg{stroke:#d4a05a}.view-mode-toggle__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0}.view-mode-toggle__label{line-height:1}.view-mode-toggle--floating{position:fixed;bottom:70px;left:60px;z-index:150;box-shadow:0 2px 8px #0000004d}@media(max-width:768px){.view-mode-toggle__btn{padding:10px 14px;min-height:44px;min-width:44px;font-size:12px;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.view-mode-toggle__btn:active{opacity:.7;transform:scale(.95)}.view-mode-toggle__icon svg{width:16px;height:16px}.view-mode-toggle__label{font-size:11px}}@media(max-width:480px){.view-mode-toggle--floating{padding:3px}.view-mode-toggle__btn{padding:8px 10px;min-height:44px}.view-mode-toggle__label{display:none}}.app.view-mode-flat .guake-terminal{display:none}.flat-view{--flat-middle-width: 1fr;--flat-inspector-width: 320px;display:grid;grid-template-columns:var(--flat-middle-width) 3px 1fr;height:100%;width:100%;background:#282a36;overflow:hidden;padding-left:64px;box-sizing:border-box;transition:grid-template-columns .25s ease}.flat-view--with-inspector{grid-template-columns:var(--flat-middle-width) 3px 1fr 3px var(--flat-inspector-width)}.flat-splitter{position:relative;cursor:col-resize;background:#ffffff0a;touch-action:none;-webkit-user-select:none;user-select:none;transition:background .15s ease;z-index:2}.flat-splitter:before{content:"";position:absolute;top:0;bottom:0;left:-5px;right:-5px}.flat-splitter:hover{background:#8be9fd73}body.flat-splitter-dragging{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}body.flat-splitter-dragging .flat-splitter{background:#8be9fd99}body.flat-splitter-dragging .flat-view{transition:none!important}.flat-middle{display:flex;flex-direction:column;background:#282a36;border-right:1px solid rgba(255,255,255,.06);overflow:hidden;min-width:280px}.flat-middle__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;gap:12px}.flat-middle__title{font-size:14px;font-weight:600;color:#f8f8f2;margin:0}.flat-middle__actions{display:flex;gap:6px;flex-shrink:0}.flat-middle__content{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:8px}.flat-middle__content::-webkit-scrollbar{width:6px}.flat-middle__content::-webkit-scrollbar-track{background:transparent}.flat-middle__content::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:3px}.flat-middle__content::-webkit-scrollbar-thumb:hover{background:#fff3}.flat-cta-btn{padding:4px 10px;font-size:11px;font-weight:500;border:none;border-radius:4px;cursor:pointer;transition:all .15s ease;white-space:nowrap}.flat-cta-btn--agent{background:#50fa7b26;color:#50fa7b}.flat-cta-btn--agent:hover{background:#50fa7b40}.flat-cta-btn--boss{background:#ffd70026;color:gold}.flat-cta-btn--boss:hover{background:#ffd70040}.flat-cta-btn--building{background:#8be9fd26;color:#8be9fd}.flat-cta-btn--building:hover{background:#8be9fd40}.flat-cta-btn--area{background:#bd93f926;color:#bd93f9}.flat-cta-btn--area:hover{background:#bd93f940}.flat-middle .agent-overview-panel{position:relative;inset:auto;width:100%;height:100%;border-right:none;flex:1;min-height:0;z-index:auto}.flat-middle .agent-overview-panel .aop-row-controls .close-btn{display:none}.flat-middle__content:has(>.agent-overview-panel){padding:0;overflow:hidden}.flat-right{display:flex;flex-direction:column;background:#21222c;overflow:hidden}.flat-chat{display:flex;flex-direction:column;height:100%}.flat-chat--empty{align-items:center;justify-content:center}.flat-chat__placeholder{display:flex;flex-direction:column;align-items:center;gap:12px;color:#6272a4}.flat-chat__placeholder-icon{font-size:48px;opacity:.5}.flat-chat__placeholder-text{font-size:14px}.flat-map{display:flex;flex-direction:column;height:100%;padding:12px 16px;gap:10px;overflow-y:auto;position:relative}.flat-map::-webkit-scrollbar{width:6px}.flat-map::-webkit-scrollbar-track{background:transparent}.flat-map::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:3px}.flat-map::-webkit-scrollbar-thumb:hover{background:#fff3}.flat-map__header{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-shrink:0;padding-right:130px}.flat-map__title{font-size:13px;font-weight:600;color:#f8f8f2}.flat-map__hint{font-size:11px;color:#6272a4}.flat-map__stats{display:none}.flat-map__view-mode{position:absolute;top:10px;right:12px;z-index:5;background:color-mix(in srgb,#1e1f29 92%,transparent);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);border-radius:999px;box-shadow:0 2px 8px #0000004d}.flat-map__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px;align-content:start}.flat-map__empty{grid-column:1/-1;display:flex;align-items:center;justify-content:center;padding:40px;color:#6272a4;font-size:13px}.flat-map-area-card{display:flex;flex-direction:column;position:relative;isolation:isolate;background:color-mix(in srgb,var(--area-color, #6272a4) 12%,#363848);border:1px solid color-mix(in srgb,var(--area-color, #6272a4) 38%,transparent);border-radius:8px;overflow:hidden;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.flat-map-area-card:hover{border-color:color-mix(in srgb,var(--area-color, #6272a4) 58%,transparent);box-shadow:0 2px 8px #00000040}.flat-map-area-card__header{display:flex;align-items:center;gap:6px;padding:6px 8px;background:transparent;border:none;cursor:pointer;width:100%;text-align:left;color:#f8f8f2;font-size:12px;font-weight:600;transition:background .15s ease}.flat-map-area-card__header:hover{background:#ffffff0a}.flat-map-area-card__color{width:8px;height:8px;border-radius:50%;flex-shrink:0}.flat-map-area-card__logo{position:absolute;right:8px;bottom:8px;width:88px;height:88px;max-width:55%;max-height:72%;object-fit:contain;opacity:.3;pointer-events:none;-webkit-user-select:none;user-select:none;z-index:-1;border-radius:4px}.flat-map-area-card__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.flat-map-area-card__count{display:inline-flex;align-items:center;gap:3px;font-size:10px;font-weight:500;color:#6272a4;background:#ffffff0f;padding:1px 5px;border-radius:8px;flex-shrink:0}.flat-map-area-card__caret{font-size:10px;color:#6272a4;flex-shrink:0;width:12px;text-align:center}.flat-map-area-card__agents{display:flex;flex-wrap:wrap;gap:4px;padding:0 8px 8px}.flat-map-agent-chip{position:relative;display:inline-flex;align-items:center;gap:5px;padding:3px 7px 6px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;color:#9a9caa;font-size:11px;text-align:left;transition:background .15s ease,color .15s ease,border-color .15s ease;white-space:nowrap;min-width:0;overflow:hidden}.flat-map-agent-chip:hover{background:#ffffff14;border-color:#ffffff1f;color:#f8f8f2}.flat-map-agent-chip.working{overflow:visible;isolation:isolate;background-color:#4a9eff1f;background-image:linear-gradient(100deg,transparent 30%,rgba(180,230,255,.45) 49%,rgba(139,220,240,.3) 51%,transparent 70%),linear-gradient(100deg,transparent 32%,rgba(139,233,253,.3) 50%,transparent 68%);background-size:220% 100%,260% 100%;background-repeat:no-repeat,no-repeat;background-position:150% 0,150% 0;border-color:#8be9fdb3;color:#f8f8f2;box-shadow:0 0 8px #4a9eff59,inset 0 0 0 1px #8be9fd00;transform-origin:center;will-change:transform,background-position,box-shadow,border-color;animation:flat-map-agent-working-shimmer .75s linear infinite,flat-map-agent-working-shimmer-2 1.15s linear infinite,flat-map-agent-working-pulse 1.1s ease-in-out infinite,flat-map-agent-working-beat .85s ease-in-out infinite,flat-map-agent-working-iris 3.2s linear infinite}.flat-map-agent-chip.working:before{content:"";position:absolute;top:-2px;right:-2px;bottom:-2px;left:-2px;border-radius:inherit;pointer-events:none;z-index:-1;background:conic-gradient(from 0deg,#8be9fd00,#8bc8fd8c,#a082e680,#dc82c873,#dcb48266,#8bc8fd8c,#8be9fd00);filter:blur(8px);transform-origin:center;will-change:transform,opacity;animation:flat-map-agent-working-spin 3.8s linear infinite,flat-map-agent-working-breath 2.6s ease-in-out infinite}.flat-map-agent-chip.working:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:inherit;pointer-events:none;z-index:1;background-image:radial-gradient(1px 1px at 18% 32%,rgba(255,255,255,.7) 0%,transparent 60%),radial-gradient(1px 1px at 72% 58%,rgba(200,240,255,.65) 0%,transparent 60%),radial-gradient(1.5px 1.5px at 42% 80%,rgba(220,200,255,.55) 0%,transparent 60%),radial-gradient(1px 1px at 88% 22%,rgba(255,255,255,.6) 0%,transparent 60%),radial-gradient(1px 1px at 12% 70%,rgba(210,190,255,.55) 0%,transparent 60%),radial-gradient(1px 1px at 58% 18%,rgba(255,255,255,.55) 0%,transparent 60%);mix-blend-mode:screen;opacity:.5;animation:flat-map-agent-working-twinkle 1.9s ease-in-out infinite}.flat-map-agent-chip.working .flat-map-agent-chip__dot{position:relative;z-index:2;box-shadow:0 0 6px #4a9effb3;animation:flat-map-agent-working-dot .65s ease-in-out infinite}.flat-map-agent-chip.working .flat-map-agent-chip__name,.flat-map-agent-chip.working .flat-map-agent-chip__provider-icon,.flat-map-agent-chip.working .flat-map-agent-chip__crown{position:relative;z-index:2}@keyframes flat-map-agent-working-shimmer{0%{background-position:150% 0,150% 0}to{background-position:-70% 0,150% 0}}@keyframes flat-map-agent-working-shimmer-2{0%{background-position:150% 0,150% 0}to{background-position:150% 0,-70% 0}}@keyframes flat-map-agent-working-pulse{0%,to{border-color:#4a9eff8c;box-shadow:0 0 6px #4a9eff59,inset 0 0 0 1px #8be9fd00}50%{border-color:#b4faff;box-shadow:0 0 18px #4a9effcc,0 0 30px #8be9fd59,inset 0 0 0 1px #b4faff8c}}@keyframes flat-map-agent-working-beat{0%,to{transform:scale(1)}35%{transform:scale(1.035)}55%{transform:scale(.99)}75%{transform:scale(1.015)}}@keyframes flat-map-agent-working-dot{0%,to{transform:scale(1);box-shadow:0 0 6px #4a9effb3}50%{transform:scale(1.7);box-shadow:0 0 12px #b4faff,0 0 22px #4a9effb3}}@keyframes flat-map-agent-working-iris{0%{border-color:#8be9fdb3}25%{border-color:#b482ffd9}50%{border-color:#ff78dccc}75%{border-color:#ffc878bf}to{border-color:#8be9fdb3}}@keyframes flat-map-agent-working-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes flat-map-agent-working-breath{0%,to{opacity:.3;filter:blur(7px)}40%{opacity:.7;filter:blur(11px)}70%{opacity:.45;filter:blur(8px)}}@keyframes flat-map-agent-working-twinkle{0%,to{opacity:.25;transform:translate(0) scale(.9)}25%{opacity:1;transform:translate(1px,-1px) scale(1.1)}50%{opacity:.55;transform:translate(-1px,1px) scale(.95)}75%{opacity:1;transform:translate(1px,1px) scale(1.15)}}@media(prefers-reduced-motion:reduce){.flat-map-agent-chip.working{animation:flat-map-agent-working-shimmer 5s linear infinite;background-image:linear-gradient(110deg,transparent 40%,rgba(139,233,253,.3) 50%,transparent 60%),linear-gradient(110deg,transparent 40%,rgba(139,233,253,0) 50%,transparent 60%);transform:none}.flat-map-agent-chip.working:before,.flat-map-agent-chip.working:after{animation:none;opacity:.3}.flat-map-agent-chip.working .flat-map-agent-chip__dot{animation:none}}.flat-map-agent-chip__name{min-width:0;overflow:hidden;text-overflow:ellipsis}.flat-map-agent-chip__dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.flat-map-agent-chip__provider-icon{width:12px;height:12px;object-fit:contain;flex-shrink:0;filter:drop-shadow(0 1px 2px rgba(0,0,0,.25))}.flat-map-agent-chip__crown{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.flat-map-agent-chip__context-bar{position:absolute;left:0;right:0;bottom:0;height:2px;background:#ffffff0f;pointer-events:none}.flat-map-agent-chip__context-bar-fill{display:block;height:100%;transition:width .2s ease,background-color .2s ease}.flat-map-area-card__buildings,.flat-map-area-card__folders{display:flex;flex-wrap:wrap;gap:4px;padding:6px 8px 8px;border-top:1px dashed rgba(255,255,255,.05);margin-top:2px}.flat-map-folder-chip{display:inline-flex;align-items:center;gap:5px;padding:3px 7px;background:#ffffff06;border:1px solid rgba(255,255,255,.06);border-radius:8px;cursor:pointer;color:#9a9caa;font-size:11px;font-family:JetBrains Mono,Fira Code,monospace;text-align:left;transition:background .15s ease,color .15s ease,border-color .15s ease;white-space:nowrap;min-width:0;max-width:100%;overflow:hidden}.flat-map-folder-chip:hover{background:#ffffff12;border-color:#ffffff2e;color:#f8f8f2}.flat-map-folder-chip__name{min-width:0;overflow:hidden;text-overflow:ellipsis}.flat-map-building-chip{display:inline-flex;align-items:center;gap:5px;padding:3px 7px;background:#ffffff06;border:1px dashed rgba(255,255,255,.08);border-left:2px solid var(--building-type-color, rgba(255, 255, 255, .08));border-radius:8px;cursor:pointer;color:#9a9caa;font-size:11px;text-align:left;transition:background .15s ease,color .15s ease,border-color .15s ease;white-space:nowrap;min-width:0;overflow:hidden}.flat-map-building-chip:hover{background:#ffffff12;border-color:#ffffff2e;border-left-color:var(--building-type-color, rgba(255, 255, 255, .18));color:#f8f8f2}.flat-map-building-chip__name{min-width:0;overflow:hidden;text-overflow:ellipsis}.flat-map-building-chip__dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.flat-map-building-chip--error{border-color:#ff4a4a66}.flat-map-building-chip--running{border-style:solid;border-color:#4aff9e40}.flat-terminal-wrapper{display:flex;flex-direction:column;height:100%;min-height:0;position:relative;background:#21222c;overflow:hidden;--guake-side-panel-width: 380px}.flat-terminal-wrapper--with-side-panel>*:not(.guake-git-panel):not(.guake-buildings-panel):not(.guake-workflow-panel):not(.agent-debug-panel){margin-right:var(--guake-side-panel-width);transition:margin-right .2s ease}.flat-terminal-wrapper__header{display:flex;flex-direction:row;align-items:center;gap:12px;padding:10px 12px 6px;border-bottom:1px solid rgba(255,255,255,.06);background:#1e1f29;flex-shrink:0;min-height:40px;overflow:visible}.flat-terminal-wrapper__header-main{display:flex;align-items:center;gap:10px;min-width:0;flex:1 1 auto;overflow:visible;padding:4px 6px;margin:0;background:transparent;border:1px solid transparent;border-radius:8px;color:inherit;font:inherit;text-align:left;cursor:pointer;transition:background .15s ease,border-color .15s ease}.flat-terminal-wrapper__header-main:hover{background:#ffffff0a;border-color:#ffffff0f}.flat-terminal-wrapper__header-main--active{background:#bd93f92e;border-color:#bd93f973}.flat-terminal-wrapper__header-main--active:hover{background:#bd93f942}.flat-terminal-wrapper__header-avatar{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;width:28px;height:28px;border-radius:8px;overflow:visible;transform-origin:center center;border:1.5px solid transparent;box-sizing:border-box}.flat-terminal-wrapper__header-avatar>*{display:block;width:100%;height:100%;object-fit:cover;border-radius:7px}.flat-terminal-wrapper__header-avatar.is-working{border-color:#8be9fd8c;animation:flat-header-avatar-sway 1.2s ease-in-out infinite!important}html.low-power .flat-terminal-wrapper__header-avatar.is-working{animation:none!important}.flat-terminal-wrapper__header-avatar.is-working{z-index:1;will-change:transform;transform-origin:center center}.flat-terminal-wrapper__header-meta{display:flex;align-items:center;justify-content:flex-end;gap:6px;flex:0 0 auto;flex-wrap:nowrap}.flat-terminal-wrapper__statusbar{display:flex;align-items:center;gap:10px;padding:6px 12px;flex-shrink:0;background:#1e1f29;border-top:1px solid rgba(255,255,255,.06);min-height:32px;box-sizing:border-box}.flat-terminal-wrapper__statusbar .flat-terminal-wrapper__cwd,.flat-terminal-wrapper__statusbar .flat-terminal-wrapper__context{background:transparent;border-color:#ffffff0a}.flat-terminal-wrapper__statusbar-spacer{flex:1 1 auto}.flat-terminal-wrapper__buildings{display:inline-flex;align-items:center;gap:4px;padding:2px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px}.flat-terminal-wrapper__building-btn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:22px;padding:0;color:#6272a4;background:transparent;border:none;border-radius:7px;cursor:pointer;transition:background .15s ease,color .15s ease}.flat-terminal-wrapper__building-btn:hover{color:#f8f8f2;background:#ffffff14}.flat-terminal-wrapper__building-btn--offline{color:#ffb86cbf}.flat-terminal-wrapper__building-btn--offline:hover{color:#ffb86c}.flat-terminal-wrapper__building-btn--active{color:#f8f8f2;background:#bd93f947;box-shadow:0 0 0 1px #bd93f973}.flat-terminal-wrapper__building-btn--active:hover{background:#bd93f95c}.flat-terminal-wrapper__building-btn--tests-working{color:#8be9fd;background:#8be9fd24;box-shadow:0 0 0 1px #8be9fd66;animation:flat-tests-glow 1.4s ease-in-out infinite}.flat-terminal-wrapper__building-btn--tests-working svg{animation:flat-tests-shake 1.1s ease-in-out infinite}.flat-terminal-wrapper__building-btn--tests-working:hover{color:#8be9fd;background:#8be9fd38}.flat-terminal-wrapper__detached{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;font-size:11px;font-weight:500;color:#ffb86c;background:#ffb86c1f;border:1px solid rgba(255,184,108,.35);border-radius:10px;animation:blink 1.6s ease-in-out infinite}.flat-terminal-wrapper__area-dir{display:inline-flex;align-items:center;gap:5px;padding:3px 8px;font-size:11px;font-family:SF Mono,Menlo,Consolas,monospace;color:#9a9caa;background:#ffffff08;border:1px solid rgba(255,255,255,.05);border-radius:10px;cursor:pointer;max-width:240px;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .15s ease,color .15s ease,border-color .15s ease}.flat-terminal-wrapper__area-dir:hover{background:#ffffff14;color:#f8f8f2;border-color:#ffffff24}.flat-terminal-wrapper__area-dir-name{overflow:hidden;text-overflow:ellipsis}.flat-terminal-wrapper__area-dir-branch{display:inline-flex;align-items:center;gap:3px;color:#8be9fd;opacity:.85}.flat-terminal-wrapper__branch-ahead{display:inline-flex;align-items:center;color:#50fa7b}.flat-terminal-wrapper__branch-behind{display:inline-flex;align-items:center;color:#ffb86c}.flat-terminal-wrapper__area-fetch{display:inline-flex;align-items:center;padding:1px 3px;border-radius:4px;color:#6272a4;cursor:pointer;transition:background .15s ease,color .15s ease}.flat-terminal-wrapper__area-fetch:hover{background:#ffffff14;color:#f8f8f2}.flat-terminal-wrapper__area-fetch--fetching{animation:blink 1s ease-in-out infinite}.flat-terminal-wrapper__context-label{color:#6272a4;margin-right:2px}.flat-terminal-wrapper__context-free{color:#6272a4;font-size:10px}.flat-terminal-wrapper__actions{display:inline-flex;align-items:center;gap:4px;padding:2px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px}.flat-terminal-wrapper__action-btn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:24px;padding:0;font-size:12px;line-height:1;color:#6272a4;background:transparent;border:none;border-radius:7px;cursor:pointer;transition:background .15s ease,color .15s ease,box-shadow .15s ease}.flat-terminal-wrapper__action-btn:hover:not(:disabled){color:#f8f8f2;background:#ffffff0f}.flat-terminal-wrapper__action-btn:disabled{opacity:.35;cursor:not-allowed}.flat-terminal-wrapper__action-btn--active{color:#f8f8f2;background:#bd93f947;box-shadow:0 0 0 1px #bd93f973}.flat-terminal-wrapper__action-btn--active:hover{background:#bd93f95c}.flat-terminal-wrapper__action-btn--danger{color:#ff5555d9}.flat-terminal-wrapper__action-btn--danger:hover{color:#f55;background:#ff55551f}.flat-terminal-wrapper__action-btn--confirm{color:#f55;background:#ff55552e;box-shadow:0 0 0 1px #ff555580;animation:blink 1s ease-in-out infinite}.flat-terminal-wrapper__more{position:relative;display:inline-flex}.flat-terminal-wrapper__more-menu{position:absolute;top:calc(100% + 4px);right:0;min-width:220px;padding:4px;background:#363848;border:1px solid rgba(255,255,255,.08);border-radius:8px;box-shadow:0 8px 28px #00000073;z-index:100}.flat-terminal-wrapper__more-item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;font-size:12px;color:#f8f8f2;background:transparent;border:none;border-radius:6px;cursor:pointer;text-align:left;transition:background .15s ease,color .15s ease}.flat-terminal-wrapper__more-item:hover:not(:disabled){background:#ffffff0f}.flat-terminal-wrapper__more-item:disabled{opacity:.45;cursor:not-allowed}.flat-terminal-wrapper__more-item--danger{color:#ff5555e6}.flat-terminal-wrapper__more-item--danger:hover:not(:disabled){color:#f55;background:#ff55551f}.flat-terminal-wrapper__more-divider{height:1px;margin:4px 2px;background:#ffffff0f}.flat-terminal-wrapper__header-info{display:flex;flex-direction:row;align-items:center;gap:6px;min-width:0;flex:1 1 auto;overflow:hidden}.flat-terminal-wrapper__header-name{font-size:13px;font-weight:600;color:#f8f8f2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex:1 1 auto}.flat-terminal-wrapper__header-status{font-size:10px;text-transform:capitalize;flex-shrink:0}.flat-terminal-wrapper__header-task{font-size:11px;color:#6272a4;max-width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:2px 8px;border-radius:10px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);flex-shrink:1}.flat-terminal-wrapper__header-model{display:inline-flex;align-items:center;gap:6px;flex-shrink:0;min-width:0}.flat-terminal-wrapper__header-provider-icon{width:16px;height:16px;object-fit:contain;flex-shrink:0;filter:drop-shadow(0 1px 2px rgba(0,0,0,.25))}.flat-terminal-wrapper__header-model-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;font-size:10px;font-family:SF Mono,Menlo,Consolas,monospace;font-weight:600;color:#9a9caa;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:999px;white-space:nowrap;max-width:180px;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.flat-terminal-wrapper__header-model-name{color:#f8f8f2;text-transform:lowercase;overflow:hidden;text-overflow:ellipsis}.flat-terminal-wrapper__header-model-sep{opacity:.6}.flat-terminal-wrapper__header-model-effort{color:#bd93f9;text-transform:lowercase}.flat-terminal-wrapper__cwd{display:inline-flex;align-items:center;gap:6px;padding:4px 9px;font-size:11px;color:#9a9caa;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;max-width:240px;transition:background .15s ease,border-color .15s ease,color .15s ease}.flat-terminal-wrapper__cwd:hover{background:#ffffff14;border-color:#ffffff24;color:#f8f8f2}.flat-terminal-wrapper__cwd-icon{font-size:12px;line-height:1}.flat-terminal-wrapper__cwd-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:SF Mono,Menlo,Consolas,monospace}.flat-terminal-wrapper__context{display:inline-flex;align-items:center;gap:6px;padding:4px 9px;font-size:11px;color:#9a9caa;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;transition:background .15s ease,border-color .15s ease}.flat-terminal-wrapper__context:hover{background:#ffffff14;border-color:#ffffff24}.flat-terminal-wrapper__context-icon{font-size:12px;line-height:1}.flat-terminal-wrapper__context-bar{position:relative;width:56px;height:5px;border-radius:3px;background:#ffffff14;overflow:hidden}.flat-terminal-wrapper__context-bar-fill{position:absolute;left:0;top:0;height:100%;border-radius:3px;transition:width .2s ease,background-color .2s ease}.flat-terminal-wrapper__context-tokens{font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px;font-weight:600;font-variant-numeric:tabular-nums}.flat-terminal-wrapper__context-warning{font-size:11px;opacity:.8}.flat-terminal-wrapper__view-mode{display:inline-flex;align-items:center;padding:2px;gap:2px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px}.flat-terminal-wrapper__view-mode-btn{display:inline-flex;align-items:center;gap:5px;padding:4px 9px;font-size:11px;font-weight:500;color:#6272a4;background:transparent;border:none;border-radius:8px;cursor:pointer;transition:background .15s ease,color .15s ease,box-shadow .15s ease}.flat-terminal-wrapper__view-mode-btn:hover{color:#f8f8f2;background:#ffffff0a}.flat-terminal-wrapper__view-mode-btn--active{color:#f8f8f2;background:#bd93f947;box-shadow:0 0 0 1px #bd93f980,0 1px 3px #00000040}.flat-terminal-wrapper__view-mode-btn--active:hover{background:#bd93f95c}.flat-terminal-wrapper__view-mode-icon{font-size:13px;line-height:1}.flat-terminal-wrapper__view-mode-label{line-height:1}.flat-terminal-wrapper__theme{display:inline-flex;align-items:center}.flat-terminal-wrapper__theme .theme-selector-trigger{padding:4px 9px;font-size:11px;border-radius:10px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06)}.flat-terminal-wrapper__theme .theme-selector-trigger:hover{background:#ffffff14;border-color:#ffffff24}.flat-terminal-wrapper__inspector-toggle{display:inline-flex;align-items:center;gap:5px;padding:4px 9px;font-size:11px;font-weight:500;color:#9a9caa;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;transition:background .15s ease,border-color .15s ease,color .15s ease,box-shadow .15s ease}.flat-terminal-wrapper__inspector-toggle:hover{color:#f8f8f2;background:#ffffff14;border-color:#ffffff24}.flat-terminal-wrapper__inspector-toggle--active{color:#f8f8f2;background:#bd93f938;border-color:#bd93f98c;box-shadow:0 0 0 1px #bd93f959,0 1px 3px #00000040}.flat-terminal-wrapper__inspector-toggle--active:hover{background:#bd93f952}.flat-terminal-wrapper__inspector-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}.flat-terminal-wrapper__inspector-label{line-height:1}.flat-terminal-wrapper__close{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;color:#6272a4;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;transition:background .15s ease,color .15s ease,border-color .15s ease}.flat-terminal-wrapper__close:hover{color:#f55;background:#ff55551f;border-color:#f556}@media(max-width:1100px){.flat-terminal-wrapper__view-mode-label,.flat-terminal-wrapper__inspector-label{display:none}.flat-terminal-wrapper__cwd{max-width:160px}}.flat-terminal-wrapper .guake-output{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px}.flat-terminal-wrapper .guake-output::-webkit-scrollbar{width:6px}.flat-terminal-wrapper .guake-output::-webkit-scrollbar-track{background:transparent}.flat-terminal-wrapper .guake-output::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:3px}.flat-terminal-wrapper .guake-input-container{position:relative;flex-shrink:0;border-top:1px solid rgba(255,255,255,.06);background:#1e1f29}.flat-terminal-wrapper .guake-search-bar,.flat-terminal-wrapper .atp-search-bar{position:sticky;top:0;z-index:10;background:#1e1f29}.flat-terminal-wrapper .guake-handle,.flat-terminal-wrapper .atp-resize-handle{display:none}.flat-terminal-wrapper .compacting-indicator{padding:12px;margin:8px}@keyframes blink{0%,to{opacity:1}50%{opacity:.3}}.flat-inspector{display:flex;flex-direction:column;min-width:0;min-height:0;height:100%;background:#1e1f29;border-left:1px solid rgba(255,255,255,.06);overflow:hidden;animation:flat-inspector-slide-in .22s ease}.flat-inspector__header{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.06);background:#21222c;flex-shrink:0}.flat-inspector__tabs{display:inline-flex;align-items:center;gap:4px;padding:2px;background:#00000040;border:1px solid rgba(255,255,255,.06);border-radius:6px}.flat-inspector__tab{padding:4px 10px;font-size:12px;font-weight:500;color:#6272a4;background:transparent;border:none;border-radius:4px;cursor:pointer;transition:background .15s ease,color .15s ease}.flat-inspector__tab:hover{color:#f8f8f2}.flat-inspector__tab--active{color:#f8f8f2;background:#ffffff14}.flat-inspector__close{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;font-size:13px;color:#6272a4;background:transparent;border:1px solid transparent;border-radius:6px;cursor:pointer;transition:background .15s ease,color .15s ease,border-color .15s ease}.flat-inspector__close:hover{color:#f8f8f2;background:#ffffff0f;border-color:#ffffff1a}.flat-inspector__body{flex:1 1 auto;min-height:0;min-width:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column}.flat-inspector__body .unit-panel{flex:1 1 auto;min-height:0;min-width:0;padding:10px}.flat-inspector__empty{display:flex;align-items:center;justify-content:center;flex:1;color:#6272a4;font-size:13px}@keyframes flat-inspector-slide-in{0%{opacity:0;transform:translate(12px)}to{opacity:1;transform:translate(0)}}.flat-mobile-sidebar-toggle,.flat-mobile-sidebar-backdrop{display:none}@media(max-width:1024px){.flat-view,.flat-view--with-inspector{grid-template-columns:1fr}.flat-splitter{display:none}.flat-right{grid-column:1/-1}.flat-right>.flat-terminal-wrapper,.flat-right>.flat-chat{flex:1 1 auto;min-height:0;height:auto}.flat-middle{position:fixed;top:0;left:0;bottom:0;width:min(380px,92vw);z-index:185;transform:translate(-110%);transition:transform .22s ease;border-right:1px solid rgba(255,255,255,.08);box-shadow:6px 0 32px #0009}.flat-view--mobile-sidebar-open .flat-middle{transform:translate(0)}.flat-mobile-sidebar-toggle{display:inline-flex;align-items:center;gap:8px;align-self:flex-start;margin:10px 12px 0;padding:8px 12px;font-size:12px;font-weight:500;color:#f8f8f2;background:#363848f2;border:1px solid rgba(255,255,255,.08);border-radius:10px;cursor:pointer;min-height:36px;flex-shrink:0;transition:background .15s ease,border-color .15s ease}.flat-mobile-sidebar-toggle:hover,.flat-mobile-sidebar-toggle:active{background:#bd93f947;border-color:#bd93f980}.flat-mobile-sidebar-toggle__label{line-height:1}.flat-mobile-sidebar-backdrop{display:block;position:fixed;top:0;right:0;bottom:0;left:0;z-index:184;background:#000000ad;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:flat-inspector-fade-in .18s ease}.flat-inspector{position:fixed;top:0;right:0;bottom:0;left:0;z-index:186;border-left:none;animation:none;transform:translate(100%);transition:transform .22s ease}.flat-inspector--open{transform:translate(0)}.flat-inspector--closing{transform:translate(100%)}.flat-inspector__tab{min-height:36px;padding:6px 14px}.flat-inspector__close{min-width:40px;min-height:40px;display:inline-flex;align-items:center;justify-content:center}}.flat-chat-actions-sheet-root{position:fixed;top:0;right:0;bottom:0;left:0;z-index:2050}.flat-chat-actions-sheet__backdrop{position:absolute;top:0;right:0;bottom:0;left:0;background:#00000073;animation:flat-sheet-fade .15s ease}.flat-chat-actions-sheet{position:absolute;left:0;right:0;bottom:var(--mobile-bottom-stack-height, 72px);display:flex;flex-direction:column;gap:10px;padding:8px 14px calc(14px + env(safe-area-inset-bottom,0px));background:#363848;border:1px solid rgba(255,255,255,.08);border-bottom:none;border-top-left-radius:18px;border-top-right-radius:18px;box-shadow:0 -12px 32px #00000080;animation:flat-sheet-slide-up .2s cubic-bezier(.22,1,.36,1)}.flat-chat-actions-sheet__grabber{width:40px;height:4px;margin:2px auto;border-radius:999px;background:#ffffff38}.flat-chat-actions-sheet__title-row{display:flex;align-items:center;justify-content:space-between;gap:8px}.flat-chat-actions-sheet__title{font-size:13px;font-weight:600;color:#f8f8f2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.flat-chat-actions-sheet__done{flex-shrink:0;font-size:13px;font-weight:500;color:#bd93f9;background:none;border:none;padding:6px 4px;cursor:pointer}.flat-chat-actions-sheet__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.flat-chat-actions-sheet__item{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;min-height:64px;padding:8px 4px;font-size:11px;color:#f8f8f2;background:#ffffff0d;border:1px solid rgba(255,255,255,.07);border-radius:12px;cursor:pointer}.flat-chat-actions-sheet__item span{text-align:center;line-height:1.2}.flat-chat-actions-sheet__item.is-active{background:#bd93f93d;border-color:#bd93f980}.flat-chat-actions-sheet__list{display:flex;flex-direction:column;gap:2px}.flat-chat-actions-sheet__row{display:flex;align-items:center;gap:12px;width:100%;min-height:48px;padding:10px 12px;font-size:14px;color:#f8f8f2;background:transparent;border:none;border-radius:10px;cursor:pointer;text-align:left}.flat-chat-actions-sheet__row:active{background:#ffffff0f}.flat-chat-actions-sheet__row:disabled{opacity:.4;cursor:not-allowed}.flat-chat-actions-sheet__row--danger{color:#ff5555e6}.flat-chat-actions-sheet__row.is-armed{color:#f55;background:#ff555529;box-shadow:inset 0 0 0 1px #ff555580}@keyframes flat-sheet-slide-up{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes flat-sheet-fade{0%{opacity:0}to{opacity:1}}@media(max-width:768px){.app.view-mode-flat .mobile-fab-toggle,.app.view-mode-flat .mobile-fab-menu,.app.view-mode-flat .voice-assistant-btn.mobile-voice-assistant{display:none!important}.app.view-mode-flat .flat-view{padding-left:0}.app.view-mode-flat .main-content{height:calc(100% - var(--mobile-bottom-stack-height, 72px))!important;max-height:calc(100% - var(--mobile-bottom-stack-height, 72px))!important;overflow:hidden}.app.view-mode-flat .flat-terminal-wrapper__header,.app.view-mode-flat .flat-inspector__header,.app.view-mode-flat .flat-middle__header,.app.view-mode-flat .flat-map__header{padding-top:calc(6px + env(safe-area-inset-top,0px))}.app.view-mode-flat .flat-terminal-wrapper__header{padding-top:calc(2px + env(safe-area-inset-top,0px))}.app.view-mode-flat .flat-inspector__body,.app.view-mode-flat .flat-middle__content{padding-bottom:var(--mobile-bottom-stack-height, 72px)}.flat-view{padding-left:56px}.flat-middle__header{flex-wrap:wrap;padding:6px 10px;gap:6px}.flat-middle__content{padding:8px}.flat-cta-btn{padding:8px 10px;font-size:11px;min-height:34px}.flat-chat--empty{align-items:stretch;justify-content:flex-start}.flat-map{width:100%;padding:0 10px 12px;gap:8px;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;touch-action:pan-y}.app.view-mode-flat .flat-map__header{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"title toggle" "stats stats";align-items:center;gap:3px 10px;position:sticky;top:0;z-index:8;margin:0 -10px;padding:calc(6px + env(safe-area-inset-top,0px)) 10px 8px;background:color-mix(in srgb,#282a36 94%,transparent);border-bottom:1px solid rgba(255,255,255,.05);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.flat-map__title{grid-area:title;font-size:15px}.flat-map__hint{display:none}.flat-map__stats{grid-area:stats;display:flex;align-items:center;gap:8px;min-width:0;color:#6272a4;font-size:10px;font-family:SF Mono,Menlo,Consolas,monospace}.flat-map__stats-working{display:inline-flex;align-items:center;gap:4px;color:color-mix(in srgb,#4a9eff 78%,#9a9caa)}.flat-map__stats-dot{width:6px;height:6px;flex-shrink:0;border-radius:50%;background:#4a9eff;box-shadow:0 0 6px #4a9eff8c}.flat-map__view-mode{grid-area:toggle;position:relative;top:auto;right:auto;justify-self:end}.flat-map__view-mode .view-mode-toggle__btn{min-width:40px;min-height:40px;padding:6px 9px}.flat-map__grid{width:100%;grid-template-columns:repeat(2,minmax(0,1fr))!important;gap:8px}.flat-map-area-card{min-width:0;grid-row:auto!important;grid-column:auto!important;border-radius:12px}.flat-map-area-card__header{padding:7px 8px;gap:6px;min-height:48px}.flat-map-area-card__name{font-size:12px}.flat-map-area-card__count{font-size:9px;padding:2px 5px}.flat-map-area-card__logo{position:static;width:22px;height:22px;max-width:22px;max-height:22px;flex-shrink:0;opacity:.82;z-index:0;border-radius:5px}.flat-map-area-card__caret{flex-shrink:0;margin-left:auto;opacity:.7}.flat-map-area-card--collapsed .flat-map-area-card__agents,.flat-map-area-card--collapsed .flat-map-area-card__buildings,.flat-map-area-card--collapsed .flat-map-area-card__folders{display:none}.flat-map-area-card--expanded{grid-column:1/-1!important;border-color:color-mix(in srgb,var(--area-color, #6272a4) 72%,transparent);box-shadow:0 6px 18px #0000004d}.flat-map-area-card__agents{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;padding:2px 8px 8px}.flat-map-agent-chip{width:100%;padding:7px 10px 9px;font-size:12px;min-height:40px}.flat-map-area-card__folders,.flat-map-area-card__buildings{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}.flat-map-folder-chip,.flat-map-building-chip{width:100%;min-height:36px}.flat-terminal-wrapper__header{flex-wrap:nowrap;padding:6px 10px 4px;gap:8px;min-height:40px;overflow:visible}.flat-terminal-wrapper__header-main{flex:1 1 auto;min-width:0;overflow:hidden;display:grid;grid-template-columns:auto minmax(0,1fr);grid-template-areas:"avatar info" "avatar model";align-items:center;column-gap:8px;row-gap:0;padding:2px 4px}.flat-terminal-wrapper__header-avatar{grid-area:avatar}.flat-terminal-wrapper__header-info{grid-area:info;min-width:0;align-self:end}.flat-terminal-wrapper__header-name{flex:1 1 auto;min-width:0}.flat-terminal-wrapper__header-status{font-size:9px;padding:1px 6px;border-radius:999px;background:#ffffff0f;max-width:72px;overflow:hidden;text-overflow:ellipsis}.flat-terminal-wrapper__header-model{grid-area:model;align-self:start;justify-self:start;min-width:0;max-width:100%;gap:4px}.flat-terminal-wrapper__header-provider-icon{width:11px;height:11px}.flat-terminal-wrapper__header-model-chip{padding:0;background:none;border:none;border-radius:0;font-size:9px;max-width:100%}.flat-terminal-wrapper__header-meta{flex:0 0 auto;justify-content:flex-end;flex-wrap:nowrap;gap:4px}.flat-terminal-wrapper__header-task{display:none}.flat-terminal-wrapper__header-avatar,.flat-terminal-wrapper__header-avatar>*{width:28px;height:28px}.flat-terminal-wrapper__action-btn,.flat-terminal-wrapper__building-btn{min-width:36px;min-height:36px}.flat-terminal-wrapper__statusbar{flex-wrap:wrap;padding:6px 10px;gap:6px;row-gap:6px}.flat-terminal-wrapper__action-btn,.flat-terminal-wrapper__building-btn,.flat-terminal-wrapper__close{width:28px;height:28px}.flat-terminal-wrapper__inspector-toggle{padding:4px 6px}.flat-terminal-wrapper__inspector-label,.flat-terminal-wrapper__actions{display:none}.flat-terminal-wrapper{--guake-side-panel-width: 100%;background:var(--bg-primary)}.flat-right{background:var(--bg-primary)}.flat-terminal-wrapper--with-side-panel>*:not(.guake-git-panel):not(.guake-buildings-panel):not(.guake-workflow-panel):not(.agent-debug-panel){margin-right:0}.flat-terminal-wrapper .guake-git-panel,.flat-terminal-wrapper .guake-buildings-panel,.flat-terminal-wrapper .guake-workflow-panel,.flat-terminal-wrapper .agent-debug-panel{width:100%}.flat-bottom-panel{height:180px}.flat-terminal-wrapper__view-mode,.flat-terminal-wrapper__close,.flat-terminal-wrapper__statusbar,.app.view-mode-flat .flat-mobile-sidebar-toggle,.app.view-mode-flat .flat-terminal-wrapper__inspector-toggle{display:none}}@media(max-width:480px){.flat-view{padding-left:52px}.flat-middle{width:100vw;max-width:100vw;box-shadow:none}.flat-middle__header{padding:8px 10px}.flat-middle__actions{gap:4px}.flat-cta-btn{padding:6px 8px;font-size:10px;min-height:32px}.flat-map-area-card__header{padding:8px 10px;font-size:13px}.flat-map-agent-chip{font-size:12px;padding:6px 8px 8px}.flat-terminal-wrapper__header-name{font-size:12px}.flat-terminal-wrapper__header-model-chip{max-width:100%}.flat-inspector__body{padding-bottom:env(safe-area-inset-bottom,0)}}@media(min-width:1400px){.flat-view{--flat-middle-width: minmax(280px, 400px);--flat-inspector-width: 360px}}@keyframes flat-inspector-fade-in{0%{opacity:0}to{opacity:1}}.flat-classic-terminal{flex:1 1 auto;min-height:0;display:flex;position:relative;overflow:hidden;background:#1a1a2e}.flat-classic-terminal .guake-bottom-terminal-embed{flex:1 1 auto;width:100%;height:100%;min-height:0}.flat-classic-terminal--message{align-items:center;justify-content:center;color:#6272a4;font-size:13px}.flat-bottom-panel{display:flex;flex-direction:column;flex-shrink:0;height:250px;min-height:0;background:#1e1f29;border-top:1px solid rgba(255,255,255,.08);overflow:hidden}.flat-bottom-panel__header{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:4px 10px;background:#21222c;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;min-height:28px}.flat-bottom-panel__title{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:500;color:#f8f8f2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.flat-bottom-panel__muted{color:#6272a4;font-weight:400;font-size:10px}.flat-bottom-panel__header-actions{display:inline-flex;align-items:center;gap:2px;flex-shrink:0}.flat-bottom-panel__close{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;padding:0;color:#6272a4;background:transparent;border:none;border-radius:6px;cursor:pointer;transition:background .15s ease,color .15s ease}.flat-bottom-panel__close:hover{color:#f8f8f2;background:#ffffff14}.flat-bottom-panel__body{flex:1 1 auto;min-height:0;display:flex;background:#282a36}.flat-bottom-panel__body>*{flex:1 1 auto;min-height:0}.flat-bottom-panel__placeholder{flex:1 1 auto;display:flex;align-items:center;justify-content:center;color:#6272a4;font-size:12px}@keyframes flat-tests-shake{0%,to{transform:rotate(0)}20%{transform:rotate(-14deg)}40%{transform:rotate(10deg)}60%{transform:rotate(-7deg)}80%{transform:rotate(4deg)}}@keyframes flat-tests-glow{0%,to{box-shadow:0 0 0 1px #8be9fd4d}50%{box-shadow:0 0 6px 1px #8be9fdb3}}@keyframes flat-header-avatar-sway{0%,to{transform:rotate(0)}25%{transform:rotate(-8deg)}75%{transform:rotate(8deg)}}