@exellix/jobs-ui 2.0.2 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @exellix/jobs-ui
2
2
 
3
- **Jobs dashboard** — React operator SPA for the Exellix job queue. Queue overview, run detail, record-centric views, Source→Records workflow, and work-factory wizards (continuous work, batches, on-demand).
3
+ **Jobs dashboard** — React operator SPA for the Exellix job factory. Monitor queue health, browse Memorix information and graph outputs, inspect the run journal, configure ongoing work and on-demand batches, and analyze pipeline performance.
4
4
 
5
5
  | Package | Role |
6
6
  |---------|------|
@@ -9,10 +9,39 @@
9
9
  | **`@exellix/jobs-ui`** (this) | Jobs **dashboard** — React SPA only |
10
10
  | [`@exellix/jobs-db`](../jobs-db/README.md) | Jobs **data tier** — Mongo persistence |
11
11
 
12
- > A **JobRun** is one graph run on one input. See [`temp/jobs/`](../temp/jobs/README.md) for the design.
12
+ > A **factory run** is one graph execution on one information item. Continuous work and on-demand flows both enqueue runs into the same journal. See [`temp/jobs/`](../temp/jobs/README.md) for the design.
13
13
 
14
14
  > **Migration from 1.x:** `@exellix/jobs-ui@1.x` bundled the HTTP API and dashboard in one package. **2.x is dashboard-only** — use [`@exellix/jobs-api`](../jobs-api/README.md) for the REST server and programmatic queries.
15
15
 
16
+ ## Core concepts
17
+
18
+ ### Information items (not just “database records”)
19
+
20
+ The UI speaks in operator terms — **Information** and **item** — but the API and Memorix layer still use **record** in paths and types (`core-records`, `recordId`, etc.). Treat those as the same idea: **one processable unit of information** that a pipeline can run on.
21
+
22
+ That unit is **not** limited to a classic entity row. What it *is* depends entirely on how the object type is modeled in Schema UI and stored in Memorix. Examples:
23
+
24
+ | What you might process | Typical Memorix shape |
25
+ |------------------------|------------------------|
26
+ | A business object (asset, ticket, person) | Core record on an **entity** |
27
+ | A document, page, or media asset | **Content** in a scoped content type |
28
+ | One chat turn | A row in a messages / content collection |
29
+ | An entire conversation | The **core** record for a chat entity (with related message content assembled at run time) |
30
+ | A time-stamped occurrence | An **event** record |
31
+ | A knowledge article or embedding source | A **knowledge** record |
32
+ | Graph output from a prior run | A row in a **processing-output** collection (shown under Outputs) |
33
+
34
+ So “record” here means **whatever your schema defines as the input identity for a run** — not necessarily a single Mongo document in `core`, and not necessarily one physical row if you merge related content types when queuing.
35
+
36
+ For the job factory:
37
+
38
+ - **One factory run = one item** — identified by `entity` + `collection` + `id` (plus optional related content pulled in as context).
39
+ - **Narratives** tag items for matching (ongoing work and batch selection) — e.g. “needs summary”, “high priority”.
40
+ - **Processing stamps** track which pipelines have touched an item and whether they succeeded.
41
+ - **Assembly** (on-demand single) lets you choose which content types and fields are merged into graph input without changing which item the run is *for*.
42
+
43
+ Browse and inspect items under **Information** (inputs) and **Outputs** (saved pipeline results). The journal always refers back to the item that was processed, whatever shape it had.
44
+
16
45
  ## Install
17
46
 
18
47
  ```bash
@@ -23,15 +52,35 @@ The dashboard requires a running `@exellix/jobs-api` instance (or any host servi
23
52
 
24
53
  ## Quick start
25
54
 
55
+ **Recommended** — one command starts API, queue worker, and UI (needs `MONGO_URI` in `graph-engine/.env`):
56
+
57
+ ```bash
58
+ npm run dev # from jobs-ui — full stack via scripts/dev-jobs.mjs
59
+ # or from monorepo root:
60
+ npm run dev:jobs
61
+ ```
62
+
63
+ | URL | Service |
64
+ |-----|---------|
65
+ | http://localhost:5190 | Dashboard (Vite, proxies `/api`) |
66
+ | http://localhost:3099 | jobs-api REST server |
67
+
68
+ **Split terminals** (UI-only with HMR against an API you start separately):
69
+
26
70
  ```bash
27
- # terminal 1 — API backend (needs MONGO_URI)
71
+ # terminal 1 — API backend
28
72
  cd ../jobs-api && npm run serve
29
73
 
30
- # terminal 2 — UI with HMR
31
- npm run dev # Vite on :5190, proxies /api → http://localhost:3099
74
+ # terminal 2 — UI only
75
+ npm run dev:ui # Vite on :5190, proxies /api → http://localhost:3099
32
76
  ```
33
77
 
34
- Set `VITE_API_PROXY` to point at a remote API during dev. Set `VITE_DEV_PORT` to change the dev server port.
78
+ ### Dev configuration
79
+
80
+ | Variable | Default | Effect |
81
+ |----------|---------|--------|
82
+ | `VITE_API_PROXY` | `http://localhost:<PORT>` | API target for the Vite `/api` proxy (`PORT` from `jobs-api/.env`, default 3099) |
83
+ | `VITE_DEV_PORT` | `5190` | Vite dev server port |
35
84
 
36
85
  ### Combined deploy (single port)
37
86
 
@@ -42,32 +91,214 @@ npm run build
42
91
  cd ../jobs-api && JOBS_UI_STATIC_DIR=../jobs-ui/dist npm run serve
43
92
  ```
44
93
 
45
- ## Browser routes
94
+ When the API sets `JOBS_UI_TOKEN`, the SPA must send `Authorization: Bearer <token>` on `/api/*` requests (configure at the reverse proxy or API layer).
95
+
96
+ ## Architecture
97
+
98
+ - **React 19** SPA with **React Router** and **TanStack Query** for data fetching and cache invalidation.
99
+ - All data flows through `web/src/api/real.ts` → `/api/*` on the jobs-api host.
100
+ - **Agent scope** — the top-bar `AgentScopeSelect` (`@x12i/memorix-agents`) filters entities, ongoing work, information lists, and journal views to a single Memorix agent when selected. Persisted in `localStorage` under `exellix-memorix-ui.selected-agent`.
101
+ - **Queue manager** — compact pause/resume control in the top bar; full card on Settings. Polls queue settings every 10s.
102
+ - **Infinite scroll** — Information browse and Journal list load pages on demand via `useCoreRecordsInfinite` / `useFactoryRunsInfinite`.
103
+
104
+ ## Navigation
105
+
106
+ | Nav item | Route(s) | Purpose |
107
+ |----------|----------|---------|
108
+ | Overview | `/` | Factory health, status counts, throughput chart, recent failed/running/pending runs |
109
+ | Work | `/work`, `/work/new`, `/work/:id` | Ongoing (continuous) work definitions |
110
+ | On-Demand | `/on-demand`, `/on-demand/single`, `/on-demand/batch`, `/on-demand/batch/:id` | Ad-hoc single-item and batch runs |
111
+ | Information | `/information`, `/information/:recordId` | Browse Memorix information items (any schema-defined processable unit) |
112
+ | Outputs | `/outputs`, `/outputs/:recordId` | Browse graph output collections and saved results |
113
+ | Journal | `/journal`, `/journal/:id` | Factory run list and per-run inspection |
114
+ | Pipeline analytics | `/pipelines`, `/pipelines/:graphId`, `/pipelines/entity/:entityName` | Aggregated performance by pipeline or entity |
115
+ | Settings | `/settings` | Queue manager, concurrency, admission interval |
116
+ | Item timeline (legacy) | `/items/:itemId` | Multi-run DAG timeline for a single item ID |
117
+
118
+ ### Legacy redirects
119
+
120
+ Older bookmarks still resolve:
121
+
122
+ | Old path | Redirects to |
123
+ |----------|--------------|
124
+ | `/records`, `/records/:id`, `/sources` | `/information` |
125
+ | `/runs`, `/runs/:id` | `/journal` |
126
+ | `/job-defs`, `/job-defs/:id` | `/work` |
127
+ | `/jobs/new` | `/on-demand` |
128
+
129
+ ## Features by area
130
+
131
+ ### Overview (`/`)
132
+
133
+ - Live status cards for all run states: blocked, pending, running, done, failed, cancelled — click a card to open Journal filtered by that status.
134
+ - Filters: source type (continuous / on-demand single / on-demand batch), ongoing work, entity.
135
+ - 24-hour throughput chart.
136
+ - Preview columns: recent failed, currently running, oldest pending (with inline cancel for pending/blocked).
137
+ - Subtitle shows job manager state (running/paused), active slot usage, and selected agent scope.
138
+
139
+ ### Ongoing work (`/work`)
140
+
141
+ Continuous work definitions poll Memorix on a schedule, match items by narratives and processing rules, and enqueue factory runs automatically.
142
+
143
+ **List** — name, status (active/inactive), entity, narratives, reprocessing mode, graph, re-scan interval, last scan, jobs created, last evaluation result. Actions: evaluate now, activate/deactivate.
144
+
145
+ **Create wizard** (`/work/new`) — six steps:
146
+
147
+ 1. Basic info — name, description, entity
148
+ 2. Narratives — select information tags on the entity
149
+ 3. Prerequisites — reprocessing TTL/skip, exclude in-flight, required graphs, cross-entity prerequisites
150
+ 4. Graph — pipeline chooser with optional persistency override
151
+ 5. Execution policy — re-scan interval (5 min – 24 h), priority
152
+ 6. Review — create inactive or create and activate
153
+
154
+ **Detail** (`/work/:id`) — tabs:
155
+
156
+ - **Overview** — configuration, schedule, jobs created, estimated matching
157
+ - **Evaluations** — history of each scan cycle (matched, created, excluded)
158
+ - **Matching Information** — live preview of items that would match current rules
159
+ - **Runs** — infinite-scroll journal filtered to this work definition
160
+ - **Settings** — edit name, narratives, processing, graph, policy, persistency; exclusion panel for last evaluation
161
+
162
+ ### On-Demand (`/on-demand`)
46
163
 
47
- | Route | Page |
48
- |-------|------|
49
- | `/` | Queue Overview |
50
- | `/runs` | Runs list |
51
- | `/runs/:id` | Run detail |
52
- | `/sources` | Source picker |
53
- | `/records` | Records list |
54
- | `/records/:recordId` | Record detail |
55
- | `/items/:itemId` | Item timeline + DAG |
56
- | `/jobs/new` | Create / enqueue job |
57
- | `/job-defs` | Job definition list |
58
- | `/job-defs/:id` | Job definition detail |
59
- | `/settings` | App-wide queue execution settings |
164
+ **Hub** choose single item or batch mode.
60
165
 
61
- Work-factory routes: `/work`, `/work/:id`, `/batches/:id`, on-demand flows see [`jobs-api` HTTP docs](../jobs-api/README.md).
166
+ **Single item** (`/on-demand/single`)seven-step wizard:
167
+
168
+ 1. Choose item — entity, collection, narratives, pick a specific item or a random sample
169
+ 2. Context — optional related records (ContentTypeAssembler)
170
+ 3. Choose graph — entity-compatible pipelines from Catalox
171
+ 4. Result writeback — simulation, graph default, same-entity inferences, or custom persistency
172
+ 5. Properties — assembly selection (which content types/fields feed the graph)
173
+ 6. Review & run — priority, summary
174
+ 7. Done — action result with link to journal entry
175
+
176
+ Supports deep-link `?entity=` from Information detail.
177
+
178
+ **Batch** (`/on-demand/batch`) — nine-step wizard (batch selection, then the same tail as single-item):
179
+
180
+ 1. Entity — object type and data sources
181
+ 2. Narratives — filter which items are included
182
+ 3. Processing — reprocessing, exclude in-flight, prerequisites
183
+ 4. Choose graph — pipeline to run
184
+ 5. Result writeback — simulation, graph default, inferences, or custom destination
185
+ 6. Context (optional) — linked data per item
186
+ 7. Properties — assembly selection
187
+ 8. Review & queue — matching preview, writeback summary, batch name, priority
188
+ 9. Queued — batch created; link to batch detail
189
+
190
+ **Batch detail** (`/on-demand/batch/:id`) — status counts, selection summary, excluded items panel, infinite-scroll run list.
191
+
192
+ ### Information (`/information`)
193
+
194
+ Browse Memorix items for an entity — see [Information items](#information-items-not-just-database-records) above. The default view is the entity’s **core** collection, but an “item” may represent a full object, a content slice, a message, a chat, or any other shape your schema defines.
195
+
196
+ - Filters: entity, collection (core and related), narratives (chip multi-select), processed-by graph, processing status (succeeded / failed / running / queued / not-processed / unknown).
197
+ - Infinite-scroll table with dynamic scalar columns from the first row.
198
+ - Actions: run on-demand for entity, create batch from current filter.
199
+ - Row click → item detail.
200
+
201
+ **Item detail** (`/information/:recordId?entity=&collection=`) — tabs:
202
+
203
+ - **Core** — id, entity, label, scalar fields, timestamps
204
+ - **Narratives** — assigned tags with provenance
205
+ - **Processing** — per-graph processing stamps and status
206
+ - **Snapshots** — Memorix snapshot history
207
+ - **Journal** — factory runs for this item (infinite scroll)
208
+
209
+ Shortcut: **Run on-demand** pre-fills the single-item wizard.
210
+
211
+ ### Outputs (`/outputs`)
212
+
213
+ Same browse UI as Information, scoped to `processing-output` collections.
214
+
215
+ - Filter by entity and output collection.
216
+ - **Clear collection** — typed confirmation (`{entity}-{collection}`) deletes all items in that output collection and clears linked stamps.
217
+ - **Item detail** — Output tab (full JSON document), Journal tab; delete a single saved result.
218
+
219
+ ### Journal (`/journal`)
220
+
221
+ Factory run list with infinite scroll.
222
+
223
+ - Scope: total / today / this week / this month.
224
+ - Filters: status, source type, ongoing work, batch, graph, entity, record ID.
225
+ - Bulk cancel for pending/blocked runs (multi-select).
226
+ - Status count chips from API.
227
+
228
+ **Run detail** (`/journal/:id`) — tabs:
229
+
230
+ - **Overview** — summary, source link (work or batch), processing result card, queue admission state, stale-running warning
231
+ - **Console** — live event stream while running (auto-refresh 1.5s)
232
+ - **Pipeline** — execution diagram and performance panel (duration, tokens, cost per node)
233
+ - **Input & Output** — assembled input, graph result, Memorix writeback (`RunIoPanel`)
234
+ - **Details** — raw metadata, assembly selection, related records, error trace
235
+
236
+ Actions: **Re-run** (new journal entry), **Execute now** (inline worker), **Run next when slot available**, **Retry same entry**, **Cancel**.
237
+
238
+ ### Pipeline analytics (`/pipelines`)
239
+
240
+ Two modes (tab switcher):
241
+
242
+ - **By pipeline** — pick a graph; see aggregate runs, success rate, duration/token/cost stats per node and sub-step; execution diagram; performance guide.
243
+ - **By entity** — roll up all graphs for an entity.
244
+
245
+ Drill-down routes: `/pipelines/:graphId`, `/pipelines/entity/:entityName`.
246
+
247
+ Links from run detail and journal rows open the matching pipeline view.
248
+
249
+ ### Settings (`/settings`)
250
+
251
+ - **Job manager** card — pause/resume with running/pending/held counts.
252
+ - **Queue execution** — max concurrent jobs, admission check interval (15s – 2 min). Saved via `PUT /api/settings`.
253
+
254
+ ### Global controls (top bar)
255
+
256
+ - **Queue manager toggle** — pause/resume without leaving the current page.
257
+ - **Agent scope** — filter multi-tenant Memorix agents; affects entity lists, work, information, journal, and pipeline entity mode.
258
+ - **Runtime badge** — Mongo database and host from `GET /api/config`.
259
+
260
+ ## Shared UI building blocks
261
+
262
+ | Component | Used for |
263
+ |-----------|----------|
264
+ | `Wizard` / `WizardSteps` | Multi-step create flows (work, on-demand) |
265
+ | `GraphChooser` | Entity-compatible pipeline picker |
266
+ | `NarrativeChecklist` | Narrative multi-select |
267
+ | `CollectionSourcePicker` | Core vs auxiliary collections |
268
+ | `MatchingPreview` | Count/sample of items matching selection rules |
269
+ | `PrerequisitesEditor` | Reprocessing and cross-graph prerequisites |
270
+ | `PersistencyOverrideEditor` / `ResultWritebackEditor` | Where graph results are saved |
271
+ | `ContentTypeAssembler` | Related-record context for single runs |
272
+ | `PipelineExecutionDiagram` / `PipelinePerformancePanel` | Run and aggregate analytics |
273
+ | `ExclusionPanel` | Why items were skipped in evaluations/batches |
274
+ | `InfiniteScrollFooter` | Paginated list footers |
275
+ | `LiveConsole` | Streaming run events |
276
+ | `DagView` | Item-level multi-run dependency graph (`/items/:itemId`) |
62
277
 
63
278
  ## Scripts
64
279
 
65
280
  ```bash
66
281
  npm run build # vite build → dist/
67
- npm run dev # Vite dev server + API proxy
68
- npm test # build smoke test + graph-picker unit tests
282
+ npm run dev # API + queue worker + UI (full local stack)
283
+ npm run dev:ui # Vite only requires jobs-api on :3099
284
+ npm run dev:all # same as npm run dev
285
+ npm test # build smoke test, graph-picker + pipeline-performance unit tests
286
+ npm run test:watch # vitest watch mode
69
287
  ```
70
288
 
289
+ ## API contract
290
+
291
+ The UI expects the full jobs-api surface documented in [`jobs-api`](../jobs-api/README.md). Key groups used by the dashboard:
292
+
293
+ - **Health / config** — `/api/health`, `/api/config`
294
+ - **Queue settings** — `GET|PUT /api/settings`, `POST /api/queue/push`
295
+ - **Factory runs** — list, detail, execute, retry, cancel, queue-next, activities
296
+ - **Work factory** — work CRUD, evaluate, batches, on-demand single/batch
297
+ - **Memorix records** — entities, narratives, core-records, clear/delete, processing stamps
298
+ - **Selection** — matching preview, assembler properties/preview
299
+ - **Stats** — throughput, stuck (overview/journal helpers)
300
+ - **Agents proxy** — `/api/agents/*` for `AgentScopeSelect`
301
+
71
302
  ## License
72
303
 
73
304
  exellix-license
@@ -0,0 +1 @@
1
+ .memorix-agents-scope{display:flex;align-items:center;gap:6px;padding:3px 6px 3px 8px;border-radius:7px;border:1px solid var(--memorix-agents-border, #252a3d);background:var(--memorix-agents-surface-raised, #1c2030)}.memorix-agents-scope-label{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--memorix-agents-text-muted, #8892a4)}.memorix-agents-scope-select{border:none;background:transparent;color:var(--memorix-agents-text, #e2e8f0);font-family:var(--memorix-agents-mono, monospace);font-size:12px;padding:2px 18px 2px 4px;max-width:220px;cursor:pointer;outline:none;-moz-appearance:auto;appearance:auto;-webkit-appearance:menulist}.memorix-agents-scope-control{position:relative;display:flex;align-items:center}.memorix-agents-scope-chevron{position:absolute;right:2px;pointer-events:none;font-size:10px;color:var(--memorix-agents-text-muted, #8892a4);line-height:1}.memorix-agents-scope-clear{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;border:none;border-radius:99px;background:transparent;color:var(--memorix-agents-text-muted, #8892a4);font-size:14px;line-height:1;cursor:pointer}.memorix-agents-scope-clear:hover{color:var(--memorix-agents-text, #e2e8f0);background:#ffffff0f}.memorix-agents-scope-select.scoped{color:var(--memorix-agents-accent, #7b93ff);font-weight:600}.memorix-agents-scope.scoped{border-color:var(--memorix-agents-accent-border, rgba(123, 147, 255, .35));background:var(--memorix-agents-accent-subtle, rgba(123, 147, 255, .08))}.memorix-agents-manager,.memorix-agents-bindings{color:var(--memorix-agents-text, #e2e8f0);font-size:14px}.memorix-agents-form-card{background:linear-gradient(180deg,rgba(123,147,255,.1) 0%,rgba(123,147,255,.03) 42%,var(--memorix-agents-surface-raised, #1c2030) 100%);border:1px solid var(--memorix-agents-accent-border, rgba(123, 147, 255, .45));border-left:4px solid var(--memorix-agents-accent, #7b93ff);border-radius:14px;padding:24px;margin-bottom:16px;box-shadow:0 8px 32px #00000059,inset 0 1px #ffffff0a}.memorix-agents-form-header{margin-bottom:20px;padding-bottom:16px;border-bottom:1px solid rgba(123,147,255,.18)}.memorix-agents-form-title{font-size:20px;font-weight:700;letter-spacing:-.02em;color:var(--memorix-agents-text, #f1f5f9);margin:0 0 6px;text-transform:none}.memorix-agents-form-subtitle{margin:0;font-size:13px;line-height:1.55;color:var(--memorix-agents-text-muted, #a8b4c8);max-width:62ch}.memorix-agents-section-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}.memorix-agents-section-header .memorix-agents-section-title{margin:0}.memorix-agents-link-btn{border:none;padding:0;background:none;color:var(--memorix-agents-accent, #7b93ff);font:inherit;cursor:pointer;text-decoration:underline;text-underline-offset:2px}.memorix-agents-link-btn:hover{color:var(--memorix-agents-text, #e2e8f0)}.memorix-agents-section-title{font-size:15px;font-weight:700;color:var(--memorix-agents-text, #e2e8f0);margin:0 0 12px;letter-spacing:-.01em}.memorix-agents-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px 20px;margin-bottom:18px}.memorix-agents-form-full{grid-column:1 / -1}.memorix-agents-field{display:flex;flex-direction:column;gap:8px}.memorix-agents-field-label{font-size:13px;font-weight:700;color:var(--memorix-agents-text, #f1f5f9);letter-spacing:.01em}.memorix-agents-field-label-required:after{content:" *";color:#fca5a5;font-weight:700}.memorix-agents-field-hint{font-size:12px;color:var(--memorix-agents-text-muted, #94a3b8);line-height:1.45}.memorix-agents-input,.memorix-agents-textarea{background:#252b3d;border:1px solid #4a5575;border-radius:8px;color:var(--memorix-agents-text, #f8fafc);padding:11px 12px;font-size:14px;font-family:inherit;outline:none;width:100%;box-shadow:inset 0 1px 2px #00000040;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.memorix-agents-input::placeholder,.memorix-agents-textarea::placeholder{color:#7c879c;opacity:1}.memorix-agents-input:hover:not(:disabled),.memorix-agents-textarea:hover:not(:disabled){border-color:#667089;background:#2a3147}.memorix-agents-input.mono{font-family:var(--memorix-agents-mono, monospace);font-size:12px}.memorix-agents-textarea{resize:vertical;min-height:72px;line-height:1.45}.memorix-agents-input:focus,.memorix-agents-textarea:focus{border-color:var(--memorix-agents-accent, #96aaff);background:#2d3550;box-shadow:0 0 0 3px #7b93ff59,inset 0 1px 2px #0003}.memorix-agents-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.memorix-agents-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;border-radius:7px;border:1px solid var(--memorix-agents-border, #252a3d);background:var(--memorix-agents-surface-raised, #1c2030);color:var(--memorix-agents-text, #e2e8f0);font-size:13px;font-family:inherit;cursor:pointer}.memorix-agents-btn:hover:not(:disabled){border-color:var(--memorix-agents-accent, #7b93ff)}.memorix-agents-btn:disabled{opacity:.45;cursor:not-allowed}.memorix-agents-btn-primary{background:var(--memorix-agents-accent, #7b93ff);border-color:var(--memorix-agents-accent, #7b93ff);color:#fff;font-weight:600}.memorix-agents-btn-primary:hover:not(:disabled){background:#96aaff;border-color:#96aaff}.memorix-agents-btn-create{padding:10px 22px;font-size:14px;min-width:140px;justify-content:center;box-shadow:0 4px 14px #7b93ff59}.memorix-agents-btn-sm{padding:3px 10px;font-size:12px}.memorix-agents-btn-danger{border-color:#f87171;color:#f87171}.memorix-agents-btn.active{border-color:var(--memorix-agents-accent, #7b93ff);color:var(--memorix-agents-accent, #7b93ff);background:var(--memorix-agents-accent-subtle, rgba(123, 147, 255, .08))}.memorix-agents-table-wrap{overflow-x:auto;background:var(--memorix-agents-surface, #13161f);border:1px solid var(--memorix-agents-border, #252a3d);border-radius:12px}.memorix-agents-table{width:100%;border-collapse:collapse;font-size:13px}.memorix-agents-table th{padding:11px 14px;text-align:left;border-bottom:1px solid var(--memorix-agents-border, #252a3d);background:var(--memorix-agents-surface-raised, #1c2030);color:var(--memorix-agents-text-muted, #8892a4);font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.07em}.memorix-agents-table td{padding:12px 14px;border-bottom:1px solid var(--memorix-agents-border, #252a3d);vertical-align:top}.memorix-agents-table tbody tr:last-child td{border-bottom:none}.memorix-agents-name{font-weight:600}.memorix-agents-id{font-family:var(--memorix-agents-mono, monospace);font-size:11px;color:var(--memorix-agents-text-dim, #5a6478);margin-top:2px}.memorix-agents-desc{font-size:12px;color:var(--memorix-agents-text-muted, #8892a4);line-height:1.45;max-width:360px}.memorix-agents-desc-empty{color:var(--memorix-agents-text-dim, #5a6478);font-size:12px}.memorix-agents-row-actions{display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap}.memorix-agents-notice{background:var(--memorix-agents-accent-subtle, rgba(123, 147, 255, .08));border:1px solid var(--memorix-agents-accent-border, rgba(123, 147, 255, .35));border-radius:12px;padding:14px 16px;margin-bottom:16px;font-size:13px}.memorix-agents-notice-warn{background:#6c83f514;border-color:#6c83f54d}.memorix-agents-empty,.memorix-agents-loading{padding:40px 24px;text-align:center;color:var(--memorix-agents-text-muted, #8892a4);font-size:13px}.memorix-agents-error{font-size:12px;color:#f87171}.memorix-agents-chip-row{display:flex;flex-wrap:wrap;gap:6px}.memorix-agents-chip{display:inline-flex;align-items:center;padding:2px 9px;border-radius:99px;font-size:11px;font-weight:500;background:var(--memorix-agents-surface-raised, #1c2030);border:1px solid var(--memorix-agents-border, #252a3d);color:var(--memorix-agents-text-muted, #8892a4)}.memorix-agents-chip.selected{background:var(--memorix-agents-accent, #7b93ff);border-color:var(--memorix-agents-accent, #7b93ff);color:#fff}.memorix-agents-badge{display:inline-block;padding:2px 8px;border-radius:999px;font-size:11px;font-weight:600;background:var(--memorix-agents-surface-raised, #1c2030);color:var(--memorix-agents-text-muted, #8892a4)}.memorix-agents-badge-entity{background:#60a5fa1f;color:#60a5fa}.memorix-agents-badge-event{background:#f59e0b1f;color:#f59e0b}.memorix-agents-badge-knowledge{background:#a78bfa1f;color:#a78bfa}.memorix-agents-multiselect{position:relative;min-width:200px;max-width:320px}.memorix-agents-multiselect-trigger{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:7px 10px;border-radius:7px;border:1px solid var(--memorix-agents-border, #252a3d);background:var(--memorix-agents-bg, #0b0d14);color:var(--memorix-agents-text, #e2e8f0);font-size:13px;font-family:inherit;cursor:pointer;text-align:left}.memorix-agents-multiselect-trigger.any{color:var(--memorix-agents-text-muted, #8892a4)}.memorix-agents-multiselect-trigger:hover:not(:disabled){border-color:var(--memorix-agents-accent, #7b93ff)}.memorix-agents-multiselect-trigger:disabled{opacity:.55;cursor:not-allowed}.memorix-agents-multiselect.open .memorix-agents-multiselect-trigger{border-color:var(--memorix-agents-accent, #7b93ff);box-shadow:0 0 0 2px #7b93ff59}.memorix-agents-multiselect-trigger-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.memorix-agents-multiselect-chevron{font-size:10px;color:var(--memorix-agents-text-dim, #5a6478);flex-shrink:0}.memorix-agents-multiselect-menu{position:absolute;z-index:50;top:calc(100% + 4px);left:0;right:0;min-width:240px;max-height:280px;overflow-y:auto;background:var(--memorix-agents-surface, #13161f);border:1px solid var(--memorix-agents-border, #252a3d);border-radius:8px;box-shadow:0 8px 24px #00000073;padding:4px}.memorix-agents-multiselect-option{display:flex;align-items:flex-start;gap:8px;width:100%;padding:8px 10px;border:none;border-radius:6px;background:transparent;color:var(--memorix-agents-text, #e2e8f0);font-size:13px;font-family:inherit;text-align:left;cursor:pointer}.memorix-agents-multiselect-option:hover{background:var(--memorix-agents-surface-raised, #1c2030)}.memorix-agents-multiselect-option.selected{background:var(--memorix-agents-accent-subtle, rgba(123, 147, 255, .08))}.memorix-agents-multiselect-option.highlighted strong{color:var(--memorix-agents-accent, #7b93ff)}.memorix-agents-multiselect-option.any{border-bottom:1px solid var(--memorix-agents-border, #252a3d);margin-bottom:2px}.memorix-agents-multiselect-check{width:14px;flex-shrink:0;color:var(--memorix-agents-accent, #7b93ff);font-size:12px;line-height:1.4}.memorix-agents-multiselect-option-hint{display:block;font-size:11px;color:var(--memorix-agents-text-dim, #5a6478);margin-top:1px}.memorix-agents-multiselect-option-hint.mono{font-family:var(--memorix-agents-mono, monospace)}.memorix-agents-multiselect-empty{padding:12px 10px;font-size:12px;color:var(--memorix-agents-text-muted, #8892a4)}@media(max-width:720px){.memorix-agents-form-grid{grid-template-columns:1fr}}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}:root{--color-bg: #0b0d14;--color-surface: #13161f;--color-surface-raised: #1c2030;--color-surface-hover: #222640;--color-border: #252a3d;--color-border-subtle: #1e2235;--color-text: #e2e8f0;--color-text-muted: #8892a4;--color-text-dim: #5a6478;--color-accent: #7b93ff;--color-accent-hover: #96aaff;--color-accent-subtle: rgba(123, 147, 255, .08);--color-accent-border: rgba(123, 147, 255, .35);--status-blocked: #f59e0b;--status-blocked-bg: rgba(245, 158, 11, .1);--status-pending: #60a5fa;--status-pending-bg: rgba(96, 165, 250, .1);--status-running: #34d399;--status-running-bg: rgba(52, 211, 153, .1);--status-done: #4ade80;--status-done-bg: rgba(74, 222, 128, .08);--status-failed: #f87171;--status-failed-bg: rgba(248, 113, 113, .1);--status-cancelled: #a78bfa;--status-cancelled-bg: rgba(167, 139, 250, .1);--radius: 7px;--radius-lg: 12px;--radius-xl: 16px;--font-mono: "Cascadia Code", "Fira Code", "Consolas", monospace;--shadow-card: 0 1px 4px rgba(0, 0, 0, .4), 0 0 0 0 transparent;--shadow-focus: 0 0 0 2px rgba(123, 147, 255, .4);--transition: .15s ease}html,body{background:var(--color-bg);color:var(--color-text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,system-ui,sans-serif;font-size:14px;line-height:1.5;min-height:100vh}a{color:var(--color-accent);text-decoration:none}a:hover{color:var(--color-accent-hover);text-decoration:underline}.layout{display:flex;flex-direction:column;min-height:100vh}.topbar{display:flex;align-items:center;gap:24px;padding:0 24px;height:56px;background:var(--color-surface);border-bottom:1px solid var(--color-border);box-shadow:0 1px 0 var(--color-border-subtle);position:sticky;top:0;z-index:100}.topbar-brand{display:flex;align-items:center;gap:9px;font-weight:700;font-size:14px;color:var(--color-text);letter-spacing:-.2px;white-space:nowrap}.topbar-brand-icon{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:7px;background:var(--color-accent-subtle);border:1px solid var(--color-accent-border);color:var(--color-accent);font-size:14px;line-height:1;flex-shrink:0}.topbar-brand span{color:var(--color-accent)}.topbar-nav{display:flex;gap:2px;flex:1;height:100%;align-items:center}.topbar-nav a{display:flex;align-items:center;height:56px;padding:0 14px;color:var(--color-text-muted);font-size:13px;font-weight:500;border-bottom:2px solid transparent;transition:color var(--transition),border-color var(--transition);white-space:nowrap}.topbar-nav a:hover{color:var(--color-text);text-decoration:none;border-bottom-color:var(--color-border)}.topbar-nav a.active{color:var(--color-text);border-bottom-color:var(--color-accent)}.topbar-meta{display:flex;align-items:center;gap:12px;flex-shrink:0;min-width:0;margin-left:auto}.topbar-meta-controls{display:flex;align-items:center;gap:10px;flex-shrink:0}.topbar-meta-host{font-size:10px;color:var(--color-text-dim);max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-left:12px;border-left:1px solid var(--color-border-subtle)}@media(max-width:1180px){.topbar-meta-host{display:none}}.topbar-agent-scope.memorix-agents-scope{padding:4px 8px;min-height:32px}.topbar-meta .memorix-agents-scope-select{-moz-appearance:none;appearance:none;-webkit-appearance:none;padding-right:16px;min-width:88px}.topbar-meta .memorix-agents-scope-chevron{right:0;font-size:11px}.app-pkg-version{font-size:9px;font-weight:500;color:var(--color-text-dim);letter-spacing:.03em;margin-left:6px;align-self:center;opacity:.7}.page{padding:28px 24px;max-width:1400px;width:100%;margin:0 auto}.page-header{margin-bottom:24px;display:flex;align-items:flex-start;gap:12px}.page-title{font-size:20px;font-weight:700;letter-spacing:-.3px}.page-subtitle{color:var(--color-text-muted);font-size:13px;margin-top:2px}.card{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:20px;box-shadow:var(--shadow-card)}.card-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--color-text-muted);margin-bottom:14px}.live-console{background:#07090f;border:1px solid var(--color-border);border-radius:var(--radius-lg);overflow:hidden;margin-bottom:16px}.live-console-head{display:flex;align-items:center;justify-content:space-between;padding:8px 14px;background:var(--color-surface);border-bottom:1px solid var(--color-border)}.live-console-title{display:inline-flex;align-items:center;gap:8px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--color-text-muted)}.live-console-meta{font-size:11px;color:var(--color-text-dim)}.live-dot{width:8px;height:8px;border-radius:50%;background:var(--color-text-dim)}.live-dot.live{background:var(--status-running);box-shadow:0 0 #34d39999;animation:live-pulse 1.4s ease-out infinite}@keyframes live-pulse{0%{box-shadow:0 0 #34d39980}70%{box-shadow:0 0 0 6px #34d39900}to{box-shadow:0 0 #34d39900}}.live-console-body{max-height:420px;overflow-y:auto;padding:10px 14px;font-family:var(--font-mono);font-size:12px;line-height:1.7}.live-console-entry{margin-bottom:2px}.live-console-line{display:flex;gap:10px;align-items:baseline;white-space:pre-wrap;word-break:break-word;border-radius:var(--radius);padding:1px 4px;margin:0 -4px}.live-console-line.expandable{cursor:pointer;-webkit-user-select:none;user-select:none}.live-console-line.expandable:hover{background:#ffffff0a}.live-console-chevron{flex-shrink:0;width:10px;font-size:9px;color:var(--color-text-dim);transition:transform var(--transition)}.live-console-chevron.open{transform:rotate(90deg)}.live-console-expand{padding:4px 0 10px 20px}.live-console-expand .json-section{margin-bottom:6px}.live-console-expand .json-section-header{font-size:11px;padding:6px 10px}.live-console-expand .json-body{max-height:240px;overflow:auto}.live-console-expand .json-body pre{font-size:11px}.live-console-line.muted{color:var(--color-text-dim)}.live-console-time{color:var(--color-text-dim);flex-shrink:0}.live-console-detail{color:var(--color-text-muted)}.live-console-foot{padding:7px 14px;font-size:11px;color:var(--color-text-muted);background:var(--color-surface);border-top:1px solid var(--color-border)}.run-io-panel .json-section{margin-bottom:8px}.run-io-hint{margin:0 0 12px;font-size:12px;color:var(--color-text-muted)}.run-io-pending{padding:10px 12px;margin-bottom:8px;font-size:12px;color:var(--color-text-muted);background:var(--color-bg);border:1px dashed var(--color-border);border-radius:var(--radius)}.run-io-warning{padding:10px 12px;margin-bottom:8px;font-size:12px;color:var(--status-failed);background:color-mix(in srgb,var(--status-failed) 8%,var(--color-bg));border:1px solid color-mix(in srgb,var(--status-failed) 25%,var(--color-border));border-radius:var(--radius)}.run-io-writeback{padding:10px 12px;margin-bottom:8px;background:color-mix(in srgb,var(--status-done) 6%,var(--color-bg));border:1px solid color-mix(in srgb,var(--status-done) 22%,var(--color-border));border-radius:var(--radius)}.run-io-writeback-title{font-size:12px;font-weight:600;margin-bottom:8px;color:var(--status-done)}.pipeline-stats{display:grid;gap:2px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid var(--color-border-subtle)}.pipeline-gantt{margin-top:8px}.pipeline-gantt-axis{display:flex;justify-content:space-between;font-size:11px;color:var(--color-text-dim);margin-bottom:8px;padding-left:148px;padding-right:56px}.pipeline-gantt-row{display:grid;grid-template-columns:140px 1fr 52px;gap:8px;align-items:center;margin-bottom:6px}.pipeline-gantt-label{font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pipeline-gantt-track{position:relative;height:22px;background:var(--color-surface-raised);border:1px solid var(--color-border-subtle);border-radius:4px;overflow:hidden}.pipeline-gantt-bar{position:absolute;top:3px;bottom:3px;border-radius:3px;background:color-mix(in srgb,var(--status-running) 75%,var(--color-accent));border:1px solid color-mix(in srgb,var(--status-running) 50%,transparent);min-width:2px}.pipeline-gantt-bar.concurrent{background:color-mix(in srgb,var(--color-accent) 70%,var(--status-running));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--color-accent) 40%,white)}.pipeline-gantt-bar.failed{background:color-mix(in srgb,var(--status-failed) 70%,var(--color-surface));border-color:color-mix(in srgb,var(--status-failed) 45%,transparent)}.pipeline-gantt-dur{font-size:11px;text-align:right}.pipeline-gantt-legend{display:flex;flex-wrap:wrap;gap:16px;font-size:11px;margin-top:10px}.pipeline-gantt-swatch{display:inline-block;width:12px;height:8px;border-radius:2px;margin-right:6px;vertical-align:middle;background:color-mix(in srgb,var(--status-running) 75%,var(--color-accent))}.pipeline-gantt-swatch.concurrent{background:color-mix(in srgb,var(--color-accent) 70%,var(--status-running))}.pipeline-table th,.pipeline-table td{font-size:12px}.pipeline-substep-row td{background:color-mix(in srgb,var(--color-surface-raised) 55%,transparent)}.pipeline-substep-label{font-size:11px;color:var(--color-text-muted)}.pipeline-substep-marker{margin-right:6px;opacity:.65}.pipeline-stat-cell{line-height:1.35}.pipeline-stat-range{font-size:10px;margin-top:2px;white-space:nowrap}.pipeline-runlog{display:flex;flex-direction:column;gap:6px;max-height:240px;overflow-y:auto;padding:8px 10px;background:var(--color-surface-raised);border:1px solid var(--color-border-subtle);border-radius:var(--radius)}.pipeline-runlog-line{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;font-size:12px;line-height:1.4}.pipeline-graph-picker{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:8px}.pipeline-graph-pick{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:10px 12px;text-align:left;background:var(--color-surface-raised);border:1px solid var(--color-border-subtle);border-radius:var(--radius);color:var(--color-text);cursor:pointer;transition:border-color var(--transition),background var(--transition)}.pipeline-graph-pick:hover{background:var(--color-surface-hover);border-color:var(--color-accent-border)}.pipeline-guide{margin-bottom:16px;padding:14px 16px;background:var(--color-accent-subtle);border:1px solid var(--color-accent-border);border-radius:var(--radius);font-size:13px;line-height:1.5}.pipeline-guide-compact p{margin:0;color:var(--color-text-muted)}.pipeline-guide-title{font-size:14px;font-weight:600;margin-bottom:12px}.pipeline-guide-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px 20px}.pipeline-guide-grid strong{display:block;font-size:12px;margin-bottom:4px}.pipeline-guide-grid p{margin:0;font-size:12px}.pipeline-empty{padding:12px 14px;margin:12px 0;font-size:13px;color:var(--color-text-muted);background:var(--color-surface-raised);border:1px dashed var(--color-border);border-radius:var(--radius)}.pipeline-empty p{margin:0}.pipeline-diagram{margin:16px 0;padding:14px 16px;background:var(--color-surface-raised);border:1px solid var(--color-border-subtle);border-radius:var(--radius)}.pipeline-diagram-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px;margin-bottom:14px}.pipeline-diagram-tabs{display:flex;gap:4px}.pipeline-diagram-tabs button,.pipeline-diagram-tabs a{padding:4px 10px;font-size:12px;border-radius:var(--radius);border:1px solid var(--color-border-subtle);background:var(--color-surface);color:var(--color-text-muted);cursor:pointer}.pipeline-diagram-tabs button.active,.pipeline-diagram-tabs a.active{background:var(--color-accent-subtle);border-color:var(--color-accent-border);color:var(--color-text)}.pipeline-flow{display:flex;flex-direction:column;gap:0}.pipeline-flow-wave{display:flex;flex-direction:column;align-items:stretch}.pipeline-flow-connector{display:flex;flex-direction:column;align-items:center;padding:6px 0;gap:2px}.pipeline-flow-arrow{font-size:16px;color:var(--color-text-dim);line-height:1}.pipeline-flow-connector-label{font-size:10px;text-transform:uppercase;letter-spacing:.04em}.pipeline-flow-wave-head{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:8px;padding:6px 10px;border-radius:var(--radius);background:var(--color-surface);border:1px solid var(--color-border-subtle)}.pipeline-flow-wave-head.parallel{border-color:color-mix(in srgb,var(--color-accent) 35%,var(--color-border-subtle));background:color-mix(in srgb,var(--color-accent-subtle) 50%,var(--color-surface))}.pipeline-flow-wave-badge{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.03em}.pipeline-flow-nodes{display:flex;flex-direction:column;gap:8px;margin-bottom:4px}.pipeline-flow-nodes.is-parallel{flex-direction:row;flex-wrap:wrap}.pipeline-flow-node{flex:1 1 160px;min-width:140px;padding:10px 12px;border-radius:var(--radius);border:1px solid var(--color-border-subtle);background:var(--color-surface);border-left:3px solid var(--status-running)}.pipeline-flow-node.concurrent{border-left-color:var(--color-accent)}.pipeline-flow-node.failed{border-left-color:var(--status-failed)}.pipeline-flow-node-id{font-size:12px;font-weight:600}.pipeline-flow-node-skill{font-size:11px;margin-top:2px}.pipeline-flow-node-dur{font-size:13px;margin-top:6px;font-weight:500}.pipeline-flow-node-peers{font-size:10px;margin-top:6px;line-height:1.35}.pipeline-flow-node-error{font-size:11px;margin-top:6px;color:var(--status-failed)}.pipeline-swimlanes{margin-top:4px}.pipeline-swimlane-row{display:grid;grid-template-columns:72px 1fr;gap:8px;align-items:center;margin-bottom:8px}.pipeline-swimlane-label{font-size:11px;color:var(--color-text-dim);text-align:right}.pipeline-swimlane-track{min-height:36px}.pipeline-swimlane-node{position:absolute;top:4px;bottom:4px;display:flex;flex-direction:column;justify-content:center;padding:2px 6px;border-radius:3px;overflow:hidden;background:color-mix(in srgb,var(--status-running) 75%,var(--color-accent));border:1px solid color-mix(in srgb,var(--status-running) 50%,transparent);min-width:4px}.pipeline-swimlane-node.concurrent{background:color-mix(in srgb,var(--color-accent) 70%,var(--status-running))}.pipeline-swimlane-node.failed{background:color-mix(in srgb,var(--status-failed) 70%,var(--color-surface));border-color:color-mix(in srgb,var(--status-failed) 45%,transparent)}.pipeline-swimlane-node-id{font-size:10px;font-family:var(--font-mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pipeline-swimlane-node-dur{font-size:9px;opacity:.85}.pipeline-node-inspector{margin-top:16px}.pipeline-node-inspector-item{border:1px solid var(--color-border-subtle);border-radius:var(--radius);margin-bottom:6px;overflow:hidden;background:var(--color-surface)}.pipeline-node-inspector-item.open{border-color:var(--color-accent-border)}.pipeline-node-inspector-head{display:flex;flex-wrap:wrap;align-items:center;gap:8px;width:100%;padding:8px 12px;text-align:left;background:var(--color-surface-raised);border:none;color:var(--color-text);cursor:pointer;font:inherit}.pipeline-node-inspector-head:hover{background:var(--color-surface-hover)}.pipeline-node-inspector-chevron{width:12px;color:var(--color-text-dim);flex-shrink:0}.pipeline-node-inspector-id{font-weight:600;font-size:12px}.pipeline-node-inspector-dur{margin-left:auto;font-size:12px}.pipeline-node-inspector-status{font-size:11px;text-transform:uppercase}.chip.parallel{background:color-mix(in srgb,var(--color-accent) 20%,var(--color-surface));border:1px solid color-mix(in srgb,var(--color-accent) 30%,transparent)}.pipeline-node-detail{padding:12px 14px 14px;border-top:1px solid var(--color-border-subtle);background:var(--color-surface)}.pipeline-node-detail-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:8px 16px}.pipeline-node-detail-grid>div{display:flex;flex-direction:column;gap:2px}.pipeline-node-detail-subtitle{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.03em;color:var(--color-text-dim);margin-bottom:6px}.pipeline-node-runlog{max-height:160px}.pipeline-attempts{display:flex;flex-wrap:wrap;gap:6px}.pipeline-attempt-chip{font-size:11px;padding:2px 8px;border-radius:999px;background:color-mix(in srgb,var(--status-done) 15%,var(--color-surface));border:1px solid color-mix(in srgb,var(--status-done) 25%,transparent)}.pipeline-attempt-chip.failed{background:color-mix(in srgb,var(--status-failed) 12%,var(--color-surface));border-color:color-mix(in srgb,var(--status-failed) 30%,transparent)}.status-cards{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:24px}@media(max-width:900px){.status-cards{grid-template-columns:repeat(3,1fr)}}.status-card{background:var(--color-surface);border:1px solid var(--color-border);border-left:3px solid var(--color-border);border-radius:var(--radius-lg);padding:16px 18px;cursor:pointer;transition:border-color var(--transition),background var(--transition);box-shadow:var(--shadow-card)}.status-card:hover,.status-card.active{background:var(--color-surface-raised)}.status-card-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;margin-bottom:8px}.status-card-count{font-size:30px;font-weight:800;line-height:1;font-variant-numeric:tabular-nums}.badge{display:inline-flex;align-items:center;gap:5px;padding:2px 8px;border-radius:99px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;white-space:nowrap}.badge:before{content:"";width:5px;height:5px;border-radius:50%;background:currentColor;flex-shrink:0}.badge-blocked{color:var(--status-blocked);background:var(--status-blocked-bg)}.badge-pending{color:var(--status-pending);background:var(--status-pending-bg)}.badge-running{color:var(--status-running);background:var(--status-running-bg);animation:pulse-running 2s ease-in-out infinite}.badge-done{color:var(--status-done);background:var(--status-done-bg)}.badge-failed{color:var(--status-failed);background:var(--status-failed-bg)}.badge-cancelled{color:var(--status-cancelled);background:var(--status-cancelled-bg)}@keyframes pulse-running{0%,to{opacity:1}50%{opacity:.65}}.mock-chip{display:inline-flex;align-items:center;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;background:#f59e0b1f;border:1px solid rgba(245,158,11,.3);color:#f59e0b;margin-right:8px}.table-wrap{overflow-x:auto;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}table{width:100%;border-collapse:collapse;font-size:13px}thead th{text-align:left;padding:11px 14px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--color-text-muted);border-bottom:1px solid var(--color-border);background:var(--color-surface-raised);white-space:nowrap}tbody tr{border-bottom:1px solid var(--color-border);transition:background var(--transition);cursor:pointer}tbody tr:last-child{border-bottom:none}tbody tr:hover{background:var(--color-surface-hover)}tbody td{padding:10px 14px;color:var(--color-text);white-space:nowrap;max-width:200px;overflow:hidden;text-overflow:ellipsis}.td-mono{font-family:var(--font-mono);font-size:12px;color:var(--color-text-muted)}.filters{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:16px;padding:14px 16px;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.filter-group{display:flex;align-items:center;gap:8px}.filter-divider{width:1px;height:28px;background:var(--color-border);margin:0 4px}select:not(.memorix-agents-scope-select),input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=submit]):not([type=button]){background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:var(--radius);color:var(--color-text);padding:6px 10px;font-size:13px;font-family:inherit;outline:none;transition:border-color var(--transition),box-shadow var(--transition)}select:not(.memorix-agents-scope-select):focus,input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=submit]):not([type=button]):focus{border-color:var(--color-accent);box-shadow:var(--shadow-focus)}select option{background:var(--color-surface-raised)}select:disabled,input:disabled{opacity:.45;cursor:not-allowed}label{font-size:12px;color:var(--color-text-muted)}textarea{background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:var(--radius);color:var(--color-text);padding:8px 10px;font-size:13px;font-family:inherit;outline:none;resize:vertical;transition:border-color var(--transition),box-shadow var(--transition);width:100%}textarea:focus{border-color:var(--color-accent);box-shadow:var(--shadow-focus)}button,.btn{display:inline-flex;align-items:center;gap:6px;background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:var(--radius);color:var(--color-text);padding:6px 14px;font-size:13px;font-family:inherit;cursor:pointer;transition:border-color var(--transition),background var(--transition),box-shadow var(--transition);white-space:nowrap}button:hover,.btn:hover{border-color:var(--color-accent);background:var(--color-surface-hover)}button:focus-visible,.btn:focus-visible{outline:none;box-shadow:var(--shadow-focus)}button:disabled,.btn:disabled{opacity:.45;cursor:not-allowed}button:disabled:hover,.btn:disabled:hover{border-color:var(--color-border);background:var(--color-surface-raised)}button.primary,.btn-primary{background:var(--color-accent);border-color:var(--color-accent);color:#fff;font-weight:600}button.primary:hover,.btn-primary:hover{background:var(--color-accent-hover);border-color:var(--color-accent-hover)}.btn-danger{border-color:var(--status-failed);color:var(--status-failed)}.btn-danger:hover{background:var(--status-failed-bg);border-color:var(--status-failed)}.btn-ghost{background:transparent;border-color:transparent;color:var(--color-text-muted)}.btn-ghost:hover{background:var(--color-surface-raised);border-color:var(--color-border);color:var(--color-text)}button.active,.btn.active{border-color:var(--color-accent);color:var(--color-accent);background:var(--color-accent-subtle)}.btn-sm{padding:3px 10px;font-size:12px}.btn-xs{padding:2px 8px;font-size:11px}.infinite-scroll-footer{display:flex;align-items:center;gap:12px;justify-content:flex-end;flex-wrap:wrap;padding:12px 16px;font-size:13px;color:var(--color-text-muted);border-top:1px solid var(--color-border)}.infinite-scroll-loading{display:inline-flex;align-items:center;gap:8px}.infinite-scroll-sentinel{width:100%;height:1px;flex-basis:100%}.refresh-control{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--color-text-muted);margin-left:auto}.refresh-dot{width:7px;height:7px;border-radius:50%;background:var(--status-running);display:inline-block}.refresh-dot.paused{background:var(--color-text-dim)}.json-section{margin-bottom:16px}.json-section-header{display:flex;align-items:center;gap:8px;cursor:pointer;padding:8px 12px;background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:var(--radius);font-size:12px;font-weight:600;color:var(--color-text-muted);-webkit-user-select:none;user-select:none;transition:border-color var(--transition)}.json-section-header:hover{border-color:var(--color-accent);color:var(--color-text)}.json-section-header.open{border-bottom-left-radius:0;border-bottom-right-radius:0}.json-chevron{font-size:10px;transition:transform var(--transition);color:var(--color-text-dim)}.json-chevron.open{transform:rotate(90deg)}.json-body{background:var(--color-bg);border:1px solid var(--color-border);border-top:none;border-bottom-left-radius:var(--radius);border-bottom-right-radius:var(--radius);padding:14px 16px;overflow-x:auto}.json-body pre{font-family:var(--font-mono);font-size:12px;line-height:1.6;color:var(--color-text);white-space:pre}.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}@media(max-width:800px){.detail-grid{grid-template-columns:1fr}}.collapsible-card{padding:0;overflow:hidden}.collapsible-card.open{padding-bottom:4px}.collapsible-card-head{display:flex;align-items:center;gap:8px;width:100%;margin:0;padding:14px 20px;border:none;background:transparent;cursor:pointer;text-align:left;font:inherit;color:inherit;-webkit-user-select:none;user-select:none;transition:background var(--transition)}.collapsible-card-head:hover{background:var(--color-surface-raised)}.collapsible-card-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--color-text-muted);flex-shrink:0}.collapsible-card-summary{margin-left:auto;font-size:12px;color:var(--color-text-dim);font-weight:400;text-transform:none;letter-spacing:normal;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:55%}.collapsible-chevron{font-size:10px;transition:transform var(--transition);color:var(--color-text-dim);flex-shrink:0}.collapsible-chevron.open{transform:rotate(90deg)}.collapsible-card-body{padding:0 20px 16px}.detail-row{display:flex;gap:8px;padding:7px 0;border-bottom:1px solid var(--color-border-subtle);font-size:13px;align-items:baseline}.detail-row:last-child{border-bottom:none}.detail-key{color:var(--color-text-muted);min-width:130px;font-size:12px;flex-shrink:0}.detail-val{color:var(--color-text);word-break:break-all;font-family:var(--font-mono);font-size:12px}.overview-cols{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:24px}@media(max-width:1000px){.overview-cols{grid-template-columns:1fr 1fr}}@media(max-width:640px){.overview-cols{grid-template-columns:1fr}}.timeline{position:relative;padding-left:28px}.timeline:before{content:"";position:absolute;left:9px;top:8px;bottom:8px;width:2px;background:var(--color-border)}.timeline-item{position:relative;margin-bottom:12px}.timeline-dot{position:absolute;left:-23px;top:14px;width:10px;height:10px;border-radius:50%;border:2px solid var(--color-bg)}.timeline-dot-blocked{background:var(--status-blocked)}.timeline-dot-pending{background:var(--status-pending)}.timeline-dot-running{background:var(--status-running)}.timeline-dot-done{background:var(--status-done)}.timeline-dot-failed{background:var(--status-failed)}.timeline-dot-cancelled{background:var(--status-cancelled)}.mono{font-family:var(--font-mono);font-size:12px}.text-muted{color:var(--color-text-muted)}.text-dim{color:var(--color-text-dim)}.empty-state{padding:52px 24px;text-align:center;color:var(--color-text-muted)}.error-state{padding:16px;color:var(--status-failed);background:var(--status-failed-bg);border:1px solid rgba(248,113,113,.3);border-radius:var(--radius);font-size:13px}.spinner{display:inline-block;width:16px;height:16px;border:2px solid var(--color-border);border-top-color:var(--color-accent);border-radius:50%;animation:spin .7s linear infinite;flex-shrink:0}@keyframes spin{to{transform:rotate(360deg)}}.loading-row{display:flex;align-items:center;gap:10px;padding:40px 24px;color:var(--color-text-muted);font-size:13px}.breadcrumb{font-size:13px;color:var(--color-text-muted);margin-bottom:18px;display:flex;align-items:center;gap:6px}.breadcrumb a{color:var(--color-text-muted)}.breadcrumb a:hover{color:var(--color-text);text-decoration:none}.breadcrumb-sep{color:var(--color-text-dim)}.memorix-panel{background:var(--color-accent-subtle);border:1px solid var(--color-accent-border);border-radius:var(--radius);padding:14px 16px;margin-bottom:16px}.memorix-panel-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--color-accent);margin-bottom:8px}.wizard-steps{display:flex;margin-bottom:24px;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.wizard-steps--scrollable{overflow-x:auto;overflow-y:hidden;scroll-snap-type:x proximity;scrollbar-width:thin;-webkit-overflow-scrolling:touch}.wizard-steps--scrollable .wizard-step{flex:0 0 auto;min-width:152px;max-width:220px;scroll-snap-align:center}.wizard-step{flex:1;display:flex;align-items:center;gap:10px;padding:14px 16px;border:none;border-right:1px solid var(--color-border);background:transparent;color:var(--color-text-dim);text-align:left;cursor:default;font:inherit;position:relative;transition:background var(--transition),color var(--transition)}.wizard-step:last-child{border-right:none}.wizard-step.is-clickable{cursor:pointer}.wizard-step.is-clickable:hover{background:var(--color-surface-raised);color:var(--color-text-muted)}.wizard-step.is-active{background:var(--color-surface-raised);color:var(--color-text)}.wizard-step.is-active:after{content:"";position:absolute;bottom:0;left:0;right:0;height:2px;background:var(--color-accent);border-radius:1px 1px 0 0}.wizard-step.is-done{color:var(--color-text-muted)}.wizard-step-num{flex-shrink:0;width:26px;height:26px;border-radius:50%;border:1.5px solid var(--color-border);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;transition:background var(--transition),border-color var(--transition),color var(--transition)}.wizard-step.is-active .wizard-step-num{background:var(--color-accent);border-color:var(--color-accent);color:#fff}.wizard-step.is-done .wizard-step-num{background:var(--status-done-bg);border-color:var(--status-done);color:var(--status-done)}.wizard-step-label{display:flex;flex-direction:column;gap:1px;min-width:0}.wizard-step-title{font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wizard-step-summary{font-size:11px;color:var(--color-text-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wizard-step.is-active .wizard-step-summary{color:var(--color-text-muted)}.wizard-lead{font-size:13px;color:var(--color-text-muted);margin-bottom:18px;line-height:1.6}.wizard-nav{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-top:24px;padding-top:18px;border-top:1px solid var(--color-border)}.review-grid{display:grid;gap:10px;font-size:13px}.review-row{display:grid;grid-template-columns:150px 1fr;gap:12px;align-items:start;padding:5px 0;border-bottom:1px solid var(--color-border-subtle)}.review-row:last-child{border-bottom:none}.review-label{color:var(--color-text-muted);font-size:12px}.queue-manager-toggle{display:inline-flex;align-items:center;gap:8px;padding:5px 10px;border-radius:999px;border:1px solid var(--color-border);background:var(--color-surface);font-size:12px;font-weight:600;line-height:1.2;cursor:pointer;flex-shrink:0}.queue-manager-toggle.running{border-color:#4ade8059;background:#4ade8014;color:#4ade80}.queue-manager-toggle.paused{border-color:#f59e0b59;background:#f59e0b1a;color:#f59e0b}.queue-manager-toggle:disabled{opacity:.6;cursor:wait}.queue-manager-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.queue-manager-dot.running{background:#4ade80;box-shadow:0 0 0 2px #4ade802e}.queue-manager-dot.paused{background:#f59e0b}.queue-manager-counts{font-weight:500;opacity:.85;font-size:11px}.queue-manager-card{padding:4px 0}.queue-manager-card.is-running{border-left:3px solid #4ade80;padding-left:14px}.queue-manager-card.is-paused{border-left:3px solid #f59e0b;padding-left:14px}.queue-manager-card-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}.queue-manager-title{font-size:15px;font-weight:600;margin-bottom:4px}.queue-manager-subtitle{font-size:13px;color:var(--color-text-muted);line-height:1.5}.queue-manager-badge{display:inline-flex;padding:4px 10px;border-radius:999px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;flex-shrink:0}.queue-manager-badge.running{color:#4ade80;background:#4ade8014;border:1px solid rgba(74,222,128,.3)}.queue-manager-badge.paused{color:#f59e0b;background:#f59e0b1a;border:1px solid rgba(245,158,11,.35)}.queue-manager-stats{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px;font-size:12px;color:var(--color-text-muted)}.result-writeback{margin-top:4px}.writeback-modes{display:grid;gap:8px;margin-bottom:4px}.writeback-mode{display:flex;gap:10px;align-items:flex-start;padding:12px 14px;border:1px solid var(--color-border);border-radius:var(--radius-md);cursor:pointer;background:var(--color-surface)}.writeback-mode.selected{border-color:var(--color-accent-border);background:var(--color-accent-subtle)}.writeback-mode input{margin-top:3px;flex-shrink:0}.writeback-summary{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.writeback-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;font-size:11px;font-weight:600;letter-spacing:.02em;text-transform:uppercase}.writeback-badge.simulation{color:#f59e0b;background:#f59e0b1f;border:1px solid rgba(245,158,11,.35)}.writeback-badge.write{color:#4ade80;background:#4ade8014;border:1px solid rgba(74,222,128,.3)}.writeback-existing{margin-top:16px}.writeback-existing-title{font-size:12px;font-weight:600;color:var(--color-text-muted);margin-bottom:8px}.writeback-existing-grid-span{grid-column:1 / -1}.tabs{display:flex;gap:0;border-bottom:1px solid var(--color-border);margin-bottom:22px;overflow-x:auto}.tab{padding:10px 16px;border:none;border-bottom:2px solid transparent;background:transparent;color:var(--color-text-muted);font-size:13px;font-weight:500;cursor:pointer;white-space:nowrap;border-radius:0;transition:color var(--transition),border-color var(--transition)}.tab:hover{color:var(--color-text);background:transparent;border-color:transparent}.tab.active{color:var(--color-text);border-bottom-color:var(--color-accent)}.chip{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:99px;font-size:11px;font-weight:500;background:var(--color-surface-raised);border:1px solid var(--color-border);color:var(--color-text-muted);white-space:nowrap}.chip.narrative{background:var(--color-accent-subtle);border-color:var(--color-accent-border);color:var(--color-accent)}.chip.selectable{cursor:pointer;-webkit-user-select:none;user-select:none}.chip.selectable:hover{border-color:var(--color-accent);color:var(--color-text)}.chip.selected{background:var(--color-accent);border-color:var(--color-accent);color:#fff}.chip-row{display:flex;flex-wrap:wrap;gap:6px}.chip-condition{background:#f59e0b1a;border-color:#f59e0b59;color:#f59e0b}.chip-query{background:var(--color-accent-subtle);border-color:var(--color-accent-border);color:var(--color-accent)}.chip-code{background:#a78bfa1a;border-color:#a78bfa59;color:#a78bfa}.chip-manual{background:#4ade8014;border-color:#4ade804d;color:#4ade80}.metric-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:24px}@media(max-width:1000px){.metric-grid{grid-template-columns:repeat(2,1fr)}}.metric-card{background:var(--color-surface);border:1px solid var(--color-border);border-top:2px solid var(--color-border);border-radius:var(--radius-lg);padding:16px 18px;box-shadow:var(--shadow-card);transition:border-color var(--transition),background var(--transition)}.metric-card.clickable{cursor:pointer}.metric-card.clickable:hover{border-color:var(--color-accent);border-top-color:var(--color-accent);background:var(--color-surface-raised)}.metric-card .metric-value{font-size:28px;font-weight:800;font-variant-numeric:tabular-nums;line-height:1.1;letter-spacing:-.5px}.metric-card .metric-label{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--color-text-muted);margin-top:5px;font-weight:600}.metric-card .metric-sub{font-size:12px;color:var(--color-text-dim);margin-top:3px}.work-list{display:flex;flex-direction:column;gap:12px}.work-card{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:18px 20px;box-shadow:var(--shadow-card);transition:border-color var(--transition),background var(--transition)}.work-card:hover{border-color:color-mix(in srgb,var(--color-accent) 35%,var(--color-border));background:var(--color-surface-raised)}.work-card-paused{border-left:3px solid var(--status-cancelled)}.work-card-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px}.work-card-title{margin:0;padding:0;border:none;background:none;font:inherit;font-size:16px;font-weight:700;color:var(--color-text);cursor:pointer;letter-spacing:-.2px;text-align:left}.work-card-title:hover{color:var(--color-accent)}.work-card-actions{display:flex;gap:8px;margin-left:auto;flex-wrap:wrap}.work-card-actions .primary{font-size:12px;padding:6px 12px}.work-card-notice{font-size:12px;color:var(--color-text-muted);background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:var(--radius);padding:8px 12px;margin:-4px 0 14px}.work-card-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:14px}@media(max-width:900px){.work-card-stats{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:520px){.work-card-stats{grid-template-columns:1fr}}.work-stat{background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:var(--radius);padding:10px 12px;min-width:0}.work-stat-wide{grid-column:span 1}@media(min-width:901px){.work-stat-wide{grid-column:span 1}}.work-stat-value{display:block;font-size:15px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--color-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.work-stat-value strong{font-weight:800;color:var(--color-accent)}.work-stat-sep{font-weight:400;color:var(--color-text-muted)}.work-stat-label{display:block;margin-top:4px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--color-text-muted)}.work-card-meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;font-size:12px;color:var(--color-text-muted)}.work-meta-item{display:inline-flex;align-items:baseline;gap:6px;min-width:0}.work-meta-k{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--color-text-dim);flex-shrink:0}.work-meta-sep{color:var(--color-text-dim);-webkit-user-select:none;user-select:none}.work-card-narratives{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-top:12px;padding-top:12px;border-top:1px solid var(--color-border)}.mode-cards{display:grid;grid-template-columns:1fr 1fr;gap:16px;max-width:760px}@media(max-width:700px){.mode-cards{grid-template-columns:1fr}}.mode-card{display:flex;flex-direction:column;gap:14px;text-align:left;padding:24px;min-height:160px;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-xl);cursor:pointer;transition:border-color var(--transition),background var(--transition),box-shadow var(--transition);box-shadow:var(--shadow-card);position:relative}.mode-card:hover{border-color:var(--color-accent);background:var(--color-surface-raised);box-shadow:0 0 0 1px var(--color-accent)}.mode-card-icon{width:44px;height:44px;border-radius:10px;background:var(--color-accent-subtle);border:1px solid var(--color-accent-border);display:flex;align-items:center;justify-content:center;font-size:20px;color:var(--color-accent);flex-shrink:0}.mode-card-title{font-size:15px;font-weight:700;color:var(--color-text);display:flex;align-items:center;gap:8px}.mode-card-desc{font-size:13px;color:var(--color-text-muted);line-height:1.55}.mode-card-arrow{position:absolute;right:20px;top:50%;transform:translateY(-50%);color:var(--color-text-dim);font-size:18px;opacity:0;transition:opacity var(--transition),color var(--transition)}.mode-card:hover .mode-card-arrow{opacity:1;color:var(--color-accent)}.selector-card{display:flex;align-items:flex-start;gap:14px;padding:14px 16px;background:var(--color-surface);border:1px solid var(--color-border);border-left:3px solid transparent;border-radius:var(--radius-lg);cursor:pointer;transition:background var(--transition),border-color var(--transition);-webkit-user-select:none;user-select:none}.selector-card:hover{background:var(--color-surface-raised);border-color:var(--color-border);border-left-color:var(--color-border)}.selector-card.selected{background:var(--color-accent-subtle);border-color:var(--color-accent-border);border-left-color:var(--color-accent)}.selector-card-indicator{flex-shrink:0;margin-top:2px;width:18px;height:18px;border-radius:50%;border:2px solid var(--color-border);display:flex;align-items:center;justify-content:center;transition:border-color var(--transition),background var(--transition)}.selector-card.selected .selector-card-indicator{border-color:var(--color-accent);background:var(--color-accent)}.selector-card.selected .selector-card-indicator:after{content:"";width:6px;height:6px;border-radius:50%;background:#fff}.selector-card-check-indicator{flex-shrink:0;margin-top:2px;width:18px;height:18px;border-radius:5px;border:2px solid var(--color-border);display:flex;align-items:center;justify-content:center;transition:border-color var(--transition),background var(--transition)}.selector-card.selected .selector-card-check-indicator{border-color:var(--color-accent);background:var(--color-accent)}.selector-card.selected .selector-card-check-indicator:after{content:"✓";font-size:11px;color:#fff;font-weight:700;line-height:1}.selector-card-body{flex:1;min-width:0}.selector-card-meta{display:flex;align-items:center;gap:8px;margin-bottom:3px;flex-wrap:wrap}.selector-card-title{font-weight:600;font-size:13px}.selector-card-id{font-family:var(--font-mono);font-size:11px;color:var(--color-text-dim)}.selector-card-desc{font-size:12px;color:var(--color-text-muted);margin-top:2px;line-height:1.45}.selector-card-sub{font-size:11px;color:var(--color-text-dim);margin-top:3px}.selector-card-count{margin-left:auto;flex-shrink:0;text-align:right}.selector-card-count-num{font-size:20px;font-weight:700;font-variant-numeric:tabular-nums;color:var(--color-text);line-height:1}.selector-card-count-label{font-size:10px;color:var(--color-text-dim);text-transform:uppercase;letter-spacing:.05em}.graph-picker{display:flex;flex-direction:column;gap:10px}.graph-picker-toolbar{display:flex;flex-direction:column;gap:8px}.graph-picker-search{width:100%;padding:8px 10px;border:1px solid var(--color-border);border-radius:var(--radius);background:var(--color-surface);color:var(--color-text);font-size:13px}.graph-picker-list{display:flex;flex-direction:column;gap:4px;overflow-y:auto;border:1px solid var(--color-border);border-radius:var(--radius);background:var(--color-surface-raised);padding:4px}.graph-picker-row{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;min-height:48px;padding:8px 10px;border:1px solid transparent;border-radius:calc(var(--radius) - 2px);background:transparent;color:var(--color-text);text-align:left;cursor:pointer}.graph-picker-row:hover{background:var(--color-surface);border-color:var(--color-border)}.graph-picker-row.selected{background:var(--color-accent-bg, rgba(59, 130, 246, .12));border-color:var(--color-accent, #3b82f6)}.graph-picker-row-main{display:flex;align-items:center;gap:8px}.graph-picker-row-title{font-weight:600;font-size:13px}.graph-picker-row-id{font-size:11px;color:var(--color-text-dim)}.graph-picker-row-desc{font-size:11px;color:var(--color-text-muted);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.graph-picker-empty{padding:16px;text-align:center;font-size:13px;color:var(--color-text-dim)}.selector-summary{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px;padding:8px 12px;background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:var(--radius);font-size:12px;color:var(--color-text-muted)}.drawer-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#0000008c;z-index:200;display:flex;justify-content:flex-end;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px)}.drawer{width:min(580px,92vw);height:100%;background:var(--color-surface);border-left:1px solid var(--color-border);overflow-y:auto;padding:22px 24px;box-shadow:-4px 0 24px #0006}.drawer-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:18px}.section{margin-bottom:24px}.section-title{font-size:13px;font-weight:700;margin-bottom:12px;color:var(--color-text)}.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}@media(max-width:640px){.form-grid{grid-template-columns:1fr}}.field{display:flex;flex-direction:column;gap:5px}.field>label{margin:0}.field .hint{font-size:11px;color:var(--color-text-dim);line-height:1.4}.field input:not([type=radio]):not([type=checkbox]),.field select,.field textarea{width:100%}.field input[type=radio],.field input[type=checkbox]{width:auto;flex-shrink:0}.prereq-section{border:1px solid var(--color-border);border-radius:var(--radius-lg);overflow:hidden;margin-bottom:12px}.prereq-section-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:var(--color-surface-raised);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background var(--transition)}.prereq-section-header:hover{background:var(--color-surface-hover)}.prereq-section-body{padding:14px 16px;border-top:1px solid var(--color-border)}.prereq-tag{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;background:var(--color-surface-raised);border:1px solid var(--color-border);border-radius:var(--radius);font-size:12px;color:var(--color-text)}.prereq-tag-remove{background:none;border:none;padding:0;color:var(--color-text-dim);cursor:pointer;font-size:14px;line-height:1;display:flex;align-items:center}.prereq-tag-remove:hover{color:var(--status-failed);background:none;border:none}.confirm-dialog-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:300;display:flex;align-items:center;justify-content:center;padding:24px;background:#05070cb8;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.confirm-dialog{width:min(480px,100%);background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-xl);box-shadow:0 24px 64px #0000008c;padding:22px 24px 20px}.confirm-dialog-title{font-size:18px;font-weight:700;margin-bottom:12px;color:var(--color-text)}.confirm-dialog-body{font-size:14px;color:var(--color-text-muted);line-height:1.55;display:flex;flex-direction:column;gap:10px}.confirm-dialog-body strong{color:var(--color-text);font-weight:600}.confirm-dialog-note{font-size:13px;color:var(--color-text-dim)}.confirm-dialog-note--warn{color:var(--status-failed)}.confirm-dialog-list{margin:4px 0 0 18px;font-size:12px;color:var(--color-text-dim);line-height:1.6}.confirm-dialog-actions{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px;margin-top:20px}.confirm-dialog-btn{border-radius:var(--radius);padding:8px 14px;font-size:13px;font-weight:600;cursor:pointer;border:1px solid var(--color-border);background:var(--color-surface-raised);color:var(--color-text);transition:background var(--transition),border-color var(--transition),color var(--transition)}.confirm-dialog-btn:hover:not(:disabled){background:var(--color-surface-hover)}.confirm-dialog-btn:disabled{opacity:.55;cursor:not-allowed}.confirm-dialog-btn--ghost{background:transparent;border-color:transparent;color:var(--color-text-muted)}.confirm-dialog-btn--ghost:hover:not(:disabled){background:var(--color-surface-raised);color:var(--color-text)}.confirm-dialog-btn--primary{background:var(--status-cancelled);border-color:color-mix(in srgb,var(--status-cancelled) 70%,#000);color:#fff}.confirm-dialog-btn--primary:hover:not(:disabled){filter:brightness(1.08)}.confirm-dialog-btn--danger{background:var(--status-failed-bg);border-color:color-mix(in srgb,var(--status-failed) 45%,transparent);color:var(--status-failed)}.confirm-dialog-btn--danger:hover:not(:disabled){background:color-mix(in srgb,var(--status-failed) 18%,transparent)}.jx-login-shell{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;background:radial-gradient(1200px 600px at 50% -10%,rgba(99,102,241,.18),transparent 60%),#0b0d12;font-family:Outfit,system-ui,-apple-system,sans-serif;color:#e6e8ee}.jx-login-card{width:100%;max-width:380px;background:#14171f;border:1px solid #232733;border-radius:16px;padding:32px 28px;box-shadow:0 24px 60px #00000073}.jx-login-brand{display:flex;align-items:center;gap:10px;font-size:20px;font-weight:600;letter-spacing:-.01em}.jx-login-brand-icon{color:#818cf8;font-size:18px}.jx-login-sub{margin:10px 0 24px;font-size:14px;color:#9aa1b1}.jx-login-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px;font-size:13px;color:#c4c9d4}.jx-login-field input{width:100%;box-sizing:border-box;padding:11px 12px;border-radius:9px;border:1px solid #2a2f3c;background:#0e1117;color:#e6e8ee;font-size:14px;font-family:inherit}.jx-login-field input:focus{outline:none;border-color:#6366f1}.jx-login-error{margin:4px 0 12px;padding:10px 12px;border-radius:9px;background:#ef44441f;border:1px solid rgba(239,68,68,.35);color:#fca5a5;font-size:13px}.jx-login-btn{display:block;box-sizing:border-box;width:100%;margin-top:8px;padding:12px;border:none;border-radius:10px;background:#6366f1;color:#fff;font-size:14px;font-weight:600;font-family:inherit;text-align:center;text-decoration:none;cursor:pointer}.jx-login-btn:hover:not(:disabled){background:#4f52e0}.jx-login-btn:disabled{opacity:.55;cursor:not-allowed}.jx-login-foot{margin-top:22px;text-align:center;font-size:12px;color:#6b7280}.jx-login-spinner{width:28px;height:28px;margin:18px auto 4px;border:3px solid #2a2f3c;border-top-color:#6366f1;border-radius:50%;animation:jx-spin .8s linear infinite}@keyframes jx-spin{to{transform:rotate(360deg)}}.jx-logout-btn{position:fixed;bottom:16px;left:16px;z-index:9999;padding:7px 13px;border:1px solid #2a2f3c;border-radius:8px;background:#14171feb;color:#c4c9d4;font-size:12px;font-family:Outfit,system-ui,sans-serif;cursor:pointer;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}.jx-logout-btn:hover{border-color:#6366f1;color:#e6e8ee}.jx-auth-splash{min-height:100vh;display:flex;align-items:center;justify-content:center;background:#0b0d12;color:#6b7280;font-family:Outfit,system-ui,sans-serif;font-size:14px}