brainctl 0.1.17 → 0.1.18

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 (72) hide show
  1. package/dist/cli.d.ts +4 -6
  2. package/dist/cli.js +11 -16
  3. package/dist/commands/profile.d.ts +4 -0
  4. package/dist/commands/profile.js +106 -16
  5. package/dist/commands/status.js +7 -7
  6. package/dist/mcp/server.js +48 -141
  7. package/dist/services/agent-asset-installer.d.ts +3 -0
  8. package/dist/services/agent-asset-installer.js +109 -0
  9. package/dist/services/agent-availability-service.d.ts +11 -0
  10. package/dist/services/agent-availability-service.js +32 -0
  11. package/dist/services/credential-redaction-service.d.ts +1 -0
  12. package/dist/services/credential-redaction-service.js +9 -3
  13. package/dist/services/doctor-service.d.ts +2 -2
  14. package/dist/services/doctor-service.js +7 -63
  15. package/dist/services/portable-profile-pack-service.d.ts +6 -0
  16. package/dist/services/portable-profile-pack-service.js +78 -4
  17. package/dist/services/profile-apply-service.d.ts +34 -0
  18. package/dist/services/profile-apply-service.js +102 -0
  19. package/dist/services/profile-export-service.d.ts +5 -1
  20. package/dist/services/profile-export-service.js +3 -1
  21. package/dist/services/profile-import-service.js +82 -127
  22. package/dist/services/profile-service.d.ts +3 -11
  23. package/dist/services/profile-service.js +57 -102
  24. package/dist/services/profile-snapshot-service.d.ts +12 -0
  25. package/dist/services/profile-snapshot-service.js +47 -0
  26. package/dist/services/status-service.d.ts +9 -7
  27. package/dist/services/status-service.js +14 -13
  28. package/dist/types.d.ts +2 -57
  29. package/dist/ui/routes.d.ts +0 -2
  30. package/dist/ui/routes.js +71 -120
  31. package/dist/web/assets/index-CGmTbSgk.js +63 -0
  32. package/dist/web/assets/index-EIVU5Woh.css +2 -0
  33. package/dist/web/index.html +2 -2
  34. package/package.json +1 -1
  35. package/dist/commands/init.d.ts +0 -3
  36. package/dist/commands/init.js +0 -27
  37. package/dist/commands/run.d.ts +0 -3
  38. package/dist/commands/run.js +0 -25
  39. package/dist/commands/sync.d.ts +0 -3
  40. package/dist/commands/sync.js +0 -31
  41. package/dist/config.d.ts +0 -14
  42. package/dist/config.js +0 -96
  43. package/dist/context/builder.d.ts +0 -6
  44. package/dist/context/builder.js +0 -13
  45. package/dist/context/memory.d.ts +0 -5
  46. package/dist/context/memory.js +0 -43
  47. package/dist/context/skills.d.ts +0 -2
  48. package/dist/context/skills.js +0 -8
  49. package/dist/executor/claude.d.ts +0 -12
  50. package/dist/executor/claude.js +0 -16
  51. package/dist/executor/codex.d.ts +0 -12
  52. package/dist/executor/codex.js +0 -16
  53. package/dist/executor/process.d.ts +0 -11
  54. package/dist/executor/process.js +0 -40
  55. package/dist/executor/resolver.d.ts +0 -13
  56. package/dist/executor/resolver.js +0 -60
  57. package/dist/executor/types.d.ts +0 -14
  58. package/dist/executor/types.js +0 -1
  59. package/dist/services/config-write-service.d.ts +0 -12
  60. package/dist/services/config-write-service.js +0 -70
  61. package/dist/services/init-service.d.ts +0 -14
  62. package/dist/services/init-service.js +0 -88
  63. package/dist/services/memory-write-service.d.ts +0 -12
  64. package/dist/services/memory-write-service.js +0 -56
  65. package/dist/services/run-service.d.ts +0 -15
  66. package/dist/services/run-service.js +0 -94
  67. package/dist/services/sync-service.d.ts +0 -15
  68. package/dist/services/sync-service.js +0 -69
  69. package/dist/ui/streaming.d.ts +0 -3
  70. package/dist/ui/streaming.js +0 -16
  71. package/dist/web/assets/index-Bbophmwh.css +0 -2
  72. package/dist/web/assets/index-DDG_ylui.js +0 -63
@@ -1,70 +0,0 @@
1
- import { lstat, mkdir, realpath, writeFile } from 'node:fs/promises';
2
- import path from 'node:path';
3
- import YAML from 'yaml';
4
- import { ConfigError } from '../errors.js';
5
- export function createConfigWriteService() {
6
- return {
7
- async execute(request) {
8
- const cwd = request.cwd ?? process.cwd();
9
- const configPath = path.join(cwd, 'ai-stack.yaml');
10
- const memoryPaths = await Promise.all(request.config.memory.paths.map((memoryPath) => normalizeMemoryPath(cwd, memoryPath)));
11
- const payload = {
12
- memory: {
13
- paths: memoryPaths
14
- },
15
- skills: request.config.skills,
16
- mcps: request.config.mcps
17
- };
18
- await mkdir(path.dirname(configPath), { recursive: true });
19
- await writeFile(configPath, `${YAML.stringify(payload)}`, 'utf8');
20
- return { configPath };
21
- }
22
- };
23
- }
24
- async function normalizeMemoryPath(cwd, filePath) {
25
- const workspaceRoot = await realpath(cwd);
26
- const resolvedPath = path.resolve(cwd, filePath);
27
- const realTargetPath = await resolvePathForWrite(resolvedPath);
28
- if (!isWithinDirectory(workspaceRoot, realTargetPath)) {
29
- throw new ConfigError('Memory paths must stay within the workspace root.');
30
- }
31
- const relativePath = path.relative(cwd, resolvedPath);
32
- return relativePath.length > 0 ? relativePath : '.';
33
- }
34
- async function resolvePathForWrite(targetPath) {
35
- const existingPath = await findNearestExistingPath(targetPath);
36
- const resolvedExistingPath = await realpath(existingPath);
37
- if (existingPath === targetPath) {
38
- return resolvedExistingPath;
39
- }
40
- return path.resolve(resolvedExistingPath, path.relative(existingPath, targetPath));
41
- }
42
- async function findNearestExistingPath(targetPath) {
43
- let currentPath = targetPath;
44
- while (true) {
45
- try {
46
- await lstat(currentPath);
47
- return currentPath;
48
- }
49
- catch (error) {
50
- if (!isMissingPathError(error)) {
51
- throw error;
52
- }
53
- }
54
- const parentPath = path.dirname(currentPath);
55
- if (parentPath === currentPath) {
56
- throw new ConfigError(`Could not resolve filesystem path for ${targetPath}.`);
57
- }
58
- currentPath = parentPath;
59
- }
60
- }
61
- function isWithinDirectory(parentDirectory, targetPath) {
62
- const relativePath = path.relative(parentDirectory, targetPath);
63
- if (relativePath === '') {
64
- return true;
65
- }
66
- return !relativePath.startsWith(`..${path.sep}`) && relativePath !== '..' && !path.isAbsolute(relativePath);
67
- }
68
- function isMissingPathError(error) {
69
- return error instanceof Error && 'code' in error && error.code === 'ENOENT';
70
- }
@@ -1,14 +0,0 @@
1
- export interface InitServiceRequest {
2
- cwd?: string;
3
- force?: boolean;
4
- }
5
- export interface InitServiceResult {
6
- created: string[];
7
- replaced: string[];
8
- skipped: string[];
9
- alreadyInitialized: boolean;
10
- }
11
- export interface InitService {
12
- execute(request?: InitServiceRequest): Promise<InitServiceResult>;
13
- }
14
- export declare function createInitService(): InitService;
@@ -1,88 +0,0 @@
1
- import { mkdir, stat, writeFile } from 'node:fs/promises';
2
- import path from 'node:path';
3
- const SAMPLE_CONFIG = `memory:
4
- paths:
5
- - ./memory
6
-
7
- skills:
8
- summarize:
9
- description: Summarize content
10
- prompt: |
11
- Summarize the following content into concise bullet points.
12
-
13
- analyze:
14
- description: Analyze content deeply
15
- prompt: |
16
- Analyze the following content and extract key insights.
17
-
18
- mcps: {}
19
- `;
20
- const SAMPLE_MEMORY = `# Team Notes
21
-
22
- - Track important project context here.
23
- - Keep prompts and references concise.
24
- `;
25
- export function createInitService() {
26
- return {
27
- async execute(request = {}) {
28
- const cwd = request.cwd ?? process.cwd();
29
- const force = request.force ?? false;
30
- const configPath = path.join(cwd, 'ai-stack.yaml');
31
- const memoryDir = path.join(cwd, 'memory');
32
- const notesPath = path.join(memoryDir, 'notes.md');
33
- const created = [];
34
- const replaced = [];
35
- const skipped = [];
36
- await writeManagedFile({
37
- targetPath: configPath,
38
- content: SAMPLE_CONFIG,
39
- force,
40
- created,
41
- replaced,
42
- skipped
43
- });
44
- const memoryDirExists = await pathExists(memoryDir);
45
- if (!memoryDirExists) {
46
- await mkdir(memoryDir, { recursive: true });
47
- created.push(memoryDir);
48
- }
49
- await writeManagedFile({
50
- targetPath: notesPath,
51
- content: SAMPLE_MEMORY,
52
- force,
53
- created,
54
- replaced,
55
- skipped
56
- });
57
- return {
58
- created,
59
- replaced,
60
- skipped,
61
- alreadyInitialized: created.length === 0 && replaced.length === 0
62
- };
63
- }
64
- };
65
- }
66
- async function writeManagedFile(options) {
67
- const exists = await pathExists(options.targetPath);
68
- if (exists && !options.force) {
69
- options.skipped.push(options.targetPath);
70
- return;
71
- }
72
- await mkdir(path.dirname(options.targetPath), { recursive: true });
73
- await writeFile(options.targetPath, options.content, 'utf8');
74
- if (exists) {
75
- options.replaced.push(options.targetPath);
76
- return;
77
- }
78
- options.created.push(options.targetPath);
79
- }
80
- async function pathExists(targetPath) {
81
- try {
82
- await stat(targetPath);
83
- return true;
84
- }
85
- catch {
86
- return false;
87
- }
88
- }
@@ -1,12 +0,0 @@
1
- export interface MemoryWriteRequest {
2
- cwd?: string;
3
- filePath: string;
4
- content: string;
5
- }
6
- export interface MemoryWriteResult {
7
- filePath: string;
8
- }
9
- export interface MemoryWriteService {
10
- execute(request: MemoryWriteRequest): Promise<MemoryWriteResult>;
11
- }
12
- export declare function createMemoryWriteService(): MemoryWriteService;
@@ -1,56 +0,0 @@
1
- import { lstat, mkdir, realpath, writeFile } from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { MemoryPathError } from '../errors.js';
4
- export function createMemoryWriteService() {
5
- return {
6
- async execute(request) {
7
- const cwd = request.cwd ?? process.cwd();
8
- const targetPath = path.resolve(cwd, request.filePath);
9
- const workspaceRoot = await realpath(cwd);
10
- const resolvedTargetPath = await resolvePathForWrite(targetPath);
11
- if (!isWithinDirectory(workspaceRoot, resolvedTargetPath)) {
12
- throw new MemoryPathError('Memory files must stay within the workspace root.');
13
- }
14
- await mkdir(path.dirname(targetPath), { recursive: true });
15
- await writeFile(targetPath, request.content, 'utf8');
16
- return { filePath: targetPath };
17
- }
18
- };
19
- }
20
- async function resolvePathForWrite(targetPath) {
21
- const existingPath = await findNearestExistingPath(targetPath);
22
- const resolvedExistingPath = await realpath(existingPath);
23
- if (existingPath === targetPath) {
24
- return resolvedExistingPath;
25
- }
26
- return path.resolve(resolvedExistingPath, path.relative(existingPath, targetPath));
27
- }
28
- async function findNearestExistingPath(targetPath) {
29
- let currentPath = targetPath;
30
- while (true) {
31
- try {
32
- await lstat(currentPath);
33
- return currentPath;
34
- }
35
- catch (error) {
36
- if (!isMissingPathError(error)) {
37
- throw error;
38
- }
39
- }
40
- const parentPath = path.dirname(currentPath);
41
- if (parentPath === currentPath) {
42
- throw new MemoryPathError(`Could not resolve filesystem path for ${targetPath}.`);
43
- }
44
- currentPath = parentPath;
45
- }
46
- }
47
- function isWithinDirectory(parentDirectory, targetPath) {
48
- const relativePath = path.relative(parentDirectory, targetPath);
49
- if (relativePath === '') {
50
- return true;
51
- }
52
- return !relativePath.startsWith(`..${path.sep}`) && relativePath !== '..' && !path.isAbsolute(relativePath);
53
- }
54
- function isMissingPathError(error) {
55
- return error instanceof Error && 'code' in error && error.code === 'ENOENT';
56
- }
@@ -1,15 +0,0 @@
1
- import type { ExecutorResolver } from '../executor/resolver.js';
2
- import type { ExecutionStep, ExecutionTrace, RunRequest } from '../types.js';
3
- export interface RunService {
4
- execute(request: RunRequest, options?: RunServiceExecuteOptions): Promise<ExecutionTrace>;
5
- }
6
- export interface RunServiceExecuteOptions {
7
- onOutputChunk?: (chunk: string) => void;
8
- streamOutput?: boolean;
9
- }
10
- interface RunServiceDependencies {
11
- resolver?: ExecutorResolver;
12
- }
13
- export declare function createRunService(dependencies?: RunServiceDependencies): RunService;
14
- export declare function buildExecutionPlan(request: RunRequest): ExecutionStep[];
15
- export {};
@@ -1,94 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { AgentNotAvailableError, InputFileError } from '../errors.js';
4
- import { loadConfig } from '../config.js';
5
- import { buildContext } from '../context/builder.js';
6
- import { loadMemory } from '../context/memory.js';
7
- import { resolveSkillPrompt } from '../context/skills.js';
8
- import { createExecutorResolver } from '../executor/resolver.js';
9
- export function createRunService(dependencies = {}) {
10
- const resolver = dependencies.resolver ?? createExecutorResolver();
11
- return {
12
- async execute(request, options = {}) {
13
- const cwd = request.cwd ?? process.cwd();
14
- const config = await loadConfig({ cwd });
15
- const memory = await loadMemory({ paths: config.memory.paths });
16
- const steps = buildExecutionPlan(request);
17
- const results = [];
18
- let previousOutput;
19
- for (const [stepIndex, step] of steps.entries()) {
20
- const input = await resolveInput(step, cwd, previousOutput);
21
- const skill = resolveSkillPrompt(config, step.skill);
22
- const context = buildContext({
23
- memory: memory.content,
24
- skill,
25
- input
26
- });
27
- let executor = await resolvePrimaryExecutor(resolver, step);
28
- let fallbackUsed = false;
29
- if (executor.fallbackRequired) {
30
- fallbackUsed = true;
31
- }
32
- const result = await executor.instance.run(context, {
33
- streamOutput: options.streamOutput ?? true,
34
- onOutputChunk: options.onOutputChunk
35
- });
36
- previousOutput = result.output;
37
- results.push({
38
- stepIndex,
39
- requestedAgent: step.primaryAgent,
40
- agent: result.agent,
41
- fallbackUsed,
42
- exitCode: result.exitCode,
43
- output: result.output
44
- });
45
- }
46
- const finalResult = results.at(-1);
47
- return {
48
- steps: results,
49
- finalOutput: finalResult?.output ?? '',
50
- finalExitCode: finalResult?.exitCode ?? 0
51
- };
52
- }
53
- };
54
- }
55
- export function buildExecutionPlan(request) {
56
- return [
57
- {
58
- skill: request.skill,
59
- inputFile: request.inputFile,
60
- primaryAgent: request.primaryAgent,
61
- fallbackAgent: request.fallbackAgent,
62
- usePreviousOutput: false
63
- }
64
- ];
65
- }
66
- async function resolveInput(step, cwd, previousOutput) {
67
- if (step.usePreviousOutput && previousOutput !== undefined) {
68
- return previousOutput;
69
- }
70
- const inputPath = path.resolve(cwd, step.inputFile);
71
- try {
72
- return await readFile(inputPath, 'utf8');
73
- }
74
- catch (error) {
75
- throw new InputFileError(`Could not read input file: ${step.inputFile}`);
76
- }
77
- }
78
- async function resolvePrimaryExecutor(resolver, step) {
79
- try {
80
- return {
81
- instance: await resolver.resolveExecutor(step.primaryAgent),
82
- fallbackRequired: false
83
- };
84
- }
85
- catch (error) {
86
- if (!(error instanceof AgentNotAvailableError) || !step.fallbackAgent) {
87
- throw error;
88
- }
89
- return {
90
- instance: await resolver.resolveExecutor(step.fallbackAgent),
91
- fallbackRequired: true
92
- };
93
- }
94
- }
@@ -1,15 +0,0 @@
1
- import type { AgentName, SyncResult } from '../types.js';
2
- import type { AgentConfigWriter } from './sync/agent-writer.js';
3
- import { type ProfileService } from './profile-service.js';
4
- export interface SyncService {
5
- execute(options?: {
6
- cwd?: string;
7
- restore?: boolean;
8
- }): Promise<SyncResult>;
9
- }
10
- interface SyncServiceDependencies {
11
- profileService?: ProfileService;
12
- writers?: Partial<Record<AgentName, AgentConfigWriter>>;
13
- }
14
- export declare function createSyncService(dependencies?: SyncServiceDependencies): SyncService;
15
- export {};
@@ -1,69 +0,0 @@
1
- import { ProfileError } from '../errors.js';
2
- import { createClaudeWriter } from './sync/claude-writer.js';
3
- import { createCodexWriter } from './sync/codex-writer.js';
4
- import { createGeminiWriter } from './sync/gemini-writer.js';
5
- import { createProfileService } from './profile-service.js';
6
- export function createSyncService(dependencies = {}) {
7
- const profileService = dependencies.profileService ?? createProfileService();
8
- const defaultWriters = {
9
- claude: createClaudeWriter(),
10
- codex: createCodexWriter(),
11
- gemini: createGeminiWriter(),
12
- };
13
- const writers = { ...defaultWriters, ...dependencies.writers };
14
- return {
15
- async execute(options = {}) {
16
- const cwd = options.cwd ?? process.cwd();
17
- if (options.restore) {
18
- return restoreAll(writers, cwd);
19
- }
20
- const meta = await profileService.getMetaConfig({ cwd });
21
- if (!meta.active_profile) {
22
- throw new Error('No active profile set. Run "brainctl profile use <name>" first.');
23
- }
24
- const profile = await profileService.get({ cwd, name: meta.active_profile });
25
- const remoteMcpName = Object.entries(profile.mcps).find(([, config]) => config.kind === 'remote')?.[0];
26
- if (remoteMcpName) {
27
- throw new ProfileError(`Profile "${profile.name}" includes remote MCP "${remoteMcpName}". Remote MCP sync is not supported yet.`);
28
- }
29
- const results = [];
30
- for (const agent of meta.agents) {
31
- const writer = writers[agent];
32
- if (!writer) {
33
- continue;
34
- }
35
- const result = await writer.write({
36
- mcpServers: profile.mcps,
37
- cwd,
38
- });
39
- results.push({
40
- agent,
41
- configPath: result.configPath,
42
- backedUpTo: result.backedUpTo,
43
- mcpCount: Object.keys(profile.mcps).length,
44
- });
45
- }
46
- return results;
47
- },
48
- };
49
- }
50
- async function restoreAll(writers, cwd) {
51
- const results = [];
52
- for (const [agent, writer] of Object.entries(writers)) {
53
- if (!writer)
54
- continue;
55
- try {
56
- const { restoredFrom } = await writer.restore({ cwd });
57
- results.push({
58
- agent: agent,
59
- configPath: restoredFrom,
60
- backedUpTo: null,
61
- mcpCount: 0,
62
- });
63
- }
64
- catch {
65
- // Skip agents with no backup
66
- }
67
- }
68
- return results;
69
- }
@@ -1,3 +0,0 @@
1
- import type { ServerResponse } from 'node:http';
2
- export declare function startSseStream(response: ServerResponse): void;
3
- export declare function writeSseEvent(response: ServerResponse, event: string, data: unknown): void;
@@ -1,16 +0,0 @@
1
- export function startSseStream(response) {
2
- response.statusCode = 200;
3
- response.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
4
- response.setHeader('Cache-Control', 'no-cache, no-transform');
5
- response.setHeader('Connection', 'keep-alive');
6
- response.setHeader('X-Accel-Buffering', 'no');
7
- response.flushHeaders?.();
8
- }
9
- export function writeSseEvent(response, event, data) {
10
- response.write(`event: ${event}\n`);
11
- const payload = typeof data === 'string' ? data : JSON.stringify(data);
12
- for (const line of payload.split(/\r?\n/)) {
13
- response.write(`data: ${line}\n`);
14
- }
15
- response.write('\n');
16
- }
@@ -1,2 +0,0 @@
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-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-700:oklch(55.5% .163 48.998);--color-emerald-50:oklch(97.9% .021 166.113);--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-emerald-800:oklch(43.2% .095 166.913);--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-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-zinc-950:oklch(14.1% .005 285.823);--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-base:1rem;--text-base--line-height:calc(1.5 / 1);--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;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--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}.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%}.left-1\/2{left:50%}.z-20{z-index:20}.z-50{z-index:50}.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}.my-6{margin-block:calc(var(--spacing) * 6)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.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-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.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\.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-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-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.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-\[44px\]{min-height:44px}.min-h-\[120px\]{min-height:120px}.min-h-\[180px\]{min-height:180px}.min-h-\[360px\]{min-height:360px}.min-h-screen{min-height:100vh}.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{flex-shrink:1}.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-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.appearance-none{appearance:none}.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-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)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}: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-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-y-auto{overflow-y:auto}.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-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-200\/80{border-color:#a4f4cfcc}@supports (color:color-mix(in lab, red, red)){.border-emerald-200\/80{border-color:color-mix(in oklab, var(--color-emerald-200) 80%, transparent)}}.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-red-200\/80{border-color:#ffcacacc}@supports (color:color-mix(in lab, red, red)){.border-red-200\/80{border-color:color-mix(in oklab, var(--color-red-200) 80%, transparent)}}.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-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\/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-red-50{background-color:var(--color-red-50)}.bg-red-50\/50{background-color:#fef2f280}@supports (color:color-mix(in lab, red, red)){.bg-red-50\/50{background-color:color-mix(in oklab, var(--color-red-50) 50%, transparent)}}.bg-red-100{background-color:var(--color-red-100)}.bg-red-600{background-color:var(--color-red-600)}.bg-white{background-color:var(--color-white)}.bg-white\/60{background-color:#fff9}@supports (color:color-mix(in lab, red, red)){.bg-white\/60{background-color:color-mix(in oklab, var(--color-white) 60%, transparent)}}.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-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)}.bg-zinc-950{background-color:var(--color-zinc-950)}.object-contain{object-fit:contain}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.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-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)}.pb-0{padding-bottom:calc(var(--spacing) * 0)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.text-center{text-align:center}.font-mono{font-family:var(--font-mono)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.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-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.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-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.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-emerald-800{color:var(--color-emerald-800)}.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-700\/90{color:#bf000fe6}@supports (color:color-mix(in lab, red, red)){.text-red-700\/90{color:color-mix(in oklab, var(--color-red-700) 90%, transparent)}}.text-red-800{color:var(--color-red-800)}.text-red-900{color:var(--color-red-900)}.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-\[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-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-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-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-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))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.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}}.placeholder\:font-normal::placeholder{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.placeholder\:text-zinc-400::placeholder{color:var(--color-zinc-400)}@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-white:hover{background-color:var(--color-white)}.hover\:bg-zinc-50:hover{background-color:var(--color-zinc-50)}.hover\:bg-zinc-800:hover{background-color:var(--color-zinc-800)}.hover\:text-red-600:hover{color:var(--color-red-600)}.hover\:text-red-700:hover{color:var(--color-red-700)}.hover\:text-zinc-900:hover{color:var(--color-zinc-900)}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-lg:hover{--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)}.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\:ring-4:focus{--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)}.focus\:ring-zinc-100:focus{--tw-ring-color:var(--color-zinc-100)}.active\:scale-\[0\.98\]:active{scale:.98}.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}@media (width>=40rem){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.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\:grid-cols-\[minmax\(0\,1\.3fr\)_minmax\(300px\,0\.9fr\)\]{grid-template-columns:minmax(0,1.3fr) minmax(300px,.9fr)}.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\:p-6{padding:calc(var(--spacing) * 6)}.lg\:p-8{padding:calc(var(--spacing) * 8)}.lg\:px-10{padding-inline:calc(var(--spacing) * 10)}.lg\:py-0{padding-block:calc(var(--spacing) * 0)}.lg\:pr-0{padding-right:calc(var(--spacing) * 0)}.lg\:pr-10{padding-right:calc(var(--spacing) * 10)}.lg\:pl-0{padding-left:calc(var(--spacing) * 0)}.lg\:pl-10{padding-left:calc(var(--spacing) * 10)}}}: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)}}