brainctl 0.1.22 → 0.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ui/routes.js CHANGED
@@ -11,9 +11,20 @@ import { createSkillPreflightService } from '../services/plugin/skill-preflight-
11
11
  import { createStatusService } from '../services/platform/status-service.js';
12
12
  import { createProfileApplyService, } from '../services/profile/profile-apply-service.js';
13
13
  import { createProfileSnapshotService, defaultBackupProfileName, } from '../services/profile/profile-snapshot-service.js';
14
+ import { createRecentProjectsService } from '../services/platform/recent-projects-service.js';
14
15
  import path from 'node:path';
16
+ import os from 'node:os';
15
17
  import { fileURLToPath } from 'node:url';
16
18
  import { spawn } from 'node:child_process';
19
+ function resolveCwd(req, fallback) {
20
+ const url = new URL(req.url ?? '/', 'http://localhost');
21
+ const raw = url.searchParams.get('cwd');
22
+ if (!raw)
23
+ return fallback;
24
+ if (!path.isAbsolute(raw))
25
+ return fallback;
26
+ return raw;
27
+ }
17
28
  const uiAssetRoot = resolveUiAssetRoot();
18
29
  export function createUiRouteHandler(dependencies) {
19
30
  const statusService = dependencies.statusService ?? createStatusService();
@@ -26,6 +37,19 @@ export function createUiRouteHandler(dependencies) {
26
37
  const mcpPreflightService = createMcpPreflightService();
27
38
  const pluginInstallService = createPluginInstallService();
28
39
  const skillPreflightService = createSkillPreflightService();
40
+ const recentsFilePath = dependencies.recentsFilePath ?? path.join(os.homedir(), '.brainctl', 'recents.json');
41
+ const claudeJsonPath = dependencies.claudeJsonPath ?? path.join(os.homedir(), '.claude.json');
42
+ const recentProjectsService = createRecentProjectsService({ filePath: recentsFilePath });
43
+ async function readClaudeProjectPaths() {
44
+ try {
45
+ const raw = await readFile(claudeJsonPath, 'utf8');
46
+ const data = JSON.parse(raw);
47
+ return Object.keys(data.projects ?? {}).sort();
48
+ }
49
+ catch {
50
+ return [];
51
+ }
52
+ }
29
53
  return async (request, response) => {
30
54
  const url = new URL(request.url ?? '/', 'http://localhost');
31
55
  switch (url.pathname) {
@@ -47,7 +71,7 @@ export function createUiRouteHandler(dependencies) {
47
71
  if (request.method !== 'GET') {
48
72
  return sendJson(response, 405, { error: 'Method not allowed' });
49
73
  }
50
- const configs = await agentConfigService.readAll({ cwd: dependencies.cwd });
74
+ const configs = await agentConfigService.readAll({ cwd: resolveCwd(request, dependencies.cwd) });
51
75
  return sendJson(response, 200, configs);
52
76
  }
53
77
  case '/api/open-folder': {
@@ -167,6 +191,36 @@ export function createUiRouteHandler(dependencies) {
167
191
  return sendProfileError(response, error);
168
192
  }
169
193
  }
194
+ case '/api/projects': {
195
+ if (request.method !== 'GET') {
196
+ return sendJson(response, 405, { error: 'Method not allowed' });
197
+ }
198
+ const [claudeProjects, recents] = await Promise.all([
199
+ readClaudeProjectPaths(),
200
+ recentProjectsService.read(),
201
+ ]);
202
+ return sendJson(response, 200, {
203
+ current: dependencies.cwd,
204
+ claudeProjects,
205
+ recents,
206
+ });
207
+ }
208
+ case '/api/projects/recent': {
209
+ if (request.method !== 'POST') {
210
+ return sendJson(response, 405, { error: 'Method not allowed' });
211
+ }
212
+ const body = await readJsonBody(request);
213
+ if (!body.ok) {
214
+ return sendJson(response, 400, { error: 'Invalid JSON body' });
215
+ }
216
+ const value = body.value;
217
+ const cwd = typeof value?.cwd === 'string' ? value.cwd : '';
218
+ if (!path.isAbsolute(cwd)) {
219
+ return sendJson(response, 400, { error: 'cwd must be an absolute path' });
220
+ }
221
+ const recents = await recentProjectsService.addRecent(cwd);
222
+ return sendJson(response, 200, { recents });
223
+ }
170
224
  case '/api/profiles/snapshot': {
171
225
  if (request.method !== 'POST') {
172
226
  return sendJson(response, 405, { error: 'Method not allowed' });
@@ -261,7 +315,7 @@ export function createUiRouteHandler(dependencies) {
261
315
  return sendJson(response, 400, { error: 'Missing key and MCP payload' });
262
316
  }
263
317
  const result = await mcpPreflightService.execute({
264
- cwd: dependencies.cwd,
318
+ cwd: resolveCwd(request, dependencies.cwd),
265
319
  agent: agentName,
266
320
  key: data.key,
267
321
  entry: data.entry,
@@ -284,11 +338,12 @@ export function createUiRouteHandler(dependencies) {
284
338
  }
285
339
  try {
286
340
  await agentConfigService.addMcp({
287
- cwd: dependencies.cwd,
341
+ cwd: resolveCwd(request, dependencies.cwd),
288
342
  agent: agentName,
289
343
  key: data.key,
290
344
  entry: data.entry,
291
345
  remoteEntry: data.remoteEntry,
346
+ scope: data.scope === 'project' ? 'project' : 'global',
292
347
  });
293
348
  return sendJson(response, 200, { ok: true });
294
349
  }
@@ -297,11 +352,13 @@ export function createUiRouteHandler(dependencies) {
297
352
  }
298
353
  }
299
354
  if (request.method === 'DELETE' && mcpKey) {
355
+ const scope = url.searchParams.get('scope') === 'project' ? 'project' : 'global';
300
356
  try {
301
357
  await agentConfigService.removeMcp({
302
- cwd: dependencies.cwd,
358
+ cwd: resolveCwd(request, dependencies.cwd),
303
359
  agent: agentName,
304
360
  key: mcpKey,
361
+ scope,
305
362
  });
306
363
  return sendJson(response, 200, { ok: true });
307
364
  }
@@ -397,7 +454,7 @@ export function createUiRouteHandler(dependencies) {
397
454
  if (!data.name || !data.sourceAgent) {
398
455
  return sendJson(response, 400, { error: 'Missing name or sourceAgent' });
399
456
  }
400
- const sourcePlugin = await resolveSourcePlugin(agentConfigService, dependencies.cwd, {
457
+ const sourcePlugin = await resolveSourcePlugin(agentConfigService, resolveCwd(request, dependencies.cwd), {
401
458
  sourceAgent: data.sourceAgent,
402
459
  name: data.name,
403
460
  });
@@ -407,7 +464,7 @@ export function createUiRouteHandler(dependencies) {
407
464
  });
408
465
  }
409
466
  const result = await pluginInstallService.plan({
410
- cwd: dependencies.cwd,
467
+ cwd: resolveCwd(request, dependencies.cwd),
411
468
  targetAgent: agentName,
412
469
  sourceAgent: data.sourceAgent,
413
470
  plugin: sourcePlugin,
@@ -427,7 +484,7 @@ export function createUiRouteHandler(dependencies) {
427
484
  if (!data.name || !data.sourceAgent) {
428
485
  return sendJson(response, 400, { error: 'Missing name or sourceAgent' });
429
486
  }
430
- const sourcePlugin = await resolveSourcePlugin(agentConfigService, dependencies.cwd, {
487
+ const sourcePlugin = await resolveSourcePlugin(agentConfigService, resolveCwd(request, dependencies.cwd), {
431
488
  sourceAgent: data.sourceAgent,
432
489
  name: data.name,
433
490
  });
@@ -438,7 +495,7 @@ export function createUiRouteHandler(dependencies) {
438
495
  }
439
496
  try {
440
497
  const result = await pluginInstallService.execute({
441
- cwd: dependencies.cwd,
498
+ cwd: resolveCwd(request, dependencies.cwd),
442
499
  targetAgent: agentName,
443
500
  sourceAgent: data.sourceAgent,
444
501
  plugin: sourcePlugin,
@@ -450,7 +507,7 @@ export function createUiRouteHandler(dependencies) {
450
507
  }
451
508
  }
452
509
  if (request.method === 'DELETE' && pluginName) {
453
- const targetPlugin = await resolveTargetPlugin(agentConfigService, dependencies.cwd, {
510
+ const targetPlugin = await resolveTargetPlugin(agentConfigService, resolveCwd(request, dependencies.cwd), {
454
511
  targetAgent: agentName,
455
512
  name: pluginName,
456
513
  });
@@ -461,7 +518,7 @@ export function createUiRouteHandler(dependencies) {
461
518
  }
462
519
  try {
463
520
  const result = await pluginInstallService.remove({
464
- cwd: dependencies.cwd,
521
+ cwd: resolveCwd(request, dependencies.cwd),
465
522
  targetAgent: agentName,
466
523
  plugin: targetPlugin,
467
524
  });
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */
2
+ @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-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--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;--tw-duration: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-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-900:oklch(39.6% .141 25.723);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-700:oklch(55.5% .163 48.998);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-700:oklch(50.8% .118 165.612);--color-sky-200:oklch(90.1% .058 230.902);--color-sky-700:oklch(50% .134 242.749);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-700:oklch(45.7% .24 277.023);--color-violet-200:oklch(89.4% .057 293.283);--color-violet-700:oklch(49.1% .27 292.581);--color-rose-50:oklch(96.9% .015 12.422);--color-rose-100:oklch(94.1% .03 12.58);--color-rose-200:oklch(89.2% .058 10.001);--color-rose-700:oklch(51.4% .222 16.935);--color-rose-800:oklch(45.5% .188 13.697);--color-zinc-50:oklch(98.5% 0 0);--color-zinc-100:oklch(96.7% .001 286.375);--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-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--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-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--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;-webkit-text-decoration:inherit;-webkit-text-decoration: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{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-1\/2{top:50%}.top-6{top:calc(var(--spacing) * 6)}.top-full{top:100%}.right-2{right:calc(var(--spacing) * 2)}.bottom-full{bottom:100%}.left-1\/2{left:50%}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.z-\[60\]{z-index:60}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.-m-4{margin:calc(var(--spacing) * -4)}.m-0{margin:calc(var(--spacing) * 0)}.m-3{margin:calc(var(--spacing) * 3)}.mx-auto{margin-inline:auto}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.-ml-4{margin-left:calc(var(--spacing) * -4)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.size-full{width:100%;height:100%}.h-0{height:calc(var(--spacing) * 0)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.max-h-64{max-height:calc(var(--spacing) * 64)}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-\[36px\]{min-height:36px}.min-h-\[120px\]{min-height:120px}.min-h-screen{min-height:100vh}.w-56{width:calc(var(--spacing) * 56)}.w-96{width:calc(var(--spacing) * 96)}.w-full{width:100%}.max-w-md{max-width:var(--container-md)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[28px\]{min-width:28px}.flex-1{flex:1}.flex-none{flex:none}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-2{rotate:2deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-\[ping_400ms_ease-out_1\]{animation:.4s ease-out ping}.animate-spin{animation:var(--animate-spin)}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}: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-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-amber-200{border-color:var(--color-amber-200)}.border-emerald-200{border-color:var(--color-emerald-200)}.border-emerald-300{border-color:var(--color-emerald-300)}.border-indigo-200{border-color:var(--color-indigo-200)}.border-red-200{border-color:var(--color-red-200)}.border-rose-200{border-color:var(--color-rose-200)}.border-sky-200{border-color:var(--color-sky-200)}.border-transparent{border-color:#0000}.border-violet-200{border-color:var(--color-violet-200)}.border-zinc-100{border-color:var(--color-zinc-100)}.border-zinc-200{border-color:var(--color-zinc-200)}.border-zinc-200\/60{border-color:#e4e4e799}@supports (color:color-mix(in lab, red, red)){.border-zinc-200\/60{border-color:color-mix(in oklab, var(--color-zinc-200) 60%, transparent)}}.border-zinc-200\/80{border-color:#e4e4e7cc}@supports (color:color-mix(in lab, red, red)){.border-zinc-200\/80{border-color:color-mix(in oklab, var(--color-zinc-200) 80%, transparent)}}.border-zinc-300{border-color:var(--color-zinc-300)}.bg-\[\#fcfcfc\]{background-color:#fcfcfc}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-200{background-color:var(--color-amber-200)}.bg-black\/30{background-color:#0000004d}@supports (color:color-mix(in lab, red, red)){.bg-black\/30{background-color:color-mix(in oklab, var(--color-black) 30%, transparent)}}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-emerald-50\/40{background-color:#ecfdf566}@supports (color:color-mix(in lab, red, red)){.bg-emerald-50\/40{background-color:color-mix(in oklab, var(--color-emerald-50) 40%, transparent)}}.bg-emerald-50\/50{background-color:#ecfdf580}@supports (color:color-mix(in lab, red, red)){.bg-emerald-50\/50{background-color:color-mix(in oklab, var(--color-emerald-50) 50%, transparent)}}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-600{background-color:var(--color-red-600)}.bg-rose-50{background-color:var(--color-rose-50)}.bg-rose-50\/40{background-color:#fff1f266}@supports (color:color-mix(in lab, red, red)){.bg-rose-50\/40{background-color:color-mix(in oklab, var(--color-rose-50) 40%, transparent)}}.bg-rose-100{background-color:var(--color-rose-100)}.bg-white{background-color:var(--color-white)}.bg-zinc-50{background-color:var(--color-zinc-50)}.bg-zinc-50\/50{background-color:#fafafa80}@supports (color:color-mix(in lab, red, red)){.bg-zinc-50\/50{background-color:color-mix(in oklab, var(--color-zinc-50) 50%, transparent)}}.bg-zinc-50\/60{background-color:#fafafa99}@supports (color:color-mix(in lab, red, red)){.bg-zinc-50\/60{background-color:color-mix(in oklab, var(--color-zinc-50) 60%, transparent)}}.bg-zinc-100{background-color:var(--color-zinc-100)}.bg-zinc-200{background-color:var(--color-zinc-200)}.bg-zinc-900{background-color:var(--color-zinc-900)}.object-contain{object-fit:contain}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:calc(var(--spacing) * 1)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-10{padding-block:calc(var(--spacing) * 10)}.pt-0{padding-top:calc(var(--spacing) * 0)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-0{padding-bottom:calc(var(--spacing) * 0)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.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-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.text-amber-700{color:var(--color-amber-700)}.text-emerald-700{color:var(--color-emerald-700)}.text-indigo-700{color:var(--color-indigo-700)}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-red-900{color:var(--color-red-900)}.text-rose-700{color:var(--color-rose-700)}.text-rose-800{color:var(--color-rose-800)}.text-sky-700{color:var(--color-sky-700)}.text-violet-700{color:var(--color-violet-700)}.text-white{color:var(--color-white)}.text-zinc-400{color:var(--color-zinc-400)}.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)}.uppercase{text-transform:uppercase}.line-through{text-decoration-line:line-through}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_12px_rgba\(16\,185\,129\,0\.15\)\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#10b98126);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 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-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-4{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-amber-400{--tw-ring-color:var(--color-amber-400)}.ring-emerald-200{--tw-ring-color:var(--color-emerald-200)}.ring-emerald-400\/20{--tw-ring-color:#00d29433}@supports (color:color-mix(in lab, red, red)){.ring-emerald-400\/20{--tw-ring-color:color-mix(in oklab, var(--color-emerald-400) 20%, transparent)}}.ring-rose-200{--tw-ring-color:var(--color-rose-200)}.ring-zinc-200\/50{--tw-ring-color:#e4e4e780}@supports (color:color-mix(in lab, red, red)){.ring-zinc-200\/50{--tw-ring-color:color-mix(in oklab, var(--color-zinc-200) 50%, transparent)}}.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))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.group-hover\:text-zinc-900:is(:where(.group):hover *){color:var(--color-zinc-900)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:border-zinc-200:hover{border-color:var(--color-zinc-200)}.hover\:border-zinc-300:hover{border-color:var(--color-zinc-300)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:bg-rose-100:hover{background-color:var(--color-rose-100)}.hover\:bg-white:hover{background-color:var(--color-white)}.hover\:bg-zinc-50:hover{background-color:var(--color-zinc-50)}.hover\:bg-zinc-100:hover{background-color:var(--color-zinc-100)}.hover\:bg-zinc-800:hover{background-color:var(--color-zinc-800)}.hover\:text-red-600:hover{color:var(--color-red-600)}.hover\:text-rose-700:hover{color:var(--color-rose-700)}.hover\:text-zinc-700:hover{color:var(--color-zinc-700)}.hover\:text-zinc-900:hover{color:var(--color-zinc-900)}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-sm:hover{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.focus\:border-zinc-400:focus{border-color:var(--color-zinc-400)}.focus\:border-zinc-500:focus{border-color:var(--color-zinc-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.data-\[highlighted\]\:bg-zinc-100[data-highlighted]{background-color:var(--color-zinc-100)}@media (width>=40rem){.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}}@media (width>=64rem){.lg\:flex{display:flex}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:items-end{align-items:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:border-t-0{border-top-style:var(--tw-border-style);border-top-width:0}.lg\:border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.lg\:px-6{padding-inline:calc(var(--spacing) * 6)}.lg\:py-0{padding-block:calc(var(--spacing) * 0)}}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--background:#fff;--foreground:#09090b}html,body,#root{background-color:var(--background);min-height:100vh;color:var(--foreground);margin:0;padding:0}body,button,input,select,textarea{letter-spacing:-.01em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Avenir Next,Helvetica Neue,Segoe UI,SF Pro Text,Arial,sans-serif}code{font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Monaco,Consolas,Liberation Mono,monospace}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@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}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}