@ikenga/pkg-tasks 0.2.0 → 0.4.1

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.
@@ -33,7 +33,8 @@ export async function connectBridge({ name, version, onContextChange }) {
33
33
 
34
34
  app.onerror = (err) => console.error('[tasks] bridge error', err);
35
35
  // Theme is NOT applied here — app.js mirrors it from the parent <html>.
36
- // We still forward context so live Supabase/auth updates reach the app.
36
+ // We still forward context so live activeFeature (side-menu) updates reach
37
+ // the app; data flows through host.dbQuery/dbExec, not the context payload.
37
38
  app.onhostcontextchanged = (ctx) => {
38
39
  onContextChange?.(ctx);
39
40
  };
@@ -129,6 +130,28 @@ export async function hostDbQuery(sql, params = []) {
129
130
  return Array.isArray(sc.rows) ? sc.rows : [];
130
131
  }
131
132
 
133
+ /**
134
+ * Write to the local `pa.db` via the host's `host.dbExec` verb (write-path WP).
135
+ * INSERT/UPDATE/DELETE only — the shell rejects reads/DDL, gates on the pkg
136
+ * declaring `capabilities.sqlite`, and scopes the target table to the pkg's
137
+ * declared `permissions['sqlite.tables']`. Resolves on success; throws on a
138
+ * closed/failed bridge so callers can surface the error in the mutation layer.
139
+ *
140
+ * sql: string — a single INSERT/UPDATE/DELETE statement with `?` params
141
+ * params: SqlValue[] — positional bind values
142
+ */
143
+ export async function hostDbExec(sql, params = []) {
144
+ if (!app) throw new Error('[tasks] bridge not connected — db_exec unavailable');
145
+ const res = await app.callServerTool({
146
+ name: 'host.dbExec',
147
+ arguments: { sql, params },
148
+ });
149
+ const sc = res?.structuredContent;
150
+ if (!sc || sc.ok !== true) {
151
+ throw new Error(sc?.error ?? res?.content?.[0]?.text ?? 'host.dbExec failed');
152
+ }
153
+ }
154
+
132
155
  /** Read the current hostContext snapshot. */
133
156
  export function getContext() {
134
157
  return app?.getHostContext() ?? null;
@@ -26,10 +26,6 @@ declare module 'https://esm.sh/@tanstack/react-query@5?deps=react@19.0.0' {
26
26
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
27
  export const useQueryClient: any;
28
28
  }
29
- declare module 'https://esm.sh/@supabase/supabase-js@2' {
30
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
- export const createClient: any;
32
- }
33
29
  declare module 'https://esm.sh/@modelcontextprotocol/ext-apps@1.7.1/app-with-deps' {
34
30
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
31
  export const App: any;
@@ -3,12 +3,13 @@
3
3
  // migration 0025_tasks_domain.sql): every selected column exists.
4
4
  //
5
5
  // WP-04 read-swap: reads go through the host's `host.dbQuery` verb (local
6
- // pa.db) instead of an in-iframe supabase-js client. The status-update WRITE
7
- // (task-detail-pane.js) still uses supabase-js moving it needs a host write
8
- // verb that does not exist yet (follow-up WP).
6
+ // pa.db) instead of an in-iframe supabase-js client. Write-path WP: the
7
+ // status-update WRITE goes through `host.dbExec` (see `updateTaskStatus`), so
8
+ // this pkg no longer depends on supabase-js at all.
9
9
 
10
- import { hostDbQuery } from './bridge.js';
10
+ import { hostDbExec, hostDbQuery } from './bridge.js';
11
11
  import { queryKeys } from './query-keys.js';
12
+ import { CURRENT_USER } from './assignees.js';
12
13
 
13
14
  // pa.db stores former Postgres array/json columns as TEXT (the Pg→SQLite
14
15
  // down-map, shell migration 0025). `tags` arrives as a string, not a JS array
@@ -191,3 +192,87 @@ export function blockingTaskQuery(blockingId) {
191
192
  enabled: !!blockingId,
192
193
  };
193
194
  }
195
+
196
+ /**
197
+ * Write a task's status to the local pa.db via `host.dbExec` (write-path WP).
198
+ * `completed_at` is set to now when moving to `completed` and cleared to NULL
199
+ * otherwise, so a non-completed task never carries a stale completion stamp.
200
+ * The host scopes this write to the pkg's declared `sqlite.tables` (`tasks`).
201
+ *
202
+ * @param {string} taskId
203
+ * @param {TaskStatus} status
204
+ * @returns {Promise<void>}
205
+ */
206
+ export async function updateTaskStatus(taskId, status) {
207
+ const completedAt = status === 'completed' ? new Date().toISOString() : null;
208
+ await hostDbExec('UPDATE tasks SET status = ?, completed_at = ? WHERE id = ?', [
209
+ status,
210
+ completedAt,
211
+ taskId,
212
+ ]);
213
+ }
214
+
215
+ /**
216
+ * @typedef {Object} CreateTaskInput
217
+ * @property {string} title required (NOT NULL in 0025)
218
+ * @property {string|null} [assignedTo] email (human) or agent id; null = unassigned
219
+ * @property {'human'|'agent'|null} [assigneeType]
220
+ * @property {TaskPriority} [priority] defaults 'medium'
221
+ * @property {string|null} [dueDate] ISO timestamp or null
222
+ * @property {string|null} [description]
223
+ * @property {string|null} [category]
224
+ */
225
+
226
+ /**
227
+ * Insert a new task into the local pa.db via `host.dbExec` (write-path WP).
228
+ * Now that `host.dbExec` allows a real INSERT (the table is in the pkg's
229
+ * declared `sqlite.tables`), creation no longer has to round-trip through the
230
+ * agent. The id is a client-generated uuid; created_at/updated_at are stamped
231
+ * now; status defaults to 'pending'. Only `id` + `title` are NOT NULL in
232
+ * migration 0025 — every other column is nullable or DB-defaulted, so we write
233
+ * just what the form collected and let SQLite default the rest.
234
+ *
235
+ * @param {CreateTaskInput} input
236
+ * @returns {Promise<string>} the new task id
237
+ */
238
+ export async function createTask(input) {
239
+ const id = crypto.randomUUID();
240
+ const now = new Date().toISOString();
241
+ await hostDbExec(
242
+ 'INSERT INTO tasks (id, title, description, status, priority, assigned_to, assignee_type, category, due_date, created_at, updated_at, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
243
+ [
244
+ id,
245
+ input.title,
246
+ input.description ?? null,
247
+ 'pending',
248
+ input.priority ?? 'medium',
249
+ input.assignedTo ?? null,
250
+ input.assigneeType ?? null,
251
+ input.category ?? null,
252
+ input.dueDate ?? null,
253
+ now,
254
+ now,
255
+ CURRENT_USER,
256
+ ],
257
+ );
258
+ return id;
259
+ }
260
+
261
+ /**
262
+ * Reassign a task to a different human/agent via `host.dbExec`. `assigned_to`
263
+ * was display-only across every view until now; this is the first write of it.
264
+ * `updated_at` is bumped so the staleness/triage logic (which keys off it)
265
+ * doesn't treat a just-reassigned task as stale. Pass `assignedTo = null` to
266
+ * clear the owner (unassign).
267
+ *
268
+ * @param {string} taskId
269
+ * @param {string|null} assignedTo
270
+ * @param {'human'|'agent'|null} assigneeType
271
+ * @returns {Promise<void>}
272
+ */
273
+ export async function reassignTask(taskId, assignedTo, assigneeType) {
274
+ await hostDbExec(
275
+ 'UPDATE tasks SET assigned_to = ?, assignee_type = ?, updated_at = ? WHERE id = ?',
276
+ [assignedTo, assigneeType, new Date().toISOString(), taskId],
277
+ );
278
+ }
@@ -67,7 +67,7 @@ export function groupTasks(tasks, showAutoclosed) {
67
67
  }
68
68
 
69
69
  // ─── In-body view switcher (Round 16 · D-2 / D-3) ───────────────────────────
70
- /** @typedef {'tasks'|'agenda'|'triage'} TaskView */
70
+ /** @typedef {'tasks'|'agenda'|'triage'|'sweeper'|'done'} TaskView */
71
71
 
72
72
  // ─── Agenda / Today (D-2) ────────────────────────────────────────────────────
73
73
  /** @typedef {'me'|'agent'|'silent'|'deadline'} AgendaLane */
@@ -1,5 +1,4 @@
1
- // Auto-derived from tasks.css — CSS-as-string so it loads via the script path
2
- // (WebKitGTK can't load <link>/fetch subresources from the about:srcdoc the
3
- // shell mounts only inlined scripts work; see index.html). app.js injects
4
- // this as an inline <style> (allowed by style-src 'unsafe-inline').
5
- export default "/* Tasks screen — Ikenga Rung 3 / Batch 3 (08-tasks.html)\n * Reuses tokens from src/lib/ikenga/tokens.css. No new tokens.\n */\n\n/* === Frame ================================================== */\n.tk-frame {\n border: 1px solid var(--border);\n border-radius: var(--radius-lg);\n background: var(--bg-surface);\n overflow: hidden;\n box-shadow: var(--shadow-2);\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n.tk-frame-head {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--space-4);\n padding: var(--space-4) var(--space-5);\n border-bottom: 1px solid var(--border-soft);\n background: linear-gradient(180deg, var(--tint-bg-active, var(--bg-surface)) 0%, var(--bg-surface) 100%);\n}\n.tk-frame-title-wrap { display: flex; align-items: center; gap: var(--space-2); }\n.tk-frame-title-mark { width: 18px; height: 18px; color: var(--tint-fg-active, var(--primary)); }\n.tk-frame-title {\n font-family: var(--font-display);\n font-weight: 500;\n font-size: var(--text-h3);\n margin: 0;\n color: var(--fg);\n}\n.tk-frame-sub {\n margin-top: 2px;\n font-size: var(--text-caption);\n color: var(--fg-muted);\n}\n.tk-frame-count {\n font-family: var(--font-mono);\n font-size: 12px;\n color: var(--fg-muted);\n font-weight: 400;\n margin-left: 6px;\n}\n\n/* === Filter bar ============================================= */\n.tk-filterbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-3) var(--space-5);\n border-bottom: 1px solid var(--border-soft);\n background: var(--bg-sunken);\n}\n.tk-filterbar .input-search-wrap { position: relative; display: inline-flex; }\n.tk-filterbar .input-search-wrap svg {\n position: absolute;\n left: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 13px;\n height: 13px;\n color: var(--fg-faint);\n}\n.tk-filterbar input[type='text'] {\n width: 280px;\n height: 28px;\n padding: 0 8px 0 28px;\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n border-radius: var(--radius-sm);\n color: var(--fg);\n font-family: inherit;\n font-size: 11.5px;\n}\n.tk-filterbar select {\n height: 28px;\n font-size: 11.5px;\n padding: 0 var(--space-2);\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n border-radius: var(--radius-sm);\n color: var(--fg);\n font-family: inherit;\n}\n.tk-filterbar .label {\n font-family: var(--font-mono);\n font-size: 10.5px;\n color: var(--fg-faint);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n.tk-filterbar .spacer { flex: 1; }\n.tk-toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 28px;\n padding: 0 10px;\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n border-radius: var(--radius-sm);\n color: var(--fg-muted);\n font-family: inherit;\n font-size: 11px;\n cursor: pointer;\n}\n.tk-toggle:hover { color: var(--fg); border-color: var(--fg-faint); }\n.tk-toggle.is-on {\n color: var(--live);\n background: var(--live-soft);\n border-color: color-mix(in srgb, var(--live) 30%, var(--border));\n}\n.tk-toggle .checkbox {\n width: 11px;\n height: 11px;\n border: 1px solid currentColor;\n border-radius: 2px;\n display: inline-grid;\n place-items: center;\n flex-shrink: 0;\n}\n.tk-toggle.is-on .checkbox::after {\n content: '✓';\n font-size: 9px;\n line-height: 1;\n color: currentColor;\n}\n\n/* === Master/detail split ==================================== */\n.tk-split {\n --list-w: 360px;\n display: grid;\n grid-template-columns: minmax(280px, var(--list-w)) 4px minmax(420px, 1fr);\n /* Bind the single row to the split's own height. Without this the implicit\n * row is `auto` (content-sized), so a tall list/detail grows the row past the\n * split and gets clipped by overflow:hidden — neither pane scrolls. */\n grid-template-rows: minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n.tk-list {\n overflow-y: auto;\n /* Grid items default to min-height:auto (won't shrink below content), which\n * defeats overflow:auto. Allow shrink so the list scrolls within its track. */\n min-height: 0;\n background: var(--bg-surface);\n}\n.tk-divider {\n background: var(--border-soft);\n cursor: col-resize;\n}\n.tk-divider:hover { background: var(--tint-fg-active, var(--primary)); }\n.tk-detail {\n background: var(--bg-base);\n overflow-y: auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n\n/* === Group dividers ========================================= */\n.tk-group-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px var(--space-4) 6px var(--space-3);\n background: var(--bg-sunken);\n border-bottom: 1px solid var(--border-soft);\n border-top: 1px solid var(--border-soft);\n font-family: var(--font-mono);\n font-size: 9.5px;\n color: var(--fg-faint);\n letter-spacing: 0.1em;\n text-transform: uppercase;\n position: sticky;\n top: 0;\n z-index: 4;\n cursor: pointer;\n user-select: none;\n}\n.tk-group-head:first-child { border-top: 0; }\n.tk-group-head .ct {\n color: var(--fg-muted);\n font-variant-numeric: tabular-nums;\n}\n.tk-group-head.is-overdue { color: var(--danger); }\n.tk-group-head.is-overdue .ct { color: var(--danger); }\n.tk-group-head.is-autoclosed { color: var(--live); }\n.tk-group-head.is-autoclosed .ct { color: var(--live); }\n.tk-group-head.is-collapsed { background: var(--bg-base); }\n.tk-group-head .chev {\n width: 10px;\n height: 10px;\n color: var(--fg-faint);\n transition: transform var(--motion-fast) var(--ease-calm);\n}\n.tk-group-head.is-collapsed .chev { transform: rotate(-90deg); }\n.tk-group-label {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n/* === Task row =============================================== */\n.tk-row {\n display: grid;\n grid-template-columns: 14px 1fr auto;\n gap: var(--space-3);\n padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);\n border-bottom: 1px solid var(--border-soft);\n cursor: pointer;\n position: relative;\n background: transparent;\n text-align: left;\n width: 100%;\n border-left: 0;\n border-right: 0;\n border-top: 0;\n font: inherit;\n color: inherit;\n transition: background var(--motion-fast) var(--ease-calm);\n}\n.tk-row:hover { background: var(--bg-raised); }\n.tk-row.is-on { background: var(--bg-raised); }\n.tk-row.is-on::before {\n content: '';\n position: absolute;\n left: 0;\n top: 8px;\n bottom: 8px;\n width: 2px;\n border-radius: 2px;\n background: var(--tint-fg-active, var(--primary));\n}\n.tk-row .pri-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n margin-top: 5px;\n background: var(--fg-faint);\n flex-shrink: 0;\n}\n.tk-row .pri-dot.is-critical {\n background: var(--danger);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 20%, transparent);\n}\n.tk-row .pri-dot.is-high { background: var(--achievement); }\n.tk-row .pri-dot.is-medium { background: var(--systemic); }\n.tk-row .pri-dot.is-low { background: var(--fg-faint); }\n.tk-row .body {\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.tk-row .title {\n font-size: var(--text-body-sm);\n color: var(--fg);\n font-weight: 500;\n line-height: 1.35;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n.tk-row.is-completed .title {\n color: var(--fg-muted);\n text-decoration: line-through;\n text-decoration-thickness: 1px;\n}\n.tk-row .meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--font-mono);\n font-size: 9.5px;\n color: var(--fg-faint);\n letter-spacing: 0.04em;\n}\n.tk-row .meta .cat {\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n color: var(--fg-muted);\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n text-transform: lowercase;\n}\n.tk-row .right {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n flex-shrink: 0;\n}\n.tk-row .due {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg-muted);\n letter-spacing: 0.04em;\n white-space: nowrap;\n}\n.tk-row .due.is-overdue { color: var(--danger); font-weight: 500; }\n.tk-row .due.is-today { color: var(--achievement); }\n\n/* === Status badge =========================================== */\n.tk-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-family: var(--font-mono);\n font-size: 9.5px;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n padding: 2px 6px;\n border-radius: var(--radius-xs);\n border: 1px solid var(--border-soft);\n color: var(--fg-muted);\n background: var(--bg-base);\n white-space: nowrap;\n}\n.tk-badge.is-pending { color: var(--fg-muted); }\n.tk-badge.is-in_progress {\n color: var(--live);\n background: var(--live-soft);\n border-color: color-mix(in srgb, var(--live) 30%, var(--border-soft));\n}\n.tk-badge.is-blocked {\n color: var(--danger);\n background: color-mix(in srgb, var(--danger) 12%, transparent);\n border-color: color-mix(in srgb, var(--danger) 30%, var(--border-soft));\n}\n.tk-badge.is-completed {\n color: var(--live);\n background: var(--live-soft);\n border-color: color-mix(in srgb, var(--live) 30%, var(--border-soft));\n}\n.tk-badge.is-cancelled { color: var(--fg-faint); }\n.tk-badge .dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: currentColor;\n}\n\n/* === Auto-close badge ======================================= */\n.tk-autoclose {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-family: var(--font-mono);\n font-size: 9px;\n letter-spacing: 0.06em;\n color: var(--live);\n background: var(--live-soft);\n border: 1px solid color-mix(in srgb, var(--live) 25%, var(--border-soft));\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n white-space: nowrap;\n}\n.tk-autoclose svg { width: 9px; height: 9px; }\n\n/* === Assignee chips ========================================= */\n.tk-assignee {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-family: var(--font-mono);\n font-size: 9.5px;\n letter-spacing: 0.04em;\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n border: 1px solid var(--border-soft);\n background: var(--bg-base);\n color: var(--fg-muted);\n white-space: nowrap;\n}\n.tk-assignee.is-agent {\n color: var(--agent);\n background: var(--agent-soft);\n border-color: color-mix(in srgb, var(--agent) 30%, var(--border-soft));\n}\n.tk-assignee .avatar {\n width: 11px;\n height: 11px;\n border-radius: 50%;\n background: var(--bg-raised);\n color: var(--fg);\n display: inline-grid;\n place-items: center;\n font-size: 7.5px;\n font-weight: 600;\n text-transform: uppercase;\n}\n.tk-assignee.is-agent .avatar {\n background: color-mix(in srgb, var(--agent) 24%, transparent);\n color: var(--agent);\n}\n.tk-assignee .dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--agent);\n}\n\n/* === Exec mode pill ========================================= */\n.tk-execmode {\n font-family: var(--font-mono);\n font-size: 9px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--fg-faint);\n border: 1px dashed var(--border-soft);\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n background: transparent;\n}\n.tk-execmode.is-autonomous {\n color: var(--agent);\n border-color: color-mix(in srgb, var(--agent) 30%, var(--border-soft));\n}\n.tk-execmode.is-approval_required {\n color: var(--achievement);\n border-color: color-mix(in srgb, var(--achievement) 35%, var(--border-soft));\n}\n.tk-execmode.is-report {\n color: var(--systemic);\n border-color: color-mix(in srgb, var(--systemic) 30%, var(--border-soft));\n}\n\n/* === Detail panel =========================================== */\n.tk-det-head {\n padding: var(--space-4) var(--space-5);\n border-bottom: 1px solid var(--border-soft);\n background: linear-gradient(180deg, var(--tint-bg-active, var(--bg-surface)) 0%, var(--bg-base) 100%);\n}\n.tk-det-topline {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n margin-bottom: 8px;\n font-family: var(--font-mono);\n font-size: 10.5px;\n color: var(--fg-faint);\n letter-spacing: 0.04em;\n}\n.tk-det-topline .id {\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n padding: 2px 6px;\n border-radius: var(--radius-xs);\n color: var(--fg);\n}\n.tk-det-actions { display: flex; gap: 4px; align-items: center; }\n.tk-det-title {\n font-family: var(--font-display);\n font-weight: 500;\n font-size: var(--text-h3);\n margin: 0;\n color: var(--fg);\n line-height: 1.25;\n}\n.tk-det-meta-row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n margin-top: var(--space-3);\n font-family: var(--font-mono);\n font-size: 10.5px;\n color: var(--fg-faint);\n letter-spacing: 0.04em;\n}\n.tk-det-meta-row .sep { color: var(--fg-faint); }\n.tk-det-meta-row .pri-label { color: var(--achievement); display: inline-flex; align-items: center; gap: 4px; }\n.tk-det-meta-row .pri-label.is-critical { color: var(--danger); }\n.tk-det-meta-row .pri-label.is-high { color: var(--achievement); }\n.tk-det-meta-row .pri-label.is-medium { color: var(--systemic); }\n.tk-det-meta-row .pri-label.is-low { color: var(--fg-muted); }\n.tk-det-meta-row .pri-label .dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n}\n.tk-det-meta-row .due-text { color: var(--fg-muted); }\n.tk-det-meta-row .due-text.is-overdue { color: var(--danger); }\n.tk-det-body {\n padding: var(--space-5);\n display: flex;\n flex-direction: column;\n gap: var(--space-5);\n flex: 1;\n}\n.tk-det-grid {\n display: grid;\n grid-template-columns: 110px 1fr;\n gap: 10px var(--space-4);\n font-size: var(--text-body-sm);\n}\n.tk-det-grid dt {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg-faint);\n letter-spacing: 0.1em;\n text-transform: uppercase;\n align-self: center;\n}\n.tk-det-grid dd {\n margin: 0;\n color: var(--fg);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-body-sm);\n}\n.tk-det-grid dd code {\n font-family: var(--font-mono);\n font-size: 11.5px;\n background: var(--bg-sunken);\n border: 1px solid var(--border-soft);\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n color: var(--fg);\n}\n.tk-section-label {\n font-family: var(--font-mono);\n font-size: 10px;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: var(--fg-faint);\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n margin-bottom: 6px;\n}\n.tk-section-label .ct {\n font-family: var(--font-mono);\n font-size: 9.5px;\n color: var(--fg-muted);\n font-variant-numeric: tabular-nums;\n letter-spacing: 0.04em;\n text-transform: none;\n}\n.tk-deferred-pill {\n font-family: var(--font-mono);\n font-size: 9px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--fg-faint);\n border: 1px dashed var(--border);\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n background: transparent;\n}\n\n.tk-desc {\n font-size: var(--text-body-sm);\n color: var(--fg-muted);\n line-height: 1.6;\n background: var(--bg-surface);\n border: 1px solid var(--border-soft);\n border-radius: var(--radius-md);\n padding: var(--space-3) var(--space-4);\n white-space: pre-wrap;\n}\n\n/* === Progress bar =========================================== */\n.tk-progress {\n flex: 1;\n height: 6px;\n background: var(--bg-sunken);\n border-radius: 3px;\n overflow: hidden;\n border: 1px solid var(--border-soft);\n min-width: 120px;\n}\n.tk-progress > span {\n display: block;\n height: 100%;\n background: var(--live);\n border-radius: 3px;\n transition: width var(--motion-fast) var(--ease-calm);\n}\n\n/* === Evidence card ========================================== */\n.tk-evidence {\n border: 1px solid color-mix(in srgb, var(--live) 30%, var(--border-soft));\n background: var(--live-soft);\n border-radius: var(--radius-md);\n padding: var(--space-3) var(--space-4);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.tk-evidence-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n}\n.tk-evidence .rule-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-family: var(--font-mono);\n font-size: 9.5px;\n letter-spacing: 0.04em;\n color: var(--live);\n background: var(--bg-surface);\n border: 1px solid color-mix(in srgb, var(--live) 30%, var(--border-soft));\n padding: 2px 6px;\n border-radius: var(--radius-xs);\n}\n.tk-evidence .rule-chip svg { width: 10px; height: 10px; }\n.tk-evidence .rule-chip.is-flag {\n color: var(--achievement);\n border-color: color-mix(in srgb, var(--achievement) 30%, var(--border-soft));\n background: var(--bg-surface);\n}\n.tk-evidence .timestamp {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg-muted);\n letter-spacing: 0.04em;\n}\n.tk-evidence .body {\n font-size: var(--text-body-sm);\n color: var(--fg);\n line-height: 1.55;\n}\n\n/* === Source-ref chips ======================================= */\n.tk-source-row {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n.tk-src {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-family: var(--font-mono);\n font-size: 10.5px;\n color: var(--fg-muted);\n background: var(--bg-sunken);\n border: 1px solid var(--border-soft);\n padding: 3px 7px;\n border-radius: var(--radius-sm);\n text-decoration: none;\n letter-spacing: 0.02em;\n cursor: pointer;\n}\n.tk-src:hover { color: var(--fg); border-color: var(--fg-faint); }\n.tk-src svg { width: 11px; height: 11px; flex-shrink: 0; color: var(--fg-faint); }\n.tk-src.is-email svg { color: var(--mail-fg, var(--achievement)); }\n.tk-src.is-session svg { color: var(--agent); }\n.tk-src.is-git svg { color: var(--systemic); }\n\n/* === Subtasks =============================================== */\n.tk-subtasks { display: flex; flex-direction: column; gap: 4px; }\n.tk-sub-row {\n display: grid;\n grid-template-columns: auto 1fr auto;\n align-items: center;\n gap: var(--space-2);\n padding: 6px var(--space-3);\n background: var(--bg-surface);\n border: 1px solid var(--border-soft);\n border-radius: var(--radius-sm);\n font-size: var(--text-body-sm);\n cursor: pointer;\n text-align: left;\n width: 100%;\n font: inherit;\n color: inherit;\n transition: background var(--motion-fast) var(--ease-calm);\n}\n.tk-sub-row:hover { background: var(--bg-raised); }\n.tk-sub-row .name {\n color: var(--fg);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.tk-sub-row.is-completed .name {\n color: var(--fg-muted);\n text-decoration: line-through;\n}\n.tk-sub-row .due {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg-faint);\n}\n\n/* === Activity timeline ====================================== */\n.tk-timeline {\n display: flex;\n flex-direction: column;\n gap: 0;\n border-left: 1px dashed var(--border);\n margin-left: 6px;\n padding-left: var(--space-4);\n position: relative;\n}\n.tk-tl-item {\n position: relative;\n padding: 6px 0;\n font-size: var(--text-body-sm);\n color: var(--fg-muted);\n}\n.tk-tl-item::before {\n content: '';\n position: absolute;\n left: calc(-1 * var(--space-4) - 4px);\n top: 12px;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--bg-sunken);\n border: 1px solid var(--border);\n}\n.tk-tl-item.is-mark::before {\n background: var(--tint-fg-active, var(--primary));\n border-color: var(--tint-fg-active, var(--primary));\n}\n.tk-tl-item.is-ok::before {\n background: var(--live);\n border-color: var(--live);\n}\n.tk-tl-item .when {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg-faint);\n letter-spacing: 0.04em;\n margin-right: 6px;\n}\n.tk-tl-item .actor {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg);\n background: var(--bg-sunken);\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n border: 1px solid var(--border-soft);\n margin-right: 6px;\n}\n.tk-tl-item .actor.is-agent { color: var(--agent); }\n\n/* === Action footer ========================================== */\n.tk-action-bar {\n border-top: 1px solid var(--border-soft);\n background: var(--bg-sunken);\n padding: var(--space-3) var(--space-5);\n display: flex;\n align-items: center;\n gap: var(--space-2);\n margin-top: auto;\n}\n.tk-action-bar .spacer { flex: 1; }\n\n/* === Empty state in detail =================================== */\n.tk-empty {\n flex: 1;\n display: grid;\n place-items: center;\n color: var(--fg-faint);\n font-family: var(--font-mono);\n font-size: 11px;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n/* === Density variants for $taskId standalone (Section B) ===== */\n.tk-detail-pane.is-compact .tk-det-head { padding: var(--space-3) var(--space-4); }\n.tk-detail-pane.is-compact .tk-det-title { font-size: var(--text-h4); }\n.tk-detail-pane.is-compact .tk-det-body { padding: var(--space-4); gap: var(--space-4); }\n.tk-detail-pane.is-compact .tk-det-grid { grid-template-columns: 90px 1fr; }\n.tk-detail-pane.is-side .tk-det-head { padding: var(--space-3); }\n.tk-detail-pane.is-side .tk-det-title { font-size: 13.5px; line-height: 1.35; }\n.tk-detail-pane.is-side .tk-det-body { padding: var(--space-3); gap: var(--space-3); }\n.tk-detail-pane.is-side .tk-det-grid { display: none; }\n.tk-detail-pane.is-side .tk-section-label { margin-bottom: 4px; }\n\n/* === In-body view switcher (D-2 / D-3) ====================== */\n.ip-tabs {\n display: flex;\n align-items: center;\n gap: 0;\n padding: 0 var(--space-3);\n height: var(--tab-h, 38px);\n border-bottom: 1px solid var(--border-soft);\n background: var(--bg-sunken);\n}\n.ip-tab {\n height: var(--tab-h, 38px);\n padding: 0 var(--space-3);\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: var(--font-body);\n font-size: var(--text-body-sm);\n color: var(--fg-faint);\n border: 0;\n background: transparent;\n cursor: pointer;\n border-bottom: 2px solid transparent;\n margin-bottom: -1px;\n}\n.ip-tab svg { width: 13px; height: 13px; opacity: 0.8; }\n.ip-tab:hover { color: var(--fg-muted); }\n.ip-tab.is-on { color: var(--fg); border-bottom-color: var(--tint-fg-active, var(--primary)); }\n.ip-tab.is-on svg { opacity: 1; color: var(--tint-fg-active, var(--primary)); }\n.ip-tab:focus-visible,\n.tk-toggle:focus-visible,\n.tk-group-head:focus-visible,\n.tk-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }\n.ip-tab-badge {\n font-family: var(--font-mono);\n font-size: 9.5px;\n line-height: 1;\n color: var(--achievement);\n background: var(--achievement-soft);\n border: 1px solid color-mix(in srgb, var(--achievement) 30%, var(--border-soft));\n border-radius: var(--radius-pill, 999px);\n padding: 2px 5px;\n}\n\n/* === Agenda / Today (D-2) =================================== */\n/* AgendaView root — rendered directly inside .tk-frame (which is overflow:hidden),\n * so it must be the scroll region itself: grow to fill the leftover height, allow\n * shrink (min-height:0), scroll its own overflow. Mirrors the Browse page's\n * `1fr` + overflow-y:auto leaf (shell .ccfg-list/.ccfg-detail). Without this the\n * agenda is clipped by the frame and can't scroll. */\n.ag-wrap { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-5); max-width: 920px; }\n.ag-head {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-3);\n margin-bottom: var(--space-5);\n}\n.ag-date { font-family: var(--font-display); font-weight: 500; font-size: var(--text-h3); color: var(--fg); }\n.ag-summary { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-faint); letter-spacing: 0.04em; }\n.ag-summary b { color: var(--fg-muted); font-weight: 500; }\n.ag-filter-note { color: var(--achievement); font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.04em; }\n.ag-grid { display: grid; grid-template-columns: 54px 1fr; column-gap: var(--space-3); }\n.ag-time { font-family: var(--font-mono); font-size: 10px; color: var(--fg-faint); text-align: right; padding-top: 8px; letter-spacing: 0.04em; }\n.ag-lane { min-width: 0; padding-bottom: var(--space-3); }\n.ag-block {\n padding: 8px var(--space-3);\n border-radius: var(--radius-sm);\n border: 1px solid var(--border-soft);\n background: var(--bg-surface);\n border-left: 3px solid var(--fg-faint);\n margin-bottom: 6px;\n}\n.ag-block:last-child { margin-bottom: 0; }\n.ag-block.is-me { border-left-color: var(--primary); }\n.ag-block.is-agent { border-left-color: var(--agent); background: var(--agent-soft); }\n.ag-block.is-silent { border-left-color: var(--systemic); border-style: dashed; background: transparent; }\n.ag-block.is-deadline { border-left-color: var(--danger); background: color-mix(in srgb, var(--danger) 8%, transparent); }\n.ag-block.is-done { opacity: 0.6; }\n.ag-block .t { font-size: var(--text-body-sm); color: var(--fg); font-weight: 500; line-height: 1.4; }\n.ag-block.is-done .t { text-decoration: line-through; text-decoration-thickness: 1px; color: var(--fg-muted); }\n.ag-block .m { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 5px; }\n.ag-now { grid-column: 1 / -1; position: relative; height: 0; border-top: 2px solid var(--live); margin: 4px 0 10px; }\n.ag-now::after {\n content: 'now';\n position: absolute;\n right: 0;\n top: -8px;\n font-family: var(--font-mono);\n font-size: 8.5px;\n letter-spacing: 0.06em;\n color: var(--live);\n background: var(--bg-base);\n padding: 0 5px;\n}\n.ag-now::before { content: ''; position: absolute; left: -5px; top: -3px; width: 6px; height: 6px; border-radius: 50%; background: var(--live); }\n\n/* === Triage / Health (D-3) ================================== */\n/* TriageView root — same as .ag-wrap: own scroll region inside the overflow-hidden\n * frame (grow to fill, min-height:0, scroll). */\n.tr-wrap { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-5); max-width: 980px; }\n.tr-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); margin-bottom: var(--space-5); }\n.tr-stat { padding: var(--space-3) var(--space-4); border: 1px solid var(--border-soft); border-radius: var(--radius-md); background: var(--bg-surface); }\n/* Numbers stay --fg (12:1+ in every theme/mode) — the colored border carries\n the semantic. --achievement big-number measured 2.57:1 on a light surface. */\n.tr-stat .n { font-family: var(--font-display); font-weight: 500; font-size: 28px; line-height: 1; color: var(--fg); font-variant-numeric: tabular-nums; }\n.tr-stat .k { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-faint); margin-top: 8px; }\n.tr-stat .sub { font-family: var(--font-mono); font-size: 9px; color: var(--fg-faint); letter-spacing: 0.02em; margin-top: 3px; }\n.tr-stat.is-danger { border-color: color-mix(in srgb, var(--danger) 35%, var(--border-soft)); }\n.tr-stat.is-warn { border-color: color-mix(in srgb, var(--achievement) 35%, var(--border-soft)); }\n.tr-stat.is-sys { border-color: color-mix(in srgb, var(--systemic) 35%, var(--border-soft)); }\n.tr-bucket { margin-bottom: var(--space-5); }\n.tr-bucket-head {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n font-family: var(--font-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--fg-faint);\n margin-bottom: var(--space-2);\n}\n.tr-bucket-head .ct { color: var(--fg-muted); font-variant-numeric: tabular-nums; }\n.tr-bucket-head::after { content: ''; flex: 1; height: 1px; background: var(--border-soft); }\n.tr-mini {\n display: grid;\n grid-template-columns: auto 1fr auto auto;\n align-items: center;\n gap: var(--space-3);\n padding: 8px var(--space-3);\n border-bottom: 1px solid var(--border-soft);\n}\n.tr-mini:last-child { border-bottom: 0; }\n.tr-mini .title { font-size: var(--text-body-sm); color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }\n.tr-mini .age { font-family: var(--font-mono); font-size: 10px; color: var(--fg-muted); letter-spacing: 0.04em; white-space: nowrap; }\n.tr-mini .age.is-bad { color: var(--danger); }\n.tr-more { font-family: var(--font-mono); font-size: 10px; color: var(--fg-faint); letter-spacing: 0.04em; padding: 6px var(--space-3); }\n.tr-health {\n display: flex;\n align-items: center;\n gap: var(--space-4);\n padding: var(--space-3) var(--space-4);\n border: 1px dashed var(--border);\n border-radius: var(--radius-md);\n background: var(--bg-sunken);\n font-size: var(--text-body-sm);\n color: var(--fg-muted);\n line-height: 1.55;\n}\n.tr-health .score { font-family: var(--font-display); font-weight: 500; font-size: var(--text-h2); color: var(--achievement); line-height: 1; flex-shrink: 0; }\n\n/* === De-Tailwinded utilities ================================== */\n/* The source app leaned on a handful of Tailwind utility classes for layout\n * chrome around the locked .tk-* / .ag-* / .tr-* visuals. With no Tailwind in\n * the no-build pkg, those are reproduced here as a tiny, scoped utility set\n * (named after their Tailwind origin so the htm transcription reads 1:1).\n * Everything load-bearing is still a .tk-*/.ag-*/.tr-* rule above. */\n\n/* Root layout shell (was: `flex h-full flex-col p-5`) */\n.tk-screen {\n display: flex;\n height: 100%;\n flex-direction: column;\n padding: var(--space-5);\n}\n\n/* Loading / error / empty inline states (was Tailwind utility soup) */\n.tk-loading {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-4);\n font-size: var(--text-body-sm);\n color: var(--fg-muted);\n}\n.tk-error {\n margin: var(--space-4);\n display: flex;\n align-items: flex-start;\n gap: var(--space-2);\n border-radius: var(--radius-md);\n border: 1px solid color-mix(in srgb, var(--danger) 50%, transparent);\n background: color-mix(in srgb, var(--danger) 10%, transparent);\n padding: var(--space-3);\n font-size: var(--text-body-sm);\n color: var(--danger);\n}\n.tk-error svg { flex-shrink: 0; margin-top: 2px; }\n.tk-error .t { font-weight: 500; }\n.tk-error .d { font-size: var(--text-caption); opacity: 0.8; margin-top: 2px; }\n.tk-empty-box {\n margin: var(--space-4);\n display: flex;\n height: 128px;\n align-items: center;\n justify-content: center;\n border-radius: var(--radius-md);\n border: 1px dashed var(--border);\n font-size: var(--text-body-sm);\n color: var(--fg-muted);\n}\n\n/* Spinner (was: `animate-spin`) */\n.tk-spin { animation: tk-spin 1s linear infinite; }\n@keyframes tk-spin { to { transform: rotate(360deg); } }\n\n/* Detail-pane status select inline-styled in source; kept inline in the htm. */\n\n/* === Button (was: src/components/Button.tsx, Tailwind utilities) ============ */\n.tk-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n font-family: inherit;\n font-weight: 500;\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--motion-fast, 120ms) var(--ease-calm, ease),\n color var(--motion-fast, 120ms) var(--ease-calm, ease),\n opacity var(--motion-fast, 120ms) var(--ease-calm, ease);\n}\n.tk-btn svg { flex-shrink: 0; }\n.tk-btn:disabled { opacity: 0.5; pointer-events: none; }\n/* sizes */\n.tk-btn.sz-md { height: 32px; padding: 0 12px; font-size: var(--text-body-sm); border-radius: var(--radius-md); }\n.tk-btn.sz-sm { height: 28px; padding: 0 10px; font-size: var(--text-caption); border-radius: var(--radius-md); gap: 4px; }\n/* variants */\n.tk-btn.v-default {\n background: var(--primary);\n color: var(--primary-fg);\n border: 1px solid transparent;\n}\n.tk-btn.v-default:hover:not(:disabled) { opacity: 0.9; }\n.tk-btn.v-outline {\n background: transparent;\n color: var(--fg);\n border: 1px solid var(--border);\n}\n.tk-btn.v-outline:hover:not(:disabled) { background: var(--bg-raised); }\n.tk-btn.v-ghost {\n background: transparent;\n color: var(--fg);\n border: 1px solid transparent;\n}\n.tk-btn.v-ghost:hover:not(:disabled) { background: var(--bg-raised); }\n.tk-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }\n\n/* Mutation error line in the detail pane footer. */\n.tk-mut-error {\n padding: 0 var(--space-5) var(--space-3);\n font-size: 11px;\n color: var(--danger);\n}\n";
1
+ // GENERATED by scripts/build.mjs from dist/tasks.css — do not edit.
2
+ // CSS-as-string: WebKitGTK cannot load link/fetch subresources from the
3
+ // about:srcdoc the shell mounts, so app.js injects this as an inline <style>.
4
+ export default "/* Tasks screen — domain RESIDUE only (P3 inc-3).\n * The kit primitives — .frame*, .ip-head / .ip-topline / .ip-title / .ip-body /\n * .ip-desc / .ip-progress* / .ip-action-bar*, .dense-row*, .tk-badge,\n * .tk-execmode — now come from the vendored @ikenga/tokens app-kit-css (injected\n * before this file by app.js, in cascade order tokens -> app-kit -> this).\n * What remains here is the Tasks-specific vocabulary the kit does not own:\n * the filter bar, master/detail split shell, group dividers, the inspector\n * field-grid / meta-row / timeline / source + evidence chips, the agenda +\n * triage layouts, the (deferred) feedback states, and the local button.\n */\n\n/* === Frame (residue: the auto-closed count chip) ============ */\n.tk-frame-count {\n font-family: var(--font-mono);\n font-size: 12px;\n color: var(--fg-muted);\n font-weight: 400;\n margin-left: 6px;\n}\n\n/* === Filter bar ============================================= */\n.tk-filterbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-3) var(--space-5);\n border-bottom: 1px solid var(--border-soft);\n background: var(--bg-sunken);\n}\n.tk-filterbar .input-search-wrap { position: relative; display: inline-flex; }\n.tk-filterbar .input-search-wrap svg {\n position: absolute;\n left: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 13px;\n height: 13px;\n color: var(--fg-faint);\n}\n.tk-filterbar input[type='text'] {\n width: 280px;\n height: 28px;\n padding: 0 8px 0 28px;\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n border-radius: var(--radius-sm);\n color: var(--fg);\n font-family: inherit;\n font-size: 11.5px;\n}\n.tk-filterbar select {\n height: 28px;\n font-size: 11.5px;\n padding: 0 var(--space-2);\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n border-radius: var(--radius-sm);\n color: var(--fg);\n font-family: inherit;\n}\n.tk-filterbar .label {\n font-family: var(--font-mono);\n font-size: 10.5px;\n color: var(--fg-faint);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n.tk-filterbar .spacer { flex: 1; }\n.tk-toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 28px;\n padding: 0 10px;\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n border-radius: var(--radius-sm);\n color: var(--fg-muted);\n font-family: inherit;\n font-size: 11px;\n cursor: pointer;\n}\n.tk-toggle:hover { color: var(--fg); border-color: var(--fg-faint); }\n.tk-toggle.is-on {\n color: var(--live);\n background: var(--live-soft);\n border-color: color-mix(in srgb, var(--live) 30%, var(--border));\n}\n.tk-toggle .checkbox {\n width: 11px;\n height: 11px;\n border: 1px solid currentColor;\n border-radius: 2px;\n display: inline-grid;\n place-items: center;\n flex-shrink: 0;\n}\n.tk-toggle.is-on .checkbox::after {\n content: '✓';\n font-size: 9px;\n line-height: 1;\n color: currentColor;\n}\n\n/* === Master/detail split ==================================== */\n.tk-split {\n --list-w: 360px;\n display: grid;\n grid-template-columns: minmax(280px, var(--list-w)) 4px minmax(420px, 1fr);\n /* Bind the single row to the split's own height. Without this the implicit\n * row is `auto` (content-sized), so a tall list/detail grows the row past the\n * split and gets clipped by overflow:hidden — neither pane scrolls. */\n grid-template-rows: minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n.tk-list {\n overflow-y: auto;\n /* Grid items default to min-height:auto (won't shrink below content), which\n * defeats overflow:auto. Allow shrink so the list scrolls within its track. */\n min-height: 0;\n background: var(--bg-surface);\n}\n.tk-divider {\n background: var(--border-soft);\n cursor: col-resize;\n}\n.tk-divider:hover { background: var(--tint-fg-active, var(--primary)); }\n.tk-detail {\n background: var(--bg-base);\n overflow-y: auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n\n/* === Group dividers ========================================= */\n.tk-group-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px var(--space-4) 6px var(--space-3);\n background: var(--bg-sunken);\n border-bottom: 1px solid var(--border-soft);\n border-top: 1px solid var(--border-soft);\n font-family: var(--font-mono);\n font-size: 9.5px;\n color: var(--fg-faint);\n letter-spacing: 0.1em;\n text-transform: uppercase;\n position: sticky;\n top: 0;\n z-index: 4;\n cursor: pointer;\n user-select: none;\n}\n.tk-group-head:first-child { border-top: 0; }\n.tk-group-head .ct {\n color: var(--fg-muted);\n font-variant-numeric: tabular-nums;\n}\n.tk-group-head.is-overdue { color: var(--danger); }\n.tk-group-head.is-overdue .ct { color: var(--danger); }\n.tk-group-head.is-autoclosed { color: var(--live); }\n.tk-group-head.is-autoclosed .ct { color: var(--live); }\n.tk-group-head.is-collapsed { background: var(--bg-base); }\n.tk-group-head .chev {\n width: 10px;\n height: 10px;\n color: var(--fg-faint);\n transition: transform var(--motion-fast) var(--ease-calm);\n}\n.tk-group-head.is-collapsed .chev { transform: rotate(-90deg); }\n.tk-group-label {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n/* === Task row (residue: the meta strip + category micro-label;\n .dense-row / .dense-row-dot / -body / -title / -right / -due now kit-owned.\n The kit's .dense-row-meta tightens the chip gap to 4px; Tasks keeps 6px,\n so .meta stays a domain child here rather than adopting .dense-row-meta.) */\n.dense-row--task .meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--font-mono);\n font-size: 9.5px;\n color: var(--fg-faint);\n letter-spacing: 0.04em;\n}\n.dense-row--task .meta .cat {\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n color: var(--fg-muted);\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n text-transform: lowercase;\n}\n\n/* === Status badge — kit-owned (.tk-badge + states live in app-kit-css,\n 11-badge-tag-chip; byte-identical, so removed here to avoid a duplicate). */\n\n/* === Auto-close badge ======================================= */\n.tk-autoclose {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-family: var(--font-mono);\n font-size: 9px;\n letter-spacing: 0.06em;\n color: var(--live);\n background: var(--live-soft);\n border: 1px solid color-mix(in srgb, var(--live) 25%, var(--border-soft));\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n white-space: nowrap;\n}\n.tk-autoclose svg { width: 9px; height: 9px; }\n\n/* === Assignee chips ========================================= */\n.tk-assignee {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-family: var(--font-mono);\n font-size: 9.5px;\n letter-spacing: 0.04em;\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n border: 1px solid var(--border-soft);\n background: var(--bg-base);\n color: var(--fg-muted);\n white-space: nowrap;\n}\n.tk-assignee.is-agent {\n color: var(--agent);\n background: var(--agent-soft);\n border-color: color-mix(in srgb, var(--agent) 30%, var(--border-soft));\n}\n.tk-assignee .avatar {\n width: 11px;\n height: 11px;\n border-radius: 50%;\n background: var(--bg-raised);\n color: var(--fg);\n display: inline-grid;\n place-items: center;\n font-size: 7.5px;\n font-weight: 600;\n text-transform: uppercase;\n}\n.tk-assignee.is-agent .avatar {\n background: color-mix(in srgb, var(--agent) 24%, transparent);\n color: var(--agent);\n}\n.tk-assignee .dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--agent);\n}\n\n/* === Exec mode pill — kit-owned (.tk-execmode + states live in app-kit-css,\n 34-ux-mode-action-surfaces; byte-identical, removed here to avoid a dup). */\n\n/* === Detail panel (residue: the id chip + meta-row; .ip-head / .ip-topline /\n .ip-topline-actions / .ip-title now kit-owned via inspector-detail).\n The kit's .ip-topline-id pads 2px 8px; Tasks keeps the shipped 2px 6px,\n so the id chip stays a domain child re-scoped under the kit .ip-topline. */\n.ip-topline .id {\n background: var(--bg-base);\n border: 1px solid var(--border-soft);\n padding: 2px 6px;\n border-radius: var(--radius-xs);\n color: var(--fg);\n}\n.tk-det-meta-row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n margin-top: var(--space-3);\n font-family: var(--font-mono);\n font-size: 10.5px;\n color: var(--fg-faint);\n letter-spacing: 0.04em;\n}\n.tk-det-meta-row .sep { color: var(--fg-faint); }\n.tk-det-meta-row .pri-label { color: var(--achievement); display: inline-flex; align-items: center; gap: 4px; }\n.tk-det-meta-row .pri-label.is-critical { color: var(--danger); }\n.tk-det-meta-row .pri-label.is-high { color: var(--achievement); }\n.tk-det-meta-row .pri-label.is-medium { color: var(--systemic); }\n.tk-det-meta-row .pri-label.is-low { color: var(--fg-muted); }\n.tk-det-meta-row .pri-label .dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n}\n.tk-det-meta-row .due-text { color: var(--fg-muted); }\n.tk-det-meta-row .due-text.is-overdue { color: var(--danger); }\n.tk-det-grid {\n display: grid;\n grid-template-columns: 110px 1fr;\n gap: 10px var(--space-4);\n font-size: var(--text-body-sm);\n}\n.tk-det-grid dt {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg-faint);\n letter-spacing: 0.1em;\n text-transform: uppercase;\n align-self: center;\n}\n.tk-det-grid dd {\n margin: 0;\n color: var(--fg);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-body-sm);\n}\n.tk-det-grid dd code {\n font-family: var(--font-mono);\n font-size: 11.5px;\n background: var(--bg-sunken);\n border: 1px solid var(--border-soft);\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n color: var(--fg);\n}\n.tk-section-label {\n font-family: var(--font-mono);\n font-size: 10px;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: var(--fg-faint);\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n margin-bottom: 6px;\n}\n.tk-section-label .ct {\n font-family: var(--font-mono);\n font-size: 9.5px;\n color: var(--fg-muted);\n font-variant-numeric: tabular-nums;\n letter-spacing: 0.04em;\n text-transform: none;\n}\n.tk-deferred-pill {\n font-family: var(--font-mono);\n font-size: 9px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--fg-faint);\n border: 1px dashed var(--border);\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n background: transparent;\n}\n\n/* === Description + progress bar — kit-owned (.ip-desc and .ip-progress /\n .ip-progress-fill live in app-kit-css, inspector-detail). */\n\n/* === Evidence card ========================================== */\n.tk-evidence {\n border: 1px solid color-mix(in srgb, var(--live) 30%, var(--border-soft));\n background: var(--live-soft);\n border-radius: var(--radius-md);\n padding: var(--space-3) var(--space-4);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.tk-evidence-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n}\n.tk-evidence .rule-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-family: var(--font-mono);\n font-size: 9.5px;\n letter-spacing: 0.04em;\n color: var(--live);\n background: var(--bg-surface);\n border: 1px solid color-mix(in srgb, var(--live) 30%, var(--border-soft));\n padding: 2px 6px;\n border-radius: var(--radius-xs);\n}\n.tk-evidence .rule-chip svg { width: 10px; height: 10px; }\n.tk-evidence .rule-chip.is-flag {\n color: var(--achievement);\n border-color: color-mix(in srgb, var(--achievement) 30%, var(--border-soft));\n background: var(--bg-surface);\n}\n.tk-evidence .timestamp {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg-muted);\n letter-spacing: 0.04em;\n}\n.tk-evidence .body {\n font-size: var(--text-body-sm);\n color: var(--fg);\n line-height: 1.55;\n}\n\n/* === Source-ref chips ======================================= */\n.tk-source-row {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n.tk-src {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-family: var(--font-mono);\n font-size: 10.5px;\n color: var(--fg-muted);\n background: var(--bg-sunken);\n border: 1px solid var(--border-soft);\n padding: 3px 7px;\n border-radius: var(--radius-sm);\n text-decoration: none;\n letter-spacing: 0.02em;\n cursor: pointer;\n}\n.tk-src:hover { color: var(--fg); border-color: var(--fg-faint); }\n.tk-src svg { width: 11px; height: 11px; flex-shrink: 0; color: var(--fg-faint); }\n.tk-src.is-email svg { color: var(--mail-fg, var(--achievement)); }\n.tk-src.is-session svg { color: var(--agent); }\n.tk-src.is-git svg { color: var(--systemic); }\n\n/* === Subtasks =============================================== */\n.tk-subtasks { display: flex; flex-direction: column; gap: 4px; }\n.tk-sub-row {\n display: grid;\n grid-template-columns: auto 1fr auto;\n align-items: center;\n gap: var(--space-2);\n padding: 6px var(--space-3);\n background: var(--bg-surface);\n border: 1px solid var(--border-soft);\n border-radius: var(--radius-sm);\n font-size: var(--text-body-sm);\n cursor: pointer;\n text-align: left;\n width: 100%;\n font: inherit;\n color: inherit;\n transition: background var(--motion-fast) var(--ease-calm);\n}\n.tk-sub-row:hover { background: var(--bg-raised); }\n.tk-sub-row .name {\n color: var(--fg);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.tk-sub-row.is-completed .name {\n color: var(--fg-muted);\n text-decoration: line-through;\n}\n.tk-sub-row .due {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg-faint);\n}\n\n/* === Activity timeline ====================================== */\n.tk-timeline {\n display: flex;\n flex-direction: column;\n gap: 0;\n border-left: 1px dashed var(--border);\n margin-left: 6px;\n padding-left: var(--space-4);\n position: relative;\n}\n.tk-tl-item {\n position: relative;\n padding: 6px 0;\n font-size: var(--text-body-sm);\n color: var(--fg-muted);\n}\n.tk-tl-item::before {\n content: '';\n position: absolute;\n left: calc(-1 * var(--space-4) - 4px);\n top: 12px;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--bg-sunken);\n border: 1px solid var(--border);\n}\n.tk-tl-item.is-mark::before {\n background: var(--tint-fg-active, var(--primary));\n border-color: var(--tint-fg-active, var(--primary));\n}\n.tk-tl-item.is-ok::before {\n background: var(--live);\n border-color: var(--live);\n}\n.tk-tl-item .when {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg-faint);\n letter-spacing: 0.04em;\n margin-right: 6px;\n}\n.tk-tl-item .actor {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--fg);\n background: var(--bg-sunken);\n padding: 1px 5px;\n border-radius: var(--radius-xs);\n border: 1px solid var(--border-soft);\n margin-right: 6px;\n}\n.tk-tl-item .actor.is-agent { color: var(--agent); }\n\n/* === Action footer — kit-owned (.ip-action-bar / .ip-action-bar-spacer live\n in app-kit-css, inspector-detail). Only rendered for density != full,\n which the shipped pane never uses. */\n\n/* === Empty state in detail (residue; feedback-state migration deferred) ==== */\n.tk-empty {\n flex: 1;\n display: grid;\n place-items: center;\n color: var(--fg-faint);\n font-family: var(--font-mono);\n font-size: 11px;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n/* === Density variants ($taskId standalone) + in-pane view switcher: REMOVED.\n The density variants are dead (the shipped pane is always density=\"full\");\n the .ip-tabs/.ip-tab switcher was dropped pre-ship (views live in the\n shell side-menu). The kit's .tabs/.tab part covers underline tabs if a\n future view needs them. */\n\n/* Keyboard focus ring for the residue interactive elements. The kit's\n .dense-row:focus-visible already covers task rows; the toggle + group head\n are domain residue, so keep their ring here. */\n.tk-toggle:focus-visible,\n.tk-group-head:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }\n\n/* === Agenda / Today (D-2) =================================== */\n/* AgendaView root — rendered directly inside .tk-frame (which is overflow:hidden),\n * so it must be the scroll region itself: grow to fill the leftover height, allow\n * shrink (min-height:0), scroll its own overflow. Mirrors the Browse page's\n * `1fr` + overflow-y:auto leaf (shell .ccfg-list/.ccfg-detail). Without this the\n * agenda is clipped by the frame and can't scroll. */\n.ag-wrap { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-5); max-width: 920px; }\n.ag-head {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-3);\n margin-bottom: var(--space-5);\n}\n.ag-date { font-family: var(--font-display); font-weight: 500; font-size: var(--text-h3); color: var(--fg); }\n.ag-summary { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-faint); letter-spacing: 0.04em; }\n.ag-summary b { color: var(--fg-muted); font-weight: 500; }\n.ag-filter-note { color: var(--achievement); font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.04em; }\n.ag-grid { display: grid; grid-template-columns: 54px 1fr; column-gap: var(--space-3); }\n.ag-time { font-family: var(--font-mono); font-size: 10px; color: var(--fg-faint); text-align: right; padding-top: 8px; letter-spacing: 0.04em; }\n.ag-lane { min-width: 0; padding-bottom: var(--space-3); }\n.ag-block {\n padding: 8px var(--space-3);\n border-radius: var(--radius-sm);\n border: 1px solid var(--border-soft);\n background: var(--bg-surface);\n border-left: 3px solid var(--fg-faint);\n margin-bottom: 6px;\n}\n.ag-block:last-child { margin-bottom: 0; }\n.ag-block.is-me { border-left-color: var(--primary); }\n.ag-block.is-agent { border-left-color: var(--agent); background: var(--agent-soft); }\n.ag-block.is-silent { border-left-color: var(--systemic); border-style: dashed; background: transparent; }\n.ag-block.is-deadline { border-left-color: var(--danger); background: color-mix(in srgb, var(--danger) 8%, transparent); }\n.ag-block.is-done { opacity: 0.6; }\n.ag-block .t { font-size: var(--text-body-sm); color: var(--fg); font-weight: 500; line-height: 1.4; }\n.ag-block.is-done .t { text-decoration: line-through; text-decoration-thickness: 1px; color: var(--fg-muted); }\n.ag-block .m { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 5px; }\n.ag-now { grid-column: 1 / -1; position: relative; height: 0; border-top: 2px solid var(--live); margin: 4px 0 10px; }\n.ag-now::after {\n content: 'now';\n position: absolute;\n right: 0;\n top: -8px;\n font-family: var(--font-mono);\n font-size: 8.5px;\n letter-spacing: 0.06em;\n color: var(--live);\n background: var(--bg-base);\n padding: 0 5px;\n}\n.ag-now::before { content: ''; position: absolute; left: -5px; top: -3px; width: 6px; height: 6px; border-radius: 50%; background: var(--live); }\n\n/* === Triage / Health (D-3) ================================== */\n/* TriageView root — same as .ag-wrap: own scroll region inside the overflow-hidden\n * frame (grow to fill, min-height:0, scroll). */\n.tr-wrap { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-5); max-width: 980px; }\n.tr-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); margin-bottom: var(--space-5); }\n.tr-stat { padding: var(--space-3) var(--space-4); border: 1px solid var(--border-soft); border-radius: var(--radius-md); background: var(--bg-surface); }\n/* Numbers stay --fg (12:1+ in every theme/mode) — the colored border carries\n the semantic. --achievement big-number measured 2.57:1 on a light surface. */\n.tr-stat .n { font-family: var(--font-display); font-weight: 500; font-size: 28px; line-height: 1; color: var(--fg); font-variant-numeric: tabular-nums; }\n.tr-stat .k { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-faint); margin-top: 8px; }\n.tr-stat .sub { font-family: var(--font-mono); font-size: 9px; color: var(--fg-faint); letter-spacing: 0.02em; margin-top: 3px; }\n.tr-stat.is-danger { border-color: color-mix(in srgb, var(--danger) 35%, var(--border-soft)); }\n.tr-stat.is-warn { border-color: color-mix(in srgb, var(--achievement) 35%, var(--border-soft)); }\n.tr-stat.is-sys { border-color: color-mix(in srgb, var(--systemic) 35%, var(--border-soft)); }\n.tr-bucket { margin-bottom: var(--space-5); }\n.tr-bucket-head {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n font-family: var(--font-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--fg-faint);\n margin-bottom: var(--space-2);\n}\n.tr-bucket-head .ct { color: var(--fg-muted); font-variant-numeric: tabular-nums; }\n.tr-bucket-head::after { content: ''; flex: 1; height: 1px; background: var(--border-soft); }\n.tr-mini {\n display: grid;\n grid-template-columns: auto 1fr auto auto;\n align-items: center;\n gap: var(--space-3);\n padding: 8px var(--space-3);\n border-bottom: 1px solid var(--border-soft);\n}\n.tr-mini:last-child { border-bottom: 0; }\n.tr-mini .title { font-size: var(--text-body-sm); color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }\n.tr-mini .age { font-family: var(--font-mono); font-size: 10px; color: var(--fg-muted); letter-spacing: 0.04em; white-space: nowrap; }\n.tr-mini .age.is-bad { color: var(--danger); }\n.tr-more { font-family: var(--font-mono); font-size: 10px; color: var(--fg-faint); letter-spacing: 0.04em; padding: 6px var(--space-3); }\n.tr-health {\n display: flex;\n align-items: center;\n gap: var(--space-4);\n padding: var(--space-3) var(--space-4);\n border: 1px dashed var(--border);\n border-radius: var(--radius-md);\n background: var(--bg-sunken);\n font-size: var(--text-body-sm);\n color: var(--fg-muted);\n line-height: 1.55;\n}\n.tr-health .score { font-family: var(--font-display); font-weight: 500; font-size: var(--text-h2); color: var(--achievement); line-height: 1; flex-shrink: 0; }\n\n/* === De-Tailwinded utilities ================================== */\n/* The source app leaned on a handful of Tailwind utility classes for layout\n * chrome around the locked .tk-* / .ag-* / .tr-* visuals. With no Tailwind in\n * the no-build pkg, those are reproduced here as a tiny, scoped utility set\n * (named after their Tailwind origin so the htm transcription reads 1:1).\n * Everything load-bearing is still a .tk-, .ag-, .tr- rule above. */\n\n/* Root layout shell (was: `flex h-full flex-col p-5`) */\n.tk-screen {\n display: flex;\n height: 100%;\n flex-direction: column;\n}\n\n/* Loading / error / empty inline states (was Tailwind utility soup) */\n.tk-loading {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-4);\n font-size: var(--text-body-sm);\n color: var(--fg-muted);\n}\n.tk-error {\n margin: var(--space-4);\n display: flex;\n align-items: flex-start;\n gap: var(--space-2);\n border-radius: var(--radius-md);\n border: 1px solid color-mix(in srgb, var(--danger) 50%, transparent);\n background: color-mix(in srgb, var(--danger) 10%, transparent);\n padding: var(--space-3);\n font-size: var(--text-body-sm);\n color: var(--danger);\n}\n.tk-error svg { flex-shrink: 0; margin-top: 2px; }\n.tk-error .t { font-weight: 500; }\n.tk-error .d { font-size: var(--text-caption); opacity: 0.8; margin-top: 2px; }\n.tk-empty-box {\n margin: var(--space-4);\n display: flex;\n height: 128px;\n align-items: center;\n justify-content: center;\n border-radius: var(--radius-md);\n border: 1px dashed var(--border);\n font-size: var(--text-body-sm);\n color: var(--fg-muted);\n}\n\n/* Spinner (was: `animate-spin`) */\n.tk-spin { animation: tk-spin 1s linear infinite; }\n@keyframes tk-spin { to { transform: rotate(360deg); } }\n\n/* Detail-pane status select inline-styled in source; kept inline in the htm. */\n\n/* === Button (was: src/components/Button.tsx, Tailwind utilities) ============ */\n.tk-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n font-family: inherit;\n font-weight: 500;\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--motion-fast, 120ms) var(--ease-calm, ease),\n color var(--motion-fast, 120ms) var(--ease-calm, ease),\n opacity var(--motion-fast, 120ms) var(--ease-calm, ease);\n}\n.tk-btn svg { flex-shrink: 0; }\n.tk-btn:disabled { opacity: 0.5; pointer-events: none; }\n/* sizes */\n.tk-btn.sz-md { height: 32px; padding: 0 12px; font-size: var(--text-body-sm); border-radius: var(--radius-md); }\n.tk-btn.sz-sm { height: 28px; padding: 0 10px; font-size: var(--text-caption); border-radius: var(--radius-md); gap: 4px; }\n/* variants */\n.tk-btn.v-default {\n background: var(--primary);\n color: var(--primary-fg);\n border: 1px solid transparent;\n}\n.tk-btn.v-default:hover:not(:disabled) { opacity: 0.9; }\n.tk-btn.v-outline {\n background: transparent;\n color: var(--fg);\n border: 1px solid var(--border);\n}\n.tk-btn.v-outline:hover:not(:disabled) { background: var(--bg-raised); }\n.tk-btn.v-ghost {\n background: transparent;\n color: var(--fg);\n border: 1px solid transparent;\n}\n.tk-btn.v-ghost:hover:not(:disabled) { background: var(--bg-raised); }\n.tk-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }\n\n/* Mutation error line in the detail pane footer. */\n.tk-mut-error {\n padding: 0 var(--space-5) var(--space-3);\n font-size: 11px;\n color: var(--danger);\n}\n"
@@ -1,5 +1,3 @@
1
- // @ikenga/tokens tokens.css, shipped as a JS string (no-build: subresource
2
- // <link>/fetch fail in the shell's about:srcdoc iframe; CSS rides the script
3
- // path and app.js injects it BEFORE tasks.css. Tokens resolve under
4
- // :root[data-mode] / [data-theme] — app.js sets those attrs on <html>.
5
- export default "/**\n * @ikenga/tokens \u2014 canonical design tokens for the Ikenga design system.\n *\n * Single source of truth for CSS custom properties used across:\n * - shell (Tauri desktop app)\n * - every UI pkg (Tasks, Studio, Outbound, \u2026)\n *\n * Consumers `@import '@ikenga/tokens/tokens.css'` and inherit the full token\n * surface. Pkgs running inside the shell iframe additionally receive a\n * curated subset via the AppBridge `host-context` handshake \u2014 those override\n * these defaults at runtime when the user flips theme/mode in the shell.\n *\n * Convention:\n * :root \u2192 mode-agnostic (typography, spacing, radii, shadows)\n * :root[data-mode=\"dark\"] \u2192 dark-mode color slots (DEFAULT)\n * :root[data-mode=\"light\"] \u2192 light-mode color slots (override)\n *\n * `data-theme` is reserved for theme variants beyond the default Ikenga palette\n * (e.g. seasonal, label-branded). Add `:root[data-theme=\"X\"][data-mode=\"dark\"]`\n * blocks below the defaults \u2014 last-match wins.\n */\n\n/* \u2500\u2500\u2500 mode-agnostic \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n:root {\n /* Spacing scale (4px base) */\n --space-1: 4px;\n --space-2: 8px;\n --space-3: 12px;\n --space-4: 16px;\n --space-5: 20px;\n --space-6: 24px;\n --space-8: 32px;\n\n /* Radii */\n --radius-xs: 3px;\n --radius-sm: 4px;\n --radius-md: 6px;\n --radius-lg: 10px;\n --radius-xl: 14px;\n --radius-pill: 999px;\n\n /* Typography */\n --font-sans: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;\n --font-display: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;\n --font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;\n --text-caption: 11.5px;\n --text-body: 13px;\n --text-h3: 16px;\n --text-h2: 20px;\n --text-h1: 28px;\n\n /* Layout */\n --header-height: 44px;\n --sidebar-width: 240px;\n\n /* Default mode is dark \u2014 ensures correct rendering even without\n [data-mode] attribute set on <html>. */\n color-scheme: dark;\n\n /* Ikenga brand accents (mode-agnostic). Used by ADR-011 chat redesign:\n ember = active streaming / hot states; kola-amber = ritual pills,\n tool calls, artifact pills, cost amounts; oxblood = errors;\n verdigris = info / passive systemic. */\n --ember: hsl(14, 78%, 52%);\n --ember-soft: hsl(14, 70%, 60%);\n --kola-amber: hsl(42, 78%, 50%);\n --kola-amber-soft: hsl(42, 60%, 64%);\n --oxblood: hsl(8, 70%, 42%);\n --verdigris: hsl(170, 30%, 38%);\n}\n\n/* \u2500\u2500\u2500 dark mode (DEFAULT) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n:root,\n:root[data-mode='dark'] {\n /* Backgrounds */\n --bg-base: hsl(220, 14%, 8%);\n --bg-surface: hsl(220, 13%, 11%);\n --bg-raised: hsl(220, 12%, 14%);\n --bg-sunken: hsl(220, 14%, 6%);\n\n /* Foregrounds */\n --fg: hsl(0, 0%, 96%);\n --fg-muted: hsl(220, 8%, 58%);\n --fg-subtle: hsl(220, 8%, 42%);\n\n /* Borders */\n --border: hsl(220, 13%, 20%);\n --border-soft: hsl(220, 13%, 16%);\n --border-strong: hsl(220, 13%, 28%);\n\n /* Brand + semantic */\n --primary: hsl(220, 90%, 60%);\n --primary-fg: hsl(0, 0%, 100%);\n --secondary: hsl(220, 12%, 14%);\n --accent: hsl(280, 70%, 65%);\n --info: hsl(200, 90%, 60%);\n --success: hsl(142, 70%, 50%);\n --warning: hsl(38, 92%, 60%);\n --danger: hsl(0, 72%, 60%);\n --agent: hsl(280, 70%, 65%);\n\n /* Tints (subtle backgrounds for active/hovered states) */\n --tint-bg-active: hsl(220, 90%, 60%, 0.08);\n --tint-fg-active: hsl(220, 90%, 70%);\n\n /* Shadows */\n --shadow-1: 0 1px 1px hsl(0 0% 0% / 0.3);\n --shadow-2: 0 1px 2px hsl(0 0% 0% / 0.4);\n --shadow-3: 0 4px 12px hsl(0 0% 0% / 0.5);\n\n /* MCP UI Apps schema bridge \u2014 these are the names the host pushes via\n AppBridge `styles.variables`. Map them to Ikenga semantic slots so a pkg\n that consumes the host context overlay (or one that doesn't) renders the\n same way. */\n --color-background-primary: var(--bg-base);\n --color-background-secondary: var(--bg-surface);\n --color-background-tertiary: var(--bg-raised);\n --color-background-inverse: hsl(0, 0%, 96%);\n --color-background-ghost: transparent;\n --color-background-info: var(--info);\n --color-background-danger: var(--danger);\n --color-background-success: var(--success);\n --color-background-warning: var(--warning);\n --color-background-disabled: hsl(220, 13%, 20%);\n\n --color-text-primary: var(--fg);\n --color-text-secondary: var(--fg-muted);\n --color-text-tertiary: var(--fg-subtle);\n --color-text-inverse: hsl(220, 14%, 8%);\n --color-text-ghost: var(--fg-muted);\n --color-text-info: var(--info);\n --color-text-danger: var(--danger);\n --color-text-success: var(--success);\n --color-text-warning: var(--warning);\n --color-text-disabled: var(--fg-subtle);\n\n --color-border-primary: var(--border);\n --color-border-secondary: var(--border-soft);\n --color-border-tertiary: var(--border-strong);\n --color-border-inverse: hsl(0, 0%, 96%);\n --color-border-ghost: transparent;\n --color-border-info: var(--info);\n --color-border-danger: var(--danger);\n --color-border-success: var(--success);\n --color-border-warning: var(--warning);\n --color-border-disabled: var(--border-soft);\n\n --color-ring-primary: var(--primary);\n --color-ring-secondary: var(--accent);\n --color-ring-inverse: hsl(0, 0%, 96%);\n --color-ring-info: var(--info);\n --color-ring-danger: var(--danger);\n --color-ring-success: var(--success);\n --color-ring-warning: var(--warning);\n\n /* Ikenga hairline + chip-carve (mode-specific). `--rule` is the canonical\n 1px divider between turns in the chat; `--rule-soft` is for grouping\n within a turn; `--chip-carve` is the dim ink used for the \u25bd\u25bd\u25bd motif\n and uppercase mono labels. */\n --rule: hsl(28, 14%, 18%);\n --rule-soft: hsl(28, 12%, 14%);\n --chip-carve: hsl(28, 14%, 32%);\n\n /* Code editor syntax palette (dark). Consumed by @ikenga/ui-lib's\n CodeEditor via CodeMirror 6 highlight tags. Tuned for HTML/TSX/CSS\n legibility on top of `--bg-surface`. */\n --syntax-keyword: hsl(280, 70%, 72%);\n --syntax-string: hsl(160, 55%, 60%);\n --syntax-comment: hsl(220, 10%, 50%);\n --syntax-number: hsl(28, 78%, 64%);\n --syntax-atom: hsl(28, 78%, 64%);\n --syntax-regexp: hsl(330, 60%, 64%);\n --syntax-operator: hsl(0, 0%, 86%);\n --syntax-punctuation: hsl(220, 8%, 62%);\n --syntax-variable: hsl(0, 0%, 92%);\n --syntax-function: hsl(200, 80%, 68%);\n --syntax-type: hsl(180, 60%, 64%);\n --syntax-tag: hsl(0, 70%, 66%);\n --syntax-attribute: hsl(42, 80%, 64%);\n --syntax-heading: hsl(0, 0%, 96%);\n --syntax-link: hsl(200, 90%, 62%);\n}\n\n/* \u2500\u2500\u2500 light mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n:root[data-mode='light'] {\n color-scheme: light;\n\n --bg-base: hsl(0, 0%, 98%);\n --bg-surface: hsl(0, 0%, 100%);\n --bg-raised: hsl(220, 14%, 96%);\n --bg-sunken: hsl(220, 14%, 94%);\n\n --fg: hsl(220, 14%, 12%);\n --fg-muted: hsl(220, 10%, 45%);\n --fg-subtle: hsl(220, 8%, 60%);\n\n --border: hsl(220, 13%, 88%);\n --border-soft: hsl(220, 13%, 93%);\n --border-strong: hsl(220, 13%, 78%);\n\n --primary: hsl(220, 90%, 52%);\n --primary-fg: hsl(0, 0%, 100%);\n --secondary: hsl(220, 14%, 96%);\n --accent: hsl(280, 65%, 50%);\n --info: hsl(200, 90%, 45%);\n --success: hsl(142, 65%, 38%);\n --warning: hsl(38, 88%, 48%);\n --danger: hsl(0, 65%, 48%);\n --agent: hsl(280, 65%, 50%);\n\n --tint-bg-active: hsl(220, 90%, 52%, 0.10);\n --tint-fg-active: hsl(220, 90%, 42%);\n\n --shadow-1: 0 1px 1px hsl(220 14% 50% / 0.06);\n --shadow-2: 0 1px 2px hsl(220 14% 50% / 0.08);\n --shadow-3: 0 4px 12px hsl(220 14% 50% / 0.10);\n\n --color-background-primary: var(--bg-base);\n --color-background-secondary: var(--bg-surface);\n --color-background-tertiary: var(--bg-raised);\n --color-background-inverse: hsl(220, 14%, 12%);\n --color-text-primary: var(--fg);\n --color-text-secondary: var(--fg-muted);\n --color-text-tertiary: var(--fg-subtle);\n --color-text-inverse: hsl(0, 0%, 98%);\n --color-border-primary: var(--border);\n --color-border-secondary: var(--border-soft);\n --color-border-tertiary: var(--border-strong);\n\n /* Light-mode hairline + chip-carve. See dark-mode block for semantics. */\n --rule: hsl(36, 14%, 84%);\n --rule-soft: hsl(36, 14%, 90%);\n --chip-carve: hsl(28, 14%, 62%);\n\n /* Code editor syntax palette (light). See dark block for semantics. */\n --syntax-keyword: hsl(280, 70%, 38%);\n --syntax-string: hsl(160, 55%, 30%);\n --syntax-comment: hsl(220, 10%, 48%);\n --syntax-number: hsl(28, 78%, 38%);\n --syntax-atom: hsl(28, 78%, 38%);\n --syntax-regexp: hsl(330, 60%, 40%);\n --syntax-operator: hsl(220, 14%, 18%);\n --syntax-punctuation: hsl(220, 10%, 42%);\n --syntax-variable: hsl(220, 14%, 14%);\n --syntax-function: hsl(220, 90%, 40%);\n --syntax-type: hsl(180, 60%, 30%);\n --syntax-tag: hsl(0, 70%, 42%);\n --syntax-attribute: hsl(42, 90%, 36%);\n --syntax-heading: hsl(220, 14%, 12%);\n --syntax-link: hsl(200, 90%, 40%);\n}\n/* === Theme A \u00b7 Dusk Wood (canonical default) ==================== */\n[data-theme=\"A\"][data-mode=\"dark\"] {\n --bg-base: hsl(28,18%,4%); --bg-surface: hsl(28,14%,7%);\n --bg-raised: hsl(28,11%,11%); --bg-sunken: hsl(28,22%,2.5%);\n --fg: hsl(36,28%,90%); --fg-muted: hsl(32,11%,56%); --fg-faint: hsl(28,9%,36%);\n --border: hsl(28,14%,15%); --border-soft: hsl(28,14%,11%);\n --primary: hsl(20,50%,34%); --primary-fg: hsl(36,30%,92%); --primary-soft: hsl(20,40%,14%);\n --achievement: hsl(42,78%,54%); --achievement-soft: hsl(42,48%,18%);\n --danger: hsl(8,68%,46%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,50%,16%);\n --systemic: hsl(170,28%,34%); --systemic-soft: hsl(170,22%,16%);\n --shadow-1: 0 1px 2px rgba(0,0,0,.55), 0 0 0 1px rgba(0,0,0,.25);\n --shadow-2: 0 4px 12px -2px rgba(0,0,0,.55);\n --shadow-3: 0 12px 28px -8px rgba(0,0,0,.6);\n --shadow-4: 0 24px 48px -16px rgba(0,0,0,.65);\n}\n[data-theme=\"A\"][data-mode=\"light\"] {\n --bg-base: hsl(36,22%,96%); --bg-surface: hsl(36,18%,93%);\n --bg-raised: hsl(36,14%,89%); --bg-sunken: hsl(36,26%,98%);\n --fg: hsl(28,30%,14%); --fg-muted: hsl(28,14%,38%); --fg-faint: hsl(28,12%,56%);\n --border: hsl(32,16%,78%); --border-soft: hsl(32,16%,84%);\n --primary: hsl(20,50%,34%); --primary-fg: hsl(36,26%,98%); --primary-soft: hsl(20,50%,90%);\n --achievement: hsl(42,78%,42%); --achievement-soft: hsl(42,60%,90%);\n --danger: hsl(8,68%,42%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,60%,92%);\n --systemic: hsl(170,36%,32%); --systemic-soft: hsl(170,30%,90%);\n --shadow-1: 0 1px 2px rgba(28,18,8,.08);\n --shadow-2: 0 4px 12px -2px rgba(28,18,8,.10);\n --shadow-3: 0 12px 28px -8px rgba(28,18,8,.14);\n --shadow-4: 0 24px 48px -16px rgba(28,18,8,.18);\n}\n\n/* === Theme B \u00b7 Kola Daylight ==================================== */\n[data-theme=\"B\"][data-mode=\"light\"] {\n --bg-base: hsl(36,28%,96%); --bg-surface: hsl(36,22%,94%);\n --bg-raised: hsl(36,18%,90%); --bg-sunken: hsl(36,32%,98%);\n --fg: hsl(28,30%,12%); --fg-muted: hsl(28,14%,38%); --fg-faint: hsl(28,12%,56%);\n --border: hsl(32,18%,80%); --border-soft: hsl(32,18%,86%);\n --primary: hsl(42,82%,46%); --primary-fg: hsl(28,30%,8%); --primary-soft: hsl(42,60%,88%);\n --achievement: hsl(14,72%,46%); --achievement-soft: hsl(14,60%,90%);\n --danger: hsl(8,68%,42%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,60%,92%);\n --systemic: hsl(170,36%,32%); --systemic-soft: hsl(170,30%,90%);\n --shadow-1: 0 1px 2px rgba(28,18,8,.08);\n --shadow-2: 0 4px 12px -2px rgba(28,18,8,.10);\n --shadow-3: 0 12px 28px -8px rgba(28,18,8,.14);\n --shadow-4: 0 24px 48px -16px rgba(28,18,8,.18);\n}\n[data-theme=\"B\"][data-mode=\"dark\"] {\n --bg-base: hsl(36,12%,8%); --bg-surface: hsl(36,10%,12%);\n --bg-raised: hsl(36,8%,16%); --bg-sunken: hsl(36,16%,6%);\n --fg: hsl(40,28%,92%); --fg-muted: hsl(36,10%,62%); --fg-faint: hsl(36,8%,42%);\n --border: hsl(36,12%,22%); --border-soft: hsl(36,12%,18%);\n --primary: hsl(42,84%,60%); --primary-fg: hsl(36,30%,8%); --primary-soft: hsl(42,60%,18%);\n --achievement: hsl(14,76%,56%); --achievement-soft: hsl(14,50%,18%);\n --danger: hsl(8,70%,52%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,50%,18%);\n --systemic: hsl(170,32%,46%); --systemic-soft: hsl(170,25%,18%);\n --shadow-1: 0 1px 2px rgba(0,0,0,.55);\n --shadow-2: 0 4px 12px -2px rgba(0,0,0,.55);\n --shadow-3: 0 12px 28px -8px rgba(0,0,0,.6);\n --shadow-4: 0 24px 48px -16px rgba(0,0,0,.65);\n}\n\n/* === Theme C \u00b7 Bronze Shrine ==================================== */\n[data-theme=\"C\"][data-mode=\"dark\"] {\n --bg-base: hsl(180,14%,7%); --bg-surface: hsl(180,12%,11%);\n --bg-raised: hsl(180,10%,15%);--bg-sunken: hsl(180,18%,5%);\n --fg: hsl(40,18%,90%); --fg-muted: hsl(180,8%,60%); --fg-faint: hsl(180,8%,42%);\n --border: hsl(180,12%,22%); --border-soft: hsl(180,12%,18%);\n --primary: hsl(170,35%,50%); --primary-fg: hsl(180,18%,6%); --primary-soft: hsl(170,30%,18%);\n --achievement: hsl(40,58%,64%); --achievement-soft: hsl(40,30%,18%);\n --danger: hsl(8,70%,50%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,50%,18%);\n --systemic: hsl(220,22%,56%); --systemic-soft: hsl(220,14%,18%);\n --shadow-1: 0 1px 2px rgba(0,0,0,.6);\n --shadow-2: 0 4px 12px -2px rgba(0,0,0,.6);\n --shadow-3: 0 12px 28px -8px rgba(0,0,0,.65);\n --shadow-4: 0 24px 48px -16px rgba(0,0,0,.7);\n}\n[data-theme=\"C\"][data-mode=\"light\"] {\n --bg-base: hsl(180,10%,95%); --bg-surface: hsl(180,8%,92%);\n --bg-raised: hsl(180,6%,88%); --bg-sunken: hsl(180,12%,97%);\n --fg: hsl(200,22%,14%); --fg-muted: hsl(200,10%,38%); --fg-faint: hsl(200,8%,58%);\n --border: hsl(180,12%,80%); --border-soft: hsl(180,12%,86%);\n --primary: hsl(170,42%,34%); --primary-fg: hsl(180,12%,97%); --primary-soft: hsl(170,30%,88%);\n --achievement: hsl(40,64%,38%); --achievement-soft: hsl(40,50%,90%);\n --danger: hsl(8,70%,42%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,60%,92%);\n --systemic: hsl(220,24%,40%); --systemic-soft: hsl(220,22%,90%);\n --shadow-1: 0 1px 2px rgba(20,28,32,.08);\n --shadow-2: 0 4px 12px -2px rgba(20,28,32,.10);\n --shadow-3: 0 12px 28px -8px rgba(20,28,32,.14);\n --shadow-4: 0 24px 48px -16px rgba(20,28,32,.18);\n}\n\n/* === Workspace tints \u2014 constant hues, mode-adaptive ============= */\n[data-mode=\"dark\"] {\n --tint-app-bg: hsl(36,14%,11%); --tint-app-fg: hsl(36,28%,78%);\n --tint-mail-bg: hsl(42,30%,11%); --tint-mail-fg: hsl(42,70%,62%);\n --tint-outbox-bg: hsl(14,38%,11%); --tint-outbox-fg: hsl(14,72%,60%);\n --tint-studio-bg: hsl(8,40%,10%); --tint-studio-fg: hsl(8,72%,60%);\n --tint-agents-bg: hsl(170,26%,10%); --tint-agents-fg: hsl(170,40%,58%);\n --tint-files-bg: hsl(28,14%,11%); --tint-files-fg: hsl(28,30%,60%);\n --tint-sessions-bg: hsl(28,28%,11%); --tint-sessions-fg: hsl(28,60%,62%);\n --tint-settings-bg: hsl(220,14%,11%); --tint-settings-fg: hsl(220,26%,66%);\n}\n[data-mode=\"light\"] {\n --tint-app-bg: hsl(36,22%,92%); --tint-app-fg: hsl(28,30%,22%);\n --tint-mail-bg: hsl(42,60%,92%); --tint-mail-fg: hsl(42,80%,28%);\n --tint-outbox-bg: hsl(14,60%,93%); --tint-outbox-fg: hsl(14,70%,32%);\n --tint-studio-bg: hsl(8,60%,93%); --tint-studio-fg: hsl(8,70%,32%);\n --tint-agents-bg: hsl(170,36%,92%); --tint-agents-fg: hsl(170,50%,24%);\n --tint-files-bg: hsl(36,26%,92%); --tint-files-fg: hsl(28,30%,22%);\n --tint-sessions-bg: hsl(28,50%,92%); --tint-sessions-fg: hsl(14,60%,30%);\n --tint-settings-bg: hsl(220,22%,93%); --tint-settings-fg: hsl(220,30%,24%);\n}\n\n/* Active tint vars (resolved per workspace) */\n[data-workspace=\"app\"] { --tint-bg-active:var(--tint-app-bg); --tint-fg-active:var(--tint-app-fg); }\n[data-workspace=\"mail\"] { --tint-bg-active:var(--tint-mail-bg); --tint-fg-active:var(--tint-mail-fg); }\n[data-workspace=\"outbox\"] { --tint-bg-active:var(--tint-outbox-bg); --tint-fg-active:var(--tint-outbox-fg); }\n[data-workspace=\"studio\"] { --tint-bg-active:var(--tint-studio-bg); --tint-fg-active:var(--tint-studio-fg); }\n[data-workspace=\"agents\"] { --tint-bg-active:var(--tint-agents-bg); --tint-fg-active:var(--tint-agents-fg); }\n[data-workspace=\"files\"] { --tint-bg-active:var(--tint-files-bg); --tint-fg-active:var(--tint-files-fg); }\n[data-workspace=\"sessions\"] { --tint-bg-active:var(--tint-sessions-bg); --tint-fg-active:var(--tint-sessions-fg); }\n[data-workspace=\"settings\"] { --tint-bg-active:var(--tint-settings-bg); --tint-fg-active:var(--tint-settings-fg); }\n";
1
+ // GENERATED by scripts/build-css.mjs from tokens.css. Do not edit.
2
+ // No-build srcdoc pkgs import this and inject it as an inline <style>.
3
+ export default "/**\n * @ikenga/tokens — canonical design tokens for the Ikenga design system.\n *\n * Single source of truth for CSS custom properties used across:\n * - shell (Tauri desktop app)\n * - every UI pkg (Tasks, Studio, Outbound, …)\n *\n * Consumers `@import '@ikenga/tokens/tokens.css'` and inherit the full token\n * surface. Pkgs running inside the shell iframe additionally receive a\n * curated subset via the AppBridge `host-context` handshake — those override\n * these defaults at runtime when the user flips theme/mode in the shell.\n *\n * Convention:\n * :root → mode-agnostic (typography, spacing, radii, shadows)\n * :root[data-mode=\"dark\"] → dark-mode color slots (DEFAULT)\n * :root[data-mode=\"light\"] → light-mode color slots (override)\n *\n * `data-theme` is reserved for theme variants beyond the default Ikenga palette\n * (e.g. seasonal, label-branded). Add `:root[data-theme=\"X\"][data-mode=\"dark\"]`\n * blocks below the defaults — last-match wins.\n */\n\n/* ─── mode-agnostic ───────────────────────────────────────────────────────── */\n:root {\n /* Spacing scale (4px base) */\n --space-1: 4px;\n --space-2: 8px;\n --space-3: 12px;\n --space-4: 16px;\n --space-5: 20px;\n --space-6: 24px;\n --space-8: 32px;\n --space-10: 40px;\n --space-12: 48px;\n --space-16: 64px;\n --space-20: 80px;\n\n /* Radii */\n --radius-xs: 3px;\n --radius-sm: 4px;\n --radius-md: 6px;\n --radius-lg: 10px;\n --radius-xl: 14px;\n --radius-pill: 999px;\n\n /* Typography. --font-sans kept for back-compat; --font-body/-display/-mono are\n the Atelier faces the shell already loads (Inter / Fraunces / JetBrains Mono).\n Type *sizes* stay on the shipped package scale — the shell renders on these;\n the app-kit + panes inherit them via var(). */\n --font-sans: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;\n --font-body: 'Inter', system-ui, -apple-system, sans-serif;\n --font-display: 'Fraunces', ui-serif, Georgia, serif;\n --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;\n --text-micro: 11px;\n --text-caption: 11.5px;\n --text-body-sm: 13px;\n --text-body: 13px;\n --text-body-lg: 16px;\n --text-code: 13px;\n --text-h4: 14px;\n --text-h3: 16px;\n --text-h2: 20px;\n --text-h1: 28px;\n --text-display: 40px;\n --text-display-xl: 56px;\n /* line-heights (leading), paired with the sizes above */\n --lead-micro: 1.4;\n --lead-caption: 1.45;\n --lead-body-sm: 1.5;\n --lead-body: 1.55;\n --lead-body-lg: 1.6;\n --lead-code: 1.55;\n --lead-h3: 1.35;\n --lead-h2: 1.2;\n --lead-h1: 1.15;\n --lead-display: 1.08;\n --lead-display-xl: 1.02;\n\n /* Layout */\n --header-height: 44px;\n --sidebar-width: 240px;\n\n /* Motion — added for the app-kit (the tasks pkg shim previously hardcoded\n --motion-fast / --ease-calm). */\n --motion-fast: 120ms;\n --motion-base: 180ms;\n --motion-slow: 260ms;\n --motion-slower: 360ms;\n --ease-calm: cubic-bezier(0.2, 0.6, 0.2, 1);\n --ease-decisive: cubic-bezier(0.4, 0, 0.2, 1);\n --ease-soft-bounce: cubic-bezier(0.34, 1.32, 0.64, 1);\n\n /* Density (default: comfortable). Chrome heights derive from this; the\n [data-density] blocks below override for compact / spacious. */\n --row-h: 36px;\n --row-pad-y: 8px;\n --gap: var(--space-2);\n --body-size: var(--text-body);\n --body-lead: var(--lead-body);\n --tab-h: 38px;\n --btn-h: 32px;\n --btn-h-sm: 26px;\n --btn-h-lg: 40px;\n --input-h: 32px;\n\n /* Default mode is dark — ensures correct rendering even without\n [data-mode] attribute set on <html>. */\n color-scheme: dark;\n\n /* Ikenga brand accents (mode-agnostic). Used by ADR-011 chat redesign:\n ember = active streaming / hot states; kola-amber = ritual pills,\n tool calls, artifact pills, cost amounts; oxblood = errors;\n verdigris = info / passive systemic. */\n --ember: hsl(14, 78%, 52%);\n --ember-soft: hsl(14, 70%, 60%);\n --kola-amber: hsl(42, 78%, 50%);\n --kola-amber-soft: hsl(42, 60%, 64%);\n --oxblood: hsl(8, 70%, 42%);\n --verdigris: hsl(170, 30%, 38%);\n}\n\n/* ─── density variants (override the comfortable defaults in :root) ───────── */\n[data-density='compact'] {\n --row-h: 28px; --row-pad-y: 5px; --gap: var(--space-1);\n --body-size: var(--text-body-sm); --body-lead: 1.4;\n --tab-h: 32px; --btn-h: 28px; --btn-h-sm: 22px; --btn-h-lg: 34px; --input-h: 28px;\n}\n[data-density='spacious'] {\n --row-h: 44px; --row-pad-y: 11px; --gap: var(--space-3);\n --body-size: var(--text-body-lg); --body-lead: 1.6;\n --tab-h: 44px; --btn-h: 36px; --btn-h-sm: 30px; --btn-h-lg: 44px; --input-h: 36px;\n}\n\n/* ─── dark mode (DEFAULT) ─────────────────────────────────────────────────── */\n:root,\n:root[data-mode='dark'] {\n /* Backgrounds */\n --bg-base: hsl(220, 14%, 8%);\n --bg-surface: hsl(220, 13%, 11%);\n --bg-raised: hsl(220, 12%, 14%);\n --bg-sunken: hsl(220, 14%, 6%);\n\n /* Foregrounds */\n --fg: hsl(0, 0%, 96%);\n --fg-muted: hsl(220, 8%, 58%);\n --fg-subtle: hsl(220, 8%, 42%);\n --fg-faint: var(--fg-subtle);\n\n /* Borders */\n --border: hsl(220, 13%, 20%);\n --border-soft: hsl(220, 13%, 16%);\n --border-strong: hsl(220, 13%, 28%);\n\n /* Brand + semantic */\n --primary: hsl(220, 90%, 60%);\n --primary-fg: hsl(0, 0%, 100%);\n --secondary: hsl(220, 12%, 14%);\n --accent: hsl(280, 70%, 65%);\n --info: hsl(200, 90%, 60%);\n --success: hsl(142, 70%, 50%);\n --warning: hsl(38, 92%, 60%);\n --danger: hsl(0, 72%, 60%);\n --agent: hsl(280, 70%, 65%);\n --agent-soft: color-mix(in srgb, var(--agent) 14%, transparent);\n --live: var(--success);\n --live-soft: color-mix(in srgb, var(--success) 14%, transparent);\n --live-fg: hsl(150, 45%, 10%);\n\n /* Tints (subtle backgrounds for active/hovered states) */\n --tint-bg-active: hsl(220, 90%, 60%, 0.08);\n --tint-fg-active: hsl(220, 90%, 70%);\n\n /* Shadows */\n --shadow-1: 0 1px 1px hsl(0 0% 0% / 0.3);\n --shadow-2: 0 1px 2px hsl(0 0% 0% / 0.4);\n --shadow-3: 0 4px 12px hsl(0 0% 0% / 0.5);\n\n /* MCP UI Apps schema bridge — these are the names the host pushes via\n AppBridge `styles.variables`. Map them to Ikenga semantic slots so a pkg\n that consumes the host context overlay (or one that doesn't) renders the\n same way. */\n --color-background-primary: var(--bg-base);\n --color-background-secondary: var(--bg-surface);\n --color-background-tertiary: var(--bg-raised);\n --color-background-inverse: hsl(0, 0%, 96%);\n --color-background-ghost: transparent;\n --color-background-info: var(--info);\n --color-background-danger: var(--danger);\n --color-background-success: var(--success);\n --color-background-warning: var(--warning);\n --color-background-disabled: hsl(220, 13%, 20%);\n\n --color-text-primary: var(--fg);\n --color-text-secondary: var(--fg-muted);\n --color-text-tertiary: var(--fg-subtle);\n --color-text-inverse: hsl(220, 14%, 8%);\n --color-text-ghost: var(--fg-muted);\n --color-text-info: var(--info);\n --color-text-danger: var(--danger);\n --color-text-success: var(--success);\n --color-text-warning: var(--warning);\n --color-text-disabled: var(--fg-subtle);\n\n --color-border-primary: var(--border);\n --color-border-secondary: var(--border-soft);\n --color-border-tertiary: var(--border-strong);\n --color-border-inverse: hsl(0, 0%, 96%);\n --color-border-ghost: transparent;\n --color-border-info: var(--info);\n --color-border-danger: var(--danger);\n --color-border-success: var(--success);\n --color-border-warning: var(--warning);\n --color-border-disabled: var(--border-soft);\n\n --color-ring-primary: var(--primary);\n --color-ring-secondary: var(--accent);\n --color-ring-inverse: hsl(0, 0%, 96%);\n --color-ring-info: var(--info);\n --color-ring-danger: var(--danger);\n --color-ring-success: var(--success);\n --color-ring-warning: var(--warning);\n\n /* Ikenga hairline + chip-carve (mode-specific). `--rule` is the canonical\n 1px divider between turns in the chat; `--rule-soft` is for grouping\n within a turn; `--chip-carve` is the dim ink used for the ▽▽▽ motif\n and uppercase mono labels. */\n --rule: hsl(28, 14%, 18%);\n --rule-soft: hsl(28, 12%, 14%);\n --chip-carve: hsl(28, 14%, 32%);\n\n /* Code editor syntax palette (dark). Consumed by @ikenga/ui-lib's\n CodeEditor via CodeMirror 6 highlight tags. Tuned for HTML/TSX/CSS\n legibility on top of `--bg-surface`. */\n --syntax-keyword: hsl(280, 70%, 72%);\n --syntax-string: hsl(160, 55%, 60%);\n --syntax-comment: hsl(220, 10%, 50%);\n --syntax-number: hsl(28, 78%, 64%);\n --syntax-atom: hsl(28, 78%, 64%);\n --syntax-regexp: hsl(330, 60%, 64%);\n --syntax-operator: hsl(0, 0%, 86%);\n --syntax-punctuation: hsl(220, 8%, 62%);\n --syntax-variable: hsl(0, 0%, 92%);\n --syntax-function: hsl(200, 80%, 68%);\n --syntax-type: hsl(180, 60%, 64%);\n --syntax-tag: hsl(0, 70%, 66%);\n --syntax-attribute: hsl(42, 80%, 64%);\n --syntax-heading: hsl(0, 0%, 96%);\n --syntax-link: hsl(200, 90%, 62%);\n}\n\n/* ─── light mode ──────────────────────────────────────────────────────────── */\n:root[data-mode='light'] {\n color-scheme: light;\n\n --bg-base: hsl(0, 0%, 98%);\n --bg-surface: hsl(0, 0%, 100%);\n --bg-raised: hsl(220, 14%, 96%);\n --bg-sunken: hsl(220, 14%, 94%);\n\n --fg: hsl(220, 14%, 12%);\n --fg-muted: hsl(220, 10%, 45%);\n --fg-subtle: hsl(220, 8%, 60%);\n --fg-faint: var(--fg-subtle);\n\n --border: hsl(220, 13%, 88%);\n --border-soft: hsl(220, 13%, 93%);\n --border-strong: hsl(220, 13%, 78%);\n\n --primary: hsl(220, 90%, 52%);\n --primary-fg: hsl(0, 0%, 100%);\n --secondary: hsl(220, 14%, 96%);\n --accent: hsl(280, 65%, 50%);\n --info: hsl(200, 90%, 45%);\n --success: hsl(142, 65%, 38%);\n --warning: hsl(38, 88%, 48%);\n --danger: hsl(0, 65%, 48%);\n --agent: hsl(280, 65%, 50%);\n --agent-soft: color-mix(in srgb, var(--agent) 14%, transparent);\n --live: var(--success);\n --live-soft: color-mix(in srgb, var(--success) 14%, transparent);\n --live-fg: hsl(150, 24%, 97%);\n\n --tint-bg-active: hsl(220, 90%, 52%, 0.10);\n --tint-fg-active: hsl(220, 90%, 42%);\n\n --shadow-1: 0 1px 1px hsl(220 14% 50% / 0.06);\n --shadow-2: 0 1px 2px hsl(220 14% 50% / 0.08);\n --shadow-3: 0 4px 12px hsl(220 14% 50% / 0.10);\n\n --color-background-primary: var(--bg-base);\n --color-background-secondary: var(--bg-surface);\n --color-background-tertiary: var(--bg-raised);\n --color-background-inverse: hsl(220, 14%, 12%);\n --color-text-primary: var(--fg);\n --color-text-secondary: var(--fg-muted);\n --color-text-tertiary: var(--fg-subtle);\n --color-text-inverse: hsl(0, 0%, 98%);\n --color-border-primary: var(--border);\n --color-border-secondary: var(--border-soft);\n --color-border-tertiary: var(--border-strong);\n\n /* Light-mode hairline + chip-carve. See dark-mode block for semantics. */\n --rule: hsl(36, 14%, 84%);\n --rule-soft: hsl(36, 14%, 90%);\n --chip-carve: hsl(28, 14%, 62%);\n\n /* Code editor syntax palette (light). See dark block for semantics. */\n --syntax-keyword: hsl(280, 70%, 38%);\n --syntax-string: hsl(160, 55%, 30%);\n --syntax-comment: hsl(220, 10%, 48%);\n --syntax-number: hsl(28, 78%, 38%);\n --syntax-atom: hsl(28, 78%, 38%);\n --syntax-regexp: hsl(330, 60%, 40%);\n --syntax-operator: hsl(220, 14%, 18%);\n --syntax-punctuation: hsl(220, 10%, 42%);\n --syntax-variable: hsl(220, 14%, 14%);\n --syntax-function: hsl(220, 90%, 40%);\n --syntax-type: hsl(180, 60%, 30%);\n --syntax-tag: hsl(0, 70%, 42%);\n --syntax-attribute: hsl(42, 90%, 36%);\n --syntax-heading: hsl(220, 14%, 12%);\n --syntax-link: hsl(200, 90%, 40%);\n}\n/* === Theme A · Dusk Wood (canonical default) ==================== */\n[data-theme=\"A\"][data-mode=\"dark\"] {\n --bg-base: hsl(28,18%,4%); --bg-surface: hsl(28,14%,7%);\n --bg-raised: hsl(28,11%,11%); --bg-sunken: hsl(28,22%,2.5%);\n --fg: hsl(36,28%,90%); --fg-muted: hsl(32,11%,56%); --fg-faint: hsl(28,9%,36%);\n --border: hsl(28,14%,15%); --border-soft: hsl(28,14%,11%);\n --primary: hsl(20,50%,34%); --primary-fg: hsl(36,30%,92%); --primary-soft: hsl(20,40%,14%);\n --achievement: hsl(42,78%,54%); --achievement-soft: hsl(42,48%,18%);\n --danger: hsl(8,68%,46%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,50%,16%);\n --systemic: hsl(170,28%,34%); --systemic-soft: hsl(170,22%,16%);\n --agent: hsl(265,52%,64%); --agent-soft: hsl(265,32%,20%);\n --live: hsl(150,48%,52%); --live-soft: hsl(150,30%,18%); --live-fg: hsl(150,50%,9%);\n --shadow-1: 0 1px 2px rgba(0,0,0,.55), 0 0 0 1px rgba(0,0,0,.25);\n --shadow-2: 0 4px 12px -2px rgba(0,0,0,.55);\n --shadow-3: 0 12px 28px -8px rgba(0,0,0,.6);\n --shadow-4: 0 24px 48px -16px rgba(0,0,0,.65);\n}\n[data-theme=\"A\"][data-mode=\"light\"] {\n --bg-base: hsl(36,22%,96%); --bg-surface: hsl(36,18%,93%);\n --bg-raised: hsl(36,14%,89%); --bg-sunken: hsl(36,26%,98%);\n --fg: hsl(28,30%,14%); --fg-muted: hsl(28,14%,38%); --fg-faint: hsl(28,12%,56%);\n --border: hsl(32,16%,78%); --border-soft: hsl(32,16%,84%);\n --primary: hsl(20,50%,34%); --primary-fg: hsl(36,26%,98%); --primary-soft: hsl(20,50%,90%);\n --achievement: hsl(42,78%,42%); --achievement-soft: hsl(42,60%,90%);\n --danger: hsl(8,68%,42%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,60%,92%);\n --systemic: hsl(170,36%,32%); --systemic-soft: hsl(170,30%,90%);\n --agent: hsl(265,55%,44%); --agent-soft: hsl(265,40%,92%);\n --live: hsl(150,55%,32%); --live-soft: hsl(150,40%,92%); --live-fg: hsl(0,0%,100%);\n --shadow-1: 0 1px 2px rgba(28,18,8,.08);\n --shadow-2: 0 4px 12px -2px rgba(28,18,8,.10);\n --shadow-3: 0 12px 28px -8px rgba(28,18,8,.14);\n --shadow-4: 0 24px 48px -16px rgba(28,18,8,.18);\n}\n\n/* === Theme B · Kola Daylight ==================================== */\n[data-theme=\"B\"][data-mode=\"light\"] {\n --bg-base: hsl(36,28%,96%); --bg-surface: hsl(36,22%,94%);\n --bg-raised: hsl(36,18%,90%); --bg-sunken: hsl(36,32%,98%);\n --fg: hsl(28,30%,12%); --fg-muted: hsl(28,14%,38%); --fg-faint: hsl(28,12%,56%);\n --border: hsl(32,18%,80%); --border-soft: hsl(32,18%,86%);\n --primary: hsl(42,82%,46%); --primary-fg: hsl(28,30%,8%); --primary-soft: hsl(42,60%,88%);\n --achievement: hsl(14,72%,46%); --achievement-soft: hsl(14,60%,90%);\n --danger: hsl(8,68%,42%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,60%,92%);\n --systemic: hsl(170,36%,32%); --systemic-soft: hsl(170,30%,90%);\n --shadow-1: 0 1px 2px rgba(28,18,8,.08);\n --shadow-2: 0 4px 12px -2px rgba(28,18,8,.10);\n --shadow-3: 0 12px 28px -8px rgba(28,18,8,.14);\n --shadow-4: 0 24px 48px -16px rgba(28,18,8,.18);\n}\n[data-theme=\"B\"][data-mode=\"dark\"] {\n --bg-base: hsl(36,12%,8%); --bg-surface: hsl(36,10%,12%);\n --bg-raised: hsl(36,8%,16%); --bg-sunken: hsl(36,16%,6%);\n --fg: hsl(40,28%,92%); --fg-muted: hsl(36,10%,62%); --fg-faint: hsl(36,8%,42%);\n --border: hsl(36,12%,22%); --border-soft: hsl(36,12%,18%);\n --primary: hsl(42,84%,60%); --primary-fg: hsl(36,30%,8%); --primary-soft: hsl(42,60%,18%);\n --achievement: hsl(14,76%,56%); --achievement-soft: hsl(14,50%,18%);\n --danger: hsl(8,70%,52%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,50%,18%);\n --systemic: hsl(170,32%,46%); --systemic-soft: hsl(170,25%,18%);\n --shadow-1: 0 1px 2px rgba(0,0,0,.55);\n --shadow-2: 0 4px 12px -2px rgba(0,0,0,.55);\n --shadow-3: 0 12px 28px -8px rgba(0,0,0,.6);\n --shadow-4: 0 24px 48px -16px rgba(0,0,0,.65);\n}\n\n/* === Theme C · Bronze Shrine ==================================== */\n[data-theme=\"C\"][data-mode=\"dark\"] {\n --bg-base: hsl(180,14%,7%); --bg-surface: hsl(180,12%,11%);\n --bg-raised: hsl(180,10%,15%);--bg-sunken: hsl(180,18%,5%);\n --fg: hsl(40,18%,90%); --fg-muted: hsl(180,8%,60%); --fg-faint: hsl(180,8%,42%);\n --border: hsl(180,12%,22%); --border-soft: hsl(180,12%,18%);\n --primary: hsl(170,35%,50%); --primary-fg: hsl(180,18%,6%); --primary-soft: hsl(170,30%,18%);\n --achievement: hsl(40,58%,64%); --achievement-soft: hsl(40,30%,18%);\n --danger: hsl(8,70%,50%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,50%,18%);\n --systemic: hsl(220,22%,56%); --systemic-soft: hsl(220,14%,18%);\n --shadow-1: 0 1px 2px rgba(0,0,0,.6);\n --shadow-2: 0 4px 12px -2px rgba(0,0,0,.6);\n --shadow-3: 0 12px 28px -8px rgba(0,0,0,.65);\n --shadow-4: 0 24px 48px -16px rgba(0,0,0,.7);\n}\n[data-theme=\"C\"][data-mode=\"light\"] {\n --bg-base: hsl(180,10%,95%); --bg-surface: hsl(180,8%,92%);\n --bg-raised: hsl(180,6%,88%); --bg-sunken: hsl(180,12%,97%);\n --fg: hsl(200,22%,14%); --fg-muted: hsl(200,10%,38%); --fg-faint: hsl(200,8%,58%);\n --border: hsl(180,12%,80%); --border-soft: hsl(180,12%,86%);\n --primary: hsl(170,42%,34%); --primary-fg: hsl(180,12%,97%); --primary-soft: hsl(170,30%,88%);\n --achievement: hsl(40,64%,38%); --achievement-soft: hsl(40,50%,90%);\n --danger: hsl(8,70%,42%); --danger-fg: hsl(0,0%,98%); --danger-soft: hsl(8,60%,92%);\n --systemic: hsl(220,24%,40%); --systemic-soft: hsl(220,22%,90%);\n --shadow-1: 0 1px 2px rgba(20,28,32,.08);\n --shadow-2: 0 4px 12px -2px rgba(20,28,32,.10);\n --shadow-3: 0 12px 28px -8px rgba(20,28,32,.14);\n --shadow-4: 0 24px 48px -16px rgba(20,28,32,.18);\n}\n\n/* === Workspace tints — constant hues, mode-adaptive ============= */\n[data-mode=\"dark\"] {\n --tint-app-bg: hsl(36,14%,11%); --tint-app-fg: hsl(36,28%,78%);\n --tint-mail-bg: hsl(42,30%,11%); --tint-mail-fg: hsl(42,70%,62%);\n --tint-outbox-bg: hsl(14,38%,11%); --tint-outbox-fg: hsl(14,72%,60%);\n --tint-studio-bg: hsl(8,40%,10%); --tint-studio-fg: hsl(8,72%,60%);\n --tint-agents-bg: hsl(170,26%,10%); --tint-agents-fg: hsl(170,40%,58%);\n --tint-files-bg: hsl(28,14%,11%); --tint-files-fg: hsl(28,30%,60%);\n --tint-sessions-bg: hsl(28,28%,11%); --tint-sessions-fg: hsl(28,60%,62%);\n --tint-settings-bg: hsl(220,14%,11%); --tint-settings-fg: hsl(220,26%,66%);\n}\n[data-mode=\"light\"] {\n --tint-app-bg: hsl(36,22%,92%); --tint-app-fg: hsl(28,30%,22%);\n --tint-mail-bg: hsl(42,60%,92%); --tint-mail-fg: hsl(42,80%,28%);\n --tint-outbox-bg: hsl(14,60%,93%); --tint-outbox-fg: hsl(14,70%,32%);\n --tint-studio-bg: hsl(8,60%,93%); --tint-studio-fg: hsl(8,70%,32%);\n --tint-agents-bg: hsl(170,36%,92%); --tint-agents-fg: hsl(170,50%,24%);\n --tint-files-bg: hsl(36,26%,92%); --tint-files-fg: hsl(28,30%,22%);\n --tint-sessions-bg: hsl(28,50%,92%); --tint-sessions-fg: hsl(14,60%,30%);\n --tint-settings-bg: hsl(220,22%,93%); --tint-settings-fg: hsl(220,30%,24%);\n}\n\n/* Active tint vars (resolved per workspace) */\n[data-workspace=\"app\"] { --tint-bg-active:var(--tint-app-bg); --tint-fg-active:var(--tint-app-fg); }\n[data-workspace=\"mail\"] { --tint-bg-active:var(--tint-mail-bg); --tint-fg-active:var(--tint-mail-fg); }\n[data-workspace=\"outbox\"] { --tint-bg-active:var(--tint-outbox-bg); --tint-fg-active:var(--tint-outbox-fg); }\n[data-workspace=\"studio\"] { --tint-bg-active:var(--tint-studio-bg); --tint-fg-active:var(--tint-studio-fg); }\n[data-workspace=\"agents\"] { --tint-bg-active:var(--tint-agents-bg); --tint-fg-active:var(--tint-agents-fg); }\n[data-workspace=\"files\"] { --tint-bg-active:var(--tint-files-bg); --tint-fg-active:var(--tint-files-fg); }\n[data-workspace=\"sessions\"] { --tint-bg-active:var(--tint-sessions-bg); --tint-fg-active:var(--tint-sessions-fg); }\n[data-workspace=\"settings\"] { --tint-bg-active:var(--tint-settings-bg); --tint-fg-active:var(--tint-settings-fg); }\n";
package/dist/lib/ui.js CHANGED
@@ -57,6 +57,11 @@ const ICONS = {
57
57
  mail: 'M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zM22 6l-10 7L2 6',
58
58
  terminal: 'M4 17l6-6-6-6M12 19h8',
59
59
  'git-branch': 'M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM18 9a9 9 0 0 1-9 9',
60
+ // ViewTabs glyphs for Sweeper + Done. `broom` mirrors the design's SWEEP
61
+ // glyph (a broom strokes + handle); `check-check` is the lucide name for
62
+ // the "double check" used for completed items.
63
+ broom: 'M9.8 12.2 5 17l3 3 4.8-4.8M14 8l-3.5 3.5 4 4L18 12l-4-4z M14 8l5-5M19 3l2 2',
64
+ 'check-check': 'M18 6 7 17l-5-5M22 10l-7.5 7.5L13 16',
60
65
  };
61
66
 
62
67
  // Class-name joiner — replaces clsx + tailwind-merge. With Tailwind gone there