@crouton-kit/humanloop 0.3.30 → 0.3.31
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/api.js +6 -0
- package/dist/browser/open.d.ts +7 -0
- package/dist/browser/open.js +26 -0
- package/dist/browser/server.d.ts +62 -0
- package/dist/browser/server.js +440 -0
- package/dist/cli.js +43 -12
- package/dist/editor/feedback.d.ts +18 -0
- package/dist/editor/feedback.js +204 -0
- package/dist/editor/review.js +162 -93
- package/dist/inbox/deck-schema.d.ts +14 -1
- package/dist/inbox/deck-schema.js +40 -18
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/tui/app.js +122 -3
- package/dist/tui/input.js +4 -1
- package/dist/tui/render.d.ts +7 -0
- package/dist/tui/render.js +25 -0
- package/dist/types.d.ts +2 -1
- package/dist/types.js +5 -1
- package/dist/web/assets/index-BxJZgs8l.css +2 -0
- package/dist/web/assets/index-DhbBiRqS.js +46 -0
- package/dist/web/index.html +13 -0
- package/package.json +8 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, lstatSync, readFileSync, realpathSync } from 'node:fs';
|
|
2
2
|
import { dirname, resolve, sep } from 'node:path';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
+
import { INTERACTION_KINDS } from '../types.js';
|
|
4
5
|
import { checkMarkdown } from '../render/termrender.js';
|
|
5
6
|
// ── zod v4 building blocks ────────────────────────────────────────────────────
|
|
6
7
|
// v4 notes: .nonempty() → .min(1); error messages use {error: 'string'} per check.
|
|
@@ -29,7 +30,7 @@ const interactionSchema = z.object({
|
|
|
29
30
|
multiSelect: z.boolean().optional(),
|
|
30
31
|
allowFreetext: z.boolean().optional(),
|
|
31
32
|
freetextLabel: z.string().optional(),
|
|
32
|
-
kind: z.enum(
|
|
33
|
+
kind: z.enum(INTERACTION_KINDS).optional(),
|
|
33
34
|
preAnswered: preAnswerSchema.optional(),
|
|
34
35
|
});
|
|
35
36
|
const deckSourceSchema = z.object({
|
|
@@ -65,12 +66,16 @@ export const deckSchema = z.object({
|
|
|
65
66
|
}
|
|
66
67
|
});
|
|
67
68
|
// ── C2 bodyPath defense + inlining ────────────────────────────────────────────
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Read `bodyPath` (relative to `dir`, the interaction directory a deck.json
|
|
71
|
+
* lives/will live in) with the traversal/symlink defenses a file read off an
|
|
72
|
+
* agent-supplied relative path needs.
|
|
73
|
+
*/
|
|
74
|
+
function readBodyPathFile(dir, bodyPath) {
|
|
75
|
+
const joined = resolve(dir, bodyPath);
|
|
71
76
|
// STEP 1: existence + lstat BEFORE realpath to catch symlinks and directories.
|
|
72
77
|
if (!existsSync(joined)) {
|
|
73
|
-
throw new Error(`bodyPath does not exist: '${bodyPath}' (resolved against deck dir '${
|
|
78
|
+
throw new Error(`bodyPath does not exist: '${bodyPath}' (resolved against deck dir '${dir}'). bodyPath is interpreted relative to the deck JSON's directory; place the body file there and use a relative path (e.g. "completion-summary.md").`);
|
|
74
79
|
}
|
|
75
80
|
const stat = lstatSync(joined);
|
|
76
81
|
if (!stat.isFile()) {
|
|
@@ -80,7 +85,7 @@ export function inlineBodyPath(deckPath, bodyPath) {
|
|
|
80
85
|
// STEP 2: realpath both sides, prefix-check (defense-in-depth for .. traversal).
|
|
81
86
|
// realpathSync is safe here: lstat already confirmed the path exists.
|
|
82
87
|
const realResolved = realpathSync(joined);
|
|
83
|
-
const realDeckDir = realpathSync(
|
|
88
|
+
const realDeckDir = realpathSync(dir);
|
|
84
89
|
const prefix = realDeckDir + sep;
|
|
85
90
|
if (realResolved !== realDeckDir && !realResolved.startsWith(prefix)) {
|
|
86
91
|
throw new Error(`bodyPath '${bodyPath}' escapes the deck's directory ('${realDeckDir}'). bodyPath is resolved relative to the deck JSON file and must stay inside its directory (no '..', absolute paths pointing elsewhere, or symlinks out). Fix: write the deck JSON next to the body file (e.g. both inside $SISYPHUS_SESSION_DIR/context/) and use a relative path like "completion-summary.md".`);
|
|
@@ -88,6 +93,29 @@ export function inlineBodyPath(deckPath, bodyPath) {
|
|
|
88
93
|
// STEP 3: read. lstat confirmed regular file; realpath confirmed in-tree.
|
|
89
94
|
return readFileSync(joined, 'utf-8');
|
|
90
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* The ONE canonical `bodyPath` → `body` normalization boundary. Resolves every
|
|
98
|
+
* interaction's `bodyPath` (relative to `dir`, the interaction directory) into
|
|
99
|
+
* `body` and strips `bodyPath` from the result.
|
|
100
|
+
*
|
|
101
|
+
* Call this once, right before a deck is (re)written to `<dir>/deck.json` —
|
|
102
|
+
* `hl deck ask`, `hl deck update`, and the public `ask()` API all do — so
|
|
103
|
+
* every reader downstream (the terminal TUI's render + its live-reload
|
|
104
|
+
* poller, the browser server's `/api/interaction`) only ever sees a plain
|
|
105
|
+
* `body` and never has to special-case `bodyPath` itself. `parseDeck` (below)
|
|
106
|
+
* reuses this same function when reading a deck straight off disk.
|
|
107
|
+
*/
|
|
108
|
+
export function resolveDeckBodyPaths(deck, dir) {
|
|
109
|
+
const interactions = deck.interactions.map((interaction) => {
|
|
110
|
+
if (interaction.bodyPath === undefined)
|
|
111
|
+
return interaction;
|
|
112
|
+
const body = readBodyPathFile(dir, interaction.bodyPath);
|
|
113
|
+
// Drop bodyPath from persisted deck.json/decisions.json (recipe §1.8).
|
|
114
|
+
const { bodyPath: _drop, ...rest } = interaction;
|
|
115
|
+
return { ...rest, body };
|
|
116
|
+
});
|
|
117
|
+
return { ...deck, interactions };
|
|
118
|
+
}
|
|
91
119
|
// ── public entry points ───────────────────────────────────────────────────────
|
|
92
120
|
export function parseDeck(deckPath) {
|
|
93
121
|
const raw = readFileSync(deckPath, 'utf-8');
|
|
@@ -99,22 +127,16 @@ export function parseDeck(deckPath) {
|
|
|
99
127
|
throw new Error('deck is not valid JSON');
|
|
100
128
|
}
|
|
101
129
|
const parsed = deckSchema.parse(json);
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
if (interaction.
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
if (body !== undefined) {
|
|
108
|
-
const check = checkMarkdown(body);
|
|
130
|
+
const resolved = resolveDeckBodyPaths(parsed, dirname(deckPath));
|
|
131
|
+
for (const interaction of resolved.interactions) {
|
|
132
|
+
if (interaction.body !== undefined) {
|
|
133
|
+
const check = checkMarkdown(interaction.body);
|
|
109
134
|
if (!check.ok) {
|
|
110
135
|
throw new Error(check.error);
|
|
111
136
|
}
|
|
112
137
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return body !== undefined ? { ...rest, body } : { ...rest };
|
|
116
|
-
});
|
|
117
|
-
return { ...parsed, interactions: inlinedInteractions };
|
|
138
|
+
}
|
|
139
|
+
return resolved;
|
|
118
140
|
}
|
|
119
141
|
export function validateDeck(parsed) {
|
|
120
142
|
return deckSchema.parse(parsed);
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { ask, notify, inbox } from './api.js';
|
|
|
7
7
|
export { display } from './surfaces/display.js';
|
|
8
8
|
export { scanInbox } from './inbox/scan.js';
|
|
9
9
|
export { renderMarkdown, checkMarkdown, ensureRenderer, isRendererReady, } from './render/termrender.js';
|
|
10
|
-
export { parseDeck, validateDeck, deckSchema } from './inbox/deck-schema.js';
|
|
10
|
+
export { parseDeck, validateDeck, deckSchema, resolveDeckBodyPaths } from './inbox/deck-schema.js';
|
|
11
11
|
export { notifyDeck } from './inbox/deck-factories.js';
|
|
12
12
|
export type { NotifyDeckOpts } from './inbox/deck-factories.js';
|
|
13
13
|
export { deckPath, responsePath, progressPath, visualsDir, interactionState, isResolved, isClaimed, atomicWriteJson, readJson, writeResponse, writeProgress, clearProgress, } from './inbox/convention.js';
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export { scanInbox } from './inbox/scan.js';
|
|
|
10
10
|
// (sisyphus md-render / ask-schema) route markdown through these.
|
|
11
11
|
export { renderMarkdown, checkMarkdown, ensureRenderer, isRendererReady, } from './render/termrender.js';
|
|
12
12
|
// Canonical deck schema + parsing/validation (consumers stop forking it).
|
|
13
|
-
export { parseDeck, validateDeck, deckSchema } from './inbox/deck-schema.js';
|
|
13
|
+
export { parseDeck, validateDeck, deckSchema, resolveDeckBodyPaths } from './inbox/deck-schema.js';
|
|
14
14
|
// Deck factories — pure builders for common deck shapes (sugar for SDK consumers
|
|
15
15
|
// who want validated Yes/No or notify decks without inline construction).
|
|
16
16
|
export { notifyDeck } from './inbox/deck-factories.js';
|
package/dist/tui/app.js
CHANGED
|
@@ -4,12 +4,14 @@ import { spawnSync } from 'node:child_process';
|
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { randomUUID } from 'node:crypto';
|
|
6
6
|
import { setupTerminal, restoreTerminal, parseKeypress, getTerminalSize } from './terminal.js';
|
|
7
|
-
import { diffFrame, renderOverview, renderItemReview, renderFinal, clampItemReviewScroll } from './render.js';
|
|
7
|
+
import { diffFrame, renderOverview, renderItemReview, renderFinal, renderHandoff, clampItemReviewScroll } from './render.js';
|
|
8
8
|
import { handleKeypress, assignShortcuts } from './input.js';
|
|
9
9
|
import { readConversation } from '../conversation/reader.js';
|
|
10
10
|
import { defaultGenerateVisual } from '../visuals/generate.js';
|
|
11
11
|
import { validateDeck } from '../inbox/deck-schema.js';
|
|
12
12
|
import { progressPath as progressPathFor, deckPath as deckPathFor, writeResponse, clearProgress } from '../inbox/convention.js';
|
|
13
|
+
import { startWebServer } from '../browser/server.js';
|
|
14
|
+
import { openBrowser } from '../browser/open.js';
|
|
13
15
|
/** Validate an arbitrary parsed value as a Deck. Delegates to the canonical
|
|
14
16
|
* Zod validator in `inbox/deck-schema.ts` (the single source of truth shared
|
|
15
17
|
* with sisyphus). Kept exported for back-compat. */
|
|
@@ -278,6 +280,18 @@ export async function resolveInteractionDir(dir, deck, opts = {}) {
|
|
|
278
280
|
// returned envelope/summary describes what was answered, not the kickoff.
|
|
279
281
|
let currentDeck = deck;
|
|
280
282
|
let deckWatch = null;
|
|
283
|
+
// Guards finalize() against running twice. The server already makes
|
|
284
|
+
// /api/submit single-assignment (only the first accepted submit fires
|
|
285
|
+
// onSubmit), but finalize() is also reachable via onComplete/onExit/a
|
|
286
|
+
// hard Ctrl+C during handoff — this is defense-in-depth so a second call
|
|
287
|
+
// from any path is a no-op instead of double-tearing-down (stop() twice,
|
|
288
|
+
// removeListener on an already-removed listener) and resolving the outer
|
|
289
|
+
// promise a second time.
|
|
290
|
+
let finalized = false;
|
|
291
|
+
// Set while the panel has handed control to the browser (the `w` keybind
|
|
292
|
+
// below). Non-null means: the panel renders nothing, the host renders the
|
|
293
|
+
// handoff screen instead, and only the take-back key reaches this loop.
|
|
294
|
+
let handoff = null;
|
|
281
295
|
const flushHost = (lines) => {
|
|
282
296
|
const { cols: currentCols, rows: currentRows } = getTerminalSize();
|
|
283
297
|
const { writes, nextPrevFrame } = diffFrame(prevFrameLocal, lines, currentRows, currentCols);
|
|
@@ -291,23 +305,45 @@ export async function resolveInteractionDir(dir, deck, opts = {}) {
|
|
|
291
305
|
// model no longer matches the screen: re-layout at the new size, clear
|
|
292
306
|
// everything, and redraw from scratch.
|
|
293
307
|
const onResize = () => {
|
|
308
|
+
const { cols: c, rows: r } = getTerminalSize();
|
|
309
|
+
if (handoff !== null) {
|
|
310
|
+
prevFrameLocal = [];
|
|
311
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
312
|
+
flushHost(renderHandoff(handoff.url, c, r));
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
294
315
|
if (panel === null)
|
|
295
316
|
return;
|
|
296
|
-
const { cols: c, rows: r } = getTerminalSize();
|
|
297
317
|
const lines = panel.handleResize(c, r);
|
|
298
318
|
prevFrameLocal = [];
|
|
299
319
|
process.stdout.write('\x1b[2J\x1b[H');
|
|
300
320
|
flushHost(lines);
|
|
301
321
|
};
|
|
302
|
-
|
|
322
|
+
// `written` is set when the browser (not this function) already wrote
|
|
323
|
+
// response.json via the web server's /api/submit — the canonical write
|
|
324
|
+
// happens exactly once, whichever surface produced it; this just converges
|
|
325
|
+
// the terminal side and resolves the promise with what's already on disk.
|
|
326
|
+
const finalize = (responses, written) => {
|
|
327
|
+
if (finalized)
|
|
328
|
+
return;
|
|
329
|
+
finalized = true;
|
|
303
330
|
if (deckWatch !== null) {
|
|
304
331
|
clearInterval(deckWatch);
|
|
305
332
|
deckWatch = null;
|
|
306
333
|
}
|
|
334
|
+
if (handoff !== null) {
|
|
335
|
+
const h = handoff;
|
|
336
|
+
handoff = null;
|
|
337
|
+
void h.stop();
|
|
338
|
+
}
|
|
307
339
|
restoreTerminal();
|
|
308
340
|
process.stdin.removeListener('data', onData);
|
|
309
341
|
process.stdout.removeListener('resize', onResize);
|
|
310
342
|
panel?.unmount();
|
|
343
|
+
if (written !== undefined) {
|
|
344
|
+
resolve({ responses, completedAt: written.completedAt, responsePath: written.responsePath, deck: currentDeck });
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
311
347
|
const completedAt = new Date().toISOString();
|
|
312
348
|
// Resolved supersedes in-progress: write response.json, drop progress.json.
|
|
313
349
|
const rp = writeResponse(dir, responses, completedAt, currentDeck);
|
|
@@ -357,6 +393,12 @@ export async function resolveInteractionDir(dir, deck, opts = {}) {
|
|
|
357
393
|
deckWatch = setInterval(() => {
|
|
358
394
|
if (panel === null)
|
|
359
395
|
return;
|
|
396
|
+
// Deck reload is deferred while handed off — the browser already fetched
|
|
397
|
+
// a snapshot and applying loadDeck() here would repaint the (currently
|
|
398
|
+
// hidden) panel over the handoff screen. Re-checked on the next tick
|
|
399
|
+
// after take-back, so a `hl deck update` mid-handoff is not lost.
|
|
400
|
+
if (handoff !== null)
|
|
401
|
+
return;
|
|
360
402
|
const m = deckMtime();
|
|
361
403
|
if (m === 0 || m === lastDeckMtime)
|
|
362
404
|
return;
|
|
@@ -457,8 +499,77 @@ export async function resolveInteractionDir(dir, deck, opts = {}) {
|
|
|
457
499
|
flushHost(lines);
|
|
458
500
|
}
|
|
459
501
|
};
|
|
502
|
+
// Start the local web server over this interaction dir, open a browser
|
|
503
|
+
// tab on it, and park the panel: from here the browser is the sole editor
|
|
504
|
+
// (browser-authoritative handoff — no two-way sync). `onSubmit` fires once
|
|
505
|
+
// the browser's POST has already written response.json; finalize() is
|
|
506
|
+
// told so via `written` and does not write it again.
|
|
507
|
+
const enterHandoff = async () => {
|
|
508
|
+
if (handoff !== null)
|
|
509
|
+
return;
|
|
510
|
+
let server;
|
|
511
|
+
try {
|
|
512
|
+
server = await startWebServer({
|
|
513
|
+
dir,
|
|
514
|
+
deck: currentDeck,
|
|
515
|
+
onSubmit: (responses, completedAt, responsePath) => {
|
|
516
|
+
finalize(responses, { responsePath, completedAt });
|
|
517
|
+
},
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
catch (err) {
|
|
521
|
+
// Failed to bind (e.g. no loopback available) — stay in the normal TUI;
|
|
522
|
+
// nothing was torn down, so surface the error as a one-line footer.
|
|
523
|
+
const { cols: c, rows: r } = getTerminalSize();
|
|
524
|
+
const lines = panel.render();
|
|
525
|
+
while (lines.length < r)
|
|
526
|
+
lines.push('');
|
|
527
|
+
lines[r - 1] = ` Could not start the browser surface: ${err instanceof Error ? err.message : String(err)}`.slice(0, c);
|
|
528
|
+
flushHost(lines);
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
handoff = server;
|
|
532
|
+
const { cols: c, rows: r } = getTerminalSize();
|
|
533
|
+
prevFrameLocal = [];
|
|
534
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
535
|
+
flushHost(renderHandoff(server.url, c, r));
|
|
536
|
+
openBrowser(server.url);
|
|
537
|
+
};
|
|
538
|
+
// Reclaim control: tell any open browser tab it's now read-only, stop the
|
|
539
|
+
// server, and restore the live panel exactly as the human left it.
|
|
540
|
+
const takeBack = () => {
|
|
541
|
+
if (handoff === null)
|
|
542
|
+
return;
|
|
543
|
+
const h = handoff;
|
|
544
|
+
handoff = null;
|
|
545
|
+
// Deck's requestTakeBack() is just an awaited flush-broadcast of
|
|
546
|
+
// taken-back (no ack-wait, deck has no autosave/dirty state to flush) —
|
|
547
|
+
// so this stays effectively instant. Kept async and NOT awaited before
|
|
548
|
+
// the render/flush below so the terminal repaint never blocks on it.
|
|
549
|
+
void (async () => {
|
|
550
|
+
await h.requestTakeBack();
|
|
551
|
+
await h.stop();
|
|
552
|
+
})();
|
|
553
|
+
prevFrameLocal = [];
|
|
554
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
555
|
+
flushHost(panel.render());
|
|
556
|
+
};
|
|
460
557
|
onData = (data) => {
|
|
461
558
|
const { input: inp, key } = parseKeypress(data);
|
|
559
|
+
if (handoff !== null) {
|
|
560
|
+
// Handed off: the panel gets no keys at all. Only take-back (and a
|
|
561
|
+
// hard Ctrl+C exit, mirroring the panel's own exit-on-partial) reach
|
|
562
|
+
// the host while the browser is the sole editor.
|
|
563
|
+
if (inp === 'w') {
|
|
564
|
+
takeBack();
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
if (key.ctrl && inp === 'c') {
|
|
568
|
+
finalize(lastResponses);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
462
573
|
if (key.ctrl && inp === 'o') {
|
|
463
574
|
const buf = panel.getInputBuffer();
|
|
464
575
|
if (buf !== undefined) {
|
|
@@ -466,6 +577,14 @@ export async function resolveInteractionDir(dir, deck, opts = {}) {
|
|
|
466
577
|
return;
|
|
467
578
|
}
|
|
468
579
|
}
|
|
580
|
+
// 'w' hands the current interaction off to the browser. Gated on
|
|
581
|
+
// canAcceptHostKeys() (not mid comment/freetext) so it never shadows a
|
|
582
|
+
// literal 'w' typed into a buffer; 'w' is also reserved from option
|
|
583
|
+
// auto-shortcuts (see assignShortcuts) so it never collides with a pick.
|
|
584
|
+
if (inp === 'w' && panel.canAcceptHostKeys()) {
|
|
585
|
+
void enterHandoff();
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
469
588
|
panel.handleKey(inp, key);
|
|
470
589
|
flushHost(panel.render());
|
|
471
590
|
};
|
package/dist/tui/input.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
// 'w' is reserved for the host-level "open in browser" handoff (see
|
|
2
|
+
// tui/app.ts resolveInteractionDir) — never auto-assignable as an option
|
|
3
|
+
// shortcut, or pressing it would race the handoff against picking that option.
|
|
4
|
+
const RESERVED = new Set(['c', 'r', 'n', 'p', 'q', 'j', 'k', 'u', 'd', 'w', ' ']);
|
|
2
5
|
export function assignShortcuts(interactions) {
|
|
3
6
|
for (const it of interactions) {
|
|
4
7
|
const used = new Set(it.options.map((o) => o.shortcut).filter((s) => s !== undefined));
|
package/dist/tui/render.d.ts
CHANGED
|
@@ -23,4 +23,11 @@ export declare function renderInputBuffer(buffer: string, cursor: number, maxWid
|
|
|
23
23
|
export declare function clampItemReviewScroll(state: TuiState, cols: number, rows: number): void;
|
|
24
24
|
export declare function renderItemReview(state: TuiState, cols: number, rows: number): string[];
|
|
25
25
|
export declare function renderFinal(state: TuiState, cols: number, rows: number): string[];
|
|
26
|
+
/**
|
|
27
|
+
* Rendered while the deck panel has handed control to the browser (see the
|
|
28
|
+
* `w` handoff in `resolveInteractionDir`). Purely informational — no keys are
|
|
29
|
+
* routed to the panel while this is on screen; the host intercepts the
|
|
30
|
+
* take-back key itself.
|
|
31
|
+
*/
|
|
32
|
+
export declare function renderHandoff(url: string, cols: number, rows: number): string[];
|
|
26
33
|
export declare function responseSummary(r: InteractionResponse, interaction: Interaction): string;
|
package/dist/tui/render.js
CHANGED
|
@@ -401,6 +401,31 @@ export function renderFinal(state, cols, rows) {
|
|
|
401
401
|
lines.push('');
|
|
402
402
|
return centerHorizontal(lines.slice(0, rows), cols, maxW + 2);
|
|
403
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* Rendered while the deck panel has handed control to the browser (see the
|
|
406
|
+
* `w` handoff in `resolveInteractionDir`). Purely informational — no keys are
|
|
407
|
+
* routed to the panel while this is on screen; the host intercepts the
|
|
408
|
+
* take-back key itself.
|
|
409
|
+
*/
|
|
410
|
+
export function renderHandoff(url, cols, rows) {
|
|
411
|
+
const maxW = Math.min(cols - 4, 68);
|
|
412
|
+
const lines = [];
|
|
413
|
+
lines.push('');
|
|
414
|
+
lines.push(` ${BOLD}${CYAN} Handed off to the browser ${RESET}`);
|
|
415
|
+
lines.push(` ${DIM}${hline(maxW)}${RESET}`);
|
|
416
|
+
lines.push('');
|
|
417
|
+
lines.push(` ${DIM}Open (or already opened):${RESET}`);
|
|
418
|
+
lines.push(` ${CYAN}${truncate(url, maxW)}${RESET}`);
|
|
419
|
+
lines.push('');
|
|
420
|
+
lines.push(` ${ITALIC}${DIM}The browser is the sole editor now — submit there.${RESET}`);
|
|
421
|
+
lines.push(` ${ITALIC}${DIM}This pane will converge automatically once it submits.${RESET}`);
|
|
422
|
+
lines.push('');
|
|
423
|
+
lines.push(` ${DIM}${hline(maxW)}${RESET}`);
|
|
424
|
+
lines.push(` ${YELLOW}w${RESET} take back control`);
|
|
425
|
+
while (lines.length < rows)
|
|
426
|
+
lines.push('');
|
|
427
|
+
return centerHorizontal(lines.slice(0, rows), cols, maxW + 2);
|
|
428
|
+
}
|
|
404
429
|
export function responseSummary(r, interaction) {
|
|
405
430
|
if (r.selectedOptionIds !== undefined) {
|
|
406
431
|
const oc = r.optionComments;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Key } from './tui/terminal.js';
|
|
2
|
-
export
|
|
2
|
+
export declare const INTERACTION_KINDS: readonly ["notify", "decision", "context", "error", "review"];
|
|
3
|
+
export type InteractionKind = (typeof INTERACTION_KINDS)[number];
|
|
3
4
|
export interface InteractionOption {
|
|
4
5
|
id: string;
|
|
5
6
|
label: string;
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
// ── v2 shapes (v1 schema dropped per cycle-16 user pivot — humanloop is v2-only) ──
|
|
2
|
-
|
|
2
|
+
// Single source of truth for the interaction-kind enum: the Zod deck schema
|
|
3
|
+
// (`src/inbox/deck-schema.ts`) and the CLI's JSON schema (`src/cli.ts`) both
|
|
4
|
+
// derive their enum values from this array so a new kind can't drift between
|
|
5
|
+
// the type and the two validation surfaces the way `'review'` once did.
|
|
6
|
+
export const INTERACTION_KINDS = ['notify', 'decision', 'context', 'error', 'review'];
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--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;--tw-content:""}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-200:oklch(88.5% .062 18.334);--color-red-500:oklch(63.7% .237 25.331);--color-red-900:oklch(39.6% .141 25.723);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-900:oklch(41.4% .112 45.904);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-900:oklch(37.8% .077 168.94);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-900:oklch(20.8% .042 265.755);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--container-3xl:48rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--leading-snug:1.375;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{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);color:var(--foreground)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:0}.z-50{z-index:50}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);margin-top:1.2em;margin-bottom:1.2em;font-size:1.25em;line-height:1.6}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);font-weight:500;text-decoration:underline}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:decimal}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:disc}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-counters);font-weight:400}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.25em;font-weight:600}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-quotes);border-inline-start-width:.25rem;border-inline-start-color:var(--tw-prose-quote-borders);quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-inline-start:1em;font-style:italic;font-weight:500}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:900}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:800}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em;display:block}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-kbd);box-shadow:0 0 0 1px var(--tw-prose-kbd-shadows), 0 3px 0 var(--tw-prose-kbd-shadows);padding-top:.1875em;padding-inline-end:.375em;padding-bottom:.1875em;border-radius:.3125rem;padding-inline-start:.375em;font-family:inherit;font-size:.875em;font-weight:500}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-size:.875em;font-weight:600}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);padding-top:.857143em;padding-inline-end:1.14286em;padding-bottom:.857143em;border-radius:.375rem;margin-top:1.71429em;margin-bottom:1.71429em;padding-inline-start:1.14286em;font-size:.875em;font-weight:400;line-height:1.71429;overflow-x:auto}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit;background-color:#0000;border-width:0;border-radius:0;padding:0}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){table-layout:auto;width:100%;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.71429}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);vertical-align:bottom;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em;font-weight:600}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(th,td):not(:where([class~=not-prose],[class~=not-prose] *)){text-align:start}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);margin-top:.857143em;font-size:.875em;line-height:1.42857}.prose{--tw-prose-body:oklch(37.3% .034 259.733);--tw-prose-headings:oklch(21% .034 264.665);--tw-prose-lead:oklch(44.6% .03 256.802);--tw-prose-links:oklch(21% .034 264.665);--tw-prose-bold:oklch(21% .034 264.665);--tw-prose-counters:oklch(55.1% .027 264.364);--tw-prose-bullets:oklch(87.2% .01 258.338);--tw-prose-hr:oklch(92.8% .006 264.531);--tw-prose-quotes:oklch(21% .034 264.665);--tw-prose-quote-borders:oklch(92.8% .006 264.531);--tw-prose-captions:oklch(55.1% .027 264.364);--tw-prose-kbd:oklch(21% .034 264.665);--tw-prose-kbd-shadows:oklab(21% -.00316127 -.0338527/.1);--tw-prose-code:oklch(21% .034 264.665);--tw-prose-pre-code:oklch(92.8% .006 264.531);--tw-prose-pre-bg:oklch(27.8% .033 256.848);--tw-prose-th-borders:oklch(87.2% .01 258.338);--tw-prose-td-borders:oklch(92.8% .006 264.531);--tw-prose-invert-body:oklch(87.2% .01 258.338);--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:oklch(70.7% .022 261.325);--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:oklch(70.7% .022 261.325);--tw-prose-invert-bullets:oklch(44.6% .03 256.802);--tw-prose-invert-hr:oklch(37.3% .034 259.733);--tw-prose-invert-quotes:oklch(96.7% .003 264.542);--tw-prose-invert-quote-borders:oklch(37.3% .034 259.733);--tw-prose-invert-captions:oklch(70.7% .022 261.325);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:#ffffff1a;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:oklch(87.2% .01 258.338);--tw-prose-invert-pre-bg:#00000080;--tw-prose-invert-th-borders:oklch(44.6% .03 256.802);--tw-prose-invert-td-borders:oklch(37.3% .034 259.733);font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-inline-start:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.571429em;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose-sm{font-size:.875rem;line-height:1.71429}.prose-sm :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em;margin-bottom:1.14286em}.prose-sm :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.888889em;margin-bottom:.888889em;font-size:1.28571em;line-height:1.55556}.prose-sm :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em;margin-bottom:1.33333em;padding-inline-start:1.11111em}.prose-sm :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:.8em;font-size:2.14286em;line-height:1.2}.prose-sm :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.6em;margin-bottom:.8em;font-size:1.42857em;line-height:1.4}.prose-sm :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.55556em;margin-bottom:.444444em;font-size:1.28571em;line-height:1.55556}.prose-sm :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.42857em;margin-bottom:.571429em;line-height:1.42857}.prose-sm :where(img):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.71429em;margin-bottom:1.71429em}.prose-sm :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-sm :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.71429em;margin-bottom:1.71429em}.prose-sm :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.142857em;padding-inline-end:.357143em;padding-bottom:.142857em;border-radius:.3125rem;padding-inline-start:.357143em;font-size:.857143em}.prose-sm :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.857143em}.prose-sm :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.9em}.prose-sm :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.888889em}.prose-sm :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.666667em;padding-inline-end:1em;padding-bottom:.666667em;border-radius:.25rem;margin-top:1.66667em;margin-bottom:1.66667em;padding-inline-start:1em;font-size:.857143em;line-height:1.66667}.prose-sm :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em;margin-bottom:1.14286em;padding-inline-start:1.57143em}.prose-sm :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.285714em;margin-bottom:.285714em}.prose-sm :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.428571em}.prose-sm :where(.prose-sm>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.571429em;margin-bottom:.571429em}.prose-sm :where(.prose-sm>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em}.prose-sm :where(.prose-sm>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.14286em}.prose-sm :where(.prose-sm>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em}.prose-sm :where(.prose-sm>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.14286em}.prose-sm :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.571429em;margin-bottom:.571429em}.prose-sm :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em;margin-bottom:1.14286em}.prose-sm :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em}.prose-sm :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.285714em;padding-inline-start:1.57143em}.prose-sm :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2.85714em;margin-bottom:2.85714em}.prose-sm :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.857143em;line-height:1.5}.prose-sm :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:1em;padding-bottom:.666667em;padding-inline-start:1em}.prose-sm :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-sm :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-sm :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.666667em;padding-inline-end:1em;padding-bottom:.666667em;padding-inline-start:1em}.prose-sm :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-sm :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-sm :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.71429em;margin-bottom:1.71429em}.prose-sm :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-sm :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.666667em;font-size:.857143em;line-height:1.33333}.prose-sm :where(.prose-sm>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(.prose-sm>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.inline{display:inline}.inline-flex{display:inline-flex}.field-sizing-content{field-sizing:content}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.max-h-24{max-height:calc(var(--spacing) * 24)}.max-h-\[45vh\]{max-height:45vh}.max-h-\[62vh\]{max-height:62vh}.min-h-16{min-height:calc(var(--spacing) * 16)}.min-h-screen{min-height:100vh}.w-fit{width:fit-content}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-content-center{place-content:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.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-6{gap:calc(var(--spacing) * 6)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-\[4px\]{border-radius:4px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-amber-500\/50{border-color:#f99c0080}@supports (color:color-mix(in lab, red, red)){.border-amber-500\/50{border-color:color-mix(in oklab, var(--color-amber-500) 50%, transparent)}}.border-border{border-color:var(--border)}.border-destructive\/50{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\/50{border-color:color-mix(in oklab, var(--destructive) 50%, transparent)}}.border-emerald-500\/50{border-color:#00bb7f80}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\/50{border-color:color-mix(in oklab, var(--color-emerald-500) 50%, transparent)}}.border-input{border-color:var(--input)}.border-red-500\/50{border-color:#fb2c3680}@supports (color:color-mix(in lab, red, red)){.border-red-500\/50{border-color:color-mix(in oklab, var(--color-red-500) 50%, transparent)}}.border-ring{border-color:var(--ring)}.border-slate-500\/50{border-color:#62748e80}@supports (color:color-mix(in lab, red, red)){.border-slate-500\/50{border-color:color-mix(in oklab, var(--color-slate-500) 50%, transparent)}}.border-transparent{border-color:#0000}.bg-accent\/60{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.bg-accent\/60{background-color:color-mix(in oklab, var(--accent) 60%, transparent)}}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\/10{background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.bg-background{background-color:var(--background)}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-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-emerald-500\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\/10{background-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.bg-muted{background-color:var(--muted)}.bg-primary{background-color:var(--primary)}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.bg-red-500\/10{background-color:color-mix(in oklab, var(--color-red-500) 10%, transparent)}}.bg-secondary{background-color:var(--secondary)}.bg-slate-500\/10{background-color:#62748e1a}@supports (color:color-mix(in lab, red, red)){.bg-slate-500\/10{background-color:color-mix(in oklab, var(--color-slate-500) 10%, transparent)}}.bg-transparent{background-color:#0000}.fill-muted-foreground\/40{fill:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.fill-muted-foreground\/40{fill:color-mix(in oklab, var(--muted-foreground) 40%, transparent)}}.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-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:var(--spacing)}.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\.5{padding-block:calc(var(--spacing) * .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)}.pt-3{padding-top:calc(var(--spacing) * 3)}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.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-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-700{color:var(--color-amber-700)}.text-amber-900{color:var(--color-amber-900)}.text-current{color:currentColor}.text-destructive{color:var(--destructive)}.text-emerald-600{color:var(--color-emerald-600)}.text-emerald-700{color:var(--color-emerald-700)}.text-emerald-900{color:var(--color-emerald-900)}.text-foreground{color:var(--foreground)}.text-muted-foreground,.text-muted-foreground\/50{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/50{color:color-mix(in oklab, var(--muted-foreground) 50%, transparent)}}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-red-900{color:var(--color-red-900)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.italic{font-style:italic}.underline-offset-2{text-underline-offset:2px}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-60{opacity:.6}.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-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-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.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-\[color\,box-shadow\]{transition-property:color,box-shadow;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))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-none{transition-property:none}.outline-none{--tw-outline-style:none;outline-style:none}.running{animation-play-state:running}.group-focus-within\:opacity-100:is(:where(.group):focus-within *){opacity:1}@media (hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--destructive) 90%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, 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-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:underline:hover{text-decoration-line:underline}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:opacity-100:focus-visible{opacity:1}.focus-visible\:ring-\[3px\]: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)}}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.has-\[\>svg\]\:px-2\.5:has(>svg){padding-inline:calc(var(--spacing) * 2.5)}.has-\[\>svg\]\:px-3:has(>svg){padding-inline:calc(var(--spacing) * 3)}.has-\[\>svg\]\:px-4:has(>svg){padding-inline:calc(var(--spacing) * 4)}.aria-invalid\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.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)}}.data-\[state\=checked\]\:border-primary[data-state=checked]{border-color:var(--primary)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--primary)}.data-\[state\=checked\]\:text-primary-foreground[data-state=checked]{color:var(--primary-foreground)}@media (width>=48rem){.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}@media (width>=64rem){.lg\:grid-cols-\[minmax\(0\,1fr\)_320px\]{grid-template-columns:minmax(0,1fr) 320px}}.dark\:bg-destructive\/60:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-destructive\/60:is(.dark *){background-color:color-mix(in oklab, var(--destructive) 60%, transparent)}}.dark\:bg-input\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-input\/30:is(.dark *){background-color:color-mix(in oklab, var(--input) 30%, transparent)}}.dark\:text-amber-200:is(.dark *){color:var(--color-amber-200)}.dark\:text-amber-400:is(.dark *){color:var(--color-amber-400)}.dark\:text-emerald-200:is(.dark *){color:var(--color-emerald-200)}.dark\:text-emerald-400:is(.dark *){color:var(--color-emerald-400)}.dark\:text-red-200:is(.dark *){color:var(--color-red-200)}.dark\:text-slate-200:is(.dark *){color:var(--color-slate-200)}.dark\:prose-invert:is(.dark *){--tw-prose-body:var(--tw-prose-invert-body);--tw-prose-headings:var(--tw-prose-invert-headings);--tw-prose-lead:var(--tw-prose-invert-lead);--tw-prose-links:var(--tw-prose-invert-links);--tw-prose-bold:var(--tw-prose-invert-bold);--tw-prose-counters:var(--tw-prose-invert-counters);--tw-prose-bullets:var(--tw-prose-invert-bullets);--tw-prose-hr:var(--tw-prose-invert-hr);--tw-prose-quotes:var(--tw-prose-invert-quotes);--tw-prose-quote-borders:var(--tw-prose-invert-quote-borders);--tw-prose-captions:var(--tw-prose-invert-captions);--tw-prose-kbd:var(--tw-prose-invert-kbd);--tw-prose-kbd-shadows:var(--tw-prose-invert-kbd-shadows);--tw-prose-code:var(--tw-prose-invert-code);--tw-prose-pre-code:var(--tw-prose-invert-pre-code);--tw-prose-pre-bg:var(--tw-prose-invert-pre-bg);--tw-prose-th-borders:var(--tw-prose-invert-th-borders);--tw-prose-td-borders:var(--tw-prose-invert-td-borders)}.dark\:focus-visible\:ring-destructive\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:focus-visible\:ring-destructive\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\:aria-invalid\:ring-destructive\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:ring-destructive\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\:data-\[state\=checked\]\:bg-primary:is(.dark *)[data-state=checked]{background-color:var(--primary)}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\>svg\]\:pointer-events-none>svg{pointer-events:none}.\[\&\>svg\]\:size-3>svg{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}@media (hover:hover){a.\[a\&\]\:hover\:bg-accent:hover{background-color:var(--accent)}a.\[a\&\]\:hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){a.\[a\&\]\:hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--destructive) 90%, transparent)}}a.\[a\&\]\:hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){a.\[a\&\]\:hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, transparent)}}a.\[a\&\]\:hover\:bg-secondary\/90:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){a.\[a\&\]\:hover\:bg-secondary\/90:hover{background-color:color-mix(in oklab, var(--secondary) 90%, transparent)}}a.\[a\&\]\:hover\:text-accent-foreground:hover{color:var(--accent-foreground)}a.\[a\&\]\:hover\:underline:hover{text-decoration-line:underline}}}@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}:root{--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)}.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)}.markdown-body{--tw-prose-body:var(--foreground);--tw-prose-headings:var(--foreground);--tw-prose-lead:var(--muted-foreground);--tw-prose-links:var(--primary);--tw-prose-bold:var(--foreground);--tw-prose-counters:var(--muted-foreground);--tw-prose-bullets:var(--muted-foreground);--tw-prose-hr:var(--border);--tw-prose-quotes:var(--foreground);--tw-prose-quote-borders:var(--border);--tw-prose-captions:var(--muted-foreground);--tw-prose-code:var(--foreground);--tw-prose-pre-code:var(--foreground);--tw-prose-pre-bg:var(--muted);--tw-prose-th-borders:var(--border);--tw-prose-td-borders:var(--border)}.markdown-body code:not(pre code){border-radius:calc(var(--radius) - 4px);background-color:var(--muted);padding-inline:var(--spacing);padding-block:calc(var(--spacing) * .5);font-family:var(--font-mono);font-size:.875em}.markdown-body code:not(pre code):before,.markdown-body code:not(pre code):after{content:var(--tw-content);--tw-content:none;content:none}.markdown-body pre{border-radius:calc(var(--radius) - 2px);border-style:var(--tw-border-style);border-width:1px;border-color:var(--border)}.markdown-body pre code.hljs{background-color:#0000;padding:0}.markdown-body table{width:100%;display:block;overflow-x:auto}.hljs{color:var(--foreground)}.hljs-comment,.hljs-quote{color:var(--muted-foreground);font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-section,.hljs-link{color:oklch(60% .19 292)}.hljs-string,.hljs-attr,.hljs-addition,.hljs-meta-string{color:oklch(64% .15 155)}.hljs-number,.hljs-symbol,.hljs-bullet{color:oklch(70% .17 60)}.hljs-title,.hljs-name,.hljs-title.function_,.hljs-title.class_{color:oklch(62% .19 250)}.hljs-variable,.hljs-template-variable,.hljs-attribute{color:oklch(65% .18 20)}.hljs-built_in,.hljs-type{color:oklch(62% .15 200)}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.review-document{cursor:text}.review-source-span{border-radius:2px}.review-source-comment{background-color:oklch(70% .17 60/.25);box-shadow:inset 0 -2px oklch(70% .17 60/.6)}.review-source-active{background-color:oklch(62% .19 250/.22)}.review-source-comment.review-source-active{background-color:oklch(66% .19 300/.28)}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-content{syntax:"*";inherits:false;initial-value:""}
|