gestalt-mobile 0.21.0 → 0.22.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/client/assets/index-Db9p-xm2.css +1 -0
- package/dist/client/assets/{index-ufTniVfO.js → index-NHzJXg1w.js} +12 -12
- package/dist/client/index.html +2 -2
- package/dist/server/server/composition.contracts.js +106 -6
- package/dist/server/server/composition.js +36 -8
- package/dist/server/server/features/agent-activity/model.js +5 -0
- package/dist/server/server/features/agent-activity/registry.js +12 -1
- package/dist/server/server/features/autopilot/application/service.js +53 -1
- package/dist/server/server/features/sessions/list-sessions/endpoint.js +10 -6
- package/dist/server/server/features/sessions/model/relay-session.js +19 -0
- package/dist/server/server/features/sessions/promote-recent-thread/use-case.js +13 -3
- package/dist/server/server/features/sessions/register-routes.js +1 -0
- package/dist/server/server/features/sessions/start-session/use-case.js +3 -5
- package/dist/server/server/platform/auth/sqlite-authorization-store.js +98 -205
- package/dist/server/server/platform/auth/sqlite.js +54 -0
- package/dist/server/server/platform/codex/activity-facts.js +4 -0
- package/dist/server/server/platform/codex/recent-thread-lister.js +37 -11
- package/dist/server/server/platform/codex/rollout-execution-policy.js +68 -0
- package/dist/server/server/platform/codex/session-runtime.js +76 -17
- package/dist/server/server/platform/persistence/migrate.js +5 -1
- package/dist/server/server/platform/persistence/sqlite-session-repository.js +11 -3
- package/package.json +1 -1
- package/dist/client/assets/index-D9-XA9jj.css +0 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2026 Dyne.org foundation
|
|
3
|
+
* Designed by Denis Roio <jaromil@dyne.org>
|
|
4
|
+
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
*/
|
|
6
|
+
import { createReadStream } from 'node:fs';
|
|
7
|
+
import { isAbsolute } from 'node:path';
|
|
8
|
+
import { createInterface } from 'node:readline';
|
|
9
|
+
import { createSessionExecutionPolicy, } from '../../features/sessions/model/relay-session.js';
|
|
10
|
+
/** Reads policy metadata only; prompts and model output are never retained or logged. */
|
|
11
|
+
export async function readRolloutExecutionPolicy(rolloutPath) {
|
|
12
|
+
if (!isAbsolute(rolloutPath))
|
|
13
|
+
return undefined;
|
|
14
|
+
let gestaltOrigin = false;
|
|
15
|
+
let first;
|
|
16
|
+
let last;
|
|
17
|
+
try {
|
|
18
|
+
const lines = createInterface({
|
|
19
|
+
input: createReadStream(rolloutPath, { encoding: 'utf8' }),
|
|
20
|
+
crlfDelay: Infinity,
|
|
21
|
+
});
|
|
22
|
+
for await (const line of lines) {
|
|
23
|
+
let record;
|
|
24
|
+
try {
|
|
25
|
+
record = JSON.parse(line);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (!record || typeof record !== 'object')
|
|
31
|
+
continue;
|
|
32
|
+
const { type, payload } = record;
|
|
33
|
+
if (!payload || typeof payload !== 'object')
|
|
34
|
+
continue;
|
|
35
|
+
if (type === 'session_meta') {
|
|
36
|
+
gestaltOrigin = payload.originator === 'gestalt-mobile';
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (type !== 'turn_context')
|
|
40
|
+
continue;
|
|
41
|
+
const policy = decodeExecutionPolicy(payload);
|
|
42
|
+
if (!policy)
|
|
43
|
+
continue;
|
|
44
|
+
first ??= policy;
|
|
45
|
+
last = policy;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
// Gestalt does not mutate policy after thread creation. Its first context is
|
|
52
|
+
// therefore authoritative and cannot be contaminated by an earlier bad import.
|
|
53
|
+
return gestaltOrigin ? first : last;
|
|
54
|
+
}
|
|
55
|
+
function decodeExecutionPolicy(payload) {
|
|
56
|
+
const sandboxPolicy = payload.sandbox_policy;
|
|
57
|
+
const sandbox = sandboxPolicy && typeof sandboxPolicy === 'object'
|
|
58
|
+
? sandboxPolicy.type
|
|
59
|
+
: undefined;
|
|
60
|
+
const approvalPolicy = payload.approval_policy;
|
|
61
|
+
if (sandbox !== 'read-only' && sandbox !== 'workspace-write' && sandbox !== 'danger-full-access')
|
|
62
|
+
return undefined;
|
|
63
|
+
if (approvalPolicy !== 'untrusted' &&
|
|
64
|
+
approvalPolicy !== 'on-request' &&
|
|
65
|
+
approvalPolicy !== 'never')
|
|
66
|
+
return undefined;
|
|
67
|
+
return createSessionExecutionPolicy({ sandbox, approvalPolicy });
|
|
68
|
+
}
|
|
@@ -22,11 +22,13 @@ class SessionResource {
|
|
|
22
22
|
unregister;
|
|
23
23
|
onDisposed;
|
|
24
24
|
disposed = false;
|
|
25
|
+
explicitShutdown = false;
|
|
25
26
|
pendingRequests = new Map();
|
|
26
27
|
threadId;
|
|
27
28
|
pendingThreadName;
|
|
28
29
|
writtenThreadName;
|
|
29
30
|
capabilities = new Map();
|
|
31
|
+
spawnedAgentModels = new Map();
|
|
30
32
|
constructor(sessionId, process, planStatusLease, planMeasurementToken, unregister, onDisposed) {
|
|
31
33
|
this.sessionId = sessionId;
|
|
32
34
|
this.process = process;
|
|
@@ -50,6 +52,12 @@ class SessionResource {
|
|
|
50
52
|
this.onDisposed();
|
|
51
53
|
return true;
|
|
52
54
|
}
|
|
55
|
+
beginExplicitShutdown() {
|
|
56
|
+
this.explicitShutdown = true;
|
|
57
|
+
}
|
|
58
|
+
get exitedUnexpectedly() {
|
|
59
|
+
return !this.explicitShutdown;
|
|
60
|
+
}
|
|
53
61
|
get active() {
|
|
54
62
|
return !this.disposed;
|
|
55
63
|
}
|
|
@@ -90,14 +98,14 @@ export class CodexSessionRuntime {
|
|
|
90
98
|
sessions = new Map();
|
|
91
99
|
historyReads = new Map();
|
|
92
100
|
writerAcquisitions = new Map();
|
|
93
|
-
async start(session, now
|
|
101
|
+
async start(session, now) {
|
|
94
102
|
const resource = await this.createResource(session);
|
|
95
103
|
try {
|
|
96
104
|
await resource.process.rpc.request('initialize', {
|
|
97
105
|
clientInfo: { name: 'gestalt-mobile', version: '0.1.0' },
|
|
98
106
|
capabilities: { experimentalApi: true },
|
|
99
107
|
});
|
|
100
|
-
const startedThreadId = await this.startThread(resource.process, session
|
|
108
|
+
const startedThreadId = await this.startThread(resource.process, session);
|
|
101
109
|
resource.threadId = startedThreadId;
|
|
102
110
|
this.sessions.set(session.id, resource);
|
|
103
111
|
await this.writePendingThreadName(session.id);
|
|
@@ -111,10 +119,15 @@ export class CodexSessionRuntime {
|
|
|
111
119
|
}
|
|
112
120
|
}
|
|
113
121
|
stop(sessionId) {
|
|
114
|
-
this.sessions.get(sessionId)
|
|
122
|
+
const resource = this.sessions.get(sessionId);
|
|
123
|
+
resource?.beginExplicitShutdown();
|
|
124
|
+
resource?.dispose();
|
|
115
125
|
}
|
|
116
126
|
async release(sessionId) {
|
|
117
127
|
const resource = this.sessions.get(sessionId);
|
|
128
|
+
// Mark intent before the await below: a process-exit callback can race the
|
|
129
|
+
// unsubscribe response, but it must not turn an explicit close into recovery.
|
|
130
|
+
resource?.beginExplicitShutdown();
|
|
118
131
|
if (resource?.threadId) {
|
|
119
132
|
try {
|
|
120
133
|
await resource.process.rpc.request('thread/unsubscribe', { threadId: resource.threadId });
|
|
@@ -127,7 +140,12 @@ export class CodexSessionRuntime {
|
|
|
127
140
|
}
|
|
128
141
|
/** Releases all relay-owned app-server children during graceful shutdown. */
|
|
129
142
|
stopAll() {
|
|
130
|
-
|
|
143
|
+
// Exit delivery can already be queued when shutdown begins. Declare the
|
|
144
|
+
// shared intent for every owner before closing any process.
|
|
145
|
+
const resources = [...this.sessions.values()];
|
|
146
|
+
for (const resource of resources)
|
|
147
|
+
resource.beginExplicitShutdown();
|
|
148
|
+
for (const resource of resources)
|
|
131
149
|
resource.dispose();
|
|
132
150
|
}
|
|
133
151
|
/** Keeps a detached session's supervised-plan status observable without launching Codex. */
|
|
@@ -236,7 +254,7 @@ export class CodexSessionRuntime {
|
|
|
236
254
|
throw new Error('CODEX_THREAD_ID_MISSING');
|
|
237
255
|
const owned = this.sessions.get(session.id);
|
|
238
256
|
if (owned)
|
|
239
|
-
return this.decodeHistory(owned.process, session.threadId);
|
|
257
|
+
return this.decodeHistory(owned.process, session.threadId, owned);
|
|
240
258
|
const existing = this.historyReads.get(session.id);
|
|
241
259
|
if (existing)
|
|
242
260
|
return existing;
|
|
@@ -294,6 +312,9 @@ export class CodexSessionRuntime {
|
|
|
294
312
|
...(typeof value.agentRole === 'string' && value.agentRole.length <= 128
|
|
295
313
|
? { role: value.agentRole }
|
|
296
314
|
: {}),
|
|
315
|
+
...(owned.spawnedAgentModels.get(value.id)
|
|
316
|
+
? { model: owned.spawnedAgentModels.get(value.id) }
|
|
317
|
+
: {}),
|
|
297
318
|
},
|
|
298
319
|
];
|
|
299
320
|
}));
|
|
@@ -329,8 +350,14 @@ export class CodexSessionRuntime {
|
|
|
329
350
|
process.close();
|
|
330
351
|
}
|
|
331
352
|
}
|
|
332
|
-
async decodeHistory(process, threadId) {
|
|
333
|
-
const
|
|
353
|
+
async decodeHistory(process, threadId, resource) {
|
|
354
|
+
const response = await process.rpc.request('thread/read', { threadId, includeTurns: true });
|
|
355
|
+
if (resource) {
|
|
356
|
+
resource.spawnedAgentModels.clear();
|
|
357
|
+
for (const [childId, model] of decodeSpawnedAgentModels(response))
|
|
358
|
+
resource.spawnedAgentModels.set(childId, model);
|
|
359
|
+
}
|
|
360
|
+
const result = decodeThreadRead(response);
|
|
334
361
|
const rawTurns = result;
|
|
335
362
|
const activeTurn = rawTurns.find((turn) => turn.status === 'inProgress' && typeof turn.id === 'string');
|
|
336
363
|
return {
|
|
@@ -360,6 +387,10 @@ export class CodexSessionRuntime {
|
|
|
360
387
|
await resource.process.rpc.request('thread/resume', {
|
|
361
388
|
threadId: session.threadId,
|
|
362
389
|
cwd: session.workspacePath,
|
|
390
|
+
...(session.executionPolicy?.approvalPolicy
|
|
391
|
+
? { approvalPolicy: session.executionPolicy.approvalPolicy }
|
|
392
|
+
: {}),
|
|
393
|
+
...(session.executionPolicy?.sandbox ? { sandbox: session.executionPolicy.sandbox } : {}),
|
|
363
394
|
dynamicTools: [gestaltQuizDynamicTool, gestaltOrgPlanAttentionDynamicTool],
|
|
364
395
|
});
|
|
365
396
|
result = {
|
|
@@ -371,9 +402,7 @@ export class CodexSessionRuntime {
|
|
|
371
402
|
catch (error) {
|
|
372
403
|
if (!canRebindMissingRollout(session, error))
|
|
373
404
|
throw error;
|
|
374
|
-
const replacementThreadId = await this.startThread(resource.process, session
|
|
375
|
-
model: session.model,
|
|
376
|
-
});
|
|
405
|
+
const replacementThreadId = await this.startThread(resource.process, session);
|
|
377
406
|
result = rebindMissingRollout(session, error, replacementThreadId, now);
|
|
378
407
|
}
|
|
379
408
|
resource.threadId = result.session.threadId;
|
|
@@ -432,16 +461,16 @@ export class CodexSessionRuntime {
|
|
|
432
461
|
resource.pendingRequests.set(requestId, { resolve, reject });
|
|
433
462
|
});
|
|
434
463
|
}
|
|
435
|
-
async startThread(process, session
|
|
436
|
-
return decodeThreadStart(await process.rpc.request('thread/start', this.threadStartParams(session
|
|
464
|
+
async startThread(process, session) {
|
|
465
|
+
return decodeThreadStart(await process.rpc.request('thread/start', this.threadStartParams(session)));
|
|
437
466
|
}
|
|
438
|
-
threadStartParams(session
|
|
467
|
+
threadStartParams(session) {
|
|
439
468
|
return {
|
|
440
469
|
cwd: session.workspacePath,
|
|
441
|
-
approvalPolicy:
|
|
470
|
+
approvalPolicy: session.executionPolicy?.approvalPolicy ?? 'on-request',
|
|
442
471
|
dynamicTools: [gestaltQuizDynamicTool, gestaltOrgPlanAttentionDynamicTool],
|
|
443
|
-
...(
|
|
444
|
-
...(
|
|
472
|
+
...(session.model ? { model: session.model } : {}),
|
|
473
|
+
...(session.executionPolicy?.sandbox ? { sandbox: session.executionPolicy.sandbox } : {}),
|
|
445
474
|
};
|
|
446
475
|
}
|
|
447
476
|
async createResource(session) {
|
|
@@ -477,7 +506,7 @@ export class CodexSessionRuntime {
|
|
|
477
506
|
// Own process exit before resume/initialization can make this resource appear healthy.
|
|
478
507
|
// A short-lived child could otherwise leave a durable ready session without a writer.
|
|
479
508
|
const exitUnsubscribe = process.onExit?.(() => {
|
|
480
|
-
if (resource.dispose())
|
|
509
|
+
if (resource.dispose() && resource.exitedUnexpectedly)
|
|
481
510
|
this.onProcessExit?.(session.id);
|
|
482
511
|
}) ?? (() => { });
|
|
483
512
|
resource.attach([exitUnsubscribe]);
|
|
@@ -666,6 +695,36 @@ function decodeHistoryItem(value) {
|
|
|
666
695
|
}
|
|
667
696
|
return [];
|
|
668
697
|
}
|
|
698
|
+
/** Recovers optional spawn metadata without exposing collaboration prompts to chat history. */
|
|
699
|
+
function decodeSpawnedAgentModels(value) {
|
|
700
|
+
const models = new Map();
|
|
701
|
+
const turns = asRecord(asRecord(value)?.thread)?.turns;
|
|
702
|
+
if (!Array.isArray(turns) || turns.length > 10_000)
|
|
703
|
+
return models;
|
|
704
|
+
for (const turn of turns) {
|
|
705
|
+
const items = asRecord(turn)?.items;
|
|
706
|
+
if (!Array.isArray(items) || items.length > 10_000)
|
|
707
|
+
continue;
|
|
708
|
+
for (const candidate of items) {
|
|
709
|
+
const item = asRecord(candidate);
|
|
710
|
+
const model = boundedString(item?.model, 256);
|
|
711
|
+
if (item?.type !== 'collabAgentToolCall' ||
|
|
712
|
+
(item.tool !== 'spawnAgent' && item.tool !== 'spawn_agent') ||
|
|
713
|
+
!model ||
|
|
714
|
+
!Array.isArray(item.receiverThreadIds) ||
|
|
715
|
+
item.receiverThreadIds.length > 64)
|
|
716
|
+
continue;
|
|
717
|
+
for (const receiver of item.receiverThreadIds) {
|
|
718
|
+
const childId = boundedString(receiver, 256);
|
|
719
|
+
if (childId)
|
|
720
|
+
models.set(childId, model);
|
|
721
|
+
if (models.size >= 64)
|
|
722
|
+
return models;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return models;
|
|
727
|
+
}
|
|
669
728
|
function decodeUserMessageContent(value) {
|
|
670
729
|
if (!Array.isArray(value) || value.length > 1_000)
|
|
671
730
|
return [];
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Designed by Denis Roio <jaromil@dyne.org>
|
|
4
4
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
5
|
*/
|
|
6
|
-
const schema = `CREATE TABLE IF NOT EXISTS relay_sessions (id TEXT PRIMARY KEY, workspace_id TEXT NOT NULL, workspace_path TEXT NOT NULL, profile TEXT NOT NULL, model TEXT, branch TEXT, thread_id TEXT, state TEXT NOT NULL, desired_state TEXT NOT NULL, active_turn_id TEXT, protocol_version TEXT, failure_count INTEGER NOT NULL DEFAULT 0, effective_skill_selection_json TEXT, last_org_plan_json TEXT, next_sequence INTEGER NOT NULL DEFAULT 1, created_at TEXT NOT NULL, updated_at TEXT NOT NULL); CREATE TABLE IF NOT EXISTS pending_interactions (session_id TEXT NOT NULL REFERENCES relay_sessions(id) ON DELETE CASCADE, request_id TEXT NOT NULL, kind TEXT NOT NULL, payload_json TEXT NOT NULL, turn_id TEXT, requested_at TEXT, resolved_at TEXT, outcome TEXT, operation_key TEXT, resolution_state TEXT NOT NULL DEFAULT 'active', PRIMARY KEY (session_id, request_id)); CREATE TABLE IF NOT EXISTS session_events (session_id TEXT NOT NULL REFERENCES relay_sessions(id) ON DELETE CASCADE, sequence INTEGER NOT NULL, occurred_at TEXT NOT NULL, type TEXT NOT NULL, payload_json TEXT NOT NULL, autopilot_outbox_id INTEGER, PRIMARY KEY (session_id, sequence), UNIQUE(session_id, autopilot_outbox_id)); CREATE TABLE IF NOT EXISTS idempotency_results (scope TEXT NOT NULL, key TEXT NOT NULL, status_code INTEGER NOT NULL, body_json TEXT NOT NULL, PRIMARY KEY (scope, key)); CREATE TABLE IF NOT EXISTS autopilot_sessions (session_id TEXT PRIMARY KEY REFERENCES relay_sessions(id) ON DELETE CASCADE, state TEXT NOT NULL, requested_enabled INTEGER NOT NULL, plan_identity TEXT, plan_fingerprint TEXT, generation INTEGER NOT NULL, no_progress_count INTEGER NOT NULL, next_evaluation_at TEXT, last_control_id TEXT, stop_reason TEXT, updated_at TEXT NOT NULL); CREATE TABLE IF NOT EXISTS autopilot_controls (session_id TEXT NOT NULL REFERENCES relay_sessions(id) ON DELETE CASCADE, control_id TEXT NOT NULL, status TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL, failure_code TEXT, turn_id TEXT, PRIMARY KEY (session_id, control_id)); CREATE TABLE IF NOT EXISTS autopilot_outbox (id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL REFERENCES relay_sessions(id) ON DELETE CASCADE, type TEXT NOT NULL, payload_json TEXT NOT NULL, occurred_at TEXT NOT NULL);`;
|
|
6
|
+
const schema = `CREATE TABLE IF NOT EXISTS relay_sessions (id TEXT PRIMARY KEY, workspace_id TEXT NOT NULL, workspace_path TEXT NOT NULL, profile TEXT NOT NULL, model TEXT, branch TEXT, sandbox TEXT, approval_policy TEXT, thread_id TEXT, state TEXT NOT NULL, desired_state TEXT NOT NULL, active_turn_id TEXT, protocol_version TEXT, failure_count INTEGER NOT NULL DEFAULT 0, effective_skill_selection_json TEXT, last_org_plan_json TEXT, next_sequence INTEGER NOT NULL DEFAULT 1, created_at TEXT NOT NULL, updated_at TEXT NOT NULL); CREATE TABLE IF NOT EXISTS pending_interactions (session_id TEXT NOT NULL REFERENCES relay_sessions(id) ON DELETE CASCADE, request_id TEXT NOT NULL, kind TEXT NOT NULL, payload_json TEXT NOT NULL, turn_id TEXT, requested_at TEXT, resolved_at TEXT, outcome TEXT, operation_key TEXT, resolution_state TEXT NOT NULL DEFAULT 'active', PRIMARY KEY (session_id, request_id)); CREATE TABLE IF NOT EXISTS session_events (session_id TEXT NOT NULL REFERENCES relay_sessions(id) ON DELETE CASCADE, sequence INTEGER NOT NULL, occurred_at TEXT NOT NULL, type TEXT NOT NULL, payload_json TEXT NOT NULL, autopilot_outbox_id INTEGER, PRIMARY KEY (session_id, sequence), UNIQUE(session_id, autopilot_outbox_id)); CREATE TABLE IF NOT EXISTS idempotency_results (scope TEXT NOT NULL, key TEXT NOT NULL, status_code INTEGER NOT NULL, body_json TEXT NOT NULL, PRIMARY KEY (scope, key)); CREATE TABLE IF NOT EXISTS autopilot_sessions (session_id TEXT PRIMARY KEY REFERENCES relay_sessions(id) ON DELETE CASCADE, state TEXT NOT NULL, requested_enabled INTEGER NOT NULL, plan_identity TEXT, plan_fingerprint TEXT, generation INTEGER NOT NULL, no_progress_count INTEGER NOT NULL, next_evaluation_at TEXT, last_control_id TEXT, stop_reason TEXT, updated_at TEXT NOT NULL); CREATE TABLE IF NOT EXISTS autopilot_controls (session_id TEXT NOT NULL REFERENCES relay_sessions(id) ON DELETE CASCADE, control_id TEXT NOT NULL, status TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL, failure_code TEXT, turn_id TEXT, PRIMARY KEY (session_id, control_id)); CREATE TABLE IF NOT EXISTS autopilot_outbox (id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL REFERENCES relay_sessions(id) ON DELETE CASCADE, type TEXT NOT NULL, payload_json TEXT NOT NULL, occurred_at TEXT NOT NULL);`;
|
|
7
7
|
export function migrate(database) {
|
|
8
8
|
database.exec(schema);
|
|
9
9
|
database.exec("CREATE INDEX IF NOT EXISTS session_events_autopilot_audit_tail_v2 ON session_events(session_id, type, sequence DESC) WHERE type IN ('autopilot.continuation-scheduled','autopilot.control-issued','autopilot.turn-started','autopilot.turn-failed','autopilot.progress-reset','autopilot.updated','org-plan.attention-required','org-plan.attention-resolved')");
|
|
@@ -18,6 +18,10 @@ export function migrate(database) {
|
|
|
18
18
|
database.exec('ALTER TABLE relay_sessions ADD COLUMN branch TEXT');
|
|
19
19
|
if (!columns.some((column) => column.name === 'attention_tool_capability'))
|
|
20
20
|
database.exec('ALTER TABLE relay_sessions ADD COLUMN attention_tool_capability TEXT');
|
|
21
|
+
if (!columns.some((column) => column.name === 'sandbox'))
|
|
22
|
+
database.exec('ALTER TABLE relay_sessions ADD COLUMN sandbox TEXT');
|
|
23
|
+
if (!columns.some((column) => column.name === 'approval_policy'))
|
|
24
|
+
database.exec('ALTER TABLE relay_sessions ADD COLUMN approval_policy TEXT');
|
|
21
25
|
const interactionColumns = database
|
|
22
26
|
.prepare('PRAGMA table_info(pending_interactions)')
|
|
23
27
|
.all();
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Designed by Denis Roio <jaromil@dyne.org>
|
|
4
4
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
5
|
*/
|
|
6
|
-
import { createEffectiveSkillSelection, } from '../../features/sessions/model/relay-session.js';
|
|
6
|
+
import { createEffectiveSkillSelection, createSessionExecutionPolicy, } from '../../features/sessions/model/relay-session.js';
|
|
7
7
|
export class SqliteSessionRepository {
|
|
8
8
|
db;
|
|
9
9
|
constructor(db) {
|
|
@@ -11,8 +11,8 @@ export class SqliteSessionRepository {
|
|
|
11
11
|
}
|
|
12
12
|
save(session) {
|
|
13
13
|
this.db
|
|
14
|
-
.prepare('INSERT INTO relay_sessions (id,workspace_id,workspace_path,profile,model,branch,thread_id,state,desired_state,active_turn_id,protocol_version,attention_tool_capability,failure_count,effective_skill_selection_json,last_org_plan_json,created_at,updated_at) VALUES (
|
|
15
|
-
.run(session.id, session.workspaceId, session.workspacePath, session.profile, session.model ?? null, session.branch ?? null, session.threadId, session.state, session.desiredState, session.activeTurnId, session.protocolVersion, session.attentionToolCapability ?? null, session.failureCount, session.effectiveSkillSelection === undefined
|
|
14
|
+
.prepare('INSERT INTO relay_sessions (id,workspace_id,workspace_path,profile,model,branch,sandbox,approval_policy,thread_id,state,desired_state,active_turn_id,protocol_version,attention_tool_capability,failure_count,effective_skill_selection_json,last_org_plan_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON CONFLICT(id) DO UPDATE SET workspace_id=excluded.workspace_id,workspace_path=excluded.workspace_path,profile=excluded.profile,model=excluded.model,branch=excluded.branch,sandbox=excluded.sandbox,approval_policy=excluded.approval_policy,thread_id=excluded.thread_id,state=excluded.state,desired_state=excluded.desired_state,active_turn_id=excluded.active_turn_id,protocol_version=excluded.protocol_version,attention_tool_capability=excluded.attention_tool_capability,failure_count=excluded.failure_count,effective_skill_selection_json=excluded.effective_skill_selection_json,last_org_plan_json=excluded.last_org_plan_json,updated_at=excluded.updated_at')
|
|
15
|
+
.run(session.id, session.workspaceId, session.workspacePath, session.profile, session.model ?? null, session.branch ?? null, session.executionPolicy?.sandbox ?? null, session.executionPolicy?.approvalPolicy ?? null, session.threadId, session.state, session.desiredState, session.activeTurnId, session.protocolVersion, session.attentionToolCapability ?? null, session.failureCount, session.effectiveSkillSelection === undefined
|
|
16
16
|
? null
|
|
17
17
|
: JSON.stringify(session.effectiveSkillSelection), session.lastOrgPlan === undefined ? null : JSON.stringify(session.lastOrgPlan), session.createdAt, session.updatedAt);
|
|
18
18
|
}
|
|
@@ -28,6 +28,13 @@ export class SqliteSessionRepository {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
function map(row) {
|
|
31
|
+
const sandbox = row.sandbox ?? null;
|
|
32
|
+
const approvalPolicy = row.approval_policy ?? null;
|
|
33
|
+
if (approvalPolicy === null && sandbox !== null)
|
|
34
|
+
throw new Error('SESSION_EXECUTION_POLICY_INVALID');
|
|
35
|
+
const executionPolicy = approvalPolicy === null
|
|
36
|
+
? undefined
|
|
37
|
+
: createSessionExecutionPolicy({ sandbox: sandbox ?? undefined, approvalPolicy });
|
|
31
38
|
const effectiveSkillSelection = row.effective_skill_selection_json
|
|
32
39
|
? createEffectiveSkillSelection(JSON.parse(row.effective_skill_selection_json))
|
|
33
40
|
: undefined;
|
|
@@ -41,6 +48,7 @@ function map(row) {
|
|
|
41
48
|
profile: row.profile,
|
|
42
49
|
...(row.model === null ? {} : { model: row.model }),
|
|
43
50
|
...(row.branch === null ? {} : { branch: row.branch }),
|
|
51
|
+
...(executionPolicy === undefined ? {} : { executionPolicy }),
|
|
44
52
|
threadId: row.thread_id,
|
|
45
53
|
state: row.state,
|
|
46
54
|
desiredState: row.desired_state,
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.session-path.svelte-t9laac{text-align:center;text-overflow:ellipsis;white-space:nowrap;flex:1 1 0;min-inline-size:0;margin:0;overflow:hidden}.session-model.svelte-t9laac{color:var(--theme-text-muted);font-family:var(--theme-font-code);margin-inline-start:clamp(.75rem,3vw,2rem)}@media (width<=34rem){.session-path.svelte-t9laac{font-size:max(.625rem,12px)}.session-model.svelte-t9laac{display:none}}.chat-activity.svelte-thyolt,.live-activity.svelte-thyolt{--activity-gap:.4rem;--activity-type-color:var(--theme-text-muted)}.chat-activity.svelte-thyolt>summary:where(.svelte-thyolt){color:var(--activity-type-color);cursor:pointer;font-size:.875em}.live-activity.svelte-thyolt{margin-block-start:.5rem}.live-activity.svelte-thyolt>strong:where(.svelte-thyolt){color:var(--activity-type-color);font-size:.875em}.activity-list.svelte-thyolt{gap:var(--activity-gap);margin-block:.25rem 0;margin-inline:0;padding:0;list-style:none;display:grid}.activity-row.svelte-thyolt{flex-wrap:wrap;align-items:baseline;gap:.25rem .5rem;display:flex}.activity-row[data-activity-status=failed].svelte-thyolt{border-inline-start:.25rem solid var(--theme-error);padding-inline-start:.375rem}.activity-row[data-activity-status=completed].svelte-thyolt{border-inline-start:.25rem solid var(--theme-success);padding-inline-start:.375rem}.activity-row[data-activity-status].svelte-thyolt:not([data-activity-status=completed]):not([data-activity-status=failed]){border-inline-start:.25rem solid var(--theme-info);padding-inline-start:.375rem}.activity-type.svelte-thyolt{color:var(--activity-type-color);font-size:.75em;line-height:1.2}.activity-content.svelte-thyolt{overflow-wrap:anywhere;white-space:pre-wrap;min-inline-size:0}.app-control.svelte-6ey372{box-sizing:border-box;min-block-size:44px;min-inline-size:44px;color:var(--theme-text);font:inherit;text-align:center;background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:var(--theme-radius);cursor:pointer;scroll-margin-block:var(--sticky-header-clearance) var(--bottom-navigation-clearance);justify-content:center;align-items:center;padding:.45rem .75rem;display:inline-flex}.app-control.svelte-6ey372:hover:not(:disabled,[aria-disabled=true]){background:var(--theme-control-hover)}.app-control.svelte-6ey372:active:not(:disabled,[aria-disabled=true]){color:var(--theme-control-pressed-contrast);background:var(--theme-control-pressed)}.app-control.svelte-6ey372:focus-visible{outline:3px solid var(--theme-accent);outline-offset:2px}.app-control.svelte-6ey372:disabled,.app-control[aria-disabled=true].svelte-6ey372{color:var(--theme-control-disabled);cursor:not-allowed;opacity:.65}.compact.svelte-6ey372{padding:.25rem .4rem;font-size:.8rem}.full.svelte-6ey372{inline-size:100%}.primary.svelte-6ey372{color:var(--theme-accent-contrast);background:var(--theme-accent);border-color:var(--theme-accent);box-shadow:inset 0 .15rem 0 var(--theme-accent-contrast);font-weight:700}@media (prefers-reduced-motion:reduce){.app-control.svelte-6ey372{transition:none!important;animation:none!important}}.agent-activity.svelte-d9jh4j{overflow-wrap:anywhere;max-inline-size:100%}.chips.svelte-d9jh4j{flex-wrap:wrap;align-items:center;gap:.4rem;min-inline-size:0;display:flex}.chip.svelte-d9jh4j,.freshness.svelte-d9jh4j{border:1px solid var(--theme-border);overflow-wrap:anywhere;border-radius:999px;padding:.35rem .55rem;font-size:.85rem}.children.svelte-d9jh4j>summary:where(.svelte-d9jh4j){cursor:pointer;align-items:center;min-block-size:2.75rem;display:inline-flex}.children.svelte-d9jh4j ul:where(.svelte-d9jh4j){max-inline-size:min(38rem,100%);margin:.45rem 0 0;padding-inline-start:1.25rem}.children.svelte-d9jh4j small:where(.svelte-d9jh4j){color:var(--theme-text-muted)}.compact.svelte-d9jh4j .agents:where(.svelte-d9jh4j){inline-size:100%;position:relative}.compact.svelte-d9jh4j .agents:where(.svelte-d9jh4j) ul:where(.svelte-d9jh4j){z-index:10;box-sizing:border-box;overscroll-behavior:contain;background:var(--theme-surface);border:1px solid var(--theme-border);max-block-size:min(20rem,50vh);inline-size:min(22rem,100vw - max(2.5rem,48px));box-shadow:0 .35rem 1rem color-mix(in srgb, var(--theme-text) 18%, transparent);border-radius:.5rem;gap:.35rem;margin:0;padding:.45rem;list-style:none;display:grid;position:absolute;inset-block-end:calc(100% + .35rem);inset-inline-end:0;overflow-y:auto}.compact.svelte-d9jh4j .agents:where(.svelte-d9jh4j) li:where(.svelte-d9jh4j){border-block-end:1px solid var(--theme-border);gap:.1rem;min-inline-size:0;padding:.3rem;display:grid}.compact.svelte-d9jh4j .agents:where(.svelte-d9jh4j) time:where(.svelte-d9jh4j),.compact.svelte-d9jh4j .agents:where(.svelte-d9jh4j) .unavailable:where(.svelte-d9jh4j){color:var(--theme-text-muted);font-size:.78rem}[data-state=blocked].svelte-d9jh4j,[data-state=awaitingHuman].svelte-d9jh4j,[data-state=disconnected].svelte-d9jh4j{font-weight:700;text-decoration:underline}.visually-hidden.svelte-d9jh4j{clip-path:inset(50%);white-space:nowrap;block-size:1px;inline-size:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.svelte-d9jh4j{transition:none!important;animation:none!important}}main.svelte-iw6wrs{box-sizing:border-box;max-inline-size:100vw;padding:1rem}h1.svelte-iw6wrs{overflow-wrap:anywhere}.autopilot-control.svelte-1qf1ppf{min-inline-size:0;max-inline-size:100%;scroll-margin-block:var(--sticky-header-clearance) var(--bottom-navigation-clearance)}.control-row.svelte-1qf1ppf{flex-wrap:wrap;align-items:center;gap:.45rem;display:flex}.compact.svelte-1qf1ppf{inline-size:100%}.status.svelte-1qf1ppf{border:1px solid var(--theme-border);overflow-wrap:anywhere;border-radius:999px;padding:.35rem .55rem}.status[data-state=attentionRequired].svelte-1qf1ppf,.status[data-state=unavailable].svelte-1qf1ppf{font-weight:700;text-decoration:underline}p.svelte-1qf1ppf{color:var(--theme-text-muted);overflow-wrap:anywhere;margin:.25rem 0 0}.visually-hidden.svelte-1qf1ppf{clip-path:inset(50%);white-space:nowrap;border:0;block-size:1px;inline-size:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.svelte-1qf1ppf{transition:none!important;animation:none!important}}.attention.svelte-1hnxk0w{border:2px solid var(--theme-error);overflow-wrap:anywhere;scroll-margin-block:var(--sticky-header-clearance) var(--bottom-navigation-clearance);border-inline-start-width:.5rem;border-radius:.5rem;padding:.75rem}h3.svelte-1hnxk0w{margin:0}dl.svelte-1hnxk0w{gap:.35rem;display:grid}dl.svelte-1hnxk0w div:where(.svelte-1hnxk0w){gap:.15rem;display:grid}dt.svelte-1hnxk0w{font-weight:700}dd.svelte-1hnxk0w{margin:0}.actions.svelte-1hnxk0w{flex-wrap:wrap;gap:.5rem;display:flex}button.svelte-1hnxk0w{min-block-size:44px;font:inherit;scroll-margin-block:var(--sticky-header-clearance) var(--bottom-navigation-clearance);padding:.45rem .75rem}textarea.svelte-1hnxk0w{box-sizing:border-box;min-block-size:5rem;inline-size:100%;font:inherit;scroll-margin-block:var(--sticky-header-clearance) var(--bottom-navigation-clearance)}.guidance-help.svelte-1hnxk0w{color:var(--theme-text-muted);margin:.25rem 0}button.svelte-1hnxk0w:focus-visible{outline:3px solid var(--theme-accent);outline-offset:2px}.safety-stop.svelte-yp6bgs{border:2px solid var(--theme-error);overflow-wrap:anywhere;scroll-margin-block:var(--sticky-header-clearance) var(--bottom-navigation-clearance);border-inline-start-width:.5rem;border-radius:.5rem;padding:.75rem}h3.svelte-yp6bgs,p.svelte-yp6bgs{margin:0 0 .5rem}.actions.svelte-yp6bgs{flex-wrap:wrap;gap:.5rem;display:flex}button.svelte-yp6bgs{min-block-size:44px;font:inherit;padding:.45rem .75rem}button.svelte-yp6bgs:focus-visible{outline:3px solid var(--theme-accent);outline-offset:2px}@media (prefers-reduced-motion:reduce){.svelte-yp6bgs{transition:none!important;animation:none!important}}form.svelte-1264sfg>[role=status]:where(.svelte-1264sfg){text-align:start;margin-block:1rem .35rem}.writer-hint.svelte-1264sfg{color:var(--theme-text-muted);margin:.35rem 0}.writer-feedback.svelte-1264sfg{border-inline-start:.25rem solid var(--theme-danger,#b42318);background:var(--theme-control-hover);flex-wrap:wrap;align-items:center;gap:.5rem;margin-block:.5rem;padding:.5rem;display:flex}.writer-feedback.svelte-1264sfg p:where(.svelte-1264sfg){flex:16rem;margin:0}.command-menu.svelte-1264sfg{background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:.375rem;gap:.125rem;max-inline-size:min(100%,32rem);margin:0 0 .35rem;padding:.25rem;list-style:none;display:grid}.command-menu.svelte-1264sfg button:where(.svelte-1264sfg){inline-size:100%;color:var(--theme-text);text-align:start;background:0 0;border:0;border-radius:.25rem;align-items:baseline;gap:.5rem;padding:.25rem .375rem;display:flex}.command-menu.svelte-1264sfg .command-selected:where(.svelte-1264sfg) button:where(.svelte-1264sfg),.command-menu.svelte-1264sfg button:where(.svelte-1264sfg):hover{background:var(--theme-control-hover)}.command-menu.svelte-1264sfg small:where(.svelte-1264sfg){color:var(--theme-text-muted);font-size:.8em}.command-menu.svelte-1264sfg button:where(.svelte-1264sfg):focus-visible{outline:2px solid var(--theme-focus);outline-offset:1px}.prompt-row.svelte-1264sfg{align-items:end;gap:.5rem;display:flex}textarea.svelte-1264sfg{resize:vertical;flex:auto;min-block-size:2.75rem}.prompt-row.svelte-1264sfg>button:where(.svelte-1264sfg),.prompt-action.svelte-1264sfg>button:where(.svelte-1264sfg){flex:none;place-items:center;min-block-size:3rem;inline-size:3rem;padding:0;display:grid}.prompt-row.svelte-1264sfg svg:where(.svelte-1264sfg){fill:none;stroke:currentColor;stroke-width:2px;stroke-linecap:round;stroke-linejoin:round;block-size:1.35rem;inline-size:1.35rem}.prompt-action.svelte-1264sfg{flex:none;position:relative}.prompt-action.svelte-1264sfg>button:where(.svelte-1264sfg){color:var(--theme-text);background:var(--theme-surface);border:1px solid var(--theme-border);cursor:pointer;border-radius:.375rem}.prompt-action.svelte-1264sfg>button:where(.svelte-1264sfg):hover{background:var(--theme-control-hover)}.prompt-action.svelte-1264sfg>button:where(.svelte-1264sfg):focus-visible{outline:2px solid var(--theme-focus);outline-offset:2px}.action-panel.svelte-1264sfg{z-index:2;background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:.375rem;gap:.125rem;min-inline-size:max-content;padding:.25rem;display:grid;position:absolute;inset-block-end:calc(100% + .35rem);inset-inline-end:0;box-shadow:0 .35rem 1rem #0000002e}.action-panel.svelte-1264sfg button:where(.svelte-1264sfg){inline-size:100%;color:var(--theme-text);text-align:start;white-space:nowrap;background:0 0;border:0;border-radius:.25rem;padding:.5rem .65rem}.action-panel.svelte-1264sfg button:where(.svelte-1264sfg):hover{background:var(--theme-control-hover)}.block-cursor.svelte-1264sfg{vertical-align:-.1em;background:var(--theme-accent);block-size:1em;inline-size:.55ch;animation:1s steps(2,start) infinite svelte-1264sfg-blink;display:inline-block}@media (prefers-reduced-motion:reduce){.block-cursor.svelte-1264sfg{animation:none}}@keyframes svelte-1264sfg-blink{50%{opacity:0}}.quiz-form.svelte-77f3gb{gap:1rem;display:grid}fieldset.svelte-77f3gb{border:0;min-inline-size:0;margin:0;padding:0}.questions.svelte-77f3gb{gap:1rem;display:grid}legend.svelte-77f3gb{gap:.25rem;max-inline-size:100%;display:grid}.choices.svelte-77f3gb{gap:.5rem;margin-block-start:.5rem;display:grid}.choice.svelte-77f3gb{position:relative}.choice.svelte-77f3gb>input:where(.svelte-77f3gb){opacity:0;cursor:pointer;block-size:100%;inline-size:100%;margin:0;position:absolute;inset:0}.choice.svelte-77f3gb>label:where(.svelte-77f3gb){background:var(--theme-surface);border:2px solid var(--theme-border);border-radius:.5rem;gap:.125rem;min-block-size:44px;padding:.75rem;display:grid}.choice.svelte-77f3gb>input:where(.svelte-77f3gb):checked+label:where(.svelte-77f3gb){border-width:3px;border-color:var(--theme-accent);background:var(--theme-surface-subtle)}.choice.svelte-77f3gb>input:where(.svelte-77f3gb):focus-visible+label:where(.svelte-77f3gb){outline:3px solid var(--theme-focus);outline-offset:2px}label.svelte-77f3gb span:where(.svelte-77f3gb),legend.svelte-77f3gb span:where(.svelte-77f3gb){color:var(--theme-text-muted)}.custom.svelte-77f3gb{margin-block-start:.25rem}.custom.svelte-77f3gb input:where(.svelte-77f3gb){box-sizing:border-box;min-block-size:44px;inline-size:100%;font:inherit;margin-block-start:.375rem}article.svelte-ajsqcq{background:var(--theme-surface-subtle);border-inline-start:.25rem solid var(--theme-info);border-radius:.375rem;margin-block:.75rem;padding:.75rem}.interaction-kind.svelte-ajsqcq,.interaction-submitting.svelte-ajsqcq,.interaction-result.svelte-ajsqcq,.interaction-failed.svelte-ajsqcq{margin-block:0 .5rem}.interaction-result.svelte-ajsqcq{font-weight:600}.command-approval-command.svelte-ajsqcq{white-space:pre-wrap;max-inline-size:100%;font-family:var(--theme-font-code);background:var(--theme-code);border:1px solid var(--theme-border);border-radius:.375rem;margin-block:.5rem .75rem;padding:.625rem;overflow-x:auto}.command-approval-missing.svelte-ajsqcq{margin-block:.5rem .75rem}.file-change-approval-targets.svelte-ajsqcq{overflow-wrap:anywhere;margin-block:.5rem .75rem;padding-inline-start:1.5rem}.file-change-approval-missing.svelte-ajsqcq{margin-block:.5rem .75rem}.approval-actions.svelte-ajsqcq{flex-wrap:wrap;gap:clamp(.5rem,2vw,1rem);display:flex}.autopilot-audit.svelte-1im954t{border-inline-start:.25rem solid var(--theme-border);overflow-wrap:anywhere;padding-inline-start:.5rem}.audit-incomplete.svelte-1im954t{border-inline-start:.35rem solid var(--theme-border);color:var(--theme-text-muted);margin-block:.5rem;padding-inline-start:.65rem}.autopilot-audit.svelte-1im954t time:where(.svelte-1im954t){color:var(--theme-text-muted);margin-inline-start:.5rem}.autopilot-audit.svelte-1im954t summary:where(.svelte-1im954t){scroll-margin-block:var(--sticky-header-clearance) var(--bottom-navigation-clearance)}ol.svelte-1im954t{inline-size:100%;margin:0;padding:0;list-style:none}li.svelte-1im954t{box-sizing:border-box;white-space:pre-wrap;overflow-wrap:anywhere;inline-size:100%;margin-block-end:0}li.svelte-1im954t+li:where(.svelte-1im954t){margin-block-start:1rem}.prompt-turn.svelte-1im954t{background:var(--theme-surface-subtle);border-inline-start:.25rem solid var(--theme-accent);border-radius:.375rem;padding:.5rem .625rem}.answer-turn.svelte-1im954t{border-inline-start:.25rem solid var(--theme-border);padding-inline-start:.625rem}.commentary-turn.svelte-1im954t,.orphan-activity-turn.svelte-1im954t,.progress-turn.svelte-1im954t,.commentary-content.svelte-1im954t{background:var(--theme-surface-subtle);border-inline-start:.25rem solid var(--theme-info);border-radius:.375rem;padding:.5rem .625rem}.live-commentary.svelte-1im954t,.progress-turn.svelte-1im954t{background:0 0}.entry-heading.svelte-1im954t{align-items:baseline;gap:.75rem;display:flex}time.svelte-1im954t{color:var(--theme-text-muted);white-space:nowrap;margin-inline-start:auto;font-size:.875em}.commentary-toggle.svelte-1im954t{min-block-size:1.5rem;color:var(--theme-text-muted);background:0 0;border:0;padding:0 .125rem;font-size:.875em}.answer-history.svelte-1im954t{flex-wrap:wrap;align-items:baseline;gap:.25rem .75rem;margin-block:.2rem .35rem;display:flex}.file-changes.svelte-1im954t{background:var(--theme-surface-subtle);border-inline-start:.25rem solid var(--theme-success);border-radius:.375rem;margin-block:.5rem;padding:.5rem .625rem}.file-changes.svelte-1im954t>strong:where(.svelte-1im954t){font-size:.875em}.file-changes.svelte-1im954t ul:where(.svelte-1im954t){gap:.15rem;margin:.25rem 0 0;padding-inline-start:1.25rem;display:grid}.commentary-content.svelte-1im954t{margin-block:.25rem .5rem}.entry-content.svelte-1im954t{margin-block:.125rem 0;margin-inline:0}pre.svelte-1im954t,code.svelte-1im954t{font-family:var(--theme-font-code)}pre.svelte-1im954t{white-space:pre;background:var(--theme-code);border:1px solid var(--theme-border);border-radius:var(--theme-radius);padding:.625rem;overflow-x:auto}.svelte-1im954t:not(pre)>code:where(.svelte-1im954t){background:var(--theme-code);border-radius:.2rem;padding-inline:.2em}a.svelte-1im954t{color:var(--theme-info)}.table-scroll.svelte-1im954t{margin-block:.75rem;overflow-x:auto}table.svelte-1im954t{border-collapse:collapse;white-space:normal;width:max-content;min-width:100%}th.svelte-1im954t,td.svelte-1im954t{text-align:left;vertical-align:top;border:1px solid var(--theme-border);padding:.25rem .5rem}th.svelte-1im954t{background:var(--theme-surface-subtle);font-weight:600}.toast-viewport.svelte-1a0rutm{z-index:10;pointer-events:none;gap:.5rem;max-block-size:calc(100dvh - 7rem);inline-size:min(24rem,100vw - 1.5rem);display:grid;position:fixed;inset-block-start:calc(1rem + env(safe-area-inset-top));inset-inline-end:max(.75rem, env(safe-area-inset-right));overflow-y:auto}.toast.svelte-1a0rutm{box-sizing:border-box;min-inline-size:0;color:var(--theme-text);background:var(--theme-surface);border:1px solid var(--theme-info);box-shadow:0 .4rem 1.2rem var(--theme-shadow);pointer-events:auto;border-inline-start-width:.35rem;border-radius:.55rem;grid-template-columns:auto minmax(0,1fr) 44px;align-items:start;gap:.6rem;padding:.65rem;display:grid}.toast.error.svelte-1a0rutm{color:var(--theme-error);border-color:var(--theme-error);border-inline-start-style:double}.toast.success.svelte-1a0rutm{color:var(--theme-success);border-color:var(--theme-success);border-inline-start-style:solid}.toast-symbol.svelte-1a0rutm{box-sizing:border-box;border:2px solid;border-radius:50%;place-items:center;block-size:1.6rem;inline-size:1.6rem;font-weight:800;line-height:1;display:grid}.toast-copy.svelte-1a0rutm{overflow-wrap:anywhere;gap:.15rem;min-inline-size:0;padding-block:.1rem;display:grid}.toast-copy.svelte-1a0rutm strong:where(.svelte-1a0rutm){text-transform:capitalize}.toast-copy.svelte-1a0rutm small:where(.svelte-1a0rutm){opacity:.72}button.svelte-1a0rutm{min-block-size:44px;inline-size:44px;color:var(--theme-text);font:inherit;background:0 0;border:0;border-radius:.35rem;place-items:center;padding:0;font-size:1.5rem;display:grid}button.svelte-1a0rutm:hover{background:var(--theme-control-hover)}@media (width<=30rem){.toast-viewport.svelte-1a0rutm{max-block-size:none;inline-size:100%;margin-block:0 .75rem;position:static}.toast.svelte-1a0rutm{grid-template-columns:minmax(0,1fr) 44px;gap:.25rem;max-block-size:5rem;padding:.35rem;overflow-y:auto}.toast-symbol.svelte-1a0rutm{display:none}.toast-copy.svelte-1a0rutm strong:where(.svelte-1a0rutm){clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;block-size:1px;inline-size:1px;padding:0;position:absolute;overflow:hidden}}@media (forced-colors:active){.toast.svelte-1a0rutm,.toast-symbol.svelte-1a0rutm{border-color:canvastext}}.evidence-page.svelte-1j55xyh{box-sizing:border-box;min-block-size:100dvh;inline-size:100%;padding:1rem 1rem 7rem}h1.svelte-1j55xyh{margin-block:0 .5rem}.evidence-composer.svelte-1j55xyh{position:fixed;inset-block-end:2.75rem;inset-inline:1rem}.evidence-prompt.svelte-1j55xyh{box-sizing:border-box;inline-size:100%;margin-block-start:.35rem;display:block}.evidence-nav.svelte-1j55xyh{padding:.5rem 1rem calc(.5rem + env(safe-area-inset-bottom));background:var(--theme-surface);border-block-start:1px solid var(--theme-border);grid-template-columns:repeat(3,minmax(0,1fr));gap:.5rem;display:grid;position:fixed;inset-block-end:0;inset-inline:0}.evidence-nav.svelte-1j55xyh button:where(.svelte-1j55xyh){text-overflow:ellipsis;min-block-size:44px;min-inline-size:0;overflow:hidden}@media (width<=24rem){.evidence-page.svelte-1j55xyh{padding:.5rem .5rem 7rem}.evidence-composer.svelte-1j55xyh{inset-inline:.5rem}}.filesystem-tree.svelte-6z3q4v{box-sizing:border-box;overscroll-behavior:contain;scrollbar-gutter:stable;border:1px solid var(--theme-border);border-radius:.6rem;max-block-size:min(22rem,48vh);inline-size:100%;max-inline-size:100%;padding:.35rem;display:grid;overflow:clip auto}.tree-row.svelte-6z3q4v{min-inline-size:0;align-items:stretch;padding-inline-start:min(calc(var(--tree-level) * .75rem), 4.5rem);display:flex}.disclosure.svelte-6z3q4v,.disclosure-spacer.svelte-6z3q4v{flex:0 0 44px;min-block-size:44px;inline-size:44px}.disclosure.svelte-6z3q4v{color:inherit;font:inherit;background:0 0;border:0;border-radius:.35rem;place-items:center;padding:0;font-size:1.25rem;font-weight:700;display:grid}.disclosure.svelte-6z3q4v:hover{background:var(--theme-control-hover)}.tree-item.svelte-6z3q4v{min-block-size:44px;min-inline-size:0;color:inherit;font:inherit;text-align:start;background:0 0;border:1px solid #0000;border-radius:.35rem;flex:auto;align-items:center;gap:.5rem;padding:.3rem .5rem;display:flex;overflow:hidden}.tree-item.svelte-6z3q4v:hover{background:var(--theme-control-hover)}.tree-item.selected.svelte-6z3q4v{color:var(--theme-control-pressed-contrast);background:var(--theme-control-pressed);border-color:var(--theme-accent);font-weight:650}.tree-item[aria-disabled=true].svelte-6z3q4v{opacity:.58}.tree-item.repository.svelte-6z3q4v{border-inline-start-width:3px}.selection-mark.svelte-6z3q4v{text-align:center;flex:0 0 1rem;inline-size:1rem}.node-copy.svelte-6z3q4v{flex:auto;min-inline-size:0;display:grid}.node-name.svelte-6z3q4v,.node-path.svelte-6z3q4v{text-overflow:ellipsis;white-space:nowrap;min-inline-size:0;overflow:hidden}.node-path.svelte-6z3q4v{opacity:.72;font-size:.75em;font-weight:400}.repository-badge.svelte-6z3q4v{border:1px solid;border-radius:999px;flex:none;padding:.1rem .35rem;font-size:.72em;font-weight:700;line-height:1.2}@media (width<=24rem){.filesystem-tree.svelte-6z3q4v{padding:.2rem}.tree-row.svelte-6z3q4v{padding-inline-start:min(calc(var(--tree-level) * .25rem), 1.5rem)}.tree-item.svelte-6z3q4v{gap:.35rem;padding-inline:.35rem}.repository-badge.svelte-6z3q4v{display:none}}@media (forced-colors:active){.tree-item.selected.svelte-6z3q4v,.tree-item.repository.svelte-6z3q4v,.repository-badge.svelte-6z3q4v{border-color:canvastext}}.evidence-shell.svelte-1d6w4ti{box-sizing:border-box;inline-size:min(100%,48rem);min-inline-size:0;margin-inline:auto;padding:1rem}.eyebrow.svelte-1d6w4ti{letter-spacing:.08em;text-transform:uppercase;margin:0;font-size:.8rem;font-weight:750}h1.svelte-1d6w4ti{margin-block:.25rem .5rem;font-size:clamp(1.35rem,6vw,2rem);line-height:1.15}.instructions.svelte-1d6w4ti{max-inline-size:42rem;margin-block:0 1rem}@media (width<=24rem){.evidence-shell.svelte-1d6w4ti{padding:.5rem}}.git-view.svelte-pudr3t{gap:1.5rem;inline-size:100%;min-inline-size:0;display:grid}.git-tree.svelte-pudr3t,.repository-details.svelte-pudr3t{min-inline-size:0}.section-heading.svelte-pudr3t h3:where(.svelte-pudr3t),.repository-details.svelte-pudr3t h3:where(.svelte-pudr3t){margin-block:0 .35rem}.section-heading.svelte-pudr3t p:where(.svelte-pudr3t){color:var(--theme-text-muted);margin-block:0 .75rem}.clone-form.svelte-pudr3t{gap:.35rem;min-inline-size:0;display:grid}.clone-controls.svelte-pudr3t{grid-template-columns:minmax(10rem,.45fr) minmax(0,1fr) auto;align-items:end;gap:.5rem;display:grid}.clone-field.svelte-pudr3t{gap:.35rem;min-inline-size:0;display:grid}.field-label.svelte-pudr3t{font-weight:600}.clone-destination.svelte-pudr3t output:where(.svelte-pudr3t){overflow-wrap:anywhere;border:1px solid var(--theme-border);border-radius:.35rem;min-block-size:2.75rem;padding:.65rem .75rem}.clone-controls.svelte-pudr3t button:where(.svelte-pudr3t){min-inline-size:5.75rem}.clone-form.svelte-pudr3t p:where(.svelte-pudr3t){color:var(--theme-text-muted);margin:0;font-size:.875rem}.clone-status.svelte-pudr3t{font-weight:600;color:var(--theme-info)!important}.git-overview.svelte-pudr3t{grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:1rem;display:grid}.git-status.svelte-pudr3t p:where(.svelte-pudr3t){margin-block:.5rem}.git-actions.svelte-pudr3t{gap:.5rem;display:grid}.git-actions.svelte-pudr3t button:where(.svelte-pudr3t){min-inline-size:6rem}.commit-history.svelte-pudr3t{margin-block-start:2rem}.commit-history.svelte-pudr3t h3:where(.svelte-pudr3t){margin-block-end:.75rem}.commit-list.svelte-pudr3t{gap:.5rem;margin:0;padding:0;list-style:none;display:grid}.commit-entry.svelte-pudr3t{border-block-end:1px solid var(--theme-border);gap:.35rem;min-inline-size:0;padding:.8rem 0;display:grid}.commit-subject.svelte-pudr3t,.commit-meta.svelte-pudr3t{gap:.65rem;min-inline-size:0;display:flex}.commit-subject.svelte-pudr3t{overflow-wrap:anywhere;align-items:baseline;font-weight:600}.commit-subject.svelte-pudr3t code:where(.svelte-pudr3t){color:var(--theme-text-muted);flex:none;font-size:.875em}.commit-meta.svelte-pudr3t{color:var(--theme-text-muted);flex-wrap:wrap;justify-content:space-between;font-size:.875rem}.commit-meta.svelte-pudr3t time:where(.svelte-pudr3t){overflow-wrap:anywhere;min-inline-size:0;max-inline-size:100%}@media (width<=28rem){.clone-controls.svelte-pudr3t{grid-template-columns:1fr}.clone-controls.svelte-pudr3t button:where(.svelte-pudr3t){inline-size:100%}}.plan.svelte-3rmyvg{overflow-wrap:anywhere;min-inline-size:0}header.svelte-3rmyvg{justify-content:space-between;align-items:start;gap:1rem;display:flex}h2.svelte-3rmyvg,p.svelte-3rmyvg{margin-block:.4rem}progress.svelte-3rmyvg{inline-size:100%}ol.svelte-3rmyvg{padding-inline-start:1.25rem}details.svelte-3rmyvg{margin-block:.5rem}summary.svelte-3rmyvg{cursor:pointer;gap:.2rem;display:grid}.measurement.svelte-3rmyvg{color:var(--muted,currentColor);font-variant-numeric:tabular-nums}.position.svelte-3rmyvg{color:var(--theme-text-muted,currentColor);font-variant-numeric:tabular-nums}.metadata.svelte-3rmyvg{gap:.25rem;display:grid}.metadata.svelte-3rmyvg div:where(.svelte-3rmyvg){gap:.5rem;display:flex}.metadata.svelte-3rmyvg dd:where(.svelte-3rmyvg){margin:0}.close.svelte-3rmyvg{flex:none;block-size:2.75rem;inline-size:2.75rem;font-size:1.5rem}button.svelte-3rmyvg:focus-visible,summary.svelte-3rmyvg:focus-visible{outline-offset:2px;outline:3px solid}@media (prefers-reduced-motion:reduce){.svelte-3rmyvg{scroll-behavior:auto}}.org-document.svelte-h7gaqo{overflow-wrap:anywhere;gap:.85rem;min-inline-size:0;display:grid}header.svelte-h7gaqo,.section-heading.svelte-h7gaqo{justify-content:space-between;align-items:flex-start;gap:.65rem;display:flex}header.svelte-h7gaqo h2:where(.svelte-h7gaqo),.section-heading.svelte-h7gaqo :is(h3:where(.svelte-h7gaqo),h4:where(.svelte-h7gaqo)),p.svelte-h7gaqo,dl.svelte-h7gaqo,dd.svelte-h7gaqo{margin:0}code.svelte-h7gaqo{font:inherit;color:var(--theme-text-muted)}.close.svelte-h7gaqo{flex:none;min-inline-size:2.5rem;font-size:1.35rem;line-height:1}.metadata.svelte-h7gaqo,.descriptions.svelte-h7gaqo,.properties.svelte-h7gaqo dl:where(.svelte-h7gaqo){gap:.4rem;display:grid}.metadata.svelte-h7gaqo div:where(.svelte-h7gaqo),.descriptions.svelte-h7gaqo div:where(.svelte-h7gaqo),.properties.svelte-h7gaqo dl:where(.svelte-h7gaqo) div:where(.svelte-h7gaqo){grid-template-columns:minmax(6rem,.3fr) minmax(0,1fr);gap:.65rem;display:grid}dt.svelte-h7gaqo{font-weight:700}.sections.svelte-h7gaqo{gap:.65rem;display:grid}.org-section.svelte-h7gaqo{background:color-mix(in srgb, var(--theme-surface) 82%, transparent);border:1px solid var(--theme-border);border-inline-start:.3rem solid var(--theme-accent);border-radius:.65rem;gap:.55rem;margin-inline-start:min(calc(var(--org-depth) * .8rem), 2.4rem);padding:.8rem;display:grid}.section-heading.svelte-h7gaqo{flex-wrap:wrap;justify-content:flex-start}.section-heading.svelte-h7gaqo :is(h3:where(.svelte-h7gaqo),h4:where(.svelte-h7gaqo)){flex:14rem}.state.svelte-h7gaqo,.priority.svelte-h7gaqo{border:1px solid;border-radius:999px;padding:.15rem .45rem;font-size:.8rem;font-weight:700}.state-done.svelte-h7gaqo{color:var(--theme-success)}.state-wip.svelte-h7gaqo{color:var(--theme-accent)}.list-item.svelte-h7gaqo{padding-inline-start:.75rem}.properties.svelte-h7gaqo summary:where(.svelte-h7gaqo){cursor:pointer;font-weight:700}.properties.svelte-h7gaqo dl:where(.svelte-h7gaqo){margin-block-start:.5rem}button.svelte-h7gaqo:focus-visible,summary.svelte-h7gaqo:focus-visible{outline-offset:2px;outline:3px solid}@media (width<=32rem){.metadata.svelte-h7gaqo div:where(.svelte-h7gaqo),.descriptions.svelte-h7gaqo div:where(.svelte-h7gaqo),.properties.svelte-h7gaqo dl:where(.svelte-h7gaqo) div:where(.svelte-h7gaqo){grid-template-columns:1fr;gap:.1rem}.org-section.svelte-h7gaqo{margin-inline-start:min(calc(var(--org-depth) * .35rem), 1rem)}}.plans.svelte-x2ko9l{overflow-wrap:anywhere;min-inline-size:0}h2.svelte-x2ko9l{margin-block:.4rem}.scope.svelte-x2ko9l{margin-block:0 .75rem}ul.svelte-x2ko9l{gap:.5rem;margin:0;padding:0;list-style:none;display:grid}.plans.svelte-x2ko9l button:where(.svelte-x2ko9l){text-align:start;gap:.2rem;min-block-size:2.75rem;inline-size:100%;padding:.75rem;display:grid}button.svelte-x2ko9l:focus-visible{outline-offset:2px;outline:3px solid}code.svelte-x2ko9l{font:inherit}.session-list.svelte-hxb22h{gap:1rem;inline-size:100%;margin-block:0 1.5rem;padding-inline:0;list-style:none;display:grid}.current-session.svelte-hxb22h{outline:2px solid var(--theme-accent);outline-offset:2px}.session-select.svelte-hxb22h{inline-size:100%;color:inherit;font:inherit;text-align:inherit;cursor:pointer;background:0 0;border:0;padding:0;display:block}.managed-session.svelte-hxb22h{box-sizing:border-box;border:1px solid var(--theme-border);border-radius:.5rem;grid-template-columns:max-content minmax(0,1fr);align-items:start;gap:.75rem;inline-size:100%;padding:.75rem;display:grid}.open-session.svelte-hxb22h{border-inline-start:.3rem solid var(--theme-accent);background:var(--theme-control-hover)}.session-details.svelte-hxb22h{min-inline-size:0}.workspace-path.svelte-hxb22h{overflow-wrap:anywhere}.profile-badge.svelte-hxb22h{background:var(--theme-control-pressed);color:var(--theme-control-pressed-contrast);overflow-wrap:anywhere;border-radius:999px;margin-block-start:.35rem;padding:.15rem .4rem;font-size:.875rem;display:inline-block}.org-plan-metadata.svelte-hxb22h{gap:.125rem;margin-block-start:.35rem;display:grid}.org-plan-title.svelte-hxb22h{font-weight:600}.org-plan-filename.svelte-hxb22h{overflow-wrap:anywhere;color:var(--theme-text-muted)}.session-actions.svelte-hxb22h{flex-wrap:wrap;gap:.5rem;display:flex}.session-monitor-controls.svelte-hxb22h{flex-wrap:nowrap;align-items:flex-start;gap:.35rem;min-inline-size:0;margin-block-start:.625rem;display:flex}.session-monitor-controls.svelte-hxb22h>*{flex:1 1 0;min-inline-size:0}@media (width<=30rem){.managed-session.svelte-hxb22h{grid-template-columns:minmax(0,1fr)}}.recent-session.svelte-hxb22h{grid-template-columns:minmax(0,1fr) max-content;align-items:start;gap:.75rem;display:grid}.session-base.svelte-hxb22h{gap:.65rem;min-inline-size:0;margin-block:1rem;display:grid}.session-base-heading.svelte-hxb22h h3:where(.svelte-hxb22h),.session-base-heading.svelte-hxb22h p:where(.svelte-hxb22h){margin:0}.session-base-heading.svelte-hxb22h p:where(.svelte-hxb22h){margin-block-start:.25rem}.session-settings.svelte-hxb22h{gap:.5rem;min-inline-size:0;margin-block-end:.75rem;display:grid}.session-setting-labels.svelte-hxb22h,.session-setting-controls.svelte-hxb22h{grid-template-columns:repeat(3,minmax(0,1fr));gap:.5rem;min-inline-size:0;display:grid}.session-setting-labels.svelte-hxb22h label:where(.svelte-hxb22h){overflow-wrap:anywhere;min-inline-size:0}.session-setting-controls.svelte-hxb22h select:where(.svelte-hxb22h){text-overflow:ellipsis;inline-size:100%;min-inline-size:0;max-inline-size:100%;overflow:hidden}.session-secondary-actions.svelte-hxb22h,.model-control.svelte-hxb22h{align-items:center;gap:.5rem;min-inline-size:0;display:flex}.session-secondary-actions.svelte-hxb22h{flex-wrap:wrap}.model-control.svelte-hxb22h{margin-inline-start:auto}.skills-profile-error.svelte-hxb22h{color:var(--theme-error);margin:0;font-size:.875rem}@media (width<=28rem){.model-control.svelte-hxb22h{margin-inline-start:0}}.skills-view.svelte-dg6sjj{min-inline-size:0;padding:1rem max(1rem, env(safe-area-inset-right)) calc(5rem + env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left))}.intro.svelte-dg6sjj,.save-intent.svelte-dg6sjj,.summary.svelte-dg6sjj{max-inline-size:70ch}form.svelte-dg6sjj,.field-grid.svelte-dg6sjj{gap:.65rem;display:grid}.field-grid.svelte-dg6sjj{grid-template-columns:minmax(0,1fr)}label.svelte-dg6sjj{font-weight:650}select.svelte-dg6sjj,input.svelte-dg6sjj,button.svelte-dg6sjj{box-sizing:border-box;min-block-size:3rem;inline-size:100%;font:inherit}dialog.svelte-dg6sjj{max-inline-size:min(100% - 2rem,32rem)}.dialog-actions.svelte-dg6sjj{gap:.65rem;display:grid}input.svelte-dg6sjj,select.svelte-dg6sjj{padding-inline:.7rem;font-size:1rem}button.svelte-dg6sjj{padding-inline:1rem}.profile-actions.svelte-dg6sjj{grid-template-columns:repeat(2,minmax(0,1fr));gap:.65rem;display:grid}.skills-toolbar.svelte-dg6sjj{flex-wrap:wrap;align-items:center;gap:.65rem;margin-block:1rem;display:flex}.refresh-skills.svelte-dg6sjj{flex:none;min-block-size:2.25rem;inline-size:auto;padding-inline:.65rem}.refresh-skills.svelte-dg6sjj span:where(.svelte-dg6sjj):first-child{font-size:1.2em;line-height:1}.summary.svelte-dg6sjj{overflow-wrap:anywhere;min-inline-size:0;margin:0}.notice.svelte-dg6sjj{border-inline-start:.3rem solid var(--theme-warning);color:var(--theme-warning);padding-inline-start:.7rem}.error.svelte-dg6sjj{border-inline-start:.3rem solid var(--theme-error);color:var(--theme-error);padding-inline-start:.7rem}.skill-list.svelte-dg6sjj{gap:.75rem;padding:0;list-style:none;display:grid}.skill-card.svelte-dg6sjj{border:1px solid var(--theme-border);border-radius:.5rem;min-inline-size:0;padding:.75rem;scroll-margin-block:1rem}.skill-toggle.svelte-dg6sjj{flex-wrap:wrap;align-items:center;gap:.65rem;min-block-size:3rem;display:flex}.skill-toggle.svelte-dg6sjj>span:where(.svelte-dg6sjj){overflow-wrap:anywhere;min-inline-size:0}.skill-toggle.svelte-dg6sjj input:where(.svelte-dg6sjj){flex:none;min-block-size:1.25rem;inline-size:1.25rem}.state.svelte-dg6sjj{margin-inline-start:auto;font-weight:500}.skill-details.svelte-dg6sjj{overflow-wrap:anywhere;padding-inline-start:1.9rem}.skill-details.svelte-dg6sjj>:where(.svelte-dg6sjj):first-child{margin-block-start:.25rem}.skill-details.svelte-dg6sjj>:where(.svelte-dg6sjj):last-child{margin-block-end:0}dl.svelte-dg6sjj{grid-template-columns:minmax(7rem,auto) minmax(0,1fr);gap:.45rem .75rem;display:grid}dt.svelte-dg6sjj{font-weight:650}dd.svelte-dg6sjj{min-inline-size:0;margin:0}dd.svelte-dg6sjj ul:where(.svelte-dg6sjj){margin:0;padding-inline-start:1.25rem}.path.svelte-dg6sjj{overflow-wrap:anywhere}.svelte-dg6sjj:where(button:where(.svelte-dg6sjj),input:where(.svelte-dg6sjj),select:where(.svelte-dg6sjj)):focus-visible{outline:3px solid var(--theme-focus);outline-offset:2px}@media (width>=42rem){.field-grid.svelte-dg6sjj{grid-template-columns:minmax(10rem,1fr) minmax(0,2fr);align-items:center}}@media (width<=30rem){dl.svelte-dg6sjj{grid-template-columns:1fr;gap:.2rem}}.devices.svelte-1nygetn{max-inline-size:48rem;color:var(--theme-text);margin:auto;padding:1rem}.devices.svelte-1nygetn header:where(.svelte-1nygetn){align-items:center;gap:1rem;display:flex}.devices.svelte-1nygetn h1:where(.svelte-1nygetn),.devices.svelte-1nygetn h2:where(.svelte-1nygetn){font-family:var(--theme-font-display)}.devices.svelte-1nygetn ul:where(.svelte-1nygetn){padding:0;list-style:none}.devices.svelte-1nygetn li:where(.svelte-1nygetn),section.svelte-1nygetn{background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:var(--theme-radius);box-shadow:0 .25rem .75rem var(--theme-shadow);margin-block:1rem;padding:1rem}.devices.svelte-1nygetn form:where(.svelte-1nygetn){gap:.65rem;display:grid}.devices.svelte-1nygetn p:where(.svelte-1nygetn){overflow-wrap:anywhere;margin:0}.devices.svelte-1nygetn input:where(.svelte-1nygetn),.devices.svelte-1nygetn textarea:where(.svelte-1nygetn),.devices.svelte-1nygetn button:where(.svelte-1nygetn){min-block-size:44px;font:inherit}.devices.svelte-1nygetn input:where(.svelte-1nygetn),.devices.svelte-1nygetn textarea:where(.svelte-1nygetn){min-inline-size:0;padding:.45rem}.devices.svelte-1nygetn textarea:where(.svelte-1nygetn){box-sizing:border-box;overflow-wrap:anywhere;resize:vertical;inline-size:100%;font-family:var(--theme-font-code)}.devices.svelte-1nygetn .actions:where(.svelte-1nygetn){flex-wrap:wrap;gap:.5rem;display:flex}.devices.svelte-1nygetn .actions:where(.svelte-1nygetn) button:where(.svelte-1nygetn){flex:11rem}.devices.svelte-1nygetn img:where(.svelte-1nygetn){background:var(--theme-canvas);inline-size:12rem;max-inline-size:100%;margin-block:.75rem;padding:.5rem;display:block}.feedback.svelte-1nygetn{color:var(--theme-error);font-weight:700}dialog.svelte-1nygetn{max-inline-size:min(32rem,100% - 2rem);color:var(--theme-text);background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:var(--theme-radius);box-shadow:0 .5rem 1.5rem var(--theme-shadow)}dialog.svelte-1nygetn h2:where(.svelte-1nygetn){font-family:var(--theme-font-display)}dialog.svelte-1nygetn form:where(.svelte-1nygetn){flex-wrap:wrap;gap:.5rem;display:flex}@media (forced-colors:active){.devices.svelte-1nygetn li:where(.svelte-1nygetn),section.svelte-1nygetn,dialog.svelte-1nygetn{border-color:canvastext}}@media (prefers-reduced-motion:reduce){.svelte-1nygetn{transition-duration:.01ms!important;animation-duration:.01ms!important}}dialog.svelte-eu5bnq{box-sizing:border-box;max-block-size:calc(100dvh - 1rem);inline-size:min(52rem,100vw - 1rem);max-inline-size:none;color:var(--theme-text);background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:var(--theme-radius);box-shadow:0 .75rem 2rem var(--theme-shadow);padding:0}dialog.svelte-eu5bnq::backdrop{background:color-mix(in srgb, var(--theme-canvas) 70%, transparent)}.scratchpad-shell.svelte-eu5bnq{box-sizing:border-box;min-block-size:min(42rem,100dvh - 1rem);max-block-size:calc(100dvh - 1rem);padding:max(1rem, env(safe-area-inset-top)) max(1rem, env(safe-area-inset-right)) max(1rem, env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left));grid-template-rows:auto auto minmax(12rem,1fr) auto;gap:.75rem;display:grid}header.svelte-eu5bnq{justify-content:space-between;align-items:flex-start;gap:1rem;display:flex}h2.svelte-eu5bnq,p.svelte-eu5bnq{margin:0}h2.svelte-eu5bnq{font-family:var(--theme-font-display)}header.svelte-eu5bnq p:where(.svelte-eu5bnq){color:var(--theme-text-muted)}label.svelte-eu5bnq{font-weight:700}textarea.svelte-eu5bnq{box-sizing:border-box;resize:none;min-block-size:12rem;inline-size:100%;min-inline-size:0;color:var(--theme-text);background:var(--theme-canvas);border:1px solid var(--theme-border);border-radius:calc(var(--theme-radius) / 2);font:1rem/1.45 var(--theme-font-code);tab-size:2;padding:.75rem}button.svelte-eu5bnq{min-block-size:44px;font:inherit}.close.svelte-eu5bnq{inline-size:44px;color:inherit;background:0 0;border:0;flex:none;padding:0;font-size:2rem;line-height:1}.actions.svelte-eu5bnq{flex-wrap:wrap;gap:.5rem;display:flex}.actions.svelte-eu5bnq button:where(.svelte-eu5bnq){flex:7rem}.danger.svelte-eu5bnq{color:var(--theme-error)}.clear-confirmation.svelte-eu5bnq{border:1px solid var(--theme-error);border-radius:calc(var(--theme-radius) / 2);gap:.5rem;padding:.75rem;display:grid}.feedback.svelte-eu5bnq{color:var(--theme-error);font-weight:700}@media (width<=32rem){dialog.svelte-eu5bnq{border-inline:0;border-radius:0;max-block-size:100dvh;inline-size:100vw}.scratchpad-shell.svelte-eu5bnq{min-block-size:100dvh;max-block-size:100dvh}}@media (forced-colors:active){dialog.svelte-eu5bnq,textarea.svelte-eu5bnq,.clear-confirmation.svelte-eu5bnq{border-color:canvastext}}.file-tree.svelte-am0nvt{gap:.2rem;min-inline-size:0;display:grid;overflow-x:clip}.tree-row.svelte-am0nvt{min-inline-size:0;flex-wrap:wrap;padding-inline-start:min(calc((var(--level) - 1) * .75rem), 4rem);display:flex}button.svelte-am0nvt{overflow-wrap:anywhere;min-block-size:2.75rem;min-inline-size:2.75rem}.treeitem.svelte-am0nvt{text-align:start;overflow-wrap:anywhere;flex:1;min-block-size:2.75rem;min-inline-size:2.75rem}.tree-label.svelte-am0nvt{flex:1}.disclosure.svelte-am0nvt{flex:0 0 2.75rem}.unsupported.svelte-am0nvt{color:var(--theme-text-muted);font-size:.875rem}dialog.svelte-qx7639{box-sizing:border-box;border:1px solid var(--theme-border);max-block-size:100dvh;inline-size:min(100%,52rem);max-inline-size:100%;color:var(--theme-text);background:var(--theme-surface);border-radius:.75rem;padding:0;overflow-x:hidden}dialog.svelte-qx7639::backdrop{background:#0000008c}.file-browser-shell.svelte-qx7639{gap:1rem;max-block-size:calc(100dvh - 1rem);min-inline-size:0;padding:1rem;display:grid;overflow:hidden auto}header.svelte-qx7639{justify-content:space-between;align-items:start;gap:1rem;display:flex}header.svelte-qx7639>div:where(.svelte-qx7639),.picker.svelte-qx7639{min-inline-size:0}h2.svelte-qx7639,p.svelte-qx7639{overflow-wrap:anywhere;margin:0}header.svelte-qx7639 p:where(.svelte-qx7639){color:var(--theme-text-muted);margin-block-start:.35rem}button.svelte-qx7639{min-block-size:2.75rem;min-inline-size:2.75rem}.close.svelte-qx7639{font-size:1.5rem;line-height:1}.browser-actions.svelte-qx7639{flex-wrap:wrap;gap:.5rem;display:flex}.upload-actions.svelte-qx7639{gap:.5rem;display:grid}.upload-actions.svelte-qx7639 p:where(.svelte-qx7639){color:var(--theme-text-muted)}.visually-hidden.svelte-qx7639{clip:rect(0 0 0 0);white-space:nowrap;block-size:1px;inline-size:1px;position:absolute;overflow:hidden}.picker.svelte-qx7639{border:1px solid var(--theme-border);border-radius:.5rem;gap:.5rem;padding:.75rem;display:grid}@media (width<=40rem){dialog.svelte-qx7639{border-radius:0;min-block-size:100dvh;inline-size:100%}.file-browser-shell.svelte-qx7639{max-block-size:100dvh}}.chat-view.svelte-1d2e8zz{margin-inline:calc(.25rem - var(--page-inline-padding))}.chat-tail.svelte-1d2e8zz{block-size:1px;scroll-margin-block-end:var(--bottom-navigation-clearance)}.chat-controls.svelte-1d2e8zz{flex-wrap:nowrap;align-items:flex-start;gap:.35rem;min-inline-size:0;margin-block-start:.625rem;display:flex}.chat-controls.svelte-1d2e8zz>*{flex:1 1 0;min-inline-size:0}.swipe-surface.svelte-1d2e8zz{touch-action:pan-y}.evidence-mode.svelte-1d2e8zz{box-sizing:border-box;inline-size:100%;min-inline-size:0;padding:0}.session-profile-manager-header.svelte-1d2e8zz{box-sizing:border-box;inline-size:100%;min-inline-size:0;padding-inline:max(1rem, env(safe-area-inset-left)) max(1rem, env(safe-area-inset-right));justify-content:space-between;align-items:safe center;gap:1rem;display:flex}.session-profile-manager-header.svelte-1d2e8zz h2:where(.svelte-1d2e8zz){overflow-wrap:anywhere;min-inline-size:0;margin:0}.close-profile-manager.svelte-1d2e8zz{min-block-size:2.5rem;inline-size:2.5rem;color:inherit;background:0 0;border:0;flex:none;padding:0;font-size:2rem;line-height:1}.enrollment.svelte-1c5qcm6{box-sizing:border-box;inline-size:100%;max-inline-size:none;background:var(--theme-page);min-height:100dvh;color:var(--theme-text);place-items:center;margin:0;padding:1rem;display:grid}.card.svelte-1c5qcm6{box-sizing:border-box;background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:calc(var(--theme-radius) * 2);width:min(100%,42rem);box-shadow:0 .5rem 1.5rem var(--theme-shadow);padding:clamp(1.25rem,5vw,3rem)}.brand.svelte-1c5qcm6{color:var(--theme-info);font-family:var(--theme-font-display);letter-spacing:.08em;text-transform:uppercase;font-weight:700}h1.svelte-1c5qcm6{font-family:var(--theme-font-display);margin-block:.25rem 1rem;font-size:clamp(1.8rem,7vw,3rem)}.warning.svelte-1c5qcm6{border-left:.3rem solid var(--theme-warning);background:var(--theme-surface-subtle);padding:1rem}label.svelte-1c5qcm6,input.svelte-1c5qcm6{box-sizing:border-box;width:100%;display:block}label.svelte-1c5qcm6{margin-top:1.5rem;font-weight:700}input.svelte-1c5qcm6,button.svelte-1c5qcm6{min-height:44px;font:inherit}input.svelte-1c5qcm6{margin-top:.4rem;padding:.6rem}button.svelte-1c5qcm6{cursor:pointer;border-radius:.4rem;margin-top:1rem;padding:.55rem 1rem}.authorize.svelte-1c5qcm6{background:var(--theme-accent);width:100%;color:var(--theme-accent-contrast);border-color:var(--theme-accent);font-weight:700}.feedback.svelte-1c5qcm6{color:var(--theme-info);font-weight:700}.error.svelte-1c5qcm6{color:var(--theme-error);font-weight:700}.handoff.svelte-1c5qcm6{border-top:1px solid var(--theme-border);grid-template-columns:minmax(0,1fr);gap:1rem;margin-top:2rem;padding-top:1.5rem;display:grid}.handoff.svelte-1c5qcm6 img:where(.svelte-1c5qcm6){background:var(--theme-canvas);width:12rem;max-width:100%;padding:.5rem}a.svelte-1c5qcm6{color:var(--theme-info);overflow-wrap:anywhere}.copy.svelte-1c5qcm6{display:block}@media (width>=48rem){.handoff.svelte-1c5qcm6{grid-template-columns:12rem minmax(0,1fr);align-items:start}}@media (prefers-reduced-motion:reduce){.svelte-1c5qcm6,.svelte-1c5qcm6:before,.svelte-1c5qcm6:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important}}.login.svelte-1byekj9{box-sizing:border-box;inline-size:100%;max-inline-size:none;background:var(--theme-page);min-height:100dvh;color:var(--theme-text);place-items:center;margin:0;padding:1rem;display:grid}.card.svelte-1byekj9{box-sizing:border-box;background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:calc(var(--theme-radius) * 2);width:min(100%,32rem);box-shadow:0 .5rem 1.5rem var(--theme-shadow);padding:clamp(1.25rem,5vw,3rem)}.brand.svelte-1byekj9{color:var(--theme-info);font-family:var(--theme-font-display);letter-spacing:.08em;text-transform:uppercase;font-weight:700}h1.svelte-1byekj9{font-family:var(--theme-font-display);margin-block:.25rem 1rem;font-size:clamp(1.8rem,7vw,3rem)}.sign-in.svelte-1byekj9{border-radius:var(--theme-radius);background:var(--theme-accent);width:100%;min-height:44px;color:var(--theme-accent-contrast);border-color:var(--theme-accent);font:inherit;margin-top:1rem;padding:.55rem 1rem;font-weight:700}.error.svelte-1byekj9{color:var(--theme-error);font-weight:700}@media (prefers-reduced-motion:reduce){.svelte-1byekj9,.svelte-1byekj9:before,.svelte-1byekj9:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important}}.auth-gate.svelte-y74n0s{max-width:32rem;color:var(--theme-text);background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:var(--theme-radius);box-shadow:0 .5rem 1.5rem var(--theme-shadow);margin:12vh auto;padding:2rem}.auth-gate.svelte-y74n0s h1:where(.svelte-y74n0s){font-family:var(--theme-font-display)}button.svelte-y74n0s{margin-right:.75rem}@font-face{font-family:Syne;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/syne-greek-600-normal-BpFII5Ja.woff2)format("woff2"),url(/assets/syne-greek-600-normal-BJs4kvyH.woff)format("woff");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:Syne;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/syne-latin-ext-600-normal-ZnizrDKU.woff2)format("woff2"),url(/assets/syne-latin-ext-600-normal-DEzBMW8B.woff)format("woff");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:Syne;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/syne-latin-600-normal-BiwQbQXw.woff2)format("woff2"),url(/assets/syne-latin-600-normal-dRu9QuIh.woff)format("woff");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}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-cyrillic-ext-400-normal-C_uLvvQ5.woff2)format("woff2"),url(/assets/jetbrains-mono-cyrillic-ext-400-normal-Bh0R7Dhr.woff)format("woff");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;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2)format("woff2"),url(/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff)format("woff");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2)format("woff2"),url(/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff)format("woff");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;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-vietnamese-400-normal-ByoDsISC.woff2)format("woff2"),url(/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff)format("woff");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;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff)format("woff");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;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff)format("woff");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{--theme-font-body:system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--theme-font-display:"Syne", var(--theme-font-body);--theme-font-code:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--theme-motion-fast:.12s;--theme-radius:.5rem}:root[data-theme=minimal-light]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--theme-page:#fff;--theme-canvas:#fff;--theme-surface:#fff;--theme-surface-subtle:#f3f4f6;--theme-text:#171717;--theme-text-muted:#525252;--theme-border:#525252;--theme-focus:#005fcc;--theme-accent:#171717;--theme-accent-contrast:#fff;--theme-control-hover:#e5e7eb;--theme-control-pressed:#262626;--theme-control-pressed-contrast:#fff;--theme-control-disabled:#737373;--theme-success:#166534;--theme-warning:#854d0e;--theme-error:#b91c1c;--theme-info:#1d4ed8;--theme-code:#f3f4f6;--theme-shadow:#17171740}:root[data-theme=minimal-dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--theme-page:#171717;--theme-canvas:#171717;--theme-surface:#262626;--theme-surface-subtle:#404040;--theme-text:#fafafa;--theme-text-muted:#d4d4d4;--theme-border:#a3a3a3;--theme-focus:#93c5fd;--theme-accent:#fafafa;--theme-accent-contrast:#171717;--theme-control-hover:#404040;--theme-control-pressed:#fafafa;--theme-control-pressed-contrast:#171717;--theme-control-disabled:#a3a3a3;--theme-success:#86efac;--theme-warning:#fcd34d;--theme-error:#fca5a5;--theme-info:#93c5fd;--theme-code:#262626;--theme-shadow:#00000080}:root[data-theme=dyne-org]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--theme-page:#f4f0e8;--theme-canvas:#fffdf8;--theme-surface:#fffaf1;--theme-surface-subtle:#eee6d8;--theme-text:#171411;--theme-text-muted:#5f564c;--theme-border:#75695b;--theme-focus:#5e2ca5;--theme-accent:#c7460c;--theme-accent-contrast:#fffdf8;--theme-control-hover:#f4ddcf;--theme-control-pressed:#bd3d0d;--theme-control-pressed-contrast:#fffdf8;--theme-control-disabled:#93887b;--theme-success:#287a50;--theme-warning:#9a5a00;--theme-error:#b42318;--theme-info:#5e2ca5;--theme-code:#f1e9db;--theme-shadow:#17141138}:root{--bottom-navigation-clearance:calc(4rem + env(safe-area-inset-bottom));--sticky-header-clearance:calc(5rem + env(safe-area-inset-top));--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;font-family:var(--theme-font-body)}body{min-block-size:100dvh;color:var(--theme-text);background:var(--theme-page);accent-color:var(--theme-accent);margin:0}.visually-hidden{clip-path:inset(50%)!important;white-space:nowrap!important;border:0!important;block-size:1px!important;inline-size:1px!important;margin:-1px!important;padding:0!important;position:absolute!important;overflow:hidden!important}main{--page-inline-padding:1rem;box-sizing:border-box;min-block-size:100dvh;max-inline-size:42rem;padding:calc(1rem + env(safe-area-inset-top)) var(--page-inline-padding) calc(var(--bottom-navigation-clearance) + 1rem);margin-inline:auto}@media (width<=24rem){main{--page-inline-padding:.5rem}.bottom-navigation.bottom-navigation button{font-size:max(.453125rem,13px)}}.app-header{z-index:2;box-sizing:border-box;inline-size:100vw;margin:calc(-1rem - env(safe-area-inset-top)) calc(50% - 50vw) 1.5rem;padding:calc(1rem + env(safe-area-inset-top)) calc(var(--page-inline-padding) - .25rem) .75rem;background:var(--theme-page);background:color-mix(in srgb, var(--theme-page) 72%, transparent);-webkit-backdrop-filter:blur(.75rem)saturate(1.2);backdrop-filter:blur(.75rem)saturate(1.2);border-block-end:1px solid color-mix(in srgb, var(--theme-border) 72%, transparent);box-shadow:0 .35rem 1rem color-mix(in srgb, var(--theme-shadow) 28%, transparent);flex-wrap:nowrap;justify-content:space-between;align-items:center;gap:.5rem;display:flex;position:sticky;inset-block-start:0}.app-header [role=status]{overflow-wrap:anywhere;text-align:end;min-inline-size:0;margin:0}.brand{flex:none;align-items:center;gap:.4rem;display:flex}.header-actions{flex:none;align-items:center;gap:.25rem;margin-inline-start:auto;display:flex}.weekly-quota{font-variant-numeric:tabular-nums;white-space:nowrap;font-size:.875rem}.menu-trigger{min-block-size:44px;inline-size:44px;color:inherit;background:0 0;border:0;flex:none;place-items:center;padding:0;display:grid}.menu-lines{gap:.25rem;inline-size:1.25rem;display:grid}.menu-lines span{box-sizing:border-box;background:currentColor;block-size:1px;display:block}.menu-lines span:first-child,.menu-lines span:nth-child(2),.menu-lines span:last-child{block-size:2px}@media (width<=28rem){.app-header [role=status]{flex-basis:100%;margin-inline-start:0}}.brand-icon{block-size:2rem;inline-size:2rem}.brand-logotype{block-size:auto;inline-size:6.25rem}.dark-asset,:root[data-logo-tone=light] .light-asset{display:none}:root[data-logo-tone=light] .dark-asset{display:initial}.configuration-panel{box-sizing:border-box;overscroll-behavior:contain;max-block-size:calc(100dvh - 5.5rem);min-inline-size:min(13rem,100vw - 2rem);max-inline-size:calc(100vw - 2rem);color:var(--theme-text);background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:var(--theme-radius);box-shadow:0 .5rem 1.5rem var(--theme-shadow);padding:.75rem;position:fixed;inset:4.5rem 1rem auto auto;overflow-y:auto}.configuration-logo{block-size:auto;inline-size:4.5rem;margin-block-end:.5rem;margin-inline-start:auto;display:block}.appearance-control{align-items:center;gap:.5rem;min-inline-size:0;display:flex}.appearance-control span{font-family:var(--theme-font-display);letter-spacing:-.08em;font-weight:700}.appearance-control select{field-sizing:content;flex:auto;min-block-size:2.25rem;inline-size:auto;min-inline-size:0;max-inline-size:100%;padding-inline:.5rem}.bottom-navigation{z-index:2;padding:.25rem calc(.375rem + env(safe-area-inset-right)) calc(.25rem + env(safe-area-inset-bottom)) calc(.375rem + env(safe-area-inset-left));background:var(--theme-surface);background:color-mix(in srgb, var(--theme-surface) 72%, transparent);-webkit-backdrop-filter:blur(.75rem)saturate(1.2);backdrop-filter:blur(.75rem)saturate(1.2);border-block-start:1px solid var(--theme-border);box-shadow:0 -.35rem 1rem color-mix(in srgb, var(--theme-shadow) 28%, transparent);grid-template-columns:repeat(4,minmax(0,1fr));gap:max(.03125rem,1px);display:grid;position:fixed;inset-block-end:0;inset-inline:0}.bottom-navigation button{text-overflow:clip;white-space:nowrap;min-inline-size:0;max-inline-size:100%;transition:color var(--theme-motion-fast) ease, background-color var(--theme-motion-fast) ease, box-shadow var(--theme-motion-fast) ease;padding-inline:0;font-size:max(.453125rem,18px);overflow:hidden}.bottom-navigation button:hover:not(:disabled){background:var(--theme-control-hover)}.bottom-navigation button:active:not(:disabled){background:var(--theme-control-pressed);color:var(--theme-control-pressed-contrast)}.bottom-navigation button[aria-pressed=true]{color:var(--theme-accent-contrast);background:var(--theme-accent);box-shadow:inset 0 .2rem 0 color-mix(in srgb, var(--theme-accent-contrast) 25%, transparent);font-weight:700}.bottom-navigation button:disabled{color:var(--theme-control-disabled);cursor:not-allowed;opacity:.65}@media (width<=30rem){.brand-logotype{display:none!important}}button{min-block-size:44px;font:inherit;color:var(--theme-text);background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:var(--theme-radius);cursor:pointer}button:hover:not(:disabled){background:var(--theme-control-hover)}button:active:not(:disabled){background:var(--theme-control-pressed);color:var(--theme-control-pressed-contrast)}button:disabled{color:var(--theme-control-disabled);cursor:not-allowed}.git-view button{scroll-margin-block:var(--sticky-header-clearance) var(--bottom-navigation-clearance)}input,select,textarea{box-sizing:border-box;min-block-size:44px;inline-size:100%;font:inherit;color:var(--theme-text);background:var(--theme-surface);border:1px solid var(--theme-border);border-radius:var(--theme-radius);font-size:max(1rem,16px)}input::placeholder,textarea::placeholder{color:var(--theme-text-muted)}:focus-visible{outline:3px solid var(--theme-focus);outline-offset:3px}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important}}@media (forced-colors:active){button,input,select,textarea{border:1px solid canvastext}}
|