speckit-kit 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/bin/speckit-kit.ts","../../src/server/app/effect-api.ts","../../src/server/health/health.contract.ts","../../src/server/specboard/specboard.contract.ts","../../src/server/health/health.http.live.ts","../../src/server/specboard/specboard.http.live.ts","../../src/server/specboard/specboard.service.ts","../../src/server/specboard/specboard.service.live.ts","../../src/server/util/repo-paths.ts","../../src/server/specboard/specboard.tasks.ts"],"sourcesContent":["import fs from 'node:fs'\nimport { createServer } from 'node:http'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { HttpApiBuilder, HttpMiddleware, HttpServer, HttpServerRequest, HttpServerResponse } from '@effect/platform'\nimport { NodeFileSystem, NodeHttpServer, NodePath, NodeRuntime } from '@effect/platform-node'\nimport { Effect, Layer } from 'effect'\nimport open from 'open'\n\nimport { EffectApi } from '../server/app/effect-api.js'\nimport { HealthLive } from '../server/health/health.http.live.js'\nimport { SpecboardLive } from '../server/specboard/specboard.http.live.js'\nimport { SpecboardServiceLive } from '../server/specboard/specboard.service.live.js'\n\ntype Command = 'kanban'\n\ninterface CliOptions {\n readonly command: Command\n readonly host: string\n readonly port: number | null\n readonly open: boolean\n readonly repoRoot: string | null\n}\n\nfunction printHelp(): void {\n console.log(`speckit-kit\n\n用法:\n speckit-kit [kanban] [--repo-root <path>] [--host <host>] [--port <port>] [--no-open]\n\n参数:\n --repo-root <path> 指定目标仓库根目录(需包含 specs/)\n --host <host> 监听地址(默认 127.0.0.1)\n --port <port> 监听端口(默认 0 随机端口)\n --no-open 不自动打开浏览器\n -h, --help 显示帮助\n`)\n}\n\nfunction parseArgs(argv: ReadonlyArray<string>): CliOptions | { readonly help: true } {\n const args = [...argv]\n const first = args[0]\n\n let command: Command = 'kanban'\n if (first && !first.startsWith('-')) {\n if (first !== 'kanban') {\n throw new Error(`未知命令:${first}`)\n }\n command = 'kanban'\n args.shift()\n }\n\n let host = process.env.HOST ?? '127.0.0.1'\n let port: number | null = process.env.PORT ? Number.parseInt(process.env.PORT, 10) : null\n let shouldOpen = !(process.env.NO_OPEN === '1' || process.env.NO_OPEN === 'true')\n let repoRoot: string | null = null\n\n const takeValue = (flag: string): string => {\n const value = args.shift()\n if (!value) throw new Error(`${flag} 缺少参数`)\n return value\n }\n\n while (args.length > 0) {\n const a = args.shift()!\n if (a === '-h' || a === '--help') return { help: true }\n\n if (a === '--host') {\n host = takeValue(a)\n continue\n }\n if (a === '--port') {\n const raw = takeValue(a)\n port = Number.parseInt(raw, 10)\n if (Number.isNaN(port) || port < 0) {\n throw new Error(`--port 非法:${raw}`)\n }\n continue\n }\n if (a === '--repo-root') {\n repoRoot = takeValue(a)\n continue\n }\n if (a === '--no-open') {\n shouldOpen = false\n continue\n }\n if (a === '--open') {\n shouldOpen = true\n continue\n }\n\n throw new Error(`未知参数:${a}`)\n }\n\n return { command, host, port, open: shouldOpen, repoRoot }\n}\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nconst UI_DIST = path.resolve(__dirname, '..', 'ui')\nconst UI_INDEX_HTML = path.join(UI_DIST, 'index.html')\n\nfunction assertUiDistExists(): void {\n if (!fs.existsSync(UI_INDEX_HTML)) {\n console.error(`UI dist 不存在:${UI_DIST}`)\n console.error(`请先构建:pnpm -C packages/speckit-kit build`)\n process.exit(1)\n }\n}\n\nfunction stripApiPrefix(req: HttpServerRequest.HttpServerRequest): HttpServerRequest.HttpServerRequest {\n let url: URL\n try {\n url = new URL(req.url, 'http://localhost')\n } catch {\n return req\n }\n\n if (!(url.pathname === '/api' || url.pathname.startsWith('/api/'))) {\n return req\n }\n\n url.pathname = url.pathname.replace(/^\\/api/, '') || '/'\n const nextUrl = `${url.pathname}${url.search}`\n return req.modify({ url: nextUrl })\n}\n\nfunction resolveUiFilePath(pathname: string): string | null {\n const decoded = (() => {\n try {\n return decodeURIComponent(pathname)\n } catch {\n return pathname\n }\n })()\n\n const withoutLeadingSlash = decoded.startsWith('/') ? decoded.slice(1) : decoded\n const relative = withoutLeadingSlash.length === 0 ? 'index.html' : withoutLeadingSlash\n const candidate = path.resolve(UI_DIST, relative)\n\n if (!candidate.startsWith(`${UI_DIST}${path.sep}`) && candidate !== UI_DIST) {\n return null\n }\n\n if (decoded.endsWith('/') || !path.extname(candidate)) {\n return UI_INDEX_HTML\n }\n\n return candidate\n}\n\nfunction runKanban(opts: CliOptions): void {\n if (opts.repoRoot) {\n process.env.SPECKIT_KIT_REPO_ROOT = path.resolve(opts.repoRoot)\n }\n\n assertUiDistExists()\n\n const ApiLive = HttpApiBuilder.api(EffectApi).pipe(\n Layer.provide(HealthLive),\n Layer.provide(SpecboardLive),\n Layer.provide(SpecboardServiceLive),\n )\n\n const NodeServerLive = NodeHttpServer.layer(createServer, {\n port: opts.port === null || Number.isNaN(opts.port) ? 0 : opts.port,\n host: opts.host,\n })\n\n const RuntimeLive = Layer.mergeAll(\n ApiLive,\n HttpApiBuilder.Router.Live,\n HttpApiBuilder.Middleware.layer,\n NodeFileSystem.layer,\n NodePath.layer,\n NodeServerLive,\n )\n\n const program = Effect.gen(function* () {\n const apiApp = yield* HttpApiBuilder.httpApp\n\n const httpApp = Effect.gen(function* () {\n const req = yield* HttpServerRequest.HttpServerRequest\n let url: URL\n try {\n url = new URL(req.url, 'http://localhost')\n } catch {\n url = new URL('http://localhost/')\n }\n\n if (url.pathname === '/api' || url.pathname.startsWith('/api/')) {\n const rewritten = stripApiPrefix(req)\n return yield* apiApp.pipe(Effect.provideService(HttpServerRequest.HttpServerRequest, rewritten))\n }\n\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n return HttpServerResponse.text('Not Found', { status: 404 })\n }\n\n const filePath = resolveUiFilePath(url.pathname)\n if (!filePath) {\n return HttpServerResponse.text('Not Found', { status: 404 })\n }\n\n return yield* HttpServerResponse.file(filePath).pipe(\n Effect.catchAll(() => Effect.succeed(HttpServerResponse.text('Not Found', { status: 404 }))),\n )\n })\n\n yield* HttpServer.serveEffect(httpApp, HttpMiddleware.logger)\n\n const address = yield* HttpServer.addressWith(Effect.succeed)\n if (address._tag === 'TcpAddress') {\n const publicUrl = `http://localhost:${address.port}`\n yield* Effect.sync(() => {\n console.log(`Server running at ${publicUrl}`)\n })\n\n if (opts.open) {\n yield* Effect.tryPromise({\n try: () => open(publicUrl),\n catch: () => undefined,\n }).pipe(Effect.ignore)\n }\n } else {\n yield* Effect.sync(() => {\n console.log(`Server running at ${HttpServer.formatAddress(address)}`)\n })\n }\n\n return yield* Effect.never\n }).pipe(Effect.provide(RuntimeLive), Effect.scoped)\n\n NodeRuntime.runMain(program)\n}\n\nasync function main(): Promise<void> {\n const parsed = parseArgs(process.argv.slice(2))\n if ('help' in parsed) {\n printHelp()\n return\n }\n\n if (parsed.command === 'kanban') {\n runKanban(parsed)\n return\n }\n}\n\nvoid main().catch((e) => {\n console.error(e)\n process.exit(1)\n})\n","import { HttpApi } from '@effect/platform'\n\nimport { HealthGroup } from '../health/health.contract.js'\nimport { SpecboardGroup } from '../specboard/specboard.contract.js'\n\nexport const EffectApi = HttpApi.make('EffectApi').add(HealthGroup).add(SpecboardGroup)\n","import { HttpApiEndpoint, HttpApiGroup } from '@effect/platform'\nimport { Schema } from 'effect'\n\nexport const HealthResponse = Schema.Struct({\n ok: Schema.Boolean,\n})\n\nexport const HealthGroup = HttpApiGroup.make('Health')\n .add(HttpApiEndpoint.get('health')`/health`.addSuccess(HealthResponse))\n","import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from '@effect/platform'\nimport { Schema } from 'effect'\n\nexport const ArtifactName = Schema.Union(\n Schema.Literal('spec.md'),\n Schema.Literal('plan.md'),\n Schema.Literal('tasks.md'),\n Schema.Literal('quickstart.md'),\n Schema.Literal('data-model.md'),\n Schema.Literal('research.md'),\n)\n\nexport const SpecTaskStats = Schema.Struct({\n total: Schema.Number,\n done: Schema.Number,\n todo: Schema.Number,\n})\n\nexport const SpecListItem = Schema.Struct({\n id: Schema.String,\n num: Schema.Number,\n title: Schema.String,\n taskStats: Schema.optional(SpecTaskStats),\n})\n\nexport const SpecListResponse = Schema.Struct({\n items: Schema.Array(SpecListItem),\n})\n\nexport const TaskItem = Schema.Struct({\n line: Schema.Number,\n checked: Schema.Boolean,\n raw: Schema.String,\n title: Schema.String,\n taskId: Schema.optional(Schema.String),\n parallel: Schema.optional(Schema.Boolean),\n story: Schema.optional(Schema.String),\n})\n\nexport const TaskListResponse = Schema.Struct({\n specId: Schema.String,\n tasks: Schema.Array(TaskItem),\n})\n\nexport const TaskToggleRequest = Schema.Struct({\n line: Schema.Number,\n checked: Schema.Boolean,\n})\n\nexport const FileReadResponse = Schema.Struct({\n name: ArtifactName,\n path: Schema.String,\n content: Schema.String,\n})\n\nexport const FileWriteRequest = Schema.Struct({\n content: Schema.String,\n})\n\nexport const FileWriteResponse = Schema.Struct({\n name: ArtifactName,\n path: Schema.String,\n})\n\nexport const ValidationError = Schema.Struct({\n _tag: Schema.Literal('ValidationError'),\n message: Schema.String,\n})\n\nexport const NotFoundError = Schema.Struct({\n _tag: Schema.Literal('NotFoundError'),\n message: Schema.String,\n})\n\nexport const ForbiddenError = Schema.Struct({\n _tag: Schema.Literal('ForbiddenError'),\n message: Schema.String,\n})\n\nexport const ConflictError = Schema.Struct({\n _tag: Schema.Literal('ConflictError'),\n message: Schema.String,\n})\n\nexport const InternalError = Schema.Struct({\n _tag: Schema.Literal('InternalError'),\n message: Schema.String,\n})\n\nexport const SpecboardGroup = HttpApiGroup.make('Specboard')\n .addError(ValidationError, { status: 400 })\n .addError(ForbiddenError, { status: 403 })\n .addError(NotFoundError, { status: 404 })\n .addError(ConflictError, { status: 409 })\n .addError(InternalError, { status: 500 })\n .add(HttpApiEndpoint.get('specList')`/specs`.addSuccess(SpecListResponse))\n .add(\n HttpApiEndpoint.get('taskList')`/specs/${HttpApiSchema.param('specId', Schema.String)}/tasks`.addSuccess(\n TaskListResponse,\n ),\n )\n .add(\n HttpApiEndpoint.post('taskToggle')`/specs/${HttpApiSchema.param('specId', Schema.String)}/tasks/toggle`\n .setPayload(TaskToggleRequest)\n .addSuccess(TaskListResponse),\n )\n .add(\n HttpApiEndpoint.get(\n 'fileRead',\n )`/specs/${HttpApiSchema.param('specId', Schema.String)}/files/${HttpApiSchema.param('name', ArtifactName)}`.addSuccess(\n FileReadResponse,\n ),\n )\n .add(\n HttpApiEndpoint.put(\n 'fileWrite',\n )`/specs/${HttpApiSchema.param('specId', Schema.String)}/files/${HttpApiSchema.param('name', ArtifactName)}`\n .setPayload(FileWriteRequest)\n .addSuccess(FileWriteResponse),\n )\n","import { HttpApiBuilder } from '@effect/platform'\nimport { Effect } from 'effect'\n\nimport { EffectApi } from '../app/effect-api.js'\n\nexport const HealthLive = HttpApiBuilder.group(EffectApi, 'Health', (handlers) =>\n handlers.handle('health', () => Effect.succeed({ ok: true })),\n)\n","import { HttpApiBuilder } from '@effect/platform'\nimport { Effect } from 'effect'\n\nimport { EffectApi } from '../app/effect-api.js'\nimport { Specboard } from './specboard.service.js'\n\nexport const SpecboardLive = HttpApiBuilder.group(EffectApi, 'Specboard', (handlers) =>\n handlers\n .handle('specList', () =>\n Effect.gen(function* () {\n const specboard = yield* Specboard\n return yield* specboard.listSpecs\n }),\n )\n .handle('taskList', ({ path }) =>\n Effect.gen(function* () {\n const specboard = yield* Specboard\n return yield* specboard.listTasks(path.specId)\n }),\n )\n .handle('taskToggle', ({ path, payload }) =>\n Effect.gen(function* () {\n const specboard = yield* Specboard\n return yield* specboard.toggleTask({ specId: path.specId, line: payload.line, checked: payload.checked })\n }),\n )\n .handle('fileRead', ({ path }) =>\n Effect.gen(function* () {\n const specboard = yield* Specboard\n return yield* specboard.readFile({ specId: path.specId, name: path.name })\n }),\n )\n .handle('fileWrite', ({ path, payload }) =>\n Effect.gen(function* () {\n const specboard = yield* Specboard\n return yield* specboard.writeFile({ specId: path.specId, name: path.name, content: payload.content })\n }),\n ),\n)\n\n","import { Context, Effect } from 'effect'\n\nexport type ArtifactName = 'spec.md' | 'plan.md' | 'tasks.md' | 'quickstart.md' | 'data-model.md' | 'research.md'\n\nexport interface SpecTaskStats {\n readonly total: number\n readonly done: number\n readonly todo: number\n}\n\nexport interface SpecListItem {\n readonly id: string\n readonly num: number\n readonly title: string\n readonly taskStats?: SpecTaskStats\n}\n\nexport interface TaskItem {\n readonly line: number\n readonly checked: boolean\n readonly raw: string\n readonly title: string\n readonly taskId?: string\n readonly parallel?: boolean\n readonly story?: string\n}\n\nexport interface ArtifactFile {\n readonly name: ArtifactName\n readonly path: string\n readonly content: string\n}\n\nexport type SpecboardError =\n | { readonly _tag: 'ValidationError'; readonly message: string }\n | { readonly _tag: 'NotFoundError'; readonly message: string }\n | { readonly _tag: 'ForbiddenError'; readonly message: string }\n | { readonly _tag: 'ConflictError'; readonly message: string }\n | { readonly _tag: 'InternalError'; readonly message: string }\n\nexport interface SpecboardService {\n readonly listSpecs: Effect.Effect<{ readonly items: ReadonlyArray<SpecListItem> }, SpecboardError>\n readonly listTasks: (specId: string) => Effect.Effect<{ readonly specId: string; readonly tasks: ReadonlyArray<TaskItem> }, SpecboardError>\n readonly toggleTask: (input: {\n readonly specId: string\n readonly line: number\n readonly checked: boolean\n }) => Effect.Effect<{ readonly specId: string; readonly tasks: ReadonlyArray<TaskItem> }, SpecboardError>\n readonly readFile: (input: {\n readonly specId: string\n readonly name: ArtifactName\n }) => Effect.Effect<ArtifactFile, SpecboardError>\n readonly writeFile: (input: {\n readonly specId: string\n readonly name: ArtifactName\n readonly content: string\n }) => Effect.Effect<{ readonly name: ArtifactName; readonly path: string }, SpecboardError>\n}\n\nexport class Specboard extends Context.Tag('Specboard')<Specboard, SpecboardService>() {}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport { Effect, Layer } from 'effect'\n\nimport {\n PathEscapeError,\n UnsafePathSegmentError,\n assertSafePathSegment,\n findRepoPaths,\n resolveWithinRoot,\n type RepoPaths,\n} from '../util/repo-paths.js'\nimport { parseTasksMarkdown, updateCheckboxLine } from './specboard.tasks.js'\nimport { Specboard, type ArtifactName, type SpecboardError, type SpecboardService } from './specboard.service.js'\n\nfunction toInternalError(message: string): SpecboardError {\n return { _tag: 'InternalError', message }\n}\n\nfunction toFsError(e: unknown): SpecboardError {\n if (e instanceof UnsafePathSegmentError || e instanceof PathEscapeError) {\n return { _tag: 'ForbiddenError', message: 'Forbidden path' }\n }\n if (typeof e === 'object' && e !== null && 'code' in e) {\n const code = (e as { readonly code?: unknown }).code\n if (code === 'ENOENT') return { _tag: 'NotFoundError', message: 'File not found' }\n if (code === 'EACCES' || code === 'EPERM') return { _tag: 'ForbiddenError', message: 'Permission denied' }\n }\n return toInternalError(e instanceof Error ? e.message : 'Internal error')\n}\n\nfunction inferTitleFromMarkdown(markdown: string, fallback: string): string {\n const line = markdown.split(/\\r?\\n/).find((l) => l.startsWith('# '))\n return line ? line.replace(/^#\\s+/, '').trim() : fallback\n}\n\nfunction parseSpecDirName(dirName: string): { readonly id: string; readonly num: number } | null {\n if (!/^\\d{3}-/.test(dirName)) return null\n const num = Number.parseInt(dirName.slice(0, 3), 10)\n if (Number.isNaN(num)) return null\n return { id: dirName, num }\n}\n\nfunction specFileRelPath(specId: string, name: ArtifactName): string {\n return path.posix.join('specs', specId, name)\n}\n\nfunction absSpecDir(paths: RepoPaths, specId: string): string {\n assertSafePathSegment(specId)\n return resolveWithinRoot(paths.specsRoot, specId)\n}\n\nfunction absSpecFile(paths: RepoPaths, specId: string, name: ArtifactName): string {\n return resolveWithinRoot(absSpecDir(paths, specId), name)\n}\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await fs.stat(p)\n return true\n } catch {\n return false\n }\n}\n\nasync function writeFileAtomic(absPath: string, content: string): Promise<void> {\n const dir = path.dirname(absPath)\n const tmpPath = path.join(dir, `.tmp.${path.basename(absPath)}.${Date.now()}.${Math.random().toString(16).slice(2)}`)\n await fs.writeFile(tmpPath, content, 'utf8')\n await fs.rename(tmpPath, absPath)\n}\n\nexport const SpecboardServiceLive: Layer.Layer<Specboard> = Layer.effect(\n Specboard,\n Effect.sync(() => {\n const pathsOrError: RepoPaths | SpecboardError = (() => {\n try {\n return findRepoPaths()\n } catch (e) {\n return toInternalError(e instanceof Error ? e.message : 'Cannot find repo root')\n }\n })()\n\n const isError = (u: RepoPaths | SpecboardError): u is SpecboardError =>\n typeof u === 'object' && u !== null && '_tag' in u\n\n const withPaths = <A>(\n f: (paths: RepoPaths) => Effect.Effect<A, SpecboardError>,\n ): Effect.Effect<A, SpecboardError> => (isError(pathsOrError) ? Effect.fail(pathsOrError) : f(pathsOrError))\n\n const listSpecs: SpecboardService['listSpecs'] = withPaths((paths) =>\n Effect.tryPromise({\n try: async () => {\n const dirents = await fs.readdir(paths.specsRoot, { withFileTypes: true })\n\n const specs = dirents\n .filter((d) => d.isDirectory())\n .map((d) => parseSpecDirName(d.name))\n .filter((v): v is { readonly id: string; readonly num: number } => v !== null)\n\n const items = await Promise.all(\n specs.map(async ({ id, num }) => {\n const specMdPath = absSpecFile(paths, id, 'spec.md')\n const specMd = (await exists(specMdPath)) ? await fs.readFile(specMdPath, 'utf8') : null\n\n const tasksMdPath = absSpecFile(paths, id, 'tasks.md')\n const tasksMd = (await exists(tasksMdPath)) ? await fs.readFile(tasksMdPath, 'utf8') : null\n const tasks = tasksMd ? parseTasksMarkdown(tasksMd) : []\n\n const done = tasks.filter((t) => t.checked).length\n const total = tasks.length\n\n return {\n id,\n num,\n title: specMd ? inferTitleFromMarkdown(specMd, id) : id,\n taskStats: tasksMd\n ? {\n total,\n done,\n todo: total - done,\n }\n : undefined,\n }\n }),\n )\n\n items.sort((a, b) => b.num - a.num || b.id.localeCompare(a.id))\n return { items }\n },\n catch: toFsError,\n }),\n )\n\n const listTasks: SpecboardService['listTasks'] = (specId) =>\n withPaths((paths) =>\n Effect.tryPromise({\n try: async () => {\n const tasksMdPath = absSpecFile(paths, specId, 'tasks.md')\n const tasksMd = await fs.readFile(tasksMdPath, 'utf8')\n const tasks = parseTasksMarkdown(tasksMd)\n return { specId, tasks }\n },\n catch: toFsError,\n }),\n )\n\n const toggleTask: SpecboardService['toggleTask'] = ({ specId, line, checked }) =>\n withPaths((paths) =>\n Effect.tryPromise({\n try: async () => {\n if (!Number.isInteger(line) || line <= 0) {\n return Promise.reject({ _tag: 'ValidationError', message: 'invalid line' } satisfies SpecboardError)\n }\n\n const tasksMdPath = absSpecFile(paths, specId, 'tasks.md')\n const tasksMd = await fs.readFile(tasksMdPath, 'utf8')\n const lines = tasksMd.split(/\\r?\\n/)\n\n const idx = line - 1\n if (idx < 0 || idx >= lines.length) {\n return Promise.reject({ _tag: 'ValidationError', message: 'line out of range' } satisfies SpecboardError)\n }\n\n const updated = updateCheckboxLine(lines[idx] ?? '', checked)\n if (!updated) {\n return Promise.reject({\n _tag: 'ValidationError',\n message: 'target line is not a checkbox task',\n } satisfies SpecboardError)\n }\n\n lines[idx] = updated\n await writeFileAtomic(tasksMdPath, lines.join('\\n'))\n\n const nextTasksMd = await fs.readFile(tasksMdPath, 'utf8')\n return { specId, tasks: parseTasksMarkdown(nextTasksMd) }\n },\n catch: (e) => {\n if (typeof e === 'object' && e !== null && '_tag' in e) {\n const tag = (e as { readonly _tag?: unknown })._tag\n if (tag === 'ValidationError') {\n return e as SpecboardError\n }\n }\n return toFsError(e)\n },\n }),\n )\n\n const readFile: SpecboardService['readFile'] = ({ specId, name }) =>\n withPaths((paths) =>\n Effect.tryPromise({\n try: async () => {\n const absPath = absSpecFile(paths, specId, name)\n const content = await fs.readFile(absPath, 'utf8')\n return { name, path: specFileRelPath(specId, name), content }\n },\n catch: toFsError,\n }),\n )\n\n const writeFile: SpecboardService['writeFile'] = ({ specId, name, content }) =>\n withPaths((paths) =>\n Effect.tryPromise({\n try: async () => {\n const specDir = absSpecDir(paths, specId)\n if (!(await exists(specDir))) {\n return Promise.reject({ _tag: 'NotFoundError', message: 'Spec not found' } satisfies SpecboardError)\n }\n\n const absPath = absSpecFile(paths, specId, name)\n await writeFileAtomic(absPath, content)\n return { name, path: specFileRelPath(specId, name) }\n },\n catch: (e) => {\n if (typeof e === 'object' && e !== null && '_tag' in e) {\n const tag = (e as { readonly _tag?: unknown })._tag\n if (tag === 'NotFoundError') {\n return e as SpecboardError\n }\n }\n return toFsError(e)\n },\n }),\n )\n\n return { listSpecs, listTasks, toggleTask, readFile, writeFile } satisfies SpecboardService\n }),\n)\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport interface RepoPaths {\n readonly repoRoot: string\n readonly specsRoot: string\n}\n\nexport class RepoRootNotFoundError extends Error {\n override readonly name = 'RepoRootNotFoundError'\n}\n\nexport class UnsafePathSegmentError extends Error {\n override readonly name = 'UnsafePathSegmentError'\n}\n\nexport class PathEscapeError extends Error {\n override readonly name = 'PathEscapeError'\n}\n\nexport function findRepoPaths(startDir: string = process.cwd()): RepoPaths {\n const envRepoRoot = process.env.SPECKIT_KIT_REPO_ROOT ?? process.env.SPECKIT_REPO_ROOT\n if (envRepoRoot) {\n const repoRoot = path.resolve(envRepoRoot)\n const specsRoot = path.join(repoRoot, 'specs')\n if (!fs.existsSync(specsRoot) || !fs.statSync(specsRoot).isDirectory()) {\n throw new RepoRootNotFoundError(`Invalid repo root: specs/ not found under ${repoRoot}`)\n }\n return { repoRoot, specsRoot }\n }\n\n let dir = path.resolve(startDir)\n while (true) {\n const specsRoot = path.join(dir, 'specs')\n if (fs.existsSync(specsRoot) && fs.statSync(specsRoot).isDirectory()) {\n return { repoRoot: dir, specsRoot }\n }\n\n const parent = path.dirname(dir)\n if (parent === dir) {\n break\n }\n dir = parent\n }\n\n throw new RepoRootNotFoundError(`Cannot locate repo root starting from: ${startDir}`)\n}\n\nexport function resolveWithinRoot(rootDir: string, relativePath: string): string {\n const rootAbs = path.resolve(rootDir)\n const targetAbs = path.resolve(rootAbs, relativePath)\n const rootPrefix = rootAbs.endsWith(path.sep) ? rootAbs : `${rootAbs}${path.sep}`\n\n if (!targetAbs.startsWith(rootPrefix)) {\n throw new PathEscapeError(`Path escapes root: ${relativePath}`)\n }\n\n return targetAbs\n}\n\nexport function assertSafePathSegment(segment: string): void {\n if (segment.includes('/') || segment.includes('\\\\')) {\n throw new UnsafePathSegmentError('Path segment contains separator')\n }\n}\n","export interface ParsedTask {\n readonly line: number\n readonly checked: boolean\n readonly raw: string\n readonly title: string\n readonly taskId?: string\n readonly parallel?: boolean\n readonly story?: string\n}\n\nconst CheckboxLine = /^(\\s*-\\s*\\[)([ xX])(\\]\\s+)(.+)$/\n\nexport function parseTasksMarkdown(markdown: string): ReadonlyArray<ParsedTask> {\n const tasks: ParsedTask[] = []\n const lines = markdown.split(/\\r?\\n/)\n\n for (let index = 0; index < lines.length; index++) {\n const raw = lines[index] ?? ''\n const match = raw.match(CheckboxLine)\n if (!match) continue\n\n const checked = match[2]?.toLowerCase() === 'x'\n const title = match[4]?.trim() ?? ''\n const taskId = title.match(/\\bT\\d{3}\\b/)?.[0]\n const parallel = /\\[P\\]/.test(title) ? true : undefined\n const story = title.match(/\\[(US\\d+)\\]/)?.[1]\n\n tasks.push({\n line: index + 1,\n checked,\n raw,\n title,\n taskId,\n parallel,\n story,\n })\n }\n\n return tasks\n}\n\nexport function updateCheckboxLine(rawLine: string, checked: boolean): string | null {\n const match = rawLine.match(CheckboxLine)\n if (!match) return null\n\n const prefix = match[1] ?? ''\n const suffix = `${match[3] ?? ''}${match[4] ?? ''}`\n return `${prefix}${checked ? 'x' : ' '}${suffix}`\n}\n\n"],"mappings":"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","names":["fs","path","HttpApiBuilder","Effect","Layer","HttpApiEndpoint","HttpApiGroup","Schema","HttpApiBuilder","Effect","HttpApiBuilder","Effect","path","fs","path","Effect","path","fs","Effect","path","fs","HttpApiBuilder","Layer","Effect"]}
@@ -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-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--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-divide-x-reverse:0;--tw-border-style:solid;--tw-divide-y-reverse:0;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--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-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}@layer theme{:root,:host{--font-sans:"Inter",system-ui,sans-serif;--font-serif:ui-serif,Georgia,Cambria,"Times New Roman",Times,serif;--font-mono:"JetBrains Mono",ui-monospace,monospace;--color-black:#000;--spacing:.25rem;--container-md:28rem;--container-6xl:72rem;--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: 1.5 ;--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);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-black:900;--tracking-tight:-.025em;--tracking-normal:0em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0,0,.2,1);--blur-sm:8px;--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}html,body{height:100%;overflow:hidden}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){*{outline-color:color-mix(in oklab,var(--ring)50%,transparent)}}body{background-color:var(--background);font-family:var(--font-sans);color:var(--foreground);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}code,pre{font-family:var(--font-mono)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.inset-x-0{inset-inline:calc(var(--spacing)*0)}.inset-y-0{inset-block:calc(var(--spacing)*0)}.top-0{top:calc(var(--spacing)*0)}.top-1{top:calc(var(--spacing)*1)}.top-2{top:calc(var(--spacing)*2)}.top-4{top:calc(var(--spacing)*4)}.right-0{right:calc(var(--spacing)*0)}.right-2{right:calc(var(--spacing)*2)}.right-4{right:calc(var(--spacing)*4)}.right-16{right:calc(var(--spacing)*16)}.bottom-4{bottom:calc(var(--spacing)*4)}.left-2{left:calc(var(--spacing)*2)}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.-mx-1{margin-inline:calc(var(--spacing)*-1)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing)*1)}.my-2{margin-block:calc(var(--spacing)*2)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.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)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.ml-5{margin-left:calc(var(--spacing)*5)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-0\.5{height:calc(var(--spacing)*.5)}.h-1{height:calc(var(--spacing)*1)}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-12{height:calc(var(--spacing)*12)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-96{max-height:calc(var(--spacing)*96)}.w-3{width:calc(var(--spacing)*3)}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-9{width:calc(var(--spacing)*9)}.w-24{width:calc(var(--spacing)*24)}.w-40{width:calc(var(--spacing)*40)}.w-\[200px\]{width:200px}.w-\[360px\]{width:360px}.w-\[480px\]{width:480px}.w-\[800px\]{width:800px}.w-\[1200px\]{width:1200px}.w-\[min\(900px\,100vw\)\]{width:min(900px,100vw)}.w-full{width:100%}.w-px{width:1px}.w-screen{width:100vw}.max-w-6xl{max-width:var(--container-6xl)}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\[8rem\]{min-width:8rem}.min-w-\[60px\]{min-width:60px}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.min-w-max{min-width:max-content}.flex-1{flex:1}.flex-none{flex:none}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.origin-left{transform-origin:0}.scale-50{--tw-scale-x:50%;--tw-scale-y:50%;--tw-scale-z:50%;scale:var(--tw-scale-x)var(--tw-scale-y)}.scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.-rotate-12{rotate:-12deg}.rotate-12{rotate:12deg}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.appearance-none{appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-\[1fr_auto_1fr\]{grid-template-columns:1fr auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0{gap:calc(var(--spacing)*0)}.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-6{gap:calc(var(--spacing)*6)}.gap-8{gap:calc(var(--spacing)*8)}.gap-12{gap:calc(var(--spacing)*12)}.gap-px{gap:1px}: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)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.divide-x>:not(:last-child)){--tw-divide-x-reverse:0;border-inline-style:var(--tw-border-style);border-inline-start-width:calc(1px*var(--tw-divide-x-reverse));border-inline-end-width:calc(1px*calc(1 - var(--tw-divide-x-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px*var(--tw-divide-y-reverse));border-bottom-width:calc(1px*calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-dashed>:not(:last-child)){--tw-border-style:dashed;border-style:dashed}:where(.divide-border>:not(:last-child)),:where(.divide-border\/30>:not(:last-child)){border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){:where(.divide-border\/30>:not(:last-child)){border-color:color-mix(in oklab,var(--border)30%,transparent)}}:where(.divide-border\/40>:not(:last-child)){border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){:where(.divide-border\/40>:not(:last-child)){border-color:color-mix(in oklab,var(--border)40%,transparent)}}:where(.divide-border\/60>:not(:last-child)){border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){:where(.divide-border\/60>:not(:last-child)){border-color:color-mix(in oklab,var(--border)60%,transparent)}}.justify-self-center{justify-self:center}.justify-self-end{justify-self:flex-end}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.rounded{border-radius:.25rem}.rounded-md{border-radius:var(--radius-md)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-4{border-bottom-style:var(--tw-border-style);border-bottom-width:4px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-double{--tw-border-style:double;border-style:double}.border-none{--tw-border-style:none;border-style:none}.border-border,.border-border\/10{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-border\/10{border-color:color-mix(in oklab,var(--border)10%,transparent)}}.border-border\/30{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-border\/30{border-color:color-mix(in oklab,var(--border)30%,transparent)}}.border-border\/40{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-border\/40{border-color:color-mix(in oklab,var(--border)40%,transparent)}}.border-border\/50{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-border\/50{border-color:color-mix(in oklab,var(--border)50%,transparent)}}.border-border\/60{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-border\/60{border-color:color-mix(in oklab,var(--border)60%,transparent)}}.border-destructive,.border-destructive\/20{border-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.border-destructive\/20{border-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.border-foreground,.border-foreground\/40{border-color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.border-foreground\/40{border-color:color-mix(in oklab,var(--foreground)40%,transparent)}}.border-input{border-color:var(--input)}.border-muted-foreground\/30{border-color:var(--muted-foreground)}@supports (color:color-mix(in lab,red,red)){.border-muted-foreground\/30{border-color:color-mix(in oklab,var(--muted-foreground)30%,transparent)}}.border-primary{border-color:var(--primary)}.border-success{border-color:var(--success)}.border-transparent{border-color:#0000}.border-warning\/50{border-color:var(--warning)}@supports (color:color-mix(in lab,red,red)){.border-warning\/50{border-color:color-mix(in oklab,var(--warning)50%,transparent)}}.bg-accent\/10{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.bg-accent\/10{background-color:color-mix(in oklab,var(--accent)10%,transparent)}}.bg-accent\/50{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.bg-accent\/50{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.bg-background,.bg-background\/80{background-color:var(--background)}@supports (color:color-mix(in lab,red,red)){.bg-background\/80{background-color:color-mix(in oklab,var(--background)80%,transparent)}}.bg-black\/10{background-color:#0000001a}@supports (color:color-mix(in lab,red,red)){.bg-black\/10{background-color:color-mix(in oklab,var(--color-black)10%,transparent)}}.bg-border,.bg-border\/40{background-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.bg-border\/40{background-color:color-mix(in oklab,var(--border)40%,transparent)}}.bg-card{background-color:var(--card)}.bg-destructive,.bg-destructive\/10{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.bg-destructive\/10{background-color:color-mix(in oklab,var(--destructive)10%,transparent)}}.bg-foreground,.bg-foreground\/20{background-color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.bg-foreground\/20{background-color:color-mix(in oklab,var(--foreground)20%,transparent)}}.bg-info,.bg-info\/10{background-color:var(--info)}@supports (color:color-mix(in lab,red,red)){.bg-info\/10{background-color:color-mix(in oklab,var(--info)10%,transparent)}}.bg-muted,.bg-muted\/10{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.bg-muted\/10{background-color:color-mix(in oklab,var(--muted)10%,transparent)}}.bg-muted\/30{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.bg-muted\/30{background-color:color-mix(in oklab,var(--muted)30%,transparent)}}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-success,.bg-success\/10{background-color:var(--success)}@supports (color:color-mix(in lab,red,red)){.bg-success\/10{background-color:color-mix(in oklab,var(--success)10%,transparent)}}.bg-transparent{background-color:#0000}.bg-warning{background-color:var(--warning)}.p-0{padding:calc(var(--spacing)*0)}.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)}.p-8{padding:calc(var(--spacing)*8)}.px-0{padding-inline:calc(var(--spacing)*0)}.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-3{padding-inline:calc(var(--spacing)*3)}.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{padding-block:calc(var(--spacing)*0)}.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-4{padding-block:calc(var(--spacing)*4)}.py-5{padding-block:calc(var(--spacing)*5)}.py-6{padding-block:calc(var(--spacing)*6)}.py-12{padding-block:calc(var(--spacing)*12)}.pt-2{padding-top:calc(var(--spacing)*2)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-8{padding-right:calc(var(--spacing)*8)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pb-4{padding-bottom:calc(var(--spacing)*4)}.pb-16{padding-bottom:calc(var(--spacing)*16)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-4{padding-left:calc(var(--spacing)*4)}.pl-8{padding-left:calc(var(--spacing)*8)}.text-center{text-align:center}.text-left{text-align:left}.align-middle{vertical-align:middle}.align-top{vertical-align:top}.font-mono{font-family:var(--font-mono)}.font-serif{font-family:var(--font-serif)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.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-\[12px\]{font-size:12px}.text-\[13\.5px\]{font-size:13.5px}.text-\[13px\]{font-size:13px}.leading-5{--tw-leading:calc(var(--spacing)*5);line-height:calc(var(--spacing)*5)}.leading-6{--tw-leading:calc(var(--spacing)*6);line-height:calc(var(--spacing)*6)}.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-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.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-normal{--tw-tracking:var(--tracking-normal);letter-spacing:var(--tracking-normal)}.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-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-background{color:var(--background)}.text-card-foreground{color:var(--card-foreground)}.text-destructive{color:var(--destructive)}.text-destructive-foreground{color:var(--destructive-foreground)}.text-foreground,.text-foreground\/80{color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.text-foreground\/80{color:color-mix(in oklab,var(--foreground)80%,transparent)}}.text-foreground\/90{color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.text-foreground\/90{color:color-mix(in oklab,var(--foreground)90%,transparent)}}.text-info{color:var(--info)}.text-info-foreground{color:var(--info-foreground)}.text-muted-foreground,.text-muted-foreground\/70{color:var(--muted-foreground)}@supports (color:color-mix(in lab,red,red)){.text-muted-foreground\/70{color:color-mix(in oklab,var(--muted-foreground)70%,transparent)}}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-success{color:var(--success)}.text-success-foreground{color:var(--success-foreground)}.text-warning{color:var(--warning)}.text-warning-foreground{color:var(--warning-foreground)}.normal-case{text-transform:none}.uppercase{text-transform:uppercase}.italic{font-style:italic}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.decoration-border{-webkit-text-decoration-color:var(--border);text-decoration-color:var(--border)}.decoration-primary\/40{-webkit-text-decoration-color:var(--primary);text-decoration-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.decoration-primary\/40{-webkit-text-decoration-color:color-mix(in oklab,var(--primary)40%,transparent);text-decoration-color:color-mix(in oklab,var(--primary)40%,transparent)}}.underline-offset-2{text-underline-offset:2px}.underline-offset-4{text-underline-offset:4px}.accent-primary{accent-color:var(--primary)}.opacity-0{opacity:0}.opacity-20{opacity:.2}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-100{opacity:1}.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-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[2px_2px_0_0_var\(--foreground\)\]{--tw-shadow:2px 2px 0 0 var(--tw-shadow-color,var(--foreground));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[var\(--shadow-elevated\)\]{--tw-shadow:var(--shadow-elevated);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[var\(--shadow-inset\)\]{--tw-shadow:var(--shadow-inset);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-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.grayscale{--tw-grayscale:grayscale(100%);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,)}.backdrop-blur-\[1px\]{--tw-backdrop-blur:blur(1px);-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.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))}.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-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media(hover:hover){.group-hover\:border-accent:is(:where(.group):hover *){border-color:var(--accent)}.group-hover\:border-foreground:is(:where(.group):hover *){border-color:var(--foreground)}.group-hover\:border-warning:is(:where(.group):hover *){border-color:var(--warning)}.group-hover\:bg-muted\/10:is(:where(.group):hover *){background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.group-hover\:bg-muted\/10:is(:where(.group):hover *){background-color:color-mix(in oklab,var(--muted)10%,transparent)}}.group-hover\:text-foreground:is(:where(.group):hover *){color:var(--foreground)}.group-hover\:text-muted-foreground:is(:where(.group):hover *){color:var(--muted-foreground)}.group-hover\:opacity-70:is(:where(.group):hover *){opacity:.7}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.peer-checked\:opacity-100:is(:where(.peer):checked~*){opacity:1}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}.checked\:border-foreground:checked{border-color:var(--foreground)}.checked\:bg-foreground:checked{background-color:var(--foreground)}@media(hover:hover){.hover\:translate-x-\[2px\]:hover{--tw-translate-x:2px;translate:var(--tw-translate-x)var(--tw-translate-y)}.hover\:translate-y-\[2px\]:hover{--tw-translate-y:2px;translate:var(--tw-translate-x)var(--tw-translate-y)}.hover\:border-accent\/50:hover{border-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.hover\:border-accent\/50:hover{border-color:color-mix(in oklab,var(--accent)50%,transparent)}}.hover\:border-border:hover,.hover\:border-border\/50:hover{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.hover\:border-border\/50:hover{border-color:color-mix(in oklab,var(--border)50%,transparent)}}.hover\:border-foreground:hover,.hover\:border-foreground\/50:hover{border-color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.hover\:border-foreground\/50:hover{border-color:color-mix(in oklab,var(--foreground)50%,transparent)}}.hover\:border-input:hover{border-color:var(--input)}.hover\:bg-accent:hover,.hover\:bg-accent\/15:hover{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/15:hover{background-color:color-mix(in oklab,var(--accent)15%,transparent)}}.hover\:bg-destructive:hover,.hover\:bg-destructive\/10:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/10:hover{background-color:color-mix(in oklab,var(--destructive)10%,transparent)}}.hover\:bg-foreground:hover{background-color:var(--foreground)}.hover\:bg-muted:hover,.hover\:bg-muted\/5:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/5:hover{background-color:color-mix(in oklab,var(--muted)5%,transparent)}}.hover\:bg-muted\/10:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/10:hover{background-color:color-mix(in oklab,var(--muted)10%,transparent)}}.hover\:bg-muted\/20:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/20:hover{background-color:color-mix(in oklab,var(--muted)20%,transparent)}}.hover\:bg-muted\/30:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/30:hover{background-color:color-mix(in oklab,var(--muted)30%,transparent)}}.hover\:bg-muted\/40:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/40:hover{background-color:color-mix(in oklab,var(--muted)40%,transparent)}}.hover\:bg-muted\/60:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/60:hover{background-color:color-mix(in oklab,var(--muted)60%,transparent)}}.hover\:bg-success\/15:hover{background-color:var(--success)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-success\/15:hover{background-color:color-mix(in oklab,var(--success)15%,transparent)}}.hover\:text-background:hover{color:var(--background)}.hover\:text-destructive:hover{color:var(--destructive)}.hover\:text-destructive-foreground:hover{color:var(--destructive-foreground)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:underline:hover{text-decoration-line:underline}.hover\:decoration-primary\/60:hover{-webkit-text-decoration-color:var(--primary);text-decoration-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:decoration-primary\/60:hover{-webkit-text-decoration-color:color-mix(in oklab,var(--primary)60%,transparent);text-decoration-color:color-mix(in oklab,var(--primary)60%,transparent)}}.hover\:shadow-none:hover{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\:bg-accent:focus{background-color:var(--accent)}.focus\:text-accent-foreground:focus{color:var(--accent-foreground)}.focus\:ring-0:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + 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-2:focus{--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)}.focus\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-0:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + 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-visible\:ring-2:focus-visible{--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)}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab,var(--ring)50%,transparent)}}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}@media(min-width:40rem){.sm\:max-w-md{max-width:var(--container-md)}.sm\:max-w-none{max-width:none}}@media(min-width:48rem){.md\:top-4{top:calc(var(--spacing)*4)}.md\:right-32{right:calc(var(--spacing)*32)}.md\:block{display:block}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.md\:opacity-10{opacity:.1}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}}:root{--radius:0;--background:oklch(98% .01 95);--foreground:oklch(13% 0 0);--card:var(--background);--card-foreground:var(--foreground);--popover:var(--background);--popover-foreground:var(--foreground);--primary:var(--foreground);--primary-foreground:var(--background);--secondary:oklch(96% 0 0);--secondary-foreground:var(--foreground);--muted:oklch(94% 0 0);--muted-foreground:oklch(40% 0 0);--accent:oklch(90% .15 100);--accent-foreground:oklch(0% 0 0);--destructive:oklch(62% .22 28.5);--destructive-foreground:var(--background);--border:oklch(13% 0 0);--input:oklch(13% 0 0);--ring:oklch(13% 0 0);--info:oklch(96% 0 0);--info-foreground:var(--foreground);--success:oklch(96% 0 0);--success-foreground:var(--foreground);--warning:oklch(96% 0 0);--warning-foreground:var(--foreground);--shadow-elevated:none;--shadow-float:0 4px 12px var(--foreground)}@supports (color:color-mix(in lab,red,red)){:root{--shadow-float:0 4px 12px color-mix(in oklab,var(--foreground)5%,transparent)}}:root{--shadow-inset:inset 0 1px 2px var(--foreground)}@supports (color:color-mix(in lab,red,red)){:root{--shadow-inset:inset 0 1px 2px color-mix(in oklab,var(--foreground)5%,transparent)}}:root{--surface-base:var(--background);--surface-card:var(--card);--surface-float:var(--card);--surface-hover:var(--accent);--surface-active:var(--muted);--border-subtle:var(--foreground)}@supports (color:color-mix(in lab,red,red)){:root{--border-subtle:color-mix(in oklab,var(--foreground)20%,transparent)}}:root{--border-highlight:var(--border);--text-primary:var(--foreground);--text-secondary:var(--muted-foreground);--text-tertiary:var(--muted-foreground);--intent-primary-bg:var(--background);--intent-primary-fg:var(--primary);--intent-info-bg:var(--background);--intent-info-fg:var(--foreground);--intent-warning-bg:var(--background);--intent-warning-fg:var(--foreground);--intent-success-bg:var(--background);--intent-success-fg:var(--foreground);--intent-danger-bg:var(--background);--intent-danger-fg:var(--foreground)}.scrollbar-none::-webkit-scrollbar{display:none}.scrollbar-none{-ms-overflow-style:none;scrollbar-width:none}@keyframes speckit-flash{0%{opacity:.4;background-color:var(--accent)}50%{opacity:.4}to{opacity:0;background-color:#0000}}.speckit-task-highlight{z-index:0;position:relative}.speckit-task-highlight:before{content:"";background-color:var(--accent);border-left:4px solid var(--foreground);z-index:-1;pointer-events:none;animation:3s ease-out forwards speckit-flash;position:absolute;inset:-4px -16px}@keyframes indeterminate-bar{0%{transform:translate(-100%)scaleX(.2)}50%{transform:translate(0)scaleX(.5)}to{transform:translate(100%)scaleX(.2)}}.animate-indeterminate-bar{animation:1.5s linear infinite indeterminate-bar}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@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-divide-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@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-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@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}