@fapost/jig-ui 0.2.0-next.30 → 0.2.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.
- package/dist/board/columns.js +2 -14
- package/dist/http/app.js +1 -58
- package/dist/jig/client.js +4 -36
- package/dist/source/local.js +11 -47
- package/dist/web/assets/CanvasView-4RWri2ak.js +1 -0
- package/dist/web/assets/index-D1V3u6PF.css +2 -0
- package/dist/web/assets/index-DOnV4WX5.js +6 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/CanvasView-BlJ7Md7X.js +0 -1
- package/dist/web/assets/index-CIutMX5d.css +0 -2
- package/dist/web/assets/index-jvDNuXHj.js +0 -6
package/dist/board/columns.js
CHANGED
|
@@ -23,19 +23,7 @@ export function placeOf(task) {
|
|
|
23
23
|
const id = columnOf(task);
|
|
24
24
|
return { id, title: COLUMNS.find((c) => c.id === id)?.title ?? id };
|
|
25
25
|
}
|
|
26
|
-
/**
|
|
27
|
-
function byQueue(a, b) {
|
|
28
|
-
if (!a.queue || !b.queue)
|
|
29
|
-
return a.queue ? -1 : b.queue ? 1 : 0;
|
|
30
|
-
const [x, y] = [a.queue.level, b.queue.level];
|
|
31
|
-
if (x !== y)
|
|
32
|
-
return x === null ? -1 : y === null ? 1 : x < y ? -1 : 1;
|
|
33
|
-
return a.queue.position - b.queue.position;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* The board: every column, in a fixed order, its cards in Jig's queue order and the tasks not queued after them in the
|
|
37
|
-
* order Jig listed them (the sort is stable). Computed on every read, never stored.
|
|
38
|
-
*/
|
|
26
|
+
/** The board: every column, in a fixed order, its cards in the order Jig listed them. Computed on every read, never stored. */
|
|
39
27
|
export function columns(tasks) {
|
|
40
|
-
return COLUMNS.map((c) => ({ ...c, cards: tasks.filter((t) => columnOf(t) === c.id)
|
|
28
|
+
return COLUMNS.map((c) => ({ ...c, cards: tasks.filter((t) => columnOf(t) === c.id) }));
|
|
41
29
|
}
|
package/dist/http/app.js
CHANGED
|
@@ -32,32 +32,6 @@ function absolute(path) {
|
|
|
32
32
|
const expanded = path.trim().replace(/^~(?=$|[\\/])/, homedir());
|
|
33
33
|
return isAbsolute(expanded) ? expanded : undefined;
|
|
34
34
|
}
|
|
35
|
-
const isId = (v) => typeof v === 'string' && v !== '';
|
|
36
|
-
const isRevision = (v) => Number.isSafeInteger(v) && v >= 0;
|
|
37
|
-
const field = (body, key) => typeof body === 'object' && body !== null ? body[key] : undefined;
|
|
38
|
-
/** Where a drop puts a task: after another, or to the top or bottom of its level; `undefined` for anything else. */
|
|
39
|
-
function place(v) {
|
|
40
|
-
if (v === 'top' || v === 'bottom')
|
|
41
|
-
return v;
|
|
42
|
-
const after = field(v, 'after');
|
|
43
|
-
return isId(after) ? { after } : undefined;
|
|
44
|
-
}
|
|
45
|
-
/** A priority as the page sends it: 0 to 5, or `null` for none. */
|
|
46
|
-
const isPriority = (v) => v === null || (Number.isInteger(v) && v >= 0 && v <= 5);
|
|
47
|
-
/** What a write came to, in the API's form. A refusal names no path: only Jig's code goes on. */
|
|
48
|
-
function written(c, w) {
|
|
49
|
-
if (w === undefined)
|
|
50
|
-
return refuse(c, 404, 'not-connected', 'No connected project has this id.');
|
|
51
|
-
if (w.state === 'written')
|
|
52
|
-
return c.json({ written: true }, 200);
|
|
53
|
-
if (w.state !== 'refused')
|
|
54
|
-
return c.json({ project: w }, 200);
|
|
55
|
-
if (w.code === 'stale-revision')
|
|
56
|
-
return refuse(c, 409, w.code, 'The project changed since the board was read.');
|
|
57
|
-
if (w.code === 'not-found')
|
|
58
|
-
return refuse(c, 404, w.code, 'This project has no live task with this id.');
|
|
59
|
-
return refuse(c, 422, w.code, 'Jig refused the change.');
|
|
60
|
-
}
|
|
61
35
|
/**
|
|
62
36
|
* The API, chained so that its type carries every route's answers: the page derives its types
|
|
63
37
|
* from `AppType` and never declares them a second time.
|
|
@@ -73,8 +47,7 @@ function apiRoutes(source, version) {
|
|
|
73
47
|
return refuse(c, 404, 'not-connected', 'No connected project has this id.');
|
|
74
48
|
if (read.state !== 'ready')
|
|
75
49
|
return c.json({ board: read }, 200);
|
|
76
|
-
|
|
77
|
-
return c.json({ board: { id, state, columns: columns(read.tasks), finished, revision } }, 200);
|
|
50
|
+
return c.json({ board: { id, state: read.state, columns: columns(read.tasks), finished: read.finished } }, 200);
|
|
78
51
|
})
|
|
79
52
|
.get('/api/projects/:id/tasks/:task', async (c) => {
|
|
80
53
|
const read = await source.task(c.req.param('id'), c.req.param('task'));
|
|
@@ -91,36 +64,6 @@ function apiRoutes(source, version) {
|
|
|
91
64
|
if (read === undefined)
|
|
92
65
|
return refuse(c, 404, 'not-connected', 'No connected project has this id.');
|
|
93
66
|
return c.json({ specs: read }, 200);
|
|
94
|
-
})
|
|
95
|
-
// A write carries the revision of the board it was based on; Jig refuses it if anything was written since.
|
|
96
|
-
.post('/api/projects/:id/queue/move', validator('json', (body) => {
|
|
97
|
-
const [task, revision] = [field(body, 'task'), field(body, 'revision')];
|
|
98
|
-
return {
|
|
99
|
-
task: isId(task) ? task : undefined,
|
|
100
|
-
place: place(field(body, 'place')),
|
|
101
|
-
revision: isRevision(revision) ? revision : undefined,
|
|
102
|
-
};
|
|
103
|
-
}), async (c) => {
|
|
104
|
-
const { task, place, revision } = c.req.valid('json');
|
|
105
|
-
if (task === undefined || place === undefined || revision === undefined) {
|
|
106
|
-
return refuse(c, 422, 'usage', 'Give a task, where it goes and the revision it was read at.');
|
|
107
|
-
}
|
|
108
|
-
return written(c, await source.move(c.req.param('id'), task, place, revision));
|
|
109
|
-
})
|
|
110
|
-
.post('/api/projects/:id/queue/priority', validator('json', (body) => {
|
|
111
|
-
const [task, priority, revision] = [field(body, 'task'), field(body, 'priority'), field(body, 'revision')];
|
|
112
|
-
return {
|
|
113
|
-
task: isId(task) ? task : undefined,
|
|
114
|
-
// `undefined` for anything but 0 to 5 or null: a priority left out is no priority of none
|
|
115
|
-
priority: isPriority(priority) ? priority : undefined,
|
|
116
|
-
revision: isRevision(revision) ? revision : undefined,
|
|
117
|
-
};
|
|
118
|
-
}), async (c) => {
|
|
119
|
-
const { task, priority, revision } = c.req.valid('json');
|
|
120
|
-
if (task === undefined || priority === undefined || revision === undefined) {
|
|
121
|
-
return refuse(c, 422, 'usage', 'Give a task, a priority from 0 to 5 or null, and the revision it was read at.');
|
|
122
|
-
}
|
|
123
|
-
return written(c, await source.prioritise(c.req.param('id'), task, priority, revision));
|
|
124
67
|
})
|
|
125
68
|
.post('/api/projects', validator('json', (body) => ({
|
|
126
69
|
path: absolute(body?.path),
|
package/dist/jig/client.js
CHANGED
|
@@ -4,8 +4,8 @@ import { join, resolve } from 'node:path';
|
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
const run = promisify(execFile);
|
|
7
|
-
/** The oldest Jig Jig UI
|
|
8
|
-
export const MIN_JIG_VERSION = '0.
|
|
7
|
+
/** The oldest Jig whose reads Jig UI understands: 0.29.0 is the first that prints JSON. */
|
|
8
|
+
export const MIN_JIG_VERSION = '0.29.0';
|
|
9
9
|
const SCRIPT = join('.ai', 'scripts', 'jig');
|
|
10
10
|
const TIMEOUT_MS = 10_000;
|
|
11
11
|
/** The directory whose changes may change what Jig reports: the main checkout's `.ai/`. */
|
|
@@ -58,7 +58,7 @@ export class JigRefusal extends Error {
|
|
|
58
58
|
this.code = code;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
const CODES = new Set(['usage', 'not-a-repository', 'not-initialised', '
|
|
61
|
+
const CODES = new Set(['usage', 'not-a-repository', 'not-initialised', 'failed']);
|
|
62
62
|
/** Jig answered in a shape this Jig UI does not read: a Jig newer than the contract its tests pin. */
|
|
63
63
|
export class JigShapeError extends Error {
|
|
64
64
|
constructor() {
|
|
@@ -67,7 +67,7 @@ export class JigShapeError extends Error {
|
|
|
67
67
|
}
|
|
68
68
|
const isObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
69
69
|
/**
|
|
70
|
-
* Runs a `--json`
|
|
70
|
+
* Runs a `--json` read and returns its `data` and the clone's revision. Jig's refusal throws
|
|
71
71
|
* JigRefusal, as does output that is no JSON at all (a crash); an envelope of another shape throws
|
|
72
72
|
* JigShapeError.
|
|
73
73
|
*/
|
|
@@ -243,38 +243,6 @@ export async function readSpecs(root, platform = process.platform) {
|
|
|
243
243
|
const { data } = await readJson(root, ['spec', 'list'], platform);
|
|
244
244
|
return parsed(SpecList, data).specs;
|
|
245
245
|
}
|
|
246
|
-
/** A task in Jig's queue: its level (`null` the top, `epic:<spec>` an open epic's), its place there, its priority. */
|
|
247
|
-
const QueueItem = z.object({
|
|
248
|
-
kind: text,
|
|
249
|
-
id: text,
|
|
250
|
-
level: maybe,
|
|
251
|
-
/** Sparse; compared only within one level. */
|
|
252
|
-
position: z.int(),
|
|
253
|
-
/** 0, the most urgent, to 5; `null` unset. A label: the order is `position`'s. */
|
|
254
|
-
priority: z.int().min(0).max(5).nullable(),
|
|
255
|
-
});
|
|
256
|
-
const Queue = z.object({ items: z.array(QueueItem) });
|
|
257
|
-
/** The tasks in the project's queue (`jig queue list --json`), in Jig's order; a task not queued is not there, nor is an epic. */
|
|
258
|
-
export async function readQueue(root, platform = process.platform) {
|
|
259
|
-
const { revision, data } = await readJson(root, ['queue', 'list'], platform);
|
|
260
|
-
const items = parsed(Queue, data)
|
|
261
|
-
.items.filter((i) => i.kind === 'task')
|
|
262
|
-
.map(({ id, level, position, priority }) => ({ id, level, position, priority }));
|
|
263
|
-
return { revision, items };
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Moves a task in the queue (`jig queue move`), adding it when it is not there; refused as `stale-revision`
|
|
267
|
-
* when anything was written in the clone since `revision`. Ids go to Jig as `task:<id>`, never as a flag.
|
|
268
|
-
*/
|
|
269
|
-
export async function moveInQueue(root, task, place, revision, platform = process.platform) {
|
|
270
|
-
const where = place === 'top' ? ['--top'] : place === 'bottom' ? ['--bottom'] : ['--after', `task:${place.after}`];
|
|
271
|
-
await readJson(root, ['queue', 'move', `task:${task}`, ...where, '--revision', String(revision)], platform);
|
|
272
|
-
}
|
|
273
|
-
/** Sets a task's priority in the queue (`jig queue set`), `null` for none; refused as `moveInQueue` is. */
|
|
274
|
-
export async function setPriority(root, task, priority, revision, platform = process.platform) {
|
|
275
|
-
const value = priority === null ? 'none' : String(priority);
|
|
276
|
-
await readJson(root, ['queue', 'set', `task:${task}`, '--priority', value, '--revision', String(revision)], platform);
|
|
277
|
-
}
|
|
278
246
|
/** True when `version` is at least the minimum Jig UI reads. */
|
|
279
247
|
export function supports(version, minimum = MIN_JIG_VERSION) {
|
|
280
248
|
const a = version.split('.').map(Number);
|
package/dist/source/local.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
-
import { JigRefusal, JigShapeError, jigVersion, MIN_JIG_VERSION,
|
|
2
|
+
import { JigRefusal, JigShapeError, jigVersion, MIN_JIG_VERSION, readSpecs, readStatus, readTasks, supports, watchDir, writtenByReads, } from '../jig/client.js';
|
|
3
3
|
import { addProject, readProjects, removeProject } from '../registry/projects.js';
|
|
4
4
|
import { watchTree } from '../watch/watch.js';
|
|
5
5
|
import { mainCheckout } from './checkout.js';
|
|
@@ -33,8 +33,8 @@ function count(tasks) {
|
|
|
33
33
|
ready: tasks.filter((t) => t.status === 'ready' && !t.paused).length,
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
-
/** A live task as a board's card shows it
|
|
37
|
-
const card = (t
|
|
36
|
+
/** A live task as a board's card shows it. */
|
|
37
|
+
const card = (t) => ({
|
|
38
38
|
id: t.id,
|
|
39
39
|
class: t.class,
|
|
40
40
|
status: t.status,
|
|
@@ -44,12 +44,10 @@ const card = (t, q) => ({
|
|
|
44
44
|
gate: t.gate?.state ?? null,
|
|
45
45
|
autopilot: t.autopilot?.state ?? null,
|
|
46
46
|
pullRequest: t.pullRequest,
|
|
47
|
-
priority: q?.priority ?? null,
|
|
48
|
-
queue: q ? { level: q.level, position: q.position } : null,
|
|
49
47
|
});
|
|
50
48
|
/** A live task in full; where its worktree is was never read, and an action Jig refuses is left out. */
|
|
51
|
-
const details = (t,
|
|
52
|
-
...card(t
|
|
49
|
+
const details = (t, attention) => ({
|
|
50
|
+
...card(t),
|
|
53
51
|
issue: t.issue,
|
|
54
52
|
branch: t.branch,
|
|
55
53
|
baseBranch: t.baseBranch,
|
|
@@ -94,17 +92,14 @@ async function reading({ id, path }, read) {
|
|
|
94
92
|
}
|
|
95
93
|
async function readProject(project) {
|
|
96
94
|
const read = await reading(project, async (root, jigVersion) => {
|
|
97
|
-
const [status, list,
|
|
98
|
-
return { status, list,
|
|
95
|
+
const [status, list, specs] = await Promise.all([readStatus(root), readTasks(root), readSpecs(root)]);
|
|
96
|
+
return { status, list, specs, jigVersion };
|
|
99
97
|
});
|
|
100
98
|
if (!('list' in read))
|
|
101
99
|
return { view: read, tasks: read, details: [], specs: read, revision: null };
|
|
102
|
-
const { status, list,
|
|
100
|
+
const { status, list, specs, jigVersion } = read;
|
|
103
101
|
// Jig's live list holds active and ready tasks only.
|
|
104
102
|
const live = list.tasks.filter((t) => t.status === 'active' || t.status === 'ready');
|
|
105
|
-
const queued = new Map(queue.items.map((q) => [q.id, q]));
|
|
106
|
-
// The oldest of the reads the board is made of: a write against it is refused if anything was written after any of them.
|
|
107
|
-
const revision = Math.min(status.revision, list.revision, queue.revision);
|
|
108
103
|
return {
|
|
109
104
|
view: {
|
|
110
105
|
id: project.id,
|
|
@@ -114,10 +109,10 @@ async function readProject(project) {
|
|
|
114
109
|
attention: status.attention,
|
|
115
110
|
housekeepingStale: status.housekeepingStale,
|
|
116
111
|
},
|
|
117
|
-
tasks: { state: 'ready', tasks: live.map(
|
|
118
|
-
details: live.map((t) => details(t,
|
|
112
|
+
tasks: { state: 'ready', tasks: live.map(card), finished: list.hidden },
|
|
113
|
+
details: live.map((t) => details(t, status.attention)),
|
|
119
114
|
specs: { state: 'ready', specs },
|
|
120
|
-
revision,
|
|
115
|
+
revision: list.revision,
|
|
121
116
|
};
|
|
122
117
|
}
|
|
123
118
|
/** A read that may have caught Jig mid-write: worth one more try before it is believed. */
|
|
@@ -246,30 +241,6 @@ export function localSource(configDir, { rescanMs = 60_000, quietMs, maxWaitMs }
|
|
|
246
241
|
entry.held = false;
|
|
247
242
|
}
|
|
248
243
|
}
|
|
249
|
-
/**
|
|
250
|
-
* Runs a write in a project once every task it names is live in what the project shows — so nothing but an id
|
|
251
|
-
* Jig itself listed reaches Jig's arguments — then reads the project again, refused or not: the page reads next.
|
|
252
|
-
*/
|
|
253
|
-
async function writing(id, taskIds, write) {
|
|
254
|
-
const project = (await readProjects(configDir)).find((p) => p.id === id);
|
|
255
|
-
if (!project)
|
|
256
|
-
return undefined;
|
|
257
|
-
const { tasks } = await shown(project);
|
|
258
|
-
if (tasks.state !== 'ready')
|
|
259
|
-
return tasks;
|
|
260
|
-
if (!taskIds.every((t) => tasks.tasks.some((live) => live.id === t)))
|
|
261
|
-
return { state: 'refused', code: 'not-found' };
|
|
262
|
-
let written = { state: 'written' };
|
|
263
|
-
try {
|
|
264
|
-
await write(project.path);
|
|
265
|
-
}
|
|
266
|
-
catch (error) {
|
|
267
|
-
// Only the code goes on: Jig's message may name a path.
|
|
268
|
-
written = { state: 'refused', code: error instanceof JigRefusal ? error.code : 'failed' };
|
|
269
|
-
}
|
|
270
|
-
await refresh(entryOf(project));
|
|
271
|
-
return written;
|
|
272
|
-
}
|
|
273
244
|
return {
|
|
274
245
|
async workspace() {
|
|
275
246
|
return Promise.all((await readProjects(configDir)).map(async (p) => (await shown(p)).view));
|
|
@@ -305,13 +276,6 @@ export function localSource(configDir, { rescanMs = 60_000, quietMs, maxWaitMs }
|
|
|
305
276
|
const project = (await readProjects(configDir)).find((p) => p.id === id);
|
|
306
277
|
return project && (await shown(project)).specs;
|
|
307
278
|
},
|
|
308
|
-
move(id, taskId, place, revision) {
|
|
309
|
-
const named = typeof place === 'object' ? [taskId, place.after] : [taskId];
|
|
310
|
-
return writing(id, named, (root) => moveInQueue(root, taskId, place, revision));
|
|
311
|
-
},
|
|
312
|
-
prioritise(id, taskId, priority, revision) {
|
|
313
|
-
return writing(id, [taskId], (root) => setPriority(root, taskId, priority, revision));
|
|
314
|
-
},
|
|
315
279
|
async disconnect(id) {
|
|
316
280
|
if (!(await removeProject(configDir, id)))
|
|
317
281
|
return false;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,B as t,C as n,D as r,E as i,F as a,G as o,H as s,I as c,J as l,K as u,L as d,M as ee,N as te,O as f,P as p,Q as m,R as h,S as ne,T as re,U as g,V as _,W as v,X as y,Y as b,Z as x,_ as S,a as ie,b as C,c as ae,d as w,f as oe,g as T,h as E,i as D,j as O,k,l as se,m as ce,n as A,o as j,p as le,q as M,r as ue,s as de,t as fe,u as pe,v as me,w as he,x as N,y as P,z as F}from"./index-DOnV4WX5.js";var I=s({__name:`BaseSeparator`,props:{orientation:{type:String,required:!1,default:`horizontal`},decorative:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(e){let t=e,n=[`horizontal`,`vertical`];function r(e){return n.includes(e)}let i=a(()=>r(t.orientation)?t.orientation:`horizontal`),s=a(()=>i.value===`vertical`?t.orientation:void 0),c=a(()=>t.decorative?{role:`none`}:{"aria-orientation":s.value,role:`separator`});return(t,n)=>(o(),d(b(f),v({as:e.as,"as-child":e.asChild,"data-orientation":i.value},c.value),{default:l(()=>[M(t.$slots,`default`)]),_:3},16,[`as`,`as-child`,`data-orientation`]))}}),L=s({__name:`Separator`,props:{orientation:{type:String,required:!1,default:`horizontal`},decorative:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(e){let t=e;return(e,n)=>(o(),d(I,x(g(t)),{default:l(()=>[M(e.$slots,`default`)]),_:3},16))}}),R=s({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e;return(e,n)=>(o(),F(`div`,{"data-slot":`card-content`,class:y(b(k)(`px-4 group-data-[size=sm]/card:px-3`,t.class))},[M(e.$slots,`default`)],2))}}),ge=s({__name:`CardDescription`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e;return(e,n)=>(o(),F(`div`,{"data-slot":`card-description`,class:y(b(k)(`text-xs/relaxed text-muted-foreground`,t.class))},[M(e.$slots,`default`)],2))}}),_e=s({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e;return(e,n)=>(o(),F(`div`,{"data-slot":`card-header`,class:y(b(k)(`group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-none px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3`,t.class))},[M(e.$slots,`default`)],2))}}),ve=s({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e;return(e,n)=>(o(),F(`div`,{"data-slot":`card-title`,class:y(b(k)(`cn-font-heading text-sm font-medium group-data-[size=sm]/card:text-sm`,t.class))},[M(e.$slots,`default`)],2))}}),z=s({__name:`Separator`,props:{orientation:{default:`horizontal`},decorative:{type:Boolean,default:!0},asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e,n=he(t,`class`);return(e,r)=>(o(),d(b(L),v({"data-slot":`separator`},b(n),{class:b(k)(`shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch`,t.class)}),null,16,[`class`]))}}),ye=[`aria-label`],be={class:`flex items-baseline gap-3 border-b bg-muted/50 px-4 py-2`},xe={class:`font-semibold tracking-wider uppercase`},Se={key:0,class:`text-muted-foreground`},Ce={class:`grid grid-cols-1 divide-y lg:grid-cols-2 lg:divide-x lg:divide-y-0`},B=s({__name:`CanvasSection`,props:{title:{},note:{}},setup(e){return(t,n)=>(o(),F(`section`,{"aria-label":e.title,class:`border-b`},[c(`h2`,be,[c(`span`,xe,m(e.title),1),e.note?(o(),F(`span`,Se,m(e.note),1)):h(``,!0)]),c(`div`,Ce,[(o(),F(p,null,u([`light`,`dark`],e=>c(`div`,{key:e,class:y([e,`flex flex-col gap-4 bg-background p-4 text-foreground`])},[M(t.$slots,`default`)],2)),64))])],8,ye))}}),V=(e,t)=>({id:e,class:`T2`,status:`active`,goal:null,paused:!1,started:!0,gate:null,autopilot:null,pullRequest:null,...t}),H=(e,t)=>({url:`https://github.com/fapost-lab/jig-ui/pull/18`,state:e,ci:t,fetchedAt:`2026-10-18T09:40:00Z`}),U=[V(`design-system`,{class:`T3`,gate:`waiting`,goal:`shadcn-vue on Tailwind v4 with light and dark themes; #/canvas with every component in every variant; the three screens rebuilt on it.`}),V(`registry-schema`,{gate:`changed`,goal:`Version the registry file so a newer Jig UI can read an older one.`}),V(`pause-request`,{class:`T3`,autopilot:`stopped`,goal:`A drop on the paused column writes a sticky request through Jig; the card shows it with its age and a cancel.`}),V(`specs-and-epics`,{autopilot:`on`,goal:`Show each spec with its phases, progress and epic branch beside the board, from Jig's spec list.`}),V(`task-details`,{status:`ready`,pullRequest:H(`open`,`green`),goal:`Open a task's details from its card.`}),V(`refusal-fixture`,{class:`T0`,status:`ready`,pullRequest:H(`open`,`red`),goal:`Replace the refusal text in task-list-states.json with one Jig prints.`}),V(`docs-board`,{class:`T1`,status:`ready`,pullRequest:H(`open`,`pending`),goal:`Describe the five columns on the projects page of the docs.`}),V(`live-updates`,{status:`ready`,pullRequest:H(`merged`,`none`),goal:`Follow connected projects without a reload.`}),V(`no-pr-yet`,{class:`T1`,status:`ready`,goal:`Ready, nothing pushed.`}),V(`jig-init-hook`,{class:`T3`,paused:!0,goal:`Register a project in an installed Jig UI from jig init.`}),V(`file-backlog-task`,{class:null,started:!1,goal:`File a minimal backlog task from the page through jig task new.`}),V(`a-task-with-a-rather-long-identifier-that-wraps`,{goal:null})],W=[{id:`needs-you`,title:`Needs you`,cards:U.slice(0,3)},{id:`in-progress`,title:`In progress`,cards:[U[3],U[11]]},{id:`ready`,title:`Ready`,cards:U.slice(4,9)},{id:`backlog`,title:`Backlog`,cards:[U[10]]},{id:`paused`,title:`Paused`,cards:[U[9]]}],G=W.map(e=>({...e,cards:[]})),we=[{id:`needs-you`,title:`Needs you`,count:3},{id:`in-progress`,title:`In progress`,count:1},{id:`ready`,title:`Ready`,count:5},{id:`backlog`,title:`Backlog`,count:1},{id:`paused`,title:`Paused`,count:1},{id:`unknown`,title:`A column this page does not know`,count:0}],K=[{kind:`gate`,subject:{type:`task`,id:`design-system`},tasks:[`design-system`],title:`Design waits at its gate`,detail:null,todo:`Review the design and approve it: jig task gate design-system approved`,url:null},{kind:`pull-request-ci-failed`,subject:{type:`task`,id:`refusal-fixture`},tasks:[`refusal-fixture`],title:`CI failed`,detail:`pull request #19`,todo:`Look at the failing check.`,url:`https://github.com/fapost-lab/jig-ui/pull/19`},{kind:`housekeeping`,subject:{type:`project`,id:null},tasks:[],title:`Housekeeping never ran`,detail:null,todo:`Run jig housekeeping.`,url:`https://example.com/docs`}],q=[{id:`approve-gate`,command:`jig task gate design-system approved`},{id:`answer-stop`,command:`jig task autopilot pause-request resume --answer <text>`},{id:`pause`,command:`jig task pause design-system`},{id:`something-new`,command:`jig task something-new design-system`}],J={state:`ready`,issue:null,baseBranch:`main`,createdAt:`2026-10-17`,updatedAt:`2026-10-18`,knowledgeConsolidated:!1,worktree:null,gateBy:null,run:null,housekeepingFlags:[],attention:[]},Y=[{...J,...U[2],gate:`approved`,gateBy:`human`,branch:`task/pause-request`,worktree:{uncommitted:4},issue:`#42`,pullRequest:H(`open`,`red`),run:{mode:`attended`,stage:`implement`,stageAt:`2026-10-18T09:00:00Z`,stopReason:`Which column takes a paused task that already has an open pull request?`,stopAt:`2026-10-18T09:12:00Z`,phase:null},housekeepingFlags:[`needs-consolidation`],attention:[K[0]],actions:q,column:{id:`needs-you`,title:`Needs you`}},{...J,...U[10],branch:null,actions:[{id:`start`,command:`jig task start file-backlog-task`}],column:{id:`backlog`,title:`Backlog`}}],X=(e,t={})=>({id:e,state:`ready`,jigVersion:`0.29.0`,counts:{active:11,paused:1,ready:3},attention:[],housekeepingStale:!1,...t}),Z=[X(`jig-ui`,{attention:K,housekeepingStale:!0}),X(`nextjs-store`,{counts:{active:0,paused:0,ready:0}}),{id:`old-jig`,state:`unsupported`,jigVersion:`0.26.0`,minimum:`0.29.0`},{id:`new-jig`,state:`incompatible`,jigVersion:`1.0.0`},{id:`busy`,state:`unreadable`,code:`locked`},{id:`moved`,state:`unavailable`,reason:`missing`}],Q=[{text:"`design-system` — design system and canvas",checked:!0,task:`design-system`,fog:!1},{text:"`specs-and-epics` — specs and epics (after: project board — `jig spec list`)",checked:!1,task:`specs-and-epics`,fog:!1},{text:"`old-task` — a task no longer live",checked:!1,task:`old-task`,fog:!1},{text:`invoices from orders, no task filed yet`,checked:!1,task:null,fog:!1},{text:"fog: registration by `jig init`",checked:!1,task:null,fog:!0}],Te=[{id:`jig-ui`,title:`Jig UI — a local control center for Jig projects`,missingFiles:[],release:null,epic:null,progress:{done:2,total:6,filed:2,fog:1},phases:[{phase:0,title:`Package and release`,done:1,total:1,filed:0,fog:0,items:[{...Q[0],text:`package and release`,task:null}]},{phase:1,title:`Read-only UI`,done:1,total:5,filed:2,fog:1,items:Q}]},{id:`billing`,title:`Billing in one place`,missingFiles:[],release:`minor`,epic:{branch:`epic/billing`,state:`open`,checkedOut:!1,missing:!1,fetched:!0},progress:{done:0,total:1,filed:0,fog:0},phases:[{phase:null,title:null,done:0,total:1,filed:0,fog:0,items:[Q[3]]}]},{id:`lost-epic`,title:`An epic whose branch is gone`,missingFiles:[],release:`major`,epic:{branch:`epic/lost`,state:`open`,checkedOut:!0,missing:!0,fetched:!1},progress:null,phases:[]},{id:`half-written`,title:null,missingFiles:[`spec.md`,`roadmap.md`],release:null,epic:null,progress:null,phases:[]}],Ee={class:`flex gap-4`},De={class:`w-24 text-muted-foreground`},Oe={class:`flex items-center gap-2`},ke={class:`flex flex-wrap gap-2`},Ae={class:`flex max-w-sm flex-col gap-2`},$={class:`flex h-5 items-center gap-2`},je={class:`grid grid-cols-2 gap-2 xl:grid-cols-3`},Me={class:`flex h-[28rem] flex-col`},Ne={class:`flex h-40 flex-col`},Pe={class:`flex h-[28rem] flex-col`},Fe={class:`flex h-64 flex-col`},Ie={class:`flex h-64 flex-col`},Le=s({__name:`CanvasView`,setup(a){let s=[`default`,`secondary`,`outline`,`ghost`,`destructive`,`link`],f=[`xs`,`sm`,`default`,`lg`],h=[`icon-xs`,`icon-sm`,`icon`,`icon-lg`],g=[`default`,`secondary`,`outline`,`ghost`,`destructive`,`link`],v=[`attention`,`good`,`bad`,`quiet`];return(a,x)=>(o(),F(`div`,null,[x[12]||=c(`div`,{class:`border-b px-4 py-3`},[c(`h1`,{class:`font-semibold tracking-wider uppercase`},`Canvas`),c(`p`,{class:`text-muted-foreground`},`Every component of the page in every variant and state; the left panel light, the right dark.`)],-1),_(B,{title:`Tones`,note:`lib/tones.ts — the only colours with a meaning`},{default:l(()=>[(o(),F(p,null,u(v,e=>c(`p`,{key:e,class:y(b(ee)[e])},m(e)+` as a rule`,3)),64)),c(`p`,Ee,[(o(),F(p,null,u(v,e=>c(`span`,{key:e,class:y(b(te)[e])},m(e),3)),64))])]),_:1}),x[13]||=c(`h2`,{class:`border-b px-4 py-2 font-bold tracking-widest uppercase`},`components/ui`,-1),_(B,{title:`Button`,note:`variant × size; icon sizes; disabled`},{default:l(()=>[(o(),F(p,null,u(s,e=>c(`div`,{key:e,class:`flex flex-wrap items-center gap-2`},[c(`span`,De,m(e),1),(o(),F(p,null,u(f,n=>_(b(r),{key:n,variant:e,size:n},{default:l(()=>[t(m(n),1)]),_:2},1032,[`variant`,`size`])),64)),_(b(r),{variant:e,disabled:``},{default:l(()=>[...x[0]||=[t(`disabled`,-1)]]),_:1},8,[`variant`])])),64)),c(`div`,Oe,[x[2]||=c(`span`,{class:`w-24 text-muted-foreground`},`icon`,-1),(o(),F(p,null,u(h,t=>_(b(r),{key:t,variant:`outline`,size:t,"aria-label":t},{default:l(()=>[_(b(e))]),_:1},8,[`size`,`aria-label`])),64)),_(b(r),{variant:`outline`,size:`sm`},{default:l(()=>[_(b(e),{"data-icon":`inline-start`}),x[1]||=t(`with icon`,-1)]),_:1})])]),_:1}),_(B,{title:`Badge`},{default:l(()=>[c(`div`,ke,[(o(),F(p,null,u(g,e=>_(b(n),{key:e,variant:e},{default:l(()=>[t(m(e),1)]),_:2},1032,[`variant`])),64))])]),_:1}),_(B,{title:`Card`},{default:l(()=>[_(b(ne),{class:`max-w-sm`},{default:l(()=>[_(b(_e),null,{default:l(()=>[_(b(ve),null,{default:l(()=>[...x[3]||=[t(`Card title`,-1)]]),_:1}),_(b(ge),null,{default:l(()=>[...x[4]||=[t(`Card description, muted.`,-1)]]),_:1})]),_:1}),_(b(R),null,{default:l(()=>[...x[5]||=[t(`Card content.`,-1)]]),_:1})]),_:1})]),_:1}),_(B,{title:`Input and Label`,note:`empty, filled, invalid, disabled`},{default:l(()=>[c(`div`,Ae,[_(b(ue),null,{default:l(()=>[...x[6]||=[t(`Project path`,-1)]]),_:1}),_(b(D),{placeholder:`/path/to/project`}),_(b(D),{"model-value":`/Users/me/project`}),_(b(D),{"model-value":`/not/a/project`,"aria-invalid":`true`}),_(b(D),{"model-value":`disabled`,disabled:``})])]),_:1}),_(B,{title:`Separator`},{default:l(()=>[_(b(z)),c(`div`,$,[x[7]||=t(`left`,-1),_(b(z),{orientation:`vertical`}),x[8]||=t(`right`,-1)])]),_:1}),_(B,{title:`ToggleGroup`,note:`the Board / List switch`},{default:l(()=>[_(b(de),{type:`single`,variant:`outline`,size:`sm`,"model-value":`board`,"aria-label":`View`},{default:l(()=>[_(b(j),{value:`board`},{default:l(()=>[...x[9]||=[t(`Board`,-1)]]),_:1}),_(b(j),{value:`list`},{default:l(()=>[...x[10]||=[t(`List`,-1)]]),_:1})]),_:1})]),_:1}),_(B,{title:`Collapsible`,note:`open and folded`},{default:l(()=>[(o(),F(p,null,u([!0,!1],e=>_(b(E),{key:String(e),"default-open":e},{default:l(()=>[_(b(le),{class:`w-full border-b bg-muted/50 px-3 py-1.5 text-left`},{default:l(()=>[t(`Trigger (`+m(e?`open`:`folded`)+`)`,1)]),_:2},1024),_(b(ce),{class:`px-3 py-2`},{default:l(()=>[...x[11]||=[t(`Content`,-1)]]),_:1})]),_:2},1032,[`default-open`])),64))]),_:1}),x[14]||=c(`h2`,{class:`border-b px-4 py-2 font-bold tracking-widest uppercase`},`components`,-1),_(B,{title:`ProjectTabs`,note:`on the workspace; on a project; empty`},{default:l(()=>[_(O,{projects:b(Z),version:`0.1.0`},{default:l(()=>[_(i)]),_:1},8,[`projects`]),_(O,{projects:b(Z),current:`jig-ui`,version:`0.1.0`},null,8,[`projects`]),_(O,{projects:[]})]),_:1}),_(B,{title:`ThemeToggle`,note:`switches the whole page; the icon is the theme it switches to`},{default:l(()=>[c(`div`,null,[_(i)])]),_:1}),_(B,{title:`ProjectCard`,note:`ready with attention and stale housekeeping; nothing needs you; each state it cannot be read in`},{default:l(()=>[(o(!0),F(p,null,u(b(Z),e=>(o(),d(fe,{key:e.id,project:e},null,8,[`project`]))),128))]),_:1}),_(B,{title:`ConnectForm`,note:`idle, busy, refused`},{default:l(()=>[_(A,{busy:!1}),_(A,{busy:!0,"model-value":`/Users/me/project`}),_(A,{busy:!1,"model-value":`/Users/me/project/.claude/worktrees/x`,refusal:`That is a worktree. Connect the main checkout instead.`})]),_:1}),_(B,{title:`AttentionItem`,note:`no link; a pull request; another link`},{default:l(()=>[(o(!0),F(p,null,u(b(K),(e,t)=>(o(),d(ie,{key:t,item:e},null,8,[`item`]))),128))]),_:1}),_(B,{title:`ColumnHeader`,note:`each column, and one this page does not know`},{default:l(()=>[(o(!0),F(p,null,u(b(we),e=>(o(),d(re,{id:e.id,key:e.id,title:e.title,count:e.count},null,8,[`id`,`title`,`count`]))),128))]),_:1}),_(B,{title:`TaskCard`,note:`every note a card carries; open with details, while reading, unreadable`},{default:l(()=>[c(`div`,je,[(o(!0),F(p,null,u(b(U),e=>(o(),d(S,{key:e.id,project:`jig-ui`,task:e,open:!1},null,8,[`task`]))),128)),_(S,{project:`jig-ui`,task:b(U)[2],open:!0,details:b(Y)[0]},null,8,[`task`,`details`]),_(S,{project:`jig-ui`,task:b(U)[0],open:!0},null,8,[`task`]),_(S,{project:`jig-ui`,task:b(U)[1],open:!0,details:`unavailable`},null,8,[`task`])])]),_:1}),_(B,{title:`TaskRow`,note:`each note; selected`},{default:l(()=>[c(`div`,null,[(o(!0),F(p,null,u(b(U),(e,t)=>(o(),d(oe,{key:e.id,task:e,selected:t===2},null,8,[`task`,`selected`]))),128))])]),_:1}),_(B,{title:`BoardColumns`,note:`cards in every column, one open with its details; no live task`},{default:l(()=>[c(`div`,Me,[_(T,{project:`jig-ui`,columns:b(W),selected:b(U)[2].id,details:b(Y)[0]},null,8,[`columns`,`selected`,`details`])]),c(`div`,Ne,[_(T,{project:`jig-ui`,columns:b(G)},null,8,[`columns`])])]),_:1}),_(B,{title:`BoardList`,note:`a row picked with its details; nothing picked; no live task`},{default:l(()=>[c(`div`,Pe,[_(w,{project:`jig-ui`,columns:b(W),selected:b(U)[2].id,details:b(Y)[0]},null,8,[`columns`,`selected`,`details`])]),c(`div`,Fe,[_(w,{project:`jig-ui`,columns:b(W)},null,8,[`columns`])]),c(`div`,Ie,[_(w,{project:`jig-ui`,columns:b(G)},null,8,[`columns`])])]),_:1}),_(B,{title:`TaskFacts`,note:`everything a task can carry; a task not started`},{default:l(()=>[(o(!0),F(p,null,u(b(Y),e=>(o(),d(P,{key:e.id,details:e,class:`border-b pb-3`},null,8,[`details`]))),128))]),_:1}),_(B,{title:`TaskBrief`,note:`facts, actions and the link to the full page`},{default:l(()=>[_(me,{project:`jig-ui`,task:b(Y)[1].id,details:b(Y)[1]},null,8,[`task`,`details`])]),_:1}),_(B,{title:`ActionList`,note:`Jig's offers, one unknown id; none`},{default:l(()=>[_(C,{actions:b(q)},null,8,[`actions`]),_(C,{actions:[]})]),_:1}),_(B,{title:`CopyCommand`,note:`short; long enough to be cut`},{default:l(()=>[_(N,{command:`jig task pause design-system`}),_(N,{command:`jig task autopilot a-task-with-a-rather-long-identifier-that-wraps resume --answer 'a long answer to the question'`,class:`max-w-xs`})]),_:1}),_(B,{title:`ProgressBar`,note:`none, part, all, an empty roadmap`},{default:l(()=>[(o(),F(p,null,u([[0,4],[3,9],[5,5],[0,0]],([e,t])=>_(pe,{key:`${e}/${t}`,done:e,total:t},null,8,[`done`,`total`])),64))]),_:1}),_(B,{title:`SpecItemRow`,note:`done with a live task; open with dependencies; a task no longer live; no task; fog`},{default:l(()=>[c(`ul`,null,[(o(!0),F(p,null,u(b(Q),(e,t)=>(o(),d(se,{key:t,item:e,project:`jig-ui`,live:t<2},null,8,[`item`,`live`]))),128))])]),_:1}),_(B,{title:`SpecCard`,note:`no epic, a finished phase folded; an open epic as of the last fetch; a lost epic branch; missing files`},{default:l(()=>[(o(!0),F(p,null,u(b(Te),e=>(o(),d(ae,{key:e.id,spec:e,project:`jig-ui`,live:[`design-system`,`specs-and-epics`]},null,8,[`spec`]))),128))]),_:1})]))}});export{Le as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | 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-divide-x-reverse:0;--tw-border-style:solid;--tw-divide-y-reverse:0;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction: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-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:"JetBrains Mono Variable", ui-monospace, monospace;--color-amber-300:oklch(87.9% .169 91.605);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-700:oklch(55.5% .163 48.998);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-700:oklch(50.8% .118 165.612);--color-sky-500:oklch(68.5% .169 237.323);--color-slate-400:oklch(70.4% .04 256.788);--color-zinc-400:oklch(70.5% .015 286.067);--color-black:#000;--spacing:.25rem;--container-xs:20rem;--container-sm:24rem;--container-3xl:48rem;--container-4xl:56rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wider:.05em;--tracking-widest:.1em;--leading-relaxed:1.625;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:"JetBrains Mono Variable", ui-monospace, monospace}}@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,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, 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:where(:not(iframe)){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}*{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:JetBrains Mono Variable,ui-monospace,monospace;font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--foreground)}}@layer components;@layer utilities{.\@container\/card-header{container:card-header/inline-size}.\@container{container-type:inline-size}.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}.sticky{position:sticky}.top-0{top:0}.z-10{z-index:10}.col-start-2{grid-column-start:2}.row-span-2{grid-row:span 2/span 2}.row-start-1{grid-row-start:1}.mx-auto{margin-inline:auto}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mb-1{margin-bottom:var(--spacing)}.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-flex{display:inline-flex}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.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-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-3{height:calc(var(--spacing) * 3)}.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-40{height:calc(var(--spacing) * 40)}.h-64{height:calc(var(--spacing) * 64)}.h-\[28rem\]{height:28rem}.h-full{height:100%}.h-screen{height:100vh}.min-h-0{min-height:0}.w-1{width:var(--spacing)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-24{width:calc(var(--spacing) * 24)}.w-40{width:calc(var(--spacing) * 40)}.w-96{width:calc(var(--spacing) * 96)}.w-fit{width:fit-content}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-sm{max-width:var(--container-sm)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:0}.min-w-7{min-width:calc(var(--spacing) * 7)}.min-w-8{min-width:calc(var(--spacing) * 8)}.min-w-9{min-width:calc(var(--spacing) * 9)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.auto-rows-min{grid-auto-rows:min-content}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\[repeat\(5\,minmax\(14rem\,1fr\)\)\]{grid-template-columns:repeat(5,minmax(14rem,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.gap-1{gap:var(--spacing)}.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-\[--spacing\(var\(--gap\)\)\]{gap:calc(var(--spacing) * var(--gap))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-y-1{row-gap:var(--spacing)}: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)))}.self-start{align-self:flex-start}.justify-self-end{justify-self:flex-end}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-none{border-radius:0}.border{border-style:var(--tw-border-style);border-width:1px}.border-y{border-block-style:var(--tw-border-style);border-block-width:1px}.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-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-amber-500{border-color:var(--color-amber-500)}.border-border{border-color:var(--border)}.border-destructive{border-color:var(--destructive)}.border-emerald-500{border-color:var(--color-emerald-500)}.border-input{border-color:var(--input)}.border-transparent{border-color:#0000}.bg-amber-500{background-color:var(--color-amber-500)}.bg-background{background-color:var(--background)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.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-emerald-500{background-color:var(--color-emerald-500)}.bg-foreground{background-color:var(--foreground)}.bg-muted,.bg-muted\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-sky-500{background-color:var(--color-sky-500)}.bg-slate-400{background-color:var(--color-slate-400)}.bg-transparent{background-color:#0000}.bg-zinc-400{background-color:var(--color-zinc-400)}.bg-clip-padding{background-clip:padding-box}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-2{padding-left:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-xs\/relaxed{font-size:var(--text-xs);line-height:var(--leading-relaxed)}.leading-none{--tw-leading:1;line-height:1}.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-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-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-background{color:var(--background)}.text-black{color:var(--color-black)}.text-card-foreground{color:var(--card-foreground)}.text-destructive{color:var(--destructive)}.text-emerald-700{color:var(--color-emerald-700)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.underline-offset-4{text-underline-offset:4px}.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-foreground,.ring-foreground\/10{--tw-ring-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.ring-foreground\/10{--tw-ring-color:color-mix(in oklab, var(--foreground) 10%, transparent)}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.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))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.paused{animation-play-state:paused}.running{animation-play-state:running}.group-data-\[disabled\=true\]\:pointer-events-none:is(:where(.group)[data-disabled=true] *){pointer-events:none}.group-data-\[disabled\=true\]\:opacity-50:is(:where(.group)[data-disabled=true] *){opacity:.5}.group-data-\[size\=sm\]\/card\:p-3:is(:where(.group\/card)[data-size=sm] *){padding:calc(var(--spacing) * 3)}.group-data-\[size\=sm\]\/card\:px-3:is(:where(.group\/card)[data-size=sm] *){padding-inline:calc(var(--spacing) * 3)}.group-data-\[size\=sm\]\/card\:text-sm:is(:where(.group\/card)[data-size=sm] *){font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.group-data-\[spacing\=0\]\/toggle-group\:rounded-none:is(:where(.group\/toggle-group)[data-spacing="0"] *){border-radius:0}.group-data-\[spacing\=0\]\/toggle-group\:px-2:is(:where(.group\/toggle-group)[data-spacing="0"] *){padding-inline:calc(var(--spacing) * 2)}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-50:is(:where(.peer):disabled~*){opacity:.5}.file\:inline-flex::file-selector-button{display:inline-flex}.file\:h-6::file-selector-button{height:calc(var(--spacing) * 6)}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-xs::file-selector-button{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--foreground)}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}@media (hover:hover){.hover\:bg-destructive\/20:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/20:hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.hover\:bg-muted:hover,.hover\:bg-muted\/50:hover{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-muted-foreground:hover{color:var(--muted-foreground)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:z-10:focus,.focus-visible\:z-10:focus-visible{z-index:10}.focus-visible\:border-destructive\/40:focus-visible{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:border-destructive\/40:focus-visible{border-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:ring-1:focus-visible{--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)}.focus-visible\:ring-3:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + 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-destructive\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.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)}}.active\:not-aria-\[haspopup\]\:translate-y-px:active:not([aria-haspopup]){--tw-translate-y:1px;translate:var(--tw-translate-x) var(--tw-translate-y)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-input\/50:disabled{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.disabled\:bg-input\/50:disabled{background-color:color-mix(in oklab, var(--input) 50%, transparent)}}.disabled\:opacity-50:disabled{opacity:.5}.has-data-\[icon\=inline-end\]\:pr-1\.5:has([data-icon=inline-end]){padding-right:calc(var(--spacing) * 1.5)}.has-data-\[icon\=inline-end\]\:pr-2:has([data-icon=inline-end]){padding-right:calc(var(--spacing) * 2)}.group-data-\[spacing\=0\]\/toggle-group\:has-data-\[icon\=inline-end\]\:pr-1\.5:is(:where(.group\/toggle-group)[data-spacing="0"] *):has([data-icon=inline-end]){padding-right:calc(var(--spacing) * 1.5)}.has-data-\[icon\=inline-start\]\:pl-1\.5:has([data-icon=inline-start]){padding-left:calc(var(--spacing) * 1.5)}.has-data-\[icon\=inline-start\]\:pl-2:has([data-icon=inline-start]){padding-left:calc(var(--spacing) * 2)}.group-data-\[spacing\=0\]\/toggle-group\:has-data-\[icon\=inline-start\]\:pl-1\.5:is(:where(.group\/toggle-group)[data-spacing="0"] *):has([data-icon=inline-start]){padding-left:calc(var(--spacing) * 1.5)}.has-data-\[slot\=card-action\]\:grid-cols-\[1fr_auto\]:has([data-slot=card-action]){grid-template-columns:1fr auto}.has-data-\[slot\=card-description\]\:grid-rows-\[auto_auto\]:has([data-slot=card-description]){grid-template-rows:auto auto}.has-data-\[slot\=card-footer\]\:pb-0:has([data-slot=card-footer]){padding-bottom:0}.has-\[\>img\:first-child\]\:pt-0:has(>img:first-child){padding-top:0}.aria-expanded\:bg-muted[aria-expanded=true]{background-color:var(--muted)}.aria-expanded\:bg-secondary[aria-expanded=true]{background-color:var(--secondary)}.aria-expanded\:text-foreground[aria-expanded=true]{color:var(--foreground)}.aria-expanded\:text-secondary-foreground[aria-expanded=true]{color:var(--secondary-foreground)}.aria-invalid\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\:ring-1[aria-invalid=true]{--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)}.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.aria-pressed\:bg-muted[aria-pressed=true]{background-color:var(--muted)}.data-vertical\:flex-col[data-vertical]{flex-direction:column}.data-vertical\:items-stretch[data-vertical]{align-items:stretch}.data-\[orientation\=horizontal\]\:h-px[data-orientation=horizontal]{height:1px}.data-\[orientation\=horizontal\]\:w-full[data-orientation=horizontal]{width:100%}.data-\[orientation\=vertical\]\:w-px[data-orientation=vertical]{width:1px}.data-\[orientation\=vertical\]\:self-stretch[data-orientation=vertical]{align-self:stretch}.data-\[size\=sm\]\:gap-2[data-size=sm]{gap:calc(var(--spacing) * 2)}.data-\[size\=sm\]\:rounded-none[data-size=sm]{border-radius:0}.data-\[size\=sm\]\:py-3[data-size=sm]{padding-block:calc(var(--spacing) * 3)}.data-\[size\=sm\]\:has-data-\[slot\=card-footer\]\:pb-0[data-size=sm]:has([data-slot=card-footer]){padding-bottom:0}.group-data-horizontal\/toggle-group\:data-\[spacing\=0\]\:first\:rounded-none:is(:where(.group\/toggle-group)[data-horizontal] *)[data-spacing="0"]:first-child,.group-data-vertical\/toggle-group\:data-\[spacing\=0\]\:first\:rounded-none:is(:where(.group\/toggle-group)[data-vertical] *)[data-spacing="0"]:first-child,.group-data-horizontal\/toggle-group\:data-\[spacing\=0\]\:last\:rounded-none:is(:where(.group\/toggle-group)[data-horizontal] *)[data-spacing="0"]:last-child,.group-data-vertical\/toggle-group\:data-\[spacing\=0\]\:last\:rounded-none:is(:where(.group\/toggle-group)[data-vertical] *)[data-spacing="0"]:last-child{border-radius:0}.data-\[state\=on\]\:bg-muted[data-state=on]{background-color:var(--muted)}.group-data-horizontal\/toggle-group\:data-\[spacing\=0\]\:data-\[variant\=outline\]\:border-l-0:is(:where(.group\/toggle-group)[data-horizontal] *)[data-spacing="0"][data-variant=outline]{border-left-style:var(--tw-border-style);border-left-width:0}.group-data-vertical\/toggle-group\:data-\[spacing\=0\]\:data-\[variant\=outline\]\:border-t-0:is(:where(.group\/toggle-group)[data-vertical] *)[data-spacing="0"][data-variant=outline]{border-top-style:var(--tw-border-style);border-top-width:0}.group-data-horizontal\/toggle-group\:data-\[spacing\=0\]\:data-\[variant\=outline\]\:first\:border-l:is(:where(.group\/toggle-group)[data-horizontal] *)[data-spacing="0"][data-variant=outline]:first-child{border-left-style:var(--tw-border-style);border-left-width:1px}.group-data-vertical\/toggle-group\:data-\[spacing\=0\]\:data-\[variant\=outline\]\:first\:border-t:is(:where(.group\/toggle-group)[data-vertical] *)[data-spacing="0"][data-variant=outline]:first-child{border-top-style:var(--tw-border-style);border-top-width:1px}@media (width>=48rem){.md\:text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}}@media (width>=64rem){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}:where(.lg\: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(.lg\:divide-y-0>: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(0px * var(--tw-divide-y-reverse));border-bottom-width:calc(0px * calc(1 - var(--tw-divide-y-reverse)))}}@media (width>=80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@container (width>=24rem){.\@sm\:mb-0{margin-bottom:0}.\@sm\:grid-cols-\[max-content_1fr\]{grid-template-columns:max-content 1fr}.\@sm\:gap-x-4{column-gap:calc(var(--spacing) * 4)}.\@sm\:gap-y-1{row-gap:var(--spacing)}}.dark\:border-input:is(.dark *):not(.light *){border-color:var(--input)}.dark\:bg-destructive\/20:is(.dark *):not(.light *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-destructive\/20:is(.dark *):not(.light *){background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.dark\:bg-input\/30:is(.dark *):not(.light *){background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-input\/30:is(.dark *):not(.light *){background-color:color-mix(in oklab, var(--input) 30%, transparent)}}.dark\:text-amber-300:is(.dark *):not(.light *){color:var(--color-amber-300)}.dark\:text-emerald-300:is(.dark *):not(.light *){color:var(--color-emerald-300)}@media (hover:hover){.dark\:hover\:bg-destructive\/30:is(.dark *):not(.light *):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-destructive\/30:is(.dark *):not(.light *):hover{background-color:color-mix(in oklab, var(--destructive) 30%, transparent)}}.dark\:hover\:bg-input\/50:is(.dark *):not(.light *):hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-input\/50:is(.dark *):not(.light *):hover{background-color:color-mix(in oklab, var(--input) 50%, transparent)}}.dark\:hover\:bg-muted\/50:is(.dark *):not(.light *):hover{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-muted\/50:is(.dark *):not(.light *):hover{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}}.dark\:focus-visible\:ring-destructive\/40:is(.dark *):not(.light *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:focus-visible\:ring-destructive\/40:is(.dark *):not(.light *):focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\:disabled\:bg-input\/80:is(.dark *):not(.light *):disabled{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:disabled\:bg-input\/80:is(.dark *):not(.light *):disabled{background-color:color-mix(in oklab, var(--input) 80%, transparent)}}.dark\:aria-invalid\:border-destructive\/50:is(.dark *):not(.light *)[aria-invalid=true]{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:border-destructive\/50:is(.dark *):not(.light *)[aria-invalid=true]{border-color:color-mix(in oklab, var(--destructive) 50%, transparent)}}.dark\:aria-invalid\:ring-destructive\/40:is(.dark *):not(.light *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:ring-destructive\/40:is(.dark *):not(.light *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=size-\]\)\]\:size-3 svg:not([class*=size-]){width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.\[\&_svg\:not\(\[class\*\=size-\]\)\]\:size-3\.5 svg:not([class*=size-]){width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.\[\&_svg\:not\(\[class\*\=size-\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\.border-b\]\:pb-4.border-b{padding-bottom:calc(var(--spacing) * 4)}.group-data-\[size\=sm\]\/card\:\[\.border-b\]\:pb-3:is(:where(.group\/card)[data-size=sm] *).border-b{padding-bottom:calc(var(--spacing) * 3)}@media (hover:hover){.\[a\]\:hover\:bg-destructive\/20:is(a):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.\[a\]\:hover\:bg-destructive\/20:is(a):hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.\[a\]\:hover\:bg-muted:is(a):hover{background-color:var(--muted)}.\[a\]\:hover\:bg-primary\/80:is(a):hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.\[a\]\:hover\:bg-primary\/80:is(a):hover{background-color:color-mix(in oklab, var(--primary) 80%, transparent)}}.\[a\]\:hover\:bg-secondary\/80:is(a):hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.\[a\]\:hover\:bg-secondary\/80:is(a):hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.\[a\]\:hover\:text-muted-foreground:is(a):hover{color:var(--muted-foreground)}}:is(.\*\:\[img\:first-child\]\:rounded-none>*):is(img:first-child),:is(.\*\:\[img\:last-child\]\:rounded-none>*):is(img:last-child){border-radius:0}.\[\&\>svg\]\:pointer-events-none>svg{pointer-events:none}.\[\&\>svg\]\:size-3\!>svg{width:calc(var(--spacing) * 3)!important;height:calc(var(--spacing) * 3)!important}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(data:font/woff2;base64,d09GMgABAAAAAAfsABQAAAAAEAwAAAeCAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhwoP0hWQVJbBmA/U1RBVIFiJyYAdC9qEQgKhGSEAAsgADCGCAE2AiQDOgQgBYlMB4EUDAcbLQ4onoexrSC/2ZyLAa8p8VHB8/x3Vue+V0hVJalMJg2nx/TCrQXxBeqLjQG7FyM1WEa/X1tEXN7cFz9EJEMmMUz3RihWSSKeQCbcIou0izz/C8v+fq3VfajEa9gDD11CImXS7qL/RJFVzC1qiB6KmKeD6TZdQ6IRGv78dL6uSVVCfgni5mzu7kcgQBgAEAQTQRCoL++STTYybkJxNfQxAAIAGu8OdEB9teW2jh4BpgDqFjAeSEByW3zFP0CBBgNMsMCGEDjgggdhiEAUAeIIED7ABTDUEnkIE9Q9ahFgKttcVhApo4ACB4qobHaccgDfEjFO6aaWUhjMLt2SyIvHKoDqoA4CSUwEIYQCEjhAO9R1G6keDeDZGjNo+AhxOjCEGTr1WeIF3kYBiLAOKvkJSMiKX0VdAyQt3SDJClCkxJCHkCzfqyVTriJZLcolS32JZHUekq2TYNkYtCtjYHMQXSxGjXDz2t/yLWXzDzxz+o3zFwDEaN23F+13pyMdQAEaSKAR9vcGq4A4MTSKCElGW+M7UcY7xqkggITb28ZJhlqc9q2twYKTt0NjixBgYvO9BIihEBLYuOFXQzfIQ7dXGUEEEgFDooBfAzqiQbpJrhiWSuKJCRFKYbHCyJKI2G5GiZbNAvgAu5pc3vwx4G+g3aDkhklABiSz0BICXrYghtYhx/cdJ+44rY2oZ0aMNRFz3VZjb6W33F3gzltqtOCV8tTHSpOeXuItfvr5lCdfzFpqtEitvqdcdGGFd28ZqqC0tPbeChGXgrIlnhSWu/eUso4uKWFLugyDzQJhflY4659+WjQ++6x72WUMv9G8mw6QJl7BVxX5fe/kpUsOvnZwee9uQ0cGXYd0o89XB2748sDSnt8d2VphdOTTgceDVvOds0v9P/s7HPq15aGun/6Vllb56f1dl0t1LejqrNkpdRZsG8TOnM5vkBG5oiVyVGnS8LHps5cfNWJs6qKPfaNSxiQNBUm3cKNWROr0GSur7Za31k1vieq7LH11VF+jXdRIasRKflc7jkobm1Z9te1IyZA0pDkhLR98+H37Zf1c/8at+dB7x+7GfVyTfJMPiYztsnl59Y5l4j+0n1RXlpHnF3Tq7HecmNF/CJodEMAikruxiyJaGLvHOdAfoA+oDvpjBm2b91cHGRZMU9n25xEU0A8fgEEAdKI3Q1iDtc034sug5YVMkE2jsE+BIkwSoQ3gxXMqz9tELp48bd0cFKOKS7xYjEuXBnZP5ia7DyiO/X/YI+PQSbt2uSdqAkWL9nQbV1XB94/+uPfdZz8dnXYFBYrcTl2SIR/ybxJNJPz/Gupb0JaZeens2ekC7EKr8t+Ls/P5VJPYJdHKyqfg2nqU6bhlidzcddQV/7MmecTzJ5VPcKXkNKSEogHjYFx6QZ7rQ+FSe8njaiNuOnXS8H2ScQ619c2mC3VTtauL0rRbXd/CkSOP37FY9Zkjz8+GibYUMOEWF+RdrFS8Ecv1SHOpPUPZGEIpjPvFyU5cXKjd6OXqorTqy9GwRd++HVufPGnVsW+aO3vggKZ18jR9sXaTC1PWTEsVUaK0FkNySbTQDqlm2PfDjZcu4aalnSLKjnOoYQ0nUlqqXcGpPu/4VgV/xU2pAqW4BW3qzhQ8/hFKhV2qE3+BKAtDqBXjfgnVdH4y0wg5tbVNRenNdTWOrenWLcupQdmsbq5b+18piTe/xRdp1xbILxNPJGInm2z6hoB21Lal0i+ePTtd7B45+3XhFJ329evskXm7qurUVREotqSluSo/L29d3qDhI4YOQqWhI4YNvBNfsMHeXKemXrxQfKeuPOGRVayA3JtkJKEgbPp+dXUDluddutRYLFoXGXWX6N3WFaGLbQtRSitVYNacTNSdy7AaG/HSaUEANcBoGXNdcZvZsOqQ1icBDv21/gzAoYPHH/WDW0qNR3QTYKEAEHig6o13NXbND06CQPlRtYjGNnSktRc09k1mAMDvAlDKfQjgy6fssInlfzmNAjKkDxoxHOBLdVRAIVt9j4qo+hA1w9T1aNBNTUOTTNUHLbqokE+UAfJXCIGw/IxCSL5GRUJeR40rL/UxTm4Q08H6MbCs70ObuNyIIXrINHQYInF06UUlevTjbQzTh5upiDMzMMogUtEnjPs/Y7jAHCJeB0GBHh04tC6FiB6ZFB1oArUSIoFoqhzCeAN6lHwm0T4C3VVPWvjpSMXReuWesMEcoqrmgtNBGd2noWeV0hNAz9rFeShNJxHGsPa3HXeKTk8b55hahySYHaYKKFFLpCfN8rsoaJn01CR04Gkc+5k7KVTCmClX8Q10HCrUEkVlSX+XO33oQR9609tJ516H497WSobWs5Up6TLaS10/dessIskgJSLiDlWvHVUywpkQ7hdPZqGyiEF0uVQerVcPamT1A3eKXdyI1vG9OoflrSXihZ1qqGE3nhmAgiIbRCQgPLEPtOM3UQwTLYaYYomNlpA44opnjV6jkD6id80OOrzf6BzmMD6eEa1zKyeYG1fzfEf16V6jw9XYOaar1/b2kP/IYX8oR2mcFvv2GtBV3JXgd437AQAA)format("woff2-variations");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2)format("woff2-variations");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2)format("woff2-variations");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root,.light{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--radius:.625rem;--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(92.2% 0 0);--input:oklch(92.2% 0 0);--ring:oklch(70.8% 0 0);--chart-1:oklch(64.6% .222 41.116);--chart-2:oklch(60% .118 184.704);--chart-3:oklch(39.8% .07 227.392);--chart-4:oklch(82.8% .189 84.429);--chart-5:oklch(76.9% .188 70.08);--sidebar:oklch(98.5% 0 0);--sidebar-foreground:oklch(14.5% 0 0);--sidebar-primary:oklch(20.5% 0 0);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(97% 0 0);--sidebar-accent-foreground:oklch(20.5% 0 0);--sidebar-border:oklch(92.2% 0 0);--sidebar-ring:oklch(70.8% 0 0)}.dark{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.6% 0 0);--chart-1:oklch(48.8% .243 264.376);--chart-2:oklch(69.6% .17 162.48);--chart-3:oklch(76.9% .188 70.08);--chart-4:oklch(62.7% .265 303.9);--chart-5:oklch(64.5% .246 16.439);--sidebar:oklch(20.5% 0 0);--sidebar-foreground:oklch(98.5% 0 0);--sidebar-primary:oklch(48.8% .243 264.376);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(26.9% 0 0);--sidebar-accent-foreground:oklch(98.5% 0 0);--sidebar-border:oklch(100% 0 0/.1);--sidebar-ring:oklch(55.6% 0 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-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{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-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}
|