brainctl 0.1.5 → 0.1.7

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 (37) hide show
  1. package/README.md +181 -131
  2. package/dist/executor/resolver.js +1 -38
  3. package/dist/mcp/server.js +183 -0
  4. package/dist/services/agent-config-service.d.ts +35 -0
  5. package/dist/services/agent-config-service.js +222 -0
  6. package/dist/services/mcp-preflight-service.d.ts +25 -0
  7. package/dist/services/mcp-preflight-service.js +84 -0
  8. package/dist/services/plugin-install-service.d.ts +92 -0
  9. package/dist/services/plugin-install-service.js +243 -0
  10. package/dist/services/profile-export-service.js +5 -5
  11. package/dist/services/profile-import-service.js +1 -1
  12. package/dist/services/profile-service.d.ts +10 -0
  13. package/dist/services/profile-service.js +140 -28
  14. package/dist/services/skill-paths.d.ts +2 -0
  15. package/dist/services/skill-paths.js +12 -0
  16. package/dist/services/skill-preflight-service.d.ts +23 -0
  17. package/dist/services/skill-preflight-service.js +40 -0
  18. package/dist/services/sync/agent-reader.d.ts +30 -0
  19. package/dist/services/sync/agent-reader.js +232 -0
  20. package/dist/services/sync/claude-writer.js +4 -1
  21. package/dist/services/sync/codex-writer.js +6 -2
  22. package/dist/services/sync/gemini-writer.js +4 -1
  23. package/dist/services/sync/managed-plugin-registry.d.ts +17 -0
  24. package/dist/services/sync/managed-plugin-registry.js +75 -0
  25. package/dist/services/sync/plugin-skill-reader.d.ts +2 -0
  26. package/dist/services/sync/plugin-skill-reader.js +33 -0
  27. package/dist/services/sync-service.js +5 -0
  28. package/dist/system/executables.d.ts +1 -0
  29. package/dist/system/executables.js +38 -0
  30. package/dist/types.d.ts +15 -5
  31. package/dist/ui/routes.js +423 -1
  32. package/dist/web/assets/index-BCkorugl.css +1 -0
  33. package/dist/web/assets/index-sGnTMhkX.js +16 -0
  34. package/dist/web/index.html +2 -2
  35. package/package.json +7 -1
  36. package/dist/web/assets/index-CRJ6cM0Q.css +0 -1
  37. package/dist/web/assets/index-Cr8gt3VF.js +0 -9
package/dist/ui/routes.js CHANGED
@@ -2,10 +2,19 @@ import { existsSync } from 'node:fs';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import { loadConfig } from '../config.js';
4
4
  import { parseConfigPayload } from '../config.js';
5
+ import { BrainctlError, ProfileError, ProfileNotFoundError, ValidationError } from '../errors.js';
5
6
  import { loadMemory } from '../context/memory.js';
7
+ import { createAgentConfigService } from '../services/agent-config-service.js';
6
8
  import { createConfigWriteService } from '../services/config-write-service.js';
9
+ import { createMcpPreflightService } from '../services/mcp-preflight-service.js';
10
+ import { createPluginInstallService } from '../services/plugin-install-service.js';
11
+ import { createProfileExportService } from '../services/profile-export-service.js';
12
+ import { createProfileImportService } from '../services/profile-import-service.js';
13
+ import { createProfileService } from '../services/profile-service.js';
7
14
  import { createRunService } from '../services/run-service.js';
15
+ import { createSkillPreflightService } from '../services/skill-preflight-service.js';
8
16
  import { createStatusService } from '../services/status-service.js';
17
+ import { createSyncService } from '../services/sync-service.js';
9
18
  import { startSseStream, writeSseEvent } from './streaming.js';
10
19
  import path from 'node:path';
11
20
  import { fileURLToPath } from 'node:url';
@@ -14,6 +23,14 @@ export function createUiRouteHandler(dependencies) {
14
23
  const statusService = dependencies.statusService ?? createStatusService();
15
24
  const runService = dependencies.runService ?? createRunService();
16
25
  const configWriteService = createConfigWriteService();
26
+ const profileService = createProfileService();
27
+ const profileExportService = createProfileExportService({ profileService });
28
+ const profileImportService = createProfileImportService();
29
+ const syncService = createSyncService({ profileService });
30
+ const agentConfigService = createAgentConfigService();
31
+ const mcpPreflightService = createMcpPreflightService();
32
+ const pluginInstallService = createPluginInstallService();
33
+ const skillPreflightService = createSkillPreflightService();
17
34
  return async (request, response) => {
18
35
  const url = new URL(request.url ?? '/', 'http://localhost');
19
36
  switch (url.pathname) {
@@ -96,7 +113,382 @@ export function createUiRouteHandler(dependencies) {
96
113
  const overview = await statusService.execute({ cwd: dependencies.cwd });
97
114
  return sendJson(response, 200, overview.agents);
98
115
  }
99
- default:
116
+ case '/api/agents/live': {
117
+ if (request.method !== 'GET') {
118
+ return sendJson(response, 405, { error: 'Method not allowed' });
119
+ }
120
+ const configs = await agentConfigService.readAll({ cwd: dependencies.cwd });
121
+ return sendJson(response, 200, configs);
122
+ }
123
+ case '/api/profiles': {
124
+ if (request.method === 'GET') {
125
+ const result = await profileService.list({ cwd: dependencies.cwd });
126
+ return sendJson(response, 200, result);
127
+ }
128
+ if (request.method === 'POST') {
129
+ const body = await readJsonBody(request);
130
+ if (!body.ok) {
131
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
132
+ }
133
+ const data = body.value;
134
+ try {
135
+ const result = await profileService.create({
136
+ cwd: dependencies.cwd,
137
+ name: String(data.name ?? ''),
138
+ description: typeof data.description === 'string' ? data.description : undefined,
139
+ });
140
+ return sendJson(response, 201, result);
141
+ }
142
+ catch (error) {
143
+ return sendProfileError(response, error);
144
+ }
145
+ }
146
+ return sendJson(response, 405, { error: 'Method not allowed' });
147
+ }
148
+ case '/api/profiles/export': {
149
+ if (request.method !== 'POST') {
150
+ return sendJson(response, 405, { error: 'Method not allowed' });
151
+ }
152
+ const body = await readJsonBody(request);
153
+ if (!body.ok) {
154
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
155
+ }
156
+ const data = body.value;
157
+ if (!data.name || data.name.trim().length === 0) {
158
+ return sendJson(response, 400, { error: 'Missing profile name' });
159
+ }
160
+ try {
161
+ const result = await profileExportService.execute({
162
+ cwd: dependencies.cwd,
163
+ name: data.name.trim(),
164
+ outputPath: typeof data.outputPath === 'string' && data.outputPath.trim().length > 0
165
+ ? data.outputPath.trim()
166
+ : undefined,
167
+ });
168
+ return sendJson(response, 200, result);
169
+ }
170
+ catch (error) {
171
+ return sendProfileError(response, error);
172
+ }
173
+ }
174
+ case '/api/profiles/import': {
175
+ if (request.method !== 'POST') {
176
+ return sendJson(response, 405, { error: 'Method not allowed' });
177
+ }
178
+ const body = await readJsonBody(request);
179
+ if (!body.ok) {
180
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
181
+ }
182
+ const data = body.value;
183
+ if (!data.archivePath || data.archivePath.trim().length === 0) {
184
+ return sendJson(response, 400, { error: 'Missing archivePath' });
185
+ }
186
+ try {
187
+ const result = await profileImportService.execute({
188
+ cwd: dependencies.cwd,
189
+ archivePath: data.archivePath.trim(),
190
+ force: data.force === true,
191
+ });
192
+ return sendJson(response, 200, result);
193
+ }
194
+ catch (error) {
195
+ return sendProfileError(response, error);
196
+ }
197
+ }
198
+ case '/api/sync': {
199
+ if (request.method !== 'POST') {
200
+ return sendJson(response, 405, { error: 'Method not allowed' });
201
+ }
202
+ try {
203
+ const result = await syncService.execute({ cwd: dependencies.cwd });
204
+ return sendJson(response, 200, result);
205
+ }
206
+ catch (error) {
207
+ return sendJson(response, 500, {
208
+ error: error instanceof Error ? error.message : 'Sync failed',
209
+ });
210
+ }
211
+ }
212
+ default: {
213
+ // Agent MCP routes: /api/agents/:name/mcps(/:key)
214
+ const agentMcpCheckMatch = url.pathname.match(/^\/api\/agents\/(claude|codex|gemini)\/mcps\/check$/);
215
+ if (agentMcpCheckMatch) {
216
+ const agentName = agentMcpCheckMatch[1];
217
+ if (request.method !== 'POST') {
218
+ return sendJson(response, 405, { error: 'Method not allowed' });
219
+ }
220
+ const body = await readJsonBody(request);
221
+ if (!body.ok) {
222
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
223
+ }
224
+ const data = body.value;
225
+ if (!data.key || !data.entry?.command) {
226
+ return sendJson(response, 400, { error: 'Missing key or entry.command' });
227
+ }
228
+ const result = await mcpPreflightService.execute({
229
+ cwd: dependencies.cwd,
230
+ agent: agentName,
231
+ key: data.key,
232
+ entry: data.entry,
233
+ });
234
+ return sendJson(response, 200, result);
235
+ }
236
+ const agentMcpMatch = url.pathname.match(/^\/api\/agents\/(claude|codex|gemini)\/mcps(?:\/(.+))?$/);
237
+ if (agentMcpMatch) {
238
+ const agentName = agentMcpMatch[1];
239
+ const mcpKey = agentMcpMatch[2] ? decodeURIComponent(agentMcpMatch[2]) : null;
240
+ if (request.method === 'POST' && !mcpKey) {
241
+ const body = await readJsonBody(request);
242
+ if (!body.ok) {
243
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
244
+ }
245
+ const data = body.value;
246
+ if (!data.key || !data.entry?.command) {
247
+ return sendJson(response, 400, { error: 'Missing key or entry.command' });
248
+ }
249
+ try {
250
+ await agentConfigService.addMcp({
251
+ cwd: dependencies.cwd,
252
+ agent: agentName,
253
+ key: data.key,
254
+ entry: data.entry,
255
+ });
256
+ return sendJson(response, 200, { ok: true });
257
+ }
258
+ catch (error) {
259
+ return sendHandledError(response, error, 'Failed to add MCP');
260
+ }
261
+ }
262
+ if (request.method === 'DELETE' && mcpKey) {
263
+ try {
264
+ await agentConfigService.removeMcp({
265
+ cwd: dependencies.cwd,
266
+ agent: agentName,
267
+ key: mcpKey,
268
+ });
269
+ return sendJson(response, 200, { ok: true });
270
+ }
271
+ catch (error) {
272
+ return sendHandledError(response, error, 'Failed to remove MCP');
273
+ }
274
+ }
275
+ return sendJson(response, 405, { error: 'Method not allowed' });
276
+ }
277
+ // Agent skill routes: /api/agents/:name/skills(/:key)
278
+ const agentSkillCheckMatch = url.pathname.match(/^\/api\/agents\/(claude|codex|gemini)\/skills\/check$/);
279
+ if (agentSkillCheckMatch) {
280
+ const agentName = agentSkillCheckMatch[1];
281
+ if (request.method !== 'POST') {
282
+ return sendJson(response, 405, { error: 'Method not allowed' });
283
+ }
284
+ const body = await readJsonBody(request);
285
+ if (!body.ok) {
286
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
287
+ }
288
+ const data = body.value;
289
+ if (!data.name || !data.sourceAgent) {
290
+ return sendJson(response, 400, { error: 'Missing name or sourceAgent' });
291
+ }
292
+ const result = await skillPreflightService.execute({
293
+ sourceAgent: data.sourceAgent,
294
+ targetAgent: agentName,
295
+ skillName: data.name,
296
+ source: typeof data.source === 'string' ? data.source : undefined,
297
+ });
298
+ return sendJson(response, 200, result);
299
+ }
300
+ const agentSkillMatch = url.pathname.match(/^\/api\/agents\/(claude|codex|gemini)\/skills(?:\/(.+))?$/);
301
+ if (agentSkillMatch) {
302
+ const agentName = agentSkillMatch[1];
303
+ const skillKey = agentSkillMatch[2] ? decodeURIComponent(agentSkillMatch[2]) : null;
304
+ if (request.method === 'POST' && !skillKey) {
305
+ const body = await readJsonBody(request);
306
+ if (!body.ok) {
307
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
308
+ }
309
+ const data = body.value;
310
+ if (!data.name || !data.sourceAgent) {
311
+ return sendJson(response, 400, { error: 'Missing name or sourceAgent' });
312
+ }
313
+ try {
314
+ const preflight = await skillPreflightService.execute({
315
+ sourceAgent: data.sourceAgent,
316
+ targetAgent: agentName,
317
+ skillName: data.name,
318
+ source: typeof data.source === 'string' ? data.source : undefined,
319
+ });
320
+ const firstError = preflight.checks.find((check) => check.status === 'error');
321
+ if (firstError) {
322
+ throw new ValidationError(`Skill "${data.name}" cannot be copied from ${data.sourceAgent} to ${agentName}: ${firstError.message}`);
323
+ }
324
+ await agentConfigService.copySkill({
325
+ sourceAgent: data.sourceAgent,
326
+ targetAgent: agentName,
327
+ skillName: data.name,
328
+ });
329
+ return sendJson(response, 200, { ok: true });
330
+ }
331
+ catch (error) {
332
+ return sendHandledError(response, error, 'Failed to copy skill');
333
+ }
334
+ }
335
+ if (request.method === 'DELETE' && skillKey) {
336
+ try {
337
+ await agentConfigService.removeSkill({
338
+ agent: agentName,
339
+ skillName: skillKey,
340
+ });
341
+ return sendJson(response, 200, { ok: true });
342
+ }
343
+ catch (error) {
344
+ return sendHandledError(response, error, 'Failed to remove skill');
345
+ }
346
+ }
347
+ return sendJson(response, 405, { error: 'Method not allowed' });
348
+ }
349
+ const agentPluginCheckMatch = url.pathname.match(/^\/api\/agents\/(claude|codex|gemini)\/plugins\/check$/);
350
+ if (agentPluginCheckMatch) {
351
+ const agentName = agentPluginCheckMatch[1];
352
+ if (request.method !== 'POST') {
353
+ return sendJson(response, 405, { error: 'Method not allowed' });
354
+ }
355
+ const body = await readJsonBody(request);
356
+ if (!body.ok) {
357
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
358
+ }
359
+ const data = body.value;
360
+ if (!data.name || !data.sourceAgent) {
361
+ return sendJson(response, 400, { error: 'Missing name or sourceAgent' });
362
+ }
363
+ const sourcePlugin = await resolveSourcePlugin(agentConfigService, dependencies.cwd, {
364
+ sourceAgent: data.sourceAgent,
365
+ name: data.name,
366
+ });
367
+ if (!sourcePlugin) {
368
+ return sendJson(response, 400, {
369
+ error: `Plugin "${data.name}" was not found in ${data.sourceAgent}.`,
370
+ });
371
+ }
372
+ const result = await pluginInstallService.plan({
373
+ cwd: dependencies.cwd,
374
+ targetAgent: agentName,
375
+ sourceAgent: data.sourceAgent,
376
+ plugin: sourcePlugin,
377
+ });
378
+ return sendJson(response, 200, result);
379
+ }
380
+ const agentPluginMatch = url.pathname.match(/^\/api\/agents\/(claude|codex|gemini)\/plugins(?:\/(.+))?$/);
381
+ if (agentPluginMatch) {
382
+ const agentName = agentPluginMatch[1];
383
+ const pluginName = agentPluginMatch[2] ? decodeURIComponent(agentPluginMatch[2]) : null;
384
+ if (request.method === 'POST' && !pluginName) {
385
+ const body = await readJsonBody(request);
386
+ if (!body.ok) {
387
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
388
+ }
389
+ const data = body.value;
390
+ if (!data.name || !data.sourceAgent) {
391
+ return sendJson(response, 400, { error: 'Missing name or sourceAgent' });
392
+ }
393
+ const sourcePlugin = await resolveSourcePlugin(agentConfigService, dependencies.cwd, {
394
+ sourceAgent: data.sourceAgent,
395
+ name: data.name,
396
+ });
397
+ if (!sourcePlugin) {
398
+ return sendJson(response, 400, {
399
+ error: `Plugin "${data.name}" was not found in ${data.sourceAgent}.`,
400
+ });
401
+ }
402
+ try {
403
+ const result = await pluginInstallService.execute({
404
+ cwd: dependencies.cwd,
405
+ targetAgent: agentName,
406
+ sourceAgent: data.sourceAgent,
407
+ plugin: sourcePlugin,
408
+ });
409
+ return sendJson(response, 200, result);
410
+ }
411
+ catch (error) {
412
+ return sendHandledError(response, error, 'Failed to install plugin');
413
+ }
414
+ }
415
+ if (request.method === 'DELETE' && pluginName) {
416
+ const targetPlugin = await resolveTargetPlugin(agentConfigService, dependencies.cwd, {
417
+ targetAgent: agentName,
418
+ name: pluginName,
419
+ });
420
+ if (!targetPlugin) {
421
+ return sendJson(response, 404, {
422
+ error: `Plugin "${pluginName}" was not found in ${agentName}.`,
423
+ });
424
+ }
425
+ try {
426
+ const result = await pluginInstallService.remove({
427
+ cwd: dependencies.cwd,
428
+ targetAgent: agentName,
429
+ plugin: targetPlugin,
430
+ });
431
+ return sendJson(response, 200, result);
432
+ }
433
+ catch (error) {
434
+ return sendHandledError(response, error, 'Failed to remove plugin');
435
+ }
436
+ }
437
+ return sendJson(response, 405, { error: 'Method not allowed' });
438
+ }
439
+ const profileMatch = url.pathname.match(/^\/api\/profiles\/([^/]+)(\/activate)?$/);
440
+ if (profileMatch) {
441
+ const name = decodeURIComponent(profileMatch[1]);
442
+ const isActivate = profileMatch[2] === '/activate';
443
+ if (isActivate) {
444
+ if (request.method !== 'POST') {
445
+ return sendJson(response, 405, { error: 'Method not allowed' });
446
+ }
447
+ try {
448
+ const result = await profileService.use({ cwd: dependencies.cwd, name });
449
+ return sendJson(response, 200, result);
450
+ }
451
+ catch (error) {
452
+ return sendProfileError(response, error);
453
+ }
454
+ }
455
+ if (request.method === 'GET') {
456
+ try {
457
+ const profile = await profileService.get({ cwd: dependencies.cwd, name });
458
+ return sendJson(response, 200, profile);
459
+ }
460
+ catch (error) {
461
+ return sendProfileError(response, error);
462
+ }
463
+ }
464
+ if (request.method === 'PUT') {
465
+ const body = await readJsonBody(request);
466
+ if (!body.ok) {
467
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
468
+ }
469
+ try {
470
+ await profileService.update({
471
+ cwd: dependencies.cwd,
472
+ name,
473
+ config: body.value,
474
+ });
475
+ return sendJson(response, 200, { ok: true });
476
+ }
477
+ catch (error) {
478
+ return sendProfileError(response, error);
479
+ }
480
+ }
481
+ if (request.method === 'DELETE') {
482
+ try {
483
+ await profileService.delete({ cwd: dependencies.cwd, name });
484
+ return sendJson(response, 200, { ok: true });
485
+ }
486
+ catch (error) {
487
+ return sendProfileError(response, error);
488
+ }
489
+ }
490
+ return sendJson(response, 405, { error: 'Method not allowed' });
491
+ }
100
492
  if (url.pathname === '/api' || url.pathname.startsWith('/api/')) {
101
493
  return sendJson(response, 404, { error: 'Not found' });
102
494
  }
@@ -104,9 +496,28 @@ export function createUiRouteHandler(dependencies) {
104
496
  return sendJson(response, 405, { error: 'Method not allowed' });
105
497
  }
106
498
  return serveUiResponse(url.pathname, response);
499
+ }
107
500
  }
108
501
  };
109
502
  }
503
+ async function resolveSourcePlugin(agentConfigService, cwd, options) {
504
+ const configs = await agentConfigService.readAll({ cwd });
505
+ const sourceConfig = configs.find((config) => config.agent === options.sourceAgent);
506
+ const plugin = sourceConfig?.skills.find((entry) => entry.kind === 'plugin' && entry.name === options.name);
507
+ return plugin ?? null;
508
+ }
509
+ async function resolveTargetPlugin(agentConfigService, cwd, options) {
510
+ const configs = await agentConfigService.readAll({ cwd });
511
+ const targetConfig = configs.find((config) => config.agent === options.targetAgent);
512
+ const plugin = targetConfig?.skills.find((entry) => entry.kind === 'plugin' && entry.name === options.name);
513
+ return plugin ?? null;
514
+ }
515
+ function sendHandledError(response, error, fallbackMessage) {
516
+ const isUserError = error instanceof BrainctlError && error.category === 'user';
517
+ sendJson(response, isUserError ? 400 : 500, {
518
+ error: error instanceof Error ? error.message : fallbackMessage,
519
+ });
520
+ }
110
521
  async function readJsonBody(request) {
111
522
  const chunks = [];
112
523
  for await (const chunk of request) {
@@ -150,6 +561,17 @@ function parseAgentName(value) {
150
561
  }
151
562
  return null;
152
563
  }
564
+ function sendProfileError(response, error) {
565
+ if (error instanceof ProfileNotFoundError) {
566
+ return sendJson(response, 404, { error: error.message });
567
+ }
568
+ if (error instanceof ProfileError) {
569
+ return sendJson(response, 400, { error: error.message });
570
+ }
571
+ return sendJson(response, 500, {
572
+ error: error instanceof Error ? error.message : 'Internal server error',
573
+ });
574
+ }
153
575
  function sendJson(response, statusCode, body) {
154
576
  response.statusCode = statusCode;
155
577
  response.setHeader('Content-Type', 'application/json; charset=utf-8');
@@ -0,0 +1 @@
1
+ @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-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--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-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@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:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-700:oklch(50.8% .118 165.612);--color-rose-50:oklch(96.9% .015 12.422);--color-rose-200:oklch(89.2% .058 10.001);--color-rose-700:oklch(51.4% .222 16.935);--color-zinc-50:oklch(98.5% 0 0);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-zinc-950:oklch(14.1% .005 285.823);--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--font-weight-semibold:600;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--animate-spin:spin 1s linear infinite;--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)}}@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%;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]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.static{position:static}.start{inset-inline-start:var(--spacing)}.mx-auto{margin-inline:auto}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-\[18px\]{width:18px;height:18px}.size-full{width:100%;height:100%}.min-h-10{min-height:calc(var(--spacing) * 10)}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-screen{min-height:100vh}.w-full{width:100%}.max-w-\[1420px\]{max-width:1420px}.min-w-0{min-width:calc(var(--spacing) * 0)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-\[28px\]{border-radius:28px}.rounded-\[32px\]{border-radius:32px}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-emerald-200{border-color:var(--color-emerald-200)}.border-rose-200{border-color:var(--color-rose-200)}.border-zinc-200{border-color:var(--color-zinc-200)}.border-zinc-300{border-color:var(--color-zinc-300)}.border-zinc-900{border-color:var(--color-zinc-900)}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-rose-50{background-color:var(--color-rose-50)}.bg-white{background-color:var(--color-white)}.bg-zinc-50{background-color:var(--color-zinc-50)}.bg-zinc-900{background-color:var(--color-zinc-900)}.bg-zinc-950{background-color:var(--color-zinc-950)}.object-contain{object-fit:contain}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-\[11px\]{font-size:11px}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.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\.03em\]{--tw-tracking:-.03em;letter-spacing:-.03em}.tracking-\[-0\.04em\]{--tw-tracking:-.04em;letter-spacing:-.04em}.tracking-\[0\.16em\]{--tw-tracking:.16em;letter-spacing:.16em}.tracking-\[0\.18em\]{--tw-tracking:.18em;letter-spacing:.18em}.text-emerald-700{color:var(--color-emerald-700)}.text-rose-700{color:var(--color-rose-700)}.text-white{color:var(--color-white)}.text-zinc-500{color:var(--color-zinc-500)}.text-zinc-600{color:var(--color-zinc-600)}.text-zinc-700{color:var(--color-zinc-700)}.text-zinc-800{color:var(--color-zinc-800)}.text-zinc-900{color:var(--color-zinc-900)}.text-zinc-950{color:var(--color-zinc-950)}.uppercase{text-transform:uppercase}.shadow-\[0_18px_50px_rgba\(0\,0\,0\,0\.04\)\]{--tw-shadow:0 18px 50px var(--tw-shadow-color,#0000000a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_20px_60px_rgba\(0\,0\,0\,0\.05\)\]{--tw-shadow:0 20px 60px var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_22px_60px_rgba\(0\,0\,0\,0\.06\)\]{--tw-shadow:0 22px 60px var(--tw-shadow-color,#0000000f);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}@media(hover:hover){.hover\:border-zinc-300:hover{border-color:var(--color-zinc-300)}.hover\:bg-zinc-800:hover{background-color:var(--color-zinc-800)}.hover\:text-zinc-900:hover{color:var(--color-zinc-900)}}.focus\:border-zinc-400:focus{border-color:var(--color-zinc-400)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-zinc-300:disabled{background-color:var(--color-zinc-300)}@media(min-width:40rem){.sm\:p-5{padding:calc(var(--spacing) * 5)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}}@media(min-width:64rem){.lg\:grid-cols-\[minmax\(0\,0\.9fr\)_minmax\(0\,1\.1fr\)\]{grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr)}.lg\:grid-cols-\[minmax\(0\,1\.15fr\)_minmax\(260px\,0\.85fr\)\]{grid-template-columns:minmax(0,1.15fr) minmax(260px,.85fr)}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-between{justify-content:space-between}.lg\:justify-center{justify-content:center}.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}}}:root{color-scheme:light;--background:#fff;--foreground:#171717;--card:#fffffff5;--muted:#6b6b6b;--muted-bg:#fafafa;--accent:#f1f1ef;--border:#e4e4e1;--border-strong:#bcbcb7;--primary:#151515;--primary-foreground:#fff;--destructive:#c94f42;--destructive-bg:#fff0ed;--success:#14855f;--success-bg:#ecfbf4;--radius-lg:1rem;--radius-md:.5rem;--radius-sm:.375rem;background:var(--background);color:var(--foreground);font-family:Avenir Next,Helvetica Neue,Segoe UI,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,sans-serif}*{box-sizing:border-box}html,body,#root{min-height:100%;margin:0}body{min-height:100vh;color:var(--foreground);background:#fff}body,button,input,select,textarea{font:inherit}button{cursor:pointer}button:disabled{cursor:not-allowed}code{font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.875em}#root{min-height:100vh}.app-shell{min-height:100vh;padding:18px 24px 24px}.shell{gap:24px;width:min(1400px,100%);margin:0 auto;display:grid}.shell.shell-compact{width:min(1220px,100%)}.shell.shell-board{gap:10px;width:min(1420px,100%)}.panel,.panel-inner,.metric-card,.config-card,.config-empty-state,.run-summary-tile,.run-empty-state,.empty-state,.agent-row,.memory-file-button,.profile-card,.profile-card-overlay,.pending-change-item{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);box-shadow:0 18px 44px #0000000d}.panel,.nav-card,.workspace-card{padding:24px}.panel-inner,.metric-card,.config-card,.config-empty-state,.run-summary-tile,.run-empty-state,.empty-state,.pending-changes-bar{padding:20px}.topbar{justify-content:space-between;align-items:center;gap:16px;display:flex}.brand-block{align-items:center;gap:12px;min-width:0;display:flex}.brand-mark{border:1px solid var(--border);border-radius:var(--radius-md);width:40px;height:40px;color:var(--foreground);background:linear-gradient(#fff,#f6f6f4);place-items:center;display:grid}.eyebrow{color:var(--muted);letter-spacing:.04em;text-transform:uppercase;margin:0 0 4px;font-size:.75rem;font-weight:600}.brand-block h1,.hero-panel h1,.workspace-header h2,.panel-heading h2,.section-header h3,.empty-state h2,.feature-card h3,.install-step h4{letter-spacing:-.02em;margin:0;font-family:Avenir Next,Helvetica Neue,Segoe UI,ui-sans-serif,system-ui,sans-serif;font-size:1.5rem;font-weight:700;line-height:1.2}.workspace-header h2,.panel-heading h2,.section-header h3{font-size:1.125rem}.status-strip,.workspace-header-meta,.chip-row,.pending-changes-actions{flex-wrap:wrap;gap:8px;display:flex}.status-chip,.muted-pill,.skill-chip,.agent-command{border:1px solid var(--border);border-radius:var(--radius-md);min-height:32px;color:var(--foreground);background:#ffffffe0;align-items:center;gap:6px;padding:0 10px;font-size:.875rem;display:inline-flex}.muted-pill{color:var(--muted)}.panel-heading,.workspace-header,.section-header,.metric-card-header,.agent-row,.agent-row-meta,.config-card-header,.profile-column-header,.pending-changes-header{justify-content:space-between;align-items:flex-start;gap:16px;display:flex}.mission-banner{gap:28px;display:grid;position:relative;overflow:hidden}.mission-banner:before{content:"";pointer-events:none;background:linear-gradient(135deg,#00000009,#0000 40%),radial-gradient(circle at 100% 0,#fff6,#0000 28%),radial-gradient(circle at 12% 88%,#e8e8e447,#0000 28%);position:absolute;inset:0}.mission-layout,.mode-switcher{z-index:1;position:relative}.mission-layout{grid-template-columns:minmax(0,1.35fr) minmax(300px,.85fr);align-items:end;gap:24px;display:grid}.mission-copy-block{gap:14px;display:grid}.mission-copy{max-width:760px;color:var(--muted);margin:0;font-size:1.02rem;line-height:1.8}.signal-board{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;display:grid}.signal-tile{border:1px solid var(--border);border-radius:calc(var(--radius-lg) + 2px);background:#ffffffd1;gap:6px;padding:16px;display:grid}.signal-tile span,.signal-tile small{color:var(--muted)}.signal-tile strong{letter-spacing:-.04em;font-size:1.85rem;line-height:1}.mode-switcher{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;display:grid}.mode-tab{border:1px solid var(--border);border-radius:calc(var(--radius-lg) + 2px);color:var(--foreground);text-align:left;background:#ffffffdb;align-items:flex-start;gap:14px;padding:18px;transition:transform .18s,border-color .18s,background .18s,box-shadow .18s;display:flex}.mode-tab:hover:not(:disabled){border-color:var(--border-strong);background:#fff;transform:translateY(-2px);box-shadow:0 14px 30px #0000000f}.mode-tab.is-active{background:linear-gradient(#fff,#f2f2f0);border-color:#0000002e;box-shadow:inset 0 1px #ffffffb3}.mode-tab:disabled{opacity:.55}.mode-tab-index,.mode-tab-icon,.ribbon-card-icon{flex:none}.mode-tab-index{min-width:2.2rem;color:var(--muted);letter-spacing:.08em;text-transform:uppercase;font-size:.76rem;font-weight:700}.mode-tab-icon,.ribbon-card-icon{border:1px solid var(--border);border-radius:var(--radius-md);width:36px;height:36px;color:var(--primary);background:linear-gradient(#fff,#f6f6f4);place-items:center;display:grid}.mode-tab-copy,.feature-hero-copy,.feature-hero-side,.ribbon-card,.ribbon-card div{gap:4px;display:grid}.mode-tab-copy{min-width:0}.mode-tab-copy strong{font-size:1.02rem}.mode-tab-copy span{color:var(--muted);font-size:.84rem}.mode-tab-kicker{letter-spacing:.08em;text-transform:uppercase;font-size:.72rem;font-weight:700}.panel-heading{margin-bottom:16px}.workspace-card{gap:24px;min-width:0;display:grid}.board-surface{padding-top:14px}.product-topbar{justify-content:space-between;align-items:center;gap:14px;padding:2px 2px 4px;display:flex}.product-topbar-copy{gap:2px;display:grid}.product-topbar-copy h1{letter-spacing:-.03em;margin:0;font-size:1.15rem}.product-agent-rail{flex-wrap:wrap;flex:1;justify-content:center;gap:8px;display:flex}.product-agent-chip{border:1px solid var(--border);min-height:34px;color:var(--foreground);background:#ffffffc7;border-radius:999px;align-items:center;gap:8px;padding:0 12px;font-size:.82rem;font-weight:600;display:inline-flex}.product-agent-logo{width:18px;height:18px;color:var(--foreground);place-items:center;display:grid;overflow:hidden}.product-agent-logo svg,.product-agent-logo img,.profile-agent-logo,.profile-agent-logo svg,.profile-agent-logo img,img.profile-agent-logo{object-fit:contain;width:100%;height:100%;display:block}.product-topbar-actions{flex-wrap:wrap;justify-content:flex-end;gap:10px;display:flex}.product-action-button{background:#fff;min-height:38px;padding-inline:12px}.product-action-badge{border:1px solid var(--border);background:var(--accent);min-height:20px;color:var(--muted);letter-spacing:.05em;text-transform:uppercase;border-radius:999px;align-items:center;padding:0 8px;font-size:.68rem;font-weight:700;display:inline-flex}.stage-shell{overflow:hidden}.section-nav,.view-stack,.config-panel,.config-list,.run-form,.agent-list,.memory-file-list,.profile-columns,.profile-column,.pending-changes-list{gap:16px;display:grid}.feature-stage,.package-stage{gap:18px;display:grid}.feature-hero,.scope-card,.install-step{border:1px solid var(--border);border-radius:var(--radius-lg);background:#ffffffe0}.feature-hero,.scope-card{padding:22px}.feature-hero{grid-template-columns:minmax(0,1.2fr) minmax(260px,.8fr);align-items:start;gap:18px;display:grid}.feature-hero-copy h2{letter-spacing:-.04em;margin:0;font-size:2rem;line-height:1.05}.feature-hero-copy p:last-child{color:var(--muted);margin:0;font-size:.92rem;line-height:1.5}.feature-hero-side{align-content:start}.stage-fact{border-bottom:1px solid #00000014;justify-content:space-between;align-items:baseline;gap:12px;padding:12px 0;display:flex}.stage-fact:last-child{border-bottom:0}.stage-fact span{color:var(--muted);text-transform:uppercase;letter-spacing:.06em;font-size:.82rem}.stage-fact strong{letter-spacing:-.02em;font-size:1rem}.feature-ribbon,.install-step-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;display:grid}.flow-lane{grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;display:grid}.flow-node{border:1px solid var(--border);border-radius:var(--radius-lg);background:#ffffffeb;gap:8px;padding:16px;display:grid;position:relative}.flow-node strong{font-size:.95rem;line-height:1.2}.flow-node span:last-child{color:var(--muted);font-size:.78rem;line-height:1.35}.flow-node-icon{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--muted-bg);place-items:center;width:32px;height:32px;display:grid}.pack-flow-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;margin-top:18px;display:grid}.ribbon-card{border:1px solid var(--border);border-radius:var(--radius-lg);background:#ffffffe0;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:14px;padding:16px 18px}.ribbon-card strong{font-size:.98rem}.ribbon-card p{color:var(--muted);margin:0;line-height:1.6}.flow-step-card{border:1px solid var(--border);border-radius:var(--radius-lg);background:#ffffffeb;gap:10px;padding:18px;display:grid}.flow-step-badge{background:var(--accent);min-height:24px;color:var(--muted);letter-spacing:.06em;border-radius:999px;justify-content:center;justify-self:start;align-items:center;padding:0 8px;font-size:.72rem;font-weight:700;display:inline-flex}.flow-step-card h4{margin:0;font-size:1rem;line-height:1.35}.flow-step-card p{color:var(--muted);margin:0;line-height:1.35}.install-outline{gap:18px;display:grid}.install-step-grid{grid-template-columns:repeat(3,minmax(0,1fr))}.install-step{grid-template-columns:auto minmax(0,1fr);align-items:start;gap:14px;padding:18px;display:grid}.install-step-number{width:32px;height:32px;color:var(--primary-foreground);background:linear-gradient(#2f2f2f,#151515);border-radius:999px;place-items:center;font-size:.8rem;font-weight:700;display:grid}.install-step h4{margin-bottom:6px;font-size:1rem}.install-step p{color:var(--muted);margin:0;line-height:1.55}.section-button{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--card);width:100%;color:var(--foreground);text-align:left;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:12px;padding:12px 14px;display:grid}.section-button:hover:not(:disabled){background:var(--muted-bg);border-color:var(--border-strong)}.section-button.is-active{background:var(--accent);border-color:var(--border-strong)}.section-button:disabled{opacity:.6}.section-button-icon,.metric-card-icon,.run-summary-tile-icon,.empty-state-icon{border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--muted-bg);width:32px;height:32px;color:var(--foreground);flex:none;place-items:center;display:grid}.section-button-label{gap:2px;min-width:0;display:grid}.section-button-label span:first-child{font-weight:600}.section-button-subtitle,.section-button-chevron,.metric-card-label,.field-help,.run-summary-tile-label,.metric-card-note{color:var(--muted)}.muted-copy{color:var(--muted);word-break:break-word;margin:8px 0 0;line-height:1.5}.metrics-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;display:grid}.metric-card{gap:12px;min-width:0;display:grid}.metric-card.is-wide{grid-column:1/-1}.metric-card-header{justify-content:flex-start;align-items:center}.metric-card-value{word-break:break-word;font-size:1rem;font-weight:600;line-height:1.5;display:block}.metric-card-note{margin:0;line-height:1.5}.skill-chip{min-height:28px}.agent-list,.memory-file-list{gap:12px}.agent-row{align-items:center;padding:14px 16px}.agent-row-meta{justify-content:flex-start;align-items:center;min-width:0}.agent-row-meta strong{text-transform:capitalize;display:block}.agent-row-meta p{color:var(--muted);margin:4px 0 0}.agent-status-dot{background:var(--border-strong);border-radius:999px;flex:none;width:10px;height:10px}.agent-status-dot.is-online{background:var(--success)}.agent-status-dot.is-offline{background:#94a3b8}.memory-layout,.run-detail-grid{gap:16px;min-width:0;display:grid}.memory-layout{grid-template-columns:280px minmax(0,1fr)}.memory-list,.memory-preview,.run-output-panel,.run-summary-panel{min-width:0}.memory-preview,.run-panel,.config-panel{gap:16px;display:grid}.memory-file-button{text-align:left;gap:4px;padding:14px 16px;display:grid}.memory-file-button:hover{background:var(--muted-bg);border-color:var(--border-strong)}.memory-file-button.is-selected{background:var(--accent);border-color:var(--border-strong)}.memory-file-button strong,.memory-file-button span{text-overflow:ellipsis;min-width:0;overflow:hidden}.memory-file-button span{color:var(--muted);font-size:.8125rem}.field{gap:8px;display:grid}.field-label{font-size:.875rem;font-weight:600}.field-control,.memory-editor,.run-output{border:1px solid var(--border);border-radius:var(--radius-md);width:100%;min-width:0;color:var(--foreground);background:#fffffff5;padding:10px 12px}.field-control:focus,.memory-editor:focus,.run-output:focus{outline-offset:2px;border-color:var(--border-strong);outline:2px solid #0000001a}.field-control:disabled{opacity:.7}.field-help{margin:0;font-size:.8125rem;line-height:1.5}.memory-editor,.run-output,.editor-textarea,.editor-code,.agent-config-path{font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Monaco,Consolas,Liberation Mono,monospace}.memory-editor{resize:vertical;min-height:420px;line-height:1.6}.config-toolbar,.run-actions{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;display:flex}.config-field-grid,.run-agent-grid,.run-summary-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;display:grid}.secondary-button,.danger-button,.run-button{border-radius:var(--radius-md);border:1px solid var(--border);justify-content:center;align-items:center;gap:8px;min-height:40px;padding:0 14px;font-weight:500;display:inline-flex}.secondary-button{color:var(--foreground);background:#fffffff0}.secondary-button:hover:not(:disabled){background:#fff}.run-button{color:var(--primary-foreground);background:linear-gradient(#2f2f2f,#151515);border-color:#232323}.run-button:hover:not(:disabled){opacity:.92}.danger-button{background:var(--destructive-bg);color:#b91c1c;border-color:#fecaca}.danger-button:hover:not(:disabled){background:#fee2e2}.secondary-button:disabled,.danger-button:disabled,.run-button:disabled{opacity:.55}.config-card{gap:16px}.config-card-header h4,.config-empty-state strong{margin:0;font-size:1rem;font-weight:600;line-height:1.4}.config-empty-state p{color:var(--muted);margin:8px 0 0;line-height:1.5}.editor-textarea{resize:vertical;min-height:180px;line-height:1.6}.save-feedback{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--muted-bg);align-items:center;gap:8px;padding:12px 14px;display:inline-flex}.save-feedback.saved{background:var(--success-bg);border-color:#bbf7d0}.save-feedback.error,.save-feedback.is-error{background:var(--destructive-bg);color:#b91c1c;border-color:#fecaca}.run-view,.config-view{gap:16px}.run-state{white-space:nowrap}.status-chip.run-state.running{background:var(--accent)}.status-chip.run-state.success{background:var(--success-bg);border-color:#bbf7d0}.status-chip.run-state.error{background:var(--destructive-bg);border-color:#fecaca}.run-button-spinner,.run-state-spinner,.spinner{animation:1s linear infinite spin}.run-detail-grid{grid-template-columns:minmax(0,1.3fr) minmax(300px,.9fr);align-items:start}.run-output{resize:vertical;min-height:360px;line-height:1.6}.run-summary-tile{gap:8px;display:grid}.run-summary-tile-value{word-break:break-word;font-size:.9375rem;line-height:1.5}.run-empty-state{grid-template-columns:auto minmax(0,1fr);align-items:start;gap:12px;min-height:220px;display:grid}.run-empty-state.is-error{background:var(--destructive-bg);border-color:#fecaca}.run-empty-state strong{margin-bottom:6px;display:block}.run-empty-state p,.empty-state p{color:var(--muted);margin:0;line-height:1.6}.empty-state{align-content:start;gap:12px;min-height:240px;display:grid}.profile-columns{grid-template-columns:repeat(3,minmax(0,1fr));align-items:start;gap:14px}.profile-column{border:1px solid var(--border);border-radius:calc(var(--radius-lg) + 2px);background:linear-gradient(#fffffffa,#f8f8f6f5);align-content:start;box-shadow:0 20px 34px #00000009}.profile-column-title{align-items:center;gap:12px;display:flex}.profile-agent-mark{border:1px solid var(--border);background:linear-gradient(#fff,#f2f2ef);border-radius:12px;place-items:center;width:38px;height:38px;font-size:.9rem;font-weight:700;display:grid}.profile-column-claude .profile-agent-mark{background:linear-gradient(#fff,#f5f1ed)}.profile-column-codex .profile-agent-mark{background:linear-gradient(#fff,#f1f3f6)}.profile-column-gemini .profile-agent-mark{background:linear-gradient(#fff,#f5f5f2)}.profile-agent-stats{flex-wrap:wrap;gap:6px;display:flex}.profile-agent-logo{width:20px;height:20px;overflow:hidden}.profile-stat-chip,.profile-stage-pill,.profile-count-pill{border:1px solid var(--border);min-height:26px;color:var(--muted);background:#ffffffeb;border-radius:999px;align-items:center;gap:6px;padding:0 9px;font-size:.72rem;font-weight:600;display:inline-flex}.profile-active-badge{background:var(--primary);border-color:var(--primary);color:var(--primary-foreground)}.profile-stage-header{border-bottom:1px solid #0000000f;justify-content:space-between;align-items:center;gap:16px;padding-bottom:2px;display:flex}.profile-stage-copy{gap:3px;display:grid}.profile-stage-copy h3{font-size:1rem}.profile-stage-copy .muted-copy{margin-top:0;font-size:.82rem}.profile-stage-toolbar{flex-wrap:wrap;justify-content:flex-end;gap:6px;display:flex}.profile-drop-zone{border:1px solid var(--border);border-radius:calc(var(--radius-md) + 2px);background:linear-gradient(#ffffffeb,#f7f7f4eb);gap:6px;min-height:88px;padding:10px;display:grid;box-shadow:inset 0 1px #fffc}.profile-drop-zone.is-over{border-color:var(--primary);background:linear-gradient(#fff,#efefec);transform:translateY(-1px)}.profile-drop-zone-header{justify-content:space-between;align-items:center;gap:12px;display:flex}.profile-drop-zone-title{align-items:center;gap:8px;display:flex}.profile-drop-zone-title .eyebrow{margin-bottom:0}.profile-drop-zone-icon,.profile-card-kind{border:1px solid var(--border);width:24px;height:24px;color:var(--foreground);background:#fff;border-radius:8px;flex:none;place-items:center;display:grid}.profile-count-pill{min-width:32px;color:var(--foreground);justify-content:center}.profile-card,.profile-card-overlay{padding:10px}.profile-card{touch-action:none;border:1px solid var(--border);background:#fff;border-radius:14px;transition:border-color .16s,background .16s,box-shadow .16s,transform .16s}.profile-card.is-editable{cursor:grab}.profile-card.is-editable:hover{border-color:var(--border-strong);box-shadow:0 8px 20px #0000000d}.profile-card.is-editable:active{cursor:grabbing}.profile-card.is-dragging{opacity:.45}.profile-card-overlay{box-shadow:0 10px 30px #0f172a1f}.profile-card-row{align-items:flex-start;gap:7px;display:flex}.profile-card-content{gap:1px;min-width:0;display:grid}.profile-card-content strong{font-size:.84rem;font-weight:650}.profile-card-content .muted-copy{text-overflow:ellipsis;white-space:nowrap;max-width:100%;margin-top:0;font-size:.71rem;overflow:hidden}.profile-card-remove,.profile-card-toggle,.pending-change-undo{color:var(--muted);border-radius:var(--radius-sm);background:0 0;border:0;flex-shrink:0;place-items:center;padding:4px;display:grid}.profile-card-remove:hover,.profile-card-toggle:hover,.pending-change-undo:hover{background:var(--accent);color:var(--foreground)}.profile-card-details{padding-bottom:.1rem;padding-left:1.95rem}.profile-card-details .muted-copy{text-overflow:clip;white-space:normal;max-width:none;line-height:1.45;overflow:visible}.profile-card.is-pending-add{background:var(--success-bg);border-color:#bbf7d0}.profile-card.is-pending-remove{background:var(--destructive-bg);opacity:.75;border-color:#fecaca;text-decoration:line-through}.pending-badge{border-radius:var(--radius-sm);min-height:20px;color:var(--muted);background:#f1f1efeb;flex-shrink:0;justify-content:center;align-items:center;padding:0 6px;font-size:.6875rem;font-weight:700;line-height:1;display:inline-flex}.pending-badge.is-add{background:var(--success-bg);color:var(--success)}.pending-badge.is-remove{background:var(--destructive-bg);color:#b91c1c}.pending-changes-bar{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);z-index:12;gap:12px;display:grid;position:sticky;top:12px;box-shadow:0 16px 34px #0000000f}.profile-edit-button.is-active{background:var(--primary);border-color:var(--primary);color:var(--primary-foreground)}.pending-change-item{align-items:center;gap:8px;padding:10px 12px;font-size:.875rem;display:flex}.pending-change-item.is-add{background:var(--success-bg);border-color:#bbf7d0}.pending-change-item.is-remove{background:var(--destructive-bg);border-color:#fecaca}.pending-change-icon{flex-shrink:0;place-items:center;display:grid}.pending-change-item.is-add .pending-change-icon{color:var(--success)}.pending-change-item.is-remove .pending-change-icon{color:#b91c1c}.pending-change-text{flex:1;min-width:0}.pending-change-text strong{font-weight:600}.profile-loading{color:var(--muted);align-items:center;gap:10px;padding:12px 0;display:flex}@keyframes spin{to{transform:rotate(360deg)}}@media(max-width:1100px){.mission-layout,.mode-switcher,.signal-board,.feature-hero,.feature-ribbon,.flow-lane,.pack-flow-grid,.metrics-grid,.memory-layout,.run-detail-grid,.profile-columns,.config-field-grid,.run-agent-grid,.run-summary-grid,.install-step-grid{grid-template-columns:1fr}.profile-stage-header{flex-direction:column;align-items:stretch}.profile-stage-toolbar{justify-content:flex-start}}@media(max-width:720px){.app-shell{padding:14px}.panel,.nav-card,.workspace-card,.panel-inner,.metric-card,.config-card,.config-empty-state,.run-summary-tile,.run-empty-state,.empty-state,.pending-changes-bar{padding:16px}.topbar,.product-topbar,.mission-layout,.workspace-header,.config-toolbar,.config-card-header,.run-actions,.pending-changes-header{flex-direction:column;align-items:stretch}.secondary-button,.danger-button,.run-button,.product-action-button{width:100%}.memory-editor,.run-output{min-height:280px}.product-agent-rail{justify-content:flex-start}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@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-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}