runcastle 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +47 -0
  2. package/bin/runcastle.js +5580 -0
  3. package/drizzle/0000_amused_bruce_banner.sql +74 -0
  4. package/drizzle/0001_mapped_feature_flag.sql +1 -0
  5. package/drizzle/0002_waypoints.sql +14 -0
  6. package/drizzle/0003_project_closed_at.sql +1 -0
  7. package/drizzle/0004_events_project_id.sql +28 -0
  8. package/drizzle/0005_project_setting_overrides.sql +2 -0
  9. package/drizzle/meta/0000_snapshot.json +466 -0
  10. package/drizzle/meta/0001_snapshot.json +474 -0
  11. package/drizzle/meta/0002_snapshot.json +568 -0
  12. package/drizzle/meta/0003_snapshot.json +575 -0
  13. package/drizzle/meta/0004_snapshot.json +582 -0
  14. package/drizzle/meta/0005_snapshot.json +596 -0
  15. package/drizzle/meta/_journal.json +48 -0
  16. package/hook-client.ts +67 -0
  17. package/index.js +5424 -0
  18. package/package.json +24 -30
  19. package/pty-host.cjs +186 -0
  20. package/sandcastle-template/Containerfile +33 -0
  21. package/sandcastle-template/Dockerfile +33 -0
  22. package/skills/burner/implement-ticket.md +42 -0
  23. package/skills/burner/research-waypoint.md +45 -0
  24. package/skills/packs/README.md +50 -0
  25. package/skills/packs/runcastle/.claude-plugin/plugin.json +6 -0
  26. package/skills/packs/runcastle/skills/converge/SKILL.md +51 -0
  27. package/skills/packs/runcastle/skills/ideate/SKILL.md +81 -0
  28. package/skills/packs/runcastle/skills/qa/SKILL.md +30 -0
  29. package/skills/packs/runcastle/skills/spec/SKILL.md +43 -0
  30. package/skills/packs/runcastle/skills/tickets/SKILL.md +52 -0
  31. package/skills/packs/runcastle/skills/waypoint/SKILL.md +54 -0
  32. package/web/assets/index-CKZ5Z7vc.css +1 -0
  33. package/web/assets/index-YBuT7tTz.js +108 -0
  34. package/web/index.html +13 -0
  35. package/dist/add-PRGLHAVL.js +0 -298
  36. package/dist/add-PRGLHAVL.js.map +0 -1
  37. package/dist/chunk-44KDPUYJ.js +0 -49
  38. package/dist/chunk-44KDPUYJ.js.map +0 -1
  39. package/dist/chunk-5VPKMXSV.js +0 -190
  40. package/dist/chunk-5VPKMXSV.js.map +0 -1
  41. package/dist/chunk-6CWCR5SO.js +0 -24
  42. package/dist/chunk-6CWCR5SO.js.map +0 -1
  43. package/dist/chunk-AHRTPV2C.js +0 -1082
  44. package/dist/chunk-AHRTPV2C.js.map +0 -1
  45. package/dist/chunk-LP5MV76P.js +0 -33
  46. package/dist/chunk-LP5MV76P.js.map +0 -1
  47. package/dist/chunk-OJ356IMJ.js +0 -136
  48. package/dist/chunk-OJ356IMJ.js.map +0 -1
  49. package/dist/chunk-PRNBOQHW.js +0 -32
  50. package/dist/chunk-PRNBOQHW.js.map +0 -1
  51. package/dist/chunk-SNUH2UT6.js +0 -95
  52. package/dist/chunk-SNUH2UT6.js.map +0 -1
  53. package/dist/chunk-UCYVC3H6.js +0 -108
  54. package/dist/chunk-UCYVC3H6.js.map +0 -1
  55. package/dist/chunk-Y5P5BQWF.js +0 -136
  56. package/dist/chunk-Y5P5BQWF.js.map +0 -1
  57. package/dist/chunk-ZQ3BK4ZD.js +0 -134
  58. package/dist/chunk-ZQ3BK4ZD.js.map +0 -1
  59. package/dist/index.js +0 -94
  60. package/dist/index.js.map +0 -1
  61. package/dist/info-U6AZZ2TV.js +0 -78
  62. package/dist/info-U6AZZ2TV.js.map +0 -1
  63. package/dist/init-MOJNLWXK.js +0 -212
  64. package/dist/init-MOJNLWXK.js.map +0 -1
  65. package/dist/logout-YPGZ6BB6.js +0 -27
  66. package/dist/logout-YPGZ6BB6.js.map +0 -1
  67. package/dist/publish-W37Y6TO6.js +0 -211
  68. package/dist/publish-W37Y6TO6.js.map +0 -1
  69. package/dist/search-2KNAXPM5.js +0 -55
  70. package/dist/search-2KNAXPM5.js.map +0 -1
  71. package/dist/update-NIIUPL2E.js +0 -123
  72. package/dist/update-NIIUPL2E.js.map +0 -1
  73. package/dist/validate-GFDSEVPV.js +0 -12
  74. package/dist/validate-GFDSEVPV.js.map +0 -1
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: spec
3
+ description: Synthesize the ideation conversation and decisions.md into docs/features/<slug>/spec.md, then complete the spec phase. No interview — pure synthesis. Invoked by /runcastle:ideate for size=full features.
4
+ disable-model-invocation: false
5
+ ---
6
+ <!-- Forked from Matt Pocock's to-spec skill, via https://github.com/mattpocock/skills, 2026-07-14, adapted for runcastle -->
7
+
8
+ # Spec
9
+
10
+ Turn the ideation conversation plus `docs/features/<slug>/decisions.md` into a spec at `docs/features/<slug>/spec.md`. **Do NOT interview the human** — you are inside the unbroken ideation window; synthesize what you already know. Do not compact or clear.
11
+
12
+ ## Process
13
+
14
+ 1. **Load state.** `mcp__runcastle__get_feature_context` for the feature, the locked `decisions.md`, and any existing `spec.md` (this may be a re-run). Explore the codebase for its current state if you have not already; use the project's domain vocabulary throughout and respect any ADRs in the area you touch.
15
+
16
+ 2. **Sketch the seams** — the public boundaries the feature will be tested at. Prefer *existing* seams to new ones; use the *highest* seam possible; the fewer across the codebase, the better — the ideal is one. If new seams are needed, propose them at the highest point you can. These seams flow straight into the tickets and the burner, so get them right here.
17
+
18
+ 3. **Write `spec.md`** with exactly these sections:
19
+
20
+ ```markdown
21
+ # <Feature title>
22
+
23
+ ## Problem
24
+ The problem the user faces, from the user's perspective.
25
+
26
+ ## Approach
27
+ The solution from the user's perspective, then the shape of it: modules built/modified, their interfaces, schema/API/contract decisions, key interactions. Prose, not a file-by-file plan.
28
+
29
+ ## Seams
30
+ The interfaces to test at (from step 2) — each named, with what it lets you observe. Flag which are existing vs. new.
31
+
32
+ ## Out of scope
33
+ What this feature explicitly does not cover.
34
+
35
+ ## Open questions
36
+ Anything still unresolved or deliberately deferred.
37
+ ```
38
+
39
+ Do **not** hardcode specific file paths or code snippets — they go stale. Exception: if the ideation produced a snippet that pins a decision more precisely than prose can (a state machine, reducer, schema, type shape), inline the decision-rich parts and note it came from that discussion.
40
+
41
+ 4. **Complete the phase.** `mcp__runcastle__record_event({ type: "spec.written", message: "<feature title>" })`, then `mcp__runcastle__complete_phase({ phase: "spec" })`. If the gate returns `ok: false`, it names what is missing — fix and retry.
42
+
43
+ Return control to `/runcastle:ideate`, which invokes `/runcastle:tickets` next.
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: tickets
3
+ description: Break the spec (or decisions.md when collapsed) into tracer-bullet vertical slices, each self-sufficient for one fresh sandboxed agent, and emit them via MCP. Then complete the tickets phase. Invoked by /runcastle:ideate.
4
+ disable-model-invocation: false
5
+ ---
6
+ <!-- Forked from Matt Pocock's to-tickets skill, via https://github.com/mattpocock/skills, 2026-07-14, adapted for runcastle -->
7
+
8
+ # Tickets
9
+
10
+ Break the work into **tickets** — tracer-bullet vertical slices — and emit them to the runcastle store via `mcp__runcastle__emit_tickets`. You are still in the unbroken ideation window: synthesize from the spec (`docs/features/<slug>/spec.md`) or, for collapsed features, straight from `decisions.md`. Do not compact or clear.
11
+
12
+ ## The one thing that makes a runcastle ticket different
13
+
14
+ Each ticket is executed by a **single fresh agent, alone, in a sandbox, with ~100k tokens and NO way to ask a follow-up question.** It sees only what you put in the ticket plus the code already in the repo. So — *inverting* the usual "avoid file paths, they go stale" rule — the ticket's `context` field **must be concrete and self-sufficient**: name the files to touch, the existing patterns to copy, the type/schema shapes, the gotchas, the commands to run and verify with. A ticket that assumes the agent can ask "where does X live?" is a broken ticket. Over-specify context; under-specify nothing.
15
+
16
+ ## 1. Draft vertical slices
17
+
18
+ <vertical-slice-rules>
19
+ - Each slice cuts a narrow but COMPLETE path through every layer it needs (schema, API, UI, tests) — vertical, NOT a horizontal slice of one layer.
20
+ - A completed slice is demoable or verifiable on its own.
21
+ - Each slice fits comfortably in one fresh ~100k-token agent session working alone.
22
+ - Any prefactoring is its own slice, done first ("make the change easy, then make the easy change").
23
+ </vertical-slice-rules>
24
+
25
+ Give each ticket its **blocking edges** — the tickets that must finish before it can start. No blockers → it can start immediately.
26
+
27
+ <wide-refactor-exception>
28
+ A **wide refactor** — one mechanical change (rename a column, retype a shared symbol) whose blast radius breaks thousands of call sites at once — cannot land green as a vertical slice. Sequence it **expand → migrate → contract** instead. Expand: add the new form beside the old so nothing breaks (one ticket). Migrate: move call sites over in batches sized by blast radius (per package/dir), each batch a ticket blocked by the expand, CI green throughout because the old form still exists. Contract: delete the old form once no caller remains, blocked by every migrate batch. If even the batches cannot stay green alone, let them share an integration branch that all block a final integrate-and-verify ticket — green is promised only there.
29
+ </wide-refactor-exception>
30
+
31
+ ## 2. Build each ticket to the schema
32
+
33
+ Emit an array of `TicketInput`. Number them from 1 in the array in **dependency order (blockers first)**; `blockedBy` holds those numbers (they are the seq numbers the store assigns).
34
+
35
+ Each ticket:
36
+ - **title** — short, descriptive, in the domain vocabulary.
37
+ - **goal** — the end-to-end behaviour this ticket makes work, from the user's/caller's perspective. Not a layer list.
38
+ - **context** — everything the sandboxed agent needs and cannot ask for: file paths to touch, existing patterns/modules to follow, type/schema shapes, gotchas, how to run and verify. Be concrete (see above).
39
+ - **acceptanceCriteria** — `string[]`, each independently *verifiable* (a behaviour you can observe, a command that passes). These are what the burner works red-green against.
40
+ - **seams** — `string[]`, the public interfaces to test at (carry them from the spec's Seams section; prefer existing, prefer the highest, prefer one).
41
+ - **blockedBy** — `number[]`, the seq numbers (from your 1..N ordering) of the tickets that *genuinely* gate this one. Only true gates.
42
+
43
+ ## 3. Self-check, then emit
44
+
45
+ There is no in-session quiz — the human's review is the **Burn** gate in the runcastle UI, reading these cards. So make them right before you emit. Check yourself: is the granularity right (each a demoable slice, none a horizontal layer)? Are the blocking edges minimal and correct? Is every `context` self-sufficient for an agent that cannot ask?
46
+
47
+ Then:
48
+ - `mcp__runcastle__emit_tickets({ tickets: [...] })` — **emit the array; do NOT write ticket files.** It returns `{ stored, ids }`.
49
+ - `mcp__runcastle__record_event({ type: "tickets.emitted", message: "<n> tickets" })`.
50
+ - `mcp__runcastle__complete_phase({ phase: "tickets" })`. If the gate returns `ok: false`, fix what it names and retry.
51
+
52
+ Return to `/runcastle:ideate` to close out the session.
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: waypoint
3
+ description: The runcastle waypoint session. Work ONE waypoint on a feature's map — grill, prototype, or run a task checklist for its assigned question — write the decision prose to the docs, then resolve the waypoint. Entry skill for kind=waypoint sessions.
4
+ disable-model-invocation: false
5
+ ---
6
+ <!-- runcastle mapped-ideation waypoint session (ADR-0001 §13.5) -->
7
+
8
+ # Waypoint — work one node on the map
9
+
10
+ This is a **mapped-ideation** feature: too big for one context window, so it was charted into a *map* of waypoints. You have been handed exactly ONE of them. Your job is narrow and finite: answer its question, write the decision down, resolve it. You are **not** converging the whole feature, writing a spec, or emitting tickets — other sessions and the human own that.
11
+
12
+ ## 0. Orient
13
+
14
+ 1. Call `mcp__runcastle__get_feature_context`. For a mapped feature it returns, besides the usual feature/phase/docs, the full `map` state: `waypoints`, the `frontier`, and — the one that matters here — `assignedWaypoint`: **your** waypoint (the one this session claimed). Read its `title`, `type`, and `question`. The injected system prompt carries the same question; trust `get_feature_context` for the live state.
15
+ 2. Read `docs/features/<slug>/map.md` (Destination, Notes, Not-yet-specified, Out-of-scope) so your answer fits the north star, and skim `decisions.md` for what is already locked — **do not re-litigate settled decisions.**
16
+ 3. `mcp__runcastle__record_event({ type: "waypoint.started", message: "<waypoint title>" })`.
17
+
18
+ ## 1. Work it — mode by type
19
+
20
+ Your `assignedWaypoint.type` picks the mode:
21
+
22
+ - **`grilling`** → grill the human on the question exactly as `/runcastle:ideate` does: one question at a time, always recommend an answer, look up facts in the code, model the domain, don't move on until you share understanding. Scope the grill to THIS waypoint's question — resist wandering into the whole feature.
23
+ - **`prototype`** → build the smallest throwaway spike that answers the question (a fork to compare approaches, a spike to prove feasibility). The prototype exists to produce a decision, not to ship — capture what it proved, then let it go.
24
+ - **`task`** → run the concrete checklist the question describes (gather the facts, enumerate the cases, fill the table). Produce the artifact the waypoint asked for.
25
+
26
+ If, while working, you discover the question really splits into new sub-questions or uncovers whole new branches, chart them: `mcp__runcastle__emit_waypoints({ waypoints: [...] })` — each with `title`, `type`, `question`, `blockedBy` (1-based positions in this batch and/or existing waypoint ids), and `originWaypointId: "<your waypoint id>"` so the lineage ("surfaced by …") is recorded. Any mapped session may branch the map; that is the recursion. Emitting a waypoint does **not** relieve you of answering your own.
27
+
28
+ ## 2. Write the decision prose — directly, to the docs
29
+
30
+ The answer is **prose in the docs**, not a tool argument. Serial HITL makes these writes race-free, so edit the files directly in this talk worktree:
31
+
32
+ - **Resolving** (question answered): append the decision to `docs/features/<slug>/decisions.md`, one entry:
33
+
34
+ ```markdown
35
+ ## <n>. <short decision title>
36
+ **Decision:** <the choice, in the project's domain vocabulary>
37
+ **Why:** <the reason / the trade-off chosen over the alternatives>
38
+ ```
39
+
40
+ - **Dropping** (no longer worth answering): record a one-line gist under `## Out of scope` in `docs/features/<slug>/map.md`, so the map remembers why it was cut.
41
+
42
+ Write the prose **before** you resolve — the resolve tool flips machinery only and does not carry your answer.
43
+
44
+ ## 3. Resolve — end the session
45
+
46
+ `mcp__runcastle__resolve_waypoint({ id: "<your waypoint id>", disposition: "resolved" | "dropped", summary: "<one-line gist>" })`.
47
+
48
+ This marks your waypoint terminal and frees any waypoint that was blocked only on yours — they appear on the frontier for the next session to Work. The `summary` is the one line shown on the map card.
49
+
50
+ Then tell the human plainly:
51
+
52
+ > This waypoint is resolved — its decision is in `decisions.md`. Back in the runcastle UI, the frontier has updated; work the next waypoint, or converge once it clears. I'll stop here.
53
+
54
+ **End the session.** One waypoint, one session. Do **not** claim or work another waypoint, do **not** converge, do **not** spec or emit tickets. If you close the terminal without resolving, runcastle auto-releases the waypoint back to the frontier and offers **Resume** — so resolving is how you signal you are genuinely done.
@@ -0,0 +1 @@
1
+ .xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}:root{--bg:#090b10;--panel:#0e1117;--panel-2:#0b0e14;--panel-3:#12151d;--panel-inset:#07080b;--hairline:#1c2230;--hairline-soft:#151a26;--hairline-strong:#2a3242;--text:#dde3ed;--text-2:#96a0b0;--text-3:#5f6a7a;--text-4:#3a4354;--accent:#7c6cf6;--accent-hi:#a49bff;--accent-2:#8f80f8;--accent-ink:#0d0722;--accent-soft:#161329;--accent-line:#3d3670;--ph-ideation:#8b7cf8;--ph-spec:#8a94a2;--ph-tickets:#d7a94a;--ph-implementation:#f0883e;--ph-review:#58a6ff;--ph-shipped:#3fb950;--danger:#f4594e;--needs:#d7a94a;--ok:#3fb950;--drive:#58a6ff;--mono:"Cascadia Code", "JetBrains Mono", Consolas, ui-monospace, monospace;--sans:system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--radius-sm:5px;--radius:6px;--radius-lg:9px;--radius-pill:999px;--control-h:26px;--sidebar-w:250px;--inspector-w:296px;--dur-1:.12s;--dur-2:.19s;--dur-3:.32s;--ease:cubic-bezier(.22, .61, .24, 1);--ease-out:cubic-bezier(.16, 1, .3, 1);--ring:0 0 0 2px var(--bg), 0 0 0 4px #7c6cf680}*{box-sizing:border-box}html,body,#root{height:100%;margin:0;padding:0}body{background:var(--bg);color:var(--text);font-family:var(--sans);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;font-size:13px;line-height:1.45;overflow:hidden}button{color:inherit;font-family:inherit}:focus-visible{box-shadow:var(--ring);border-radius:var(--radius-sm);outline:none}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:#1c2230 padding-box padding-box;border:2px solid #0000;border-radius:5px}::-webkit-scrollbar-thumb:hover{background:#2a3242 padding-box padding-box;border:2px solid #0000}::-webkit-scrollbar-track{background:0 0}.mono{font-family:var(--mono);font-size:12.5px}.dim{color:var(--text-3)}.dim-line{color:var(--text-3);font-family:var(--mono);padding:2px 0;font-size:12.5px}.section-title{text-transform:uppercase;letter-spacing:.09em;color:var(--text-3);padding:4px 0;font-size:11px;font-weight:600}.phase-fg-ideation{color:var(--ph-ideation)}.phase-fg-spec{color:var(--ph-spec)}.phase-fg-tickets{color:var(--ph-tickets)}.phase-fg-implementation{color:var(--ph-implementation)}.phase-fg-review{color:var(--ph-review)}.phase-fg-shipped{color:var(--ph-shipped)}.btn{height:var(--control-h);border-radius:var(--radius);border:1px solid var(--hairline);color:var(--text);cursor:pointer;white-space:nowrap;transition:border-color var(--dur-1) var(--ease), background var(--dur-1) var(--ease), color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease), box-shadow var(--dur-2) var(--ease), opacity var(--dur-1);background:0 0;justify-content:center;align-items:center;gap:6px;padding:0 12px;font-size:12.5px;display:inline-flex}.btn:disabled{opacity:.4;cursor:not-allowed}.btn:active:not(:disabled){transform:translateY(.5px)scale(.99)}.btn-ghost:hover:not(:disabled){border-color:var(--hairline-strong);background:var(--panel);color:var(--text)}.btn-solid{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:600}.btn-solid:hover:not(:disabled){background:var(--accent-2);border-color:var(--accent-2);transform:translateY(-1px);box-shadow:0 4px 16px -6px #7c6cf6b3}.btn-solid:active:not(:disabled){box-shadow:none;transform:translateY(0)}.btn-danger{border-color:color-mix(in srgb, var(--danger) 55%, var(--hairline));color:var(--danger)}.btn-danger:hover:not(:disabled){border-color:var(--danger);background:#f4594e1f}.btn-xs{border-radius:var(--radius-sm);height:22px;padding:0 9px;font-size:11.5px}.btn-lg{height:32px;padding:0 16px;font-size:13px}.ghost-link{color:var(--text-2);cursor:pointer;transition:color var(--dur-1) var(--ease);background:0 0;border:none;padding:2px 0;font-size:12.5px}.ghost-link:hover:not(:disabled){color:var(--accent-hi)}.ghost-link:disabled{opacity:.4;cursor:not-allowed}.chip{border-radius:var(--radius-pill);border:1px solid var(--hairline);height:19px;font-family:var(--mono);color:var(--text-2);white-space:nowrap;align-items:center;gap:5px;padding:0 8px;font-size:10.5px;display:inline-flex}.chip-neutral{color:var(--text-2)}.chip-blocked{color:var(--needs);border-color:color-mix(in srgb, var(--needs) 40%, transparent)}.chip-ticket-pending{color:var(--text-3)}.chip-ticket-burning{color:var(--ph-implementation);border-color:color-mix(in srgb, var(--ph-implementation) 45%, transparent);background:color-mix(in srgb, var(--ph-implementation) 8%, transparent);animation:1.5s ease-in-out infinite pulse}.chip-ticket-done{color:var(--ok);border-color:color-mix(in srgb, var(--ok) 40%, transparent)}.chip-ticket-failed{color:var(--danger);border-color:color-mix(in srgb, var(--danger) 45%, transparent)}.chip-run-running{color:var(--ph-implementation);border-color:color-mix(in srgb, var(--ph-implementation) 45%, transparent);animation:1.5s ease-in-out infinite pulse}.chip-run-succeeded{color:var(--ok);border-color:color-mix(in srgb, var(--ok) 40%, transparent)}.chip-run-failed{color:var(--danger);border-color:color-mix(in srgb, var(--danger) 45%, transparent)}.chip-run-cancelled{color:var(--text-3)}.tag{font-family:var(--mono);text-transform:lowercase;font-size:12px;font-weight:600}.status-dot{background:var(--text-3);border-radius:50%;flex:none;width:7px;height:7px;display:inline-block}.sess-dot-launching{background:var(--needs);animation:1.3s ease-in-out infinite pulse}.sess-dot-live{background:var(--ok);box-shadow:0 0 0 3px #3fb95029}.sess-dot-ended{background:var(--text-3)}.spinner,.spin-ring{border:1.6px solid var(--ph-implementation);border-top-color:#0000;border-radius:50%;flex:none;width:12px;height:12px;animation:.8s linear infinite spin;display:inline-block}.shell{grid-template-rows:42px 1fr 26px;height:100%;display:grid}.shell-body{grid-template-columns:var(--sidebar-w) 1fr var(--inspector-w);min-height:0;display:grid}.shell.inspector-collapsed .shell-body{grid-template-columns:var(--sidebar-w) 1fr}.titlebar{border-bottom:1px solid var(--hairline);background:var(--panel);align-items:center;gap:9px;padding:0 14px;font-size:13px;display:flex}.tb-logo{border-radius:var(--radius-sm);background:var(--accent);width:18px;height:18px;color:var(--accent-ink);font-family:var(--mono);flex:none;justify-content:center;align-items:center;font-size:11px;font-weight:700;display:flex}.tb-app{color:var(--text);letter-spacing:.02em;font-weight:600}.tb-arrow,.tb-dot{color:var(--text-4)}.tb-project{color:var(--text-2)}.tb-branch{color:var(--text-3);font-family:var(--mono);font-size:11.5px}.tb-spacer{flex:1}.tb-search{background:var(--panel-inset);border:1px solid var(--hairline);border-radius:var(--radius);height:26px;color:var(--text-3);cursor:pointer;transition:border-color var(--dur-1), color var(--dur-1);align-items:center;gap:8px;min-width:190px;padding:0 10px;font-size:12px;display:flex}.tb-search:hover{border-color:var(--hairline-strong);color:var(--text-2)}.tb-search-spacer{flex:1}.kbd{font-family:var(--mono);border:1px solid var(--hairline-strong);color:var(--text-3);border-radius:4px;padding:1px 5px;font-size:10px;line-height:1.4}.tb-runs{border-radius:var(--radius-pill);border:1px solid color-mix(in srgb, var(--ph-implementation) 30%, transparent);background:color-mix(in srgb, var(--ph-implementation) 9%, transparent);height:24px;color:var(--ph-implementation);font-family:var(--mono);animation:fadeUp var(--dur-3) var(--ease-out);align-items:center;gap:7px;padding:0 10px;font-size:11px;display:inline-flex}.health-dot{background:var(--text-3);width:8px;height:8px;transition:background var(--dur-2);border-radius:50%;display:inline-block}.tb-health.is-ok .health-dot,.sb-health.is-ok .health-dot{background:var(--ok)}.tb-health.is-down .health-dot,.sb-health.is-down .health-dot{background:var(--danger);animation:1s ease-in-out infinite pulse}.tb-icon-btn{border:1px solid var(--hairline);border-radius:var(--radius);width:26px;height:26px;color:var(--text-3);cursor:pointer;transition:color var(--dur-1), border-color var(--dur-1);background:0 0;justify-content:center;align-items:center;font-size:12px;display:inline-flex}.tb-icon-btn:hover{color:var(--text);border-color:var(--hairline-strong)}.sidebar{border-right:1px solid var(--hairline);background:var(--panel-2);flex-direction:column;min-height:0;display:flex}.sidebar-head{border-bottom:1px solid var(--hairline-soft);flex:0 0 40px;justify-content:space-between;align-items:center;height:40px;padding:0 12px;display:flex}.sidebar-head .pane-title{text-transform:uppercase;letter-spacing:.09em;color:var(--text-3);font-size:11px;font-weight:600}.new-btn{border:1px solid var(--accent-line);border-radius:var(--radius);height:22px;color:var(--accent-hi);cursor:pointer;transition:background var(--dur-1), border-color var(--dur-1), transform var(--dur-1);background:0 0;padding:0 9px;font-size:11.5px}.new-btn:hover{background:var(--accent-soft);border-color:var(--accent)}.new-btn:active{transform:scale(.96)}.sidebar-list{flex:1;min-height:0;padding:4px 6px 12px;overflow-y:auto}.triage-group+.triage-group{margin-top:4px}.triage-label{letter-spacing:.09em;text-transform:uppercase;align-items:center;gap:6px;padding:11px 8px 5px;font-size:10px;font-weight:700;display:flex}.triage-count{color:var(--text-4);font-family:var(--mono);font-weight:500}.triage-needsYou .triage-label>.triage-name{color:var(--needs)}.triage-agentWorking .triage-label>.triage-name{color:var(--ph-implementation)}.triage-inProgress .triage-label>.triage-name{color:var(--text-3)}.triage-shipped .triage-label>.triage-name{color:var(--ph-shipped)}.feature-row{border-radius:var(--radius-sm);cursor:pointer;text-align:left;width:100%;min-height:30px;transition:background var(--dur-1) var(--ease);background:0 0;border:none;align-items:center;gap:8px;padding:0 8px 0 9px;display:flex;position:relative}.feature-row:before{content:"";background:var(--accent);transform-origin:50%;width:2px;transition:transform var(--dur-2) var(--ease-out);border-radius:2px;position:absolute;top:6px;bottom:6px;left:1px;transform:scaleY(0)}.feature-row:hover,.feature-row.is-active{background:var(--panel-3)}.feature-row.is-active:before{transform:scaleY(1)}.feature-row.is-active .feature-slug{color:var(--text)}.feature-row.is-shipped{opacity:.55}.feature-row.is-shipped:hover{opacity:.85}.feature-glyph{font-family:var(--mono);text-align:center;flex:none;width:14px;font-size:12px}.feature-slug{min-width:0;color:var(--text-2);text-overflow:ellipsis;white-space:nowrap;transition:color var(--dur-1);flex:1;font-size:12.5px;overflow:hidden}.feature-flag{flex:none;align-items:center;gap:3px;display:flex}.needs-dot{background:var(--needs);border-radius:50%;width:7px;height:7px}.needs-attention{background:var(--danger)}.needs-grill,.needs-burn,.needs-ship{background:var(--needs)}.mini-check{color:var(--ph-shipped);font-family:var(--mono);font-size:10px}.mini-map{align-items:center;gap:2px;display:flex}.mini-seg{background:var(--text-4);width:6px;height:6px;transition:background var(--dur-2);border-radius:2px}.mini-seg.is-done{background:var(--text-3)}.mini-seg.is-current{background:var(--accent);box-shadow:0 0 0 2px #7c6cf638}.mini-seg.is-skipped{border:1px solid var(--text-4);background:0 0}.sidebar-foot{border-top:1px solid var(--hairline-soft);color:var(--text-4);padding:10px 12px;font-size:11px;line-height:1.5}.nf-form{border:1px solid var(--hairline);border-radius:var(--radius);background:var(--panel);animation:fadeUp var(--dur-2) var(--ease-out);flex-direction:column;gap:8px;margin:6px;padding:10px;display:flex}.workspace{background:var(--bg);flex-direction:column;min-width:0;min-height:0;display:flex;position:relative}.ws-empty{height:100%;color:var(--text-3);flex-direction:column;justify-content:center;align-items:center;gap:12px;display:flex}.ws-empty-logo{background:var(--panel);border:1px solid var(--hairline);width:46px;height:46px;color:var(--accent);font-family:var(--mono);border-radius:12px;justify-content:center;align-items:center;font-size:22px;font-weight:700;display:flex}.ws-head{flex:none;padding:16px 28px 0}.ws-title-row{align-items:center;gap:10px;display:flex}.ws-title{color:var(--text);font-size:16px;font-weight:600}.ws-title-spacer{flex:1}.ws-branch{font-family:var(--mono);color:var(--text-3);cursor:pointer;transition:color var(--dur-1);background:0 0;border:none;font-size:11.5px}.ws-branch:hover{color:var(--text)}.pipeline{align-items:center;margin-top:16px;display:flex}.pstep{border-radius:var(--radius-pill);cursor:default;height:26px;color:var(--text-3);transition:background var(--dur-1), color var(--dur-1), border-color var(--dur-1), transform var(--dur-1);background:0 0;border:1px solid #0000;align-items:center;gap:7px;padding:0 10px;font-size:12px;display:inline-flex}.pstep.is-clickable{cursor:pointer}.pstep.is-clickable:hover{background:var(--panel);color:var(--text)}.pstep.is-clickable:active{transform:scale(.97)}.pstep-dot{opacity:.5;width:8px;height:8px;transition:opacity var(--dur-2), box-shadow var(--dur-2);background:currentColor;border-radius:50%;flex:none}.pstep-label{text-transform:lowercase}.pstep.is-done{color:var(--text-2)}.pstep.is-done .pstep-dot{opacity:1}.pstep.is-current{color:var(--text);font-weight:600}.pstep.is-current .pstep-dot{opacity:1;background:var(--accent);animation:2.4s ease-in-out infinite dotGlow;box-shadow:0 0 0 3px #7c6cf633}.pstep.is-upcoming,.pstep.is-skipped{color:var(--text-4)}.pstep.is-skipped .pstep-label{opacity:.7;text-decoration:line-through}.pstep.is-viewed{border-color:var(--hairline);background:var(--panel)}.pstep.is-viewed.is-current{border-color:var(--accent-line)}.pconn{background:var(--hairline);width:16px;height:1px;transition:background var(--dur-2);flex:none}.pconn.is-done{background:var(--text-4)}.nextstep{border:1px solid var(--hairline);background:var(--panel);border-radius:var(--radius-lg);animation:fadeUp var(--dur-3) var(--ease-out);align-items:center;gap:14px;margin:14px 28px 0;padding:13px 16px;display:flex}.nextstep-spin{flex:none}.nextstep-main{flex:1;min-width:0}.nextstep-kick{letter-spacing:.1em;color:var(--accent-hi);font-size:10px;font-weight:700}.nextstep-kick.is-progress{color:var(--ph-implementation)}.nextstep-kick.is-shipped{color:var(--ph-shipped)}.nextstep-kick.is-waiting{color:var(--text-3)}.nextstep-title{color:var(--text);margin-top:2px;font-size:13.5px;font-weight:600}.nextstep-desc{color:var(--text-2);text-wrap:pretty;margin-top:2px;font-size:12px;line-height:1.5}.nextstep-actions{flex:none;align-items:center;gap:8px;display:flex}.readonly-bar{border:1px dashed var(--hairline-strong);border-radius:var(--radius);background:var(--panel-2);color:var(--text-2);animation:fadeUp var(--dur-2) var(--ease-out);align-items:center;gap:10px;margin:12px 28px 0;padding:8px 14px;font-size:12px;display:flex}.readonly-tag{font-family:var(--mono);letter-spacing:.06em;color:var(--text-3);border:1px solid var(--hairline);border-radius:4px;padding:1px 6px;font-size:10px}.readonly-back{color:var(--accent-hi);cursor:pointer;background:0 0;border:none;margin-left:auto;font-size:12px}.readonly-back:hover{color:var(--accent-2)}.ws-banner{border:1px solid color-mix(in srgb, var(--danger) 55%, var(--hairline));border-radius:var(--radius);background:color-mix(in srgb, var(--danger) 8%, var(--panel-2));color:var(--danger);cursor:pointer;animation:fadeUp var(--dur-2) var(--ease-out);align-items:center;gap:10px;margin:10px 28px 0;padding:8px 14px;font-size:12.5px;display:flex}.ws-banner.is-offline{cursor:default;border-color:color-mix(in srgb, var(--warn,#d9a441) 45%, var(--hairline));background:color-mix(in srgb, var(--warn,#d9a441) 7%, var(--panel-2));color:var(--warn,#d9a441)}.ws-banner.is-offline .ws-banner-tag{border-color:color-mix(in srgb, var(--warn,#d9a441) 40%, var(--hairline))}.ws-banner-tag{font-family:var(--mono);letter-spacing:.06em;border:1px solid color-mix(in srgb, var(--danger) 45%, var(--hairline));border-radius:4px;flex-shrink:0;padding:1px 6px;font-size:10px}.ws-body{flex:1;min-height:0;padding:18px 28px 32px;overflow-y:auto}.ws-body-inner{animation:bodyIn var(--dur-3) var(--ease-out)}.body-title{align-items:baseline;gap:10px;margin-bottom:12px;display:flex}.body-title .section-title{padding:0}.body-hint{color:var(--text-3);text-wrap:pretty;font-size:12px}.body-meta{font-family:var(--mono);color:var(--text-2);font-size:11.5px}.surface{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel-2);overflow:hidden}.grill{max-width:900px}.grill-panel{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel-2);flex-direction:column;display:flex;overflow:hidden}.grill-strip{background:var(--panel);border-bottom:1px solid var(--hairline-soft);flex:0 0 34px;align-items:center;gap:10px;height:34px;padding:0 12px;display:flex}.grill-kind{border-radius:var(--radius-pill);border:1px solid var(--accent-line);background:var(--accent-soft);height:18px;color:var(--accent-hi);font-family:var(--mono);align-items:center;padding:0 8px;font-size:10.5px;display:inline-flex}.grill-sid{font-family:var(--mono);color:var(--text-3);font-size:11px}.grill-strip-spacer{flex:1}.sess-end{color:color-mix(in srgb, var(--danger) 70%, var(--text-2))}.sess-end:hover:not(:disabled){color:var(--danger);border-color:color-mix(in srgb, var(--danger) 55%, var(--hairline))}.grill-term{background:var(--bg);height:420px;min-height:260px;position:relative}.tickets-session{max-width:900px;margin-bottom:18px}.grill-empty{text-align:center;color:var(--text-3);flex-direction:column;align-items:center;gap:10px;padding:40px 24px;display:flex}.spec-doc{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel-2);max-width:780px;padding:22px 26px}.spec-meta{font-family:var(--mono);color:var(--text-3);font-size:11px}.spec-body{font-family:var(--mono);color:var(--text);white-space:pre-wrap;word-break:break-word;margin:10px 0 0;font-size:12.5px;line-height:1.7}.map-panel{max-width:780px;margin-bottom:22px}.map-sections{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--hairline);flex-direction:column;gap:1px;display:flex;overflow:hidden}.map-section{background:var(--panel-2);padding:14px 18px}.map-section-title{font-family:var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--accent-hi);margin-bottom:6px;font-size:10.5px}.map-section-body{font-family:var(--mono);color:var(--text);white-space:pre-wrap;word-break:break-word;font-size:12.5px;line-height:1.7}.map-waypoints{margin-top:16px}.map-waypoints:has(.wp-group){border:0;padding:0}.map-waypoints>.dim-line{border:1px dashed var(--hairline);border-radius:var(--radius-lg);text-align:center;padding:18px}.wp-group{margin-bottom:14px}.wp-group-title{font-family:var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--text-3);margin-bottom:7px;font-size:10.5px}.wp-group-frontier .wp-group-title{color:var(--accent-hi)}.wp-group-claimed .wp-group-title{color:var(--drive)}details.wp-group-done{border-top:1px solid var(--hairline-soft);padding-top:12px}details.wp-group-done>summary{cursor:pointer;list-style:revert}.wp{border:1px solid var(--hairline);border-radius:var(--radius-sm);background:var(--panel-2);flex-wrap:wrap;align-items:baseline;gap:9px;margin-bottom:6px;padding:9px 12px;display:flex}.wp-frontier{border-color:var(--accent-line)}.wp-blocked{opacity:.55}.wp-claimed{border-color:color-mix(in srgb, var(--drive) 45%, var(--hairline))}.wp-done{opacity:.6}.wp-type{font-family:var(--mono);letter-spacing:.05em;text-transform:uppercase;color:var(--text-2);border:1px solid var(--hairline-strong);border-radius:var(--radius-sm);flex-shrink:0;padding:1px 6px;font-size:10px}.wp-title{color:var(--text);font-size:13px}.wp-blockers,.wp-lineage,.wp-resume,.wp-summary{font-family:var(--mono);color:var(--text-3);font-size:11px}.wp-blockers{color:var(--needs)}.wp-lineage{flex-basis:100%}.wp-resume{color:var(--drive)}.wp-run-note{font-family:var(--mono);color:var(--drive);font-size:11px;font-style:italic}.wp-work{flex-shrink:0;align-self:center;margin-left:auto}.wp-pulse{background:var(--drive);border-radius:50%;flex-shrink:0;width:7px;height:7px;animation:1.4s ease-in-out infinite pulse}.converge-resume{flex-wrap:wrap;align-items:center;gap:12px;margin-top:14px;display:flex}.converge-bar{border-top:1px solid var(--hairline);flex-direction:column;align-items:flex-start;gap:12px;margin-top:18px;padding-top:16px;display:flex}.converge-fog{font-family:var(--mono);color:var(--needs);align-items:baseline;gap:8px;font-size:11.5px;line-height:1.6;display:flex}.converge-fog-icon{flex-shrink:0}.converge-fog-text{color:color-mix(in srgb, var(--needs) 82%, var(--text))}.converge-btn{min-width:120px}.converge-override{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.converge-blocked{flex-wrap:wrap;align-items:center;gap:12px;display:flex}.ledger{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel-2);max-width:1000px;overflow:hidden}.ledger-row+.ledger-row{border-top:1px solid var(--hairline-soft)}.ledger-head{cursor:pointer;text-align:left;width:100%;transition:background var(--dur-1);background:0 0;border:none;align-items:center;gap:10px;padding:10px 14px;display:flex}.ledger-head:hover{background:var(--panel-3)}.lg-caret{color:var(--text-4);width:10px;transition:transform var(--dur-2) var(--ease);flex:none;font-size:10px}.ledger-row.is-open .lg-caret{transform:rotate(90deg)}.lg-seq{color:var(--text-3);font-family:var(--mono);flex:none;width:22px;font-size:11.5px}.lg-title{min-width:0;color:var(--text);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:13px;overflow:hidden}.lg-block{font-family:var(--mono);color:var(--needs);flex:none;font-size:10.5px}.lg-meta{flex:none;align-items:center;gap:8px;display:flex}.lg-commits{color:var(--text-2);font-size:11px}.ledger-detail{background:var(--panel-inset);border-top:1px solid var(--hairline-soft);animation:detailIn var(--dur-2) var(--ease-out);padding:2px 16px 16px 46px;overflow:hidden}.td-section{margin-top:12px}.td-heading{letter-spacing:.07em;text-transform:uppercase;color:var(--text-3);margin-bottom:4px;font-size:10.5px;font-weight:600}.td-body{color:var(--text);white-space:pre-wrap;word-break:break-word;text-wrap:pretty;max-width:640px;line-height:1.55}.td-list{margin:0;padding-left:0;list-style:none}.td-list li{color:var(--text-2);gap:8px;padding:2px 0;line-height:1.5;display:flex}.td-list li:before{content:"—";color:var(--text-4);flex:none}.td-seams{flex-wrap:wrap;gap:6px;display:flex}.seam{font-family:var(--mono);color:var(--text-2);border:1px solid var(--hairline);background:var(--panel-2);border-radius:var(--radius-sm);padding:2px 7px;font-size:11px}.td-commits{flex-wrap:wrap;gap:6px;display:flex}.commit-sha{font-family:var(--mono);color:var(--ph-shipped);border:1px solid var(--hairline);cursor:pointer;transition:border-color var(--dur-1);background:0 0;border-radius:4px;padding:1px 6px;font-size:11px}.commit-sha:hover{border-color:var(--ph-shipped)}.td-error .td-heading{color:var(--danger)}.td-error-body{color:var(--danger);white-space:pre-wrap;word-break:break-word}.td-empty{font-family:var(--mono);color:var(--text-4);font-size:11.5px}.run-split{align-items:stretch;gap:14px;max-width:1120px;display:flex}.run-lanes-panel{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel-2);flex:2;align-self:flex-start;min-width:0;overflow:hidden}.panel-cap{border-bottom:1px solid var(--hairline-soft);letter-spacing:.07em;text-transform:uppercase;color:var(--text-3);padding:8px 12px;font-size:10.5px;font-weight:600}.run-lanes{flex-direction:column;gap:6px;padding:8px;display:flex}.lane{border:1px solid var(--hairline);border-left:2px solid var(--text-4);border-radius:var(--radius-sm);transition:border-color var(--dur-2);padding:8px 10px}.lane.status-burning{border-left-color:var(--ph-implementation);animation:1.7s ease-in-out infinite pulse}.lane.status-done{border-left-color:var(--ok)}.lane.status-failed{border-left-color:var(--danger)}.lane-head{align-items:center;gap:8px;display:flex}.lane-seq{color:var(--text-3);font-family:var(--mono);flex:none;font-size:11.5px}.lane-title{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12.5px;overflow:hidden}.lane-foot{justify-content:space-between;align-items:center;gap:8px;margin-top:6px;display:flex}.lane-commits{flex-wrap:wrap;gap:4px;display:flex}.lane-dur{color:var(--text-3);font-family:var(--mono);font-size:11px}.run-stream-panel{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel-inset);flex-direction:column;flex:3;min-width:0;max-height:460px;display:flex;overflow:hidden}.stream-head{border-bottom:1px solid var(--hairline-soft);background:var(--panel-2);justify-content:space-between;align-items:center;padding:8px 12px;display:flex}.follow-pill{border:1px solid var(--accent);color:var(--accent-hi);border-radius:var(--radius-pill);cursor:pointer;animation:fadeUp var(--dur-2) var(--ease-out);background:0 0;padding:1px 10px;font-size:11px}.stream-body{font-family:var(--mono);flex:1;padding:10px 14px;font-size:11.5px;line-height:1.85;overflow-y:auto}.stream-line{animation:lineIn var(--dur-2) var(--ease-out);gap:10px;display:flex}.sl-time{color:var(--text-4);flex:0 0 42px}.sl-type{text-overflow:ellipsis;white-space:nowrap;color:var(--text-2);flex:0 0 118px;overflow:hidden}.sl-msg{min-width:0;color:var(--text-2);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.level-error .sl-type{color:var(--danger)}.level-ok .sl-type{color:var(--ok)}.level-active .sl-type{color:var(--ph-implementation)}.level-info .sl-type{color:var(--accent-hi)}.review-grid{grid-template-columns:1fr 1fr;gap:14px;max-width:1000px;display:grid}@media (width<=900px){.review-grid{grid-template-columns:1fr}}.review-card{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel-2);padding:14px 16px}.check-row{align-items:center;gap:10px;margin-top:11px;display:flex}.check-dot{border-radius:50%;flex:0 0 7px;width:7px;height:7px}.check-k{font-family:var(--mono);color:var(--text);flex:none;width:92px;font-size:12px}.check-v{font-family:var(--mono);color:var(--text-3);font-size:11.5px}.review-foot{border-top:1px solid var(--hairline-soft);font-family:var(--mono);color:var(--text-2);margin-top:14px;padding-top:12px;font-size:11.5px}.drive-live{align-items:center;gap:9px;margin-top:12px;display:flex}.drive-pulse{background:var(--drive);border-radius:50%;width:8px;height:8px;animation:1.4s ease-in-out infinite pulse}.drive-label{color:var(--drive);font-size:12.5px;font-weight:600}.drive-loc{font-family:var(--mono);color:var(--text-2);font-size:11.5px}.drive-copy{color:var(--text-2);text-wrap:pretty;margin-top:12px;font-size:12.5px;line-height:1.55}.review-body{flex-direction:column;gap:14px;display:flex}.drive-pane{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel-2);max-width:1000px;overflow:hidden}.drive-pane-strip{background:var(--panel);border-bottom:1px solid var(--hairline-soft);align-items:center;gap:10px;height:38px;padding:0 12px;display:flex}.drive-pane-kind{border-radius:var(--radius-pill);border:1px solid var(--drive-line,var(--accent-line));background:var(--accent-soft);height:18px;color:var(--drive);font-family:var(--mono);align-items:center;padding:0 8px;font-size:10.5px;display:inline-flex}.drive-pane-loc{font-family:var(--mono);color:var(--text-3);font-size:11.5px}.drive-pane-spacer{flex:1}.drive-open{font-family:var(--mono);color:var(--drive);border:1px solid color-mix(in srgb, var(--drive) 40%, var(--hairline));border-radius:var(--radius-pill);background:var(--accent-soft);padding:4px 10px;font-size:11.5px;font-weight:600;text-decoration:none}.drive-open:hover{border-color:var(--drive)}.drive-pane-term{background:var(--bg);height:420px;min-height:260px;position:relative}.drive-pane-empty{color:var(--text-3);padding:20px 16px;font-size:12.5px}.shipped-hero{text-align:center;max-width:560px;animation:fadeUp var(--dur-3) var(--ease-out);margin:36px auto 0}.shipped-check{border:1px solid color-mix(in srgb, var(--ok) 45%, transparent);width:40px;height:40px;color:var(--ok);animation:popIn var(--dur-3) var(--ease-out);border-radius:50%;justify-content:center;align-items:center;margin:0 auto;font-size:17px;display:flex}.shipped-title{margin-top:14px;font-size:16px;font-weight:600}.shipped-meta{font-family:var(--mono);color:var(--text-2);margin-top:6px;font-size:12px}.shipped-sub{color:var(--text-3);margin-top:10px;font-size:12.5px;line-height:1.55}.nf-overlay{flex:1;justify-content:center;align-items:center;padding:24px;display:flex}.nf-card{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel);width:540px;max-width:100%;animation:popIn var(--dur-3) var(--ease-out);padding:26px 28px}.nf-kick{letter-spacing:.09em;color:var(--accent-hi);font-size:11px;font-weight:700}.nf-h{margin-top:6px;font-size:16px;font-weight:600}.nf-sub{color:var(--text-2);margin-top:5px;font-size:12.5px;line-height:1.55}.nf-input{background:var(--panel-inset);border:1px solid var(--hairline);border-radius:var(--radius);width:100%;height:36px;color:var(--text);transition:border-color var(--dur-1);outline:none;margin-top:18px;padding:0 12px;font-family:inherit;font-size:13px}.nf-input:focus{border-color:var(--accent)}.nf-oneliner{height:32px;margin-top:8px;font-size:12.5px}.nf-controls{align-items:center;gap:12px;margin-top:14px;display:flex}.size-toggle{border:1px solid var(--hairline);border-radius:var(--radius);display:inline-flex;overflow:hidden}.size-toggle button{color:var(--text-3);font-family:var(--mono);cursor:pointer;transition:background var(--dur-1), color var(--dur-1);background:0 0;border:none;padding:5px 11px;font-size:11.5px}.size-toggle button:hover:not(.is-on){color:var(--text)}.size-toggle button.is-on{background:var(--accent);color:#fff}.size-hint{color:var(--text-3);font-size:12px}.nf-branch{font-family:var(--mono);color:var(--text-3);margin-top:16px;font-size:11.5px}.nf-actions{justify-content:flex-end;gap:10px;margin-top:22px;display:flex}.nf-mapped{cursor:pointer;align-items:flex-start;gap:10px;margin-top:16px;display:flex}.nf-mapped input{accent-color:var(--accent);margin-top:3px}.nf-mapped-text{flex-direction:column;gap:2px;display:flex}.nf-mapped-label{color:var(--text);font-size:13px}.inspector{border-left:1px solid var(--hairline);background:var(--panel-2);flex-direction:column;gap:20px;min-height:0;padding:16px;display:flex;overflow-y:auto}.insp-section>.insp-cap{letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);margin-bottom:8px;font-size:10.5px;font-weight:600}.gate-card{border:1px solid var(--hairline);border-radius:var(--radius);background:var(--panel);padding:12px 14px}.gate-idrow{align-items:center;gap:8px;display:flex}.gate-id{font-family:var(--mono);color:var(--accent-hi);font-size:11px}.gate-name{color:var(--text);font-size:12.5px;font-weight:600}.gate-req{color:var(--text-2);text-wrap:pretty;margin-top:6px;font-size:11.5px;line-height:1.5}.gate-state{align-items:center;gap:8px;margin-top:11px;font-size:12px;display:flex}.gate-state.is-ok{color:var(--ok)}.gate-state.is-block{color:var(--needs)}.gate-state-dot{background:currentColor;border-radius:50%;flex:none;width:7px;height:7px}.gate-hint{color:var(--text-4);margin-top:10px;font-size:11px;line-height:1.5}.gate-empty{border:1px dashed var(--hairline-strong);border-radius:var(--radius);color:var(--text-3);padding:12px 14px;font-size:11.5px}.override-form{flex-direction:column;gap:6px;margin-top:11px;display:flex}.override-input{background:var(--panel-inset);border:1px solid var(--hairline);border-radius:var(--radius-sm);height:26px;color:var(--text);outline:none;padding:0 8px;font-size:12px}.override-input:focus{border-color:var(--accent)}.doc-list{margin:0;padding:0;list-style:none}.doc-link{cursor:pointer;text-align:left;border-radius:var(--radius-sm);width:100%;transition:background var(--dur-1);background:0 0;border:none;align-items:center;gap:8px;margin:0 -8px;padding:7px 8px;display:flex}.doc-link:hover{background:var(--panel-3)}.doc-title{color:var(--text);text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12.5px;overflow:hidden}.doc-meta{color:var(--text-4);flex:none;font-size:11px}.activity-log{flex-direction:column;display:flex}.act-line{border-top:1px solid var(--hairline-soft);gap:10px;padding:5px 0;display:flex}.act-line:first-child{border-top:none}.act-time{font-family:var(--mono);color:var(--text-4);flex:0 0 30px;padding-top:1px;font-size:10.5px}.act-body{flex:1;min-width:0}.act-type{font-family:var(--mono);color:var(--accent-hi);text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.act-msg{color:var(--text-2);text-overflow:ellipsis;white-space:nowrap;margin-top:1px;font-size:11.5px;line-height:1.45;overflow:hidden}.statusbar{border-top:1px solid var(--hairline);background:var(--panel);font-family:var(--mono);color:var(--text-3);align-items:center;gap:14px;padding:0 12px;font-size:11px;display:flex}.sb-item{align-items:center;gap:6px;display:inline-flex}.sb-branch{color:var(--text-3);cursor:pointer;font-family:var(--mono);transition:color var(--dur-1);background:0 0;border:none;padding:0;font-size:11px}.sb-branch:hover{color:var(--text)}.sb-driving{color:var(--drive);align-items:center;gap:7px;display:flex}.sb-driving-dot{background:var(--drive);border-radius:50%;width:6px;height:6px;animation:1.4s ease-in-out infinite pulse}.sb-stop{border:1px solid color-mix(in srgb, var(--drive) 40%, transparent);height:16px;color:var(--drive);cursor:pointer;background:0 0;border-radius:4px;padding:0 6px;font-size:10px}.sb-stop:hover:not(:disabled){background:#58a6ff1f}.sb-spacer{flex:1}.sb-health{color:var(--ph-shipped);align-items:center;gap:6px;display:inline-flex}.cmdk-backdrop{-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:300;animation:backdropIn var(--dur-2) var(--ease-out);background:#04060a8c;justify-content:center;align-items:flex-start;padding:12vh 16px 16px;display:flex;position:fixed;inset:0}.cmdk{background:var(--panel);border:1px solid var(--hairline-strong);border-radius:var(--radius-lg);width:100%;max-width:560px;animation:cmdkIn var(--dur-2) var(--ease-out);overflow:hidden;box-shadow:0 24px 60px -20px #000c}.cmdk-input{border:none;border-bottom:1px solid var(--hairline);width:100%;height:46px;color:var(--text);background:0 0;outline:none;padding:0 16px;font-family:inherit;font-size:14px}.cmdk-input::placeholder{color:var(--text-3)}.cmdk-list{max-height:340px;padding:6px;overflow-y:auto}.cmdk-group-label{letter-spacing:.09em;text-transform:uppercase;color:var(--text-4);padding:8px 10px 4px;font-size:10px;font-weight:700}.cmdk-item{border-radius:var(--radius-sm);cursor:pointer;color:var(--text-2);align-items:center;gap:10px;padding:8px 10px;display:flex}.cmdk-item.is-active{background:var(--panel-3);color:var(--text)}.cmdk-item-glyph{font-family:var(--mono);text-align:center;flex:none;width:14px;font-size:12px}.cmdk-item-label{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:13px;overflow:hidden}.cmdk-item-slug{font-family:var(--mono);color:var(--text-4);font-size:11px}.cmdk-item-hint{color:var(--text-4);font-size:11px}.cmdk-empty{text-align:center;color:var(--text-3);padding:24px;font-size:13px}.cmdk-foot{border-top:1px solid var(--hairline);color:var(--text-4);align-items:center;gap:14px;padding:8px 14px;font-size:11px;display:flex}.cmdk-foot .kbd{font-size:10px}.peek-backdrop{-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:200;animation:backdropIn var(--dur-2) var(--ease-out);background:#030508b8;justify-content:center;align-items:flex-start;padding:8vh 16px 16px;display:flex;position:fixed;inset:0}.peek{background:var(--panel);border:1px solid var(--hairline-strong);border-radius:var(--radius-lg);width:100%;max-width:780px;max-height:82vh;animation:cmdkIn var(--dur-2) var(--ease-out);flex-direction:column;display:flex;overflow:hidden}.peek-head{border-bottom:1px solid var(--hairline);justify-content:space-between;align-items:center;padding:10px 14px;display:flex}.peek-path{color:var(--text-2);font-size:12px}.peek-close{color:var(--text-3);cursor:pointer;background:0 0;border:none;font-size:12px}.peek-close:hover{color:var(--text)}.peek-body{padding:14px 18px;overflow:auto}.peek-pre{font-family:var(--mono);white-space:pre-wrap;word-break:break-word;color:var(--text);margin:0;font-size:12.5px;line-height:1.6}.peek.settings{max-width:620px}.settings-title{color:var(--text);font-size:13px;font-weight:600}.settings-body{flex-direction:column;gap:26px;display:flex}.settings-section{flex-direction:column;gap:14px;display:flex}.settings-section-head{border-bottom:1px solid var(--hairline);align-items:baseline;gap:10px;padding-bottom:8px;display:flex}.settings-section-title{letter-spacing:.09em;text-transform:uppercase;color:var(--text-2);margin:0;font-size:11px;font-weight:700}.settings-section-hint{color:var(--text-4);font-size:11.5px}.settings-field{flex-direction:column;gap:5px;display:flex}.settings-field-head{align-items:center;gap:8px;display:flex}.settings-field-label{color:var(--text);font-size:12.5px}.settings-field.is-locked .settings-field-label{color:var(--text-2)}.settings-field-help{color:var(--text-4);font-size:11.5px;line-height:1.4}.settings-badge{letter-spacing:.04em;text-transform:uppercase;border:1px solid var(--hairline-strong);color:var(--text-3);border-radius:999px;padding:1px 6px;font-size:9.5px}.settings-badge.is-warn{color:var(--drive);border-color:color-mix(in srgb, var(--drive) 40%, transparent)}.settings-badge.is-override{color:var(--accent-hi);border-color:var(--accent-line)}.settings-saving{color:var(--text-4);font-size:10.5px;font-style:italic}.settings-input{background:var(--panel-inset);border:1px solid var(--hairline);border-radius:var(--radius);width:100%;height:32px;color:var(--text);transition:border-color var(--dur-1);outline:none;padding:0 10px;font-family:inherit;font-size:12.5px}.settings-input:focus{border-color:var(--accent)}.settings-input:disabled{opacity:.6;cursor:progress}select.settings-input{cursor:pointer}.settings-readonly{background:var(--panel-inset);border:1px dashed var(--hairline);border-radius:var(--radius);min-height:32px;color:var(--text-2);align-items:center;padding:0 10px;font-size:12.5px;display:flex}.settings-field-note{color:var(--text-4);font-size:11px}.settings-clear{color:var(--text-3);cursor:pointer;text-underline-offset:2px;background:0 0;border:none;align-self:flex-start;margin-top:2px;padding:0;font-size:11px;text-decoration:underline}.settings-clear:hover:not(:disabled){color:var(--accent-hi)}.settings-clear:disabled{opacity:.5;cursor:default}.settings-combo{flex-direction:column;gap:6px;display:flex}.settings-advanced-toggle{cursor:pointer;text-align:left;width:100%;color:inherit;background:0 0;border:none;justify-content:space-between;align-items:baseline;gap:8px;padding:0;display:flex}.settings-advanced-toggle:hover .settings-section-title{color:var(--accent-hi)}.settings-advanced-body{border-left:1px solid var(--border-1,var(--text-5,#333));flex-direction:column;gap:14px;margin-top:4px;padding-left:10px;display:flex}.terminal-placeholder,.boundary-fallback{background:var(--bg);justify-content:center;align-items:center;height:100%;display:flex}.toasts{z-index:400;flex-direction:column;gap:8px;max-width:380px;display:flex;position:fixed;bottom:34px;right:16px}.toast{border-radius:var(--radius);cursor:pointer;border:1px solid var(--hairline);background:var(--panel);color:var(--text);word-break:break-word;animation:toastIn var(--dur-3) var(--ease-out);padding:9px 13px;font-size:12.5px;box-shadow:0 12px 30px -14px #000c}.toast-error{border-color:color-mix(in srgb, var(--danger) 55%, var(--hairline));color:var(--danger)}.toast-success{border-color:color-mix(in srgb, var(--ok) 50%, var(--hairline));color:var(--ok)}.toast-info{color:var(--text-2)}.update-banner{border-radius:var(--radius-pill);border:1px solid var(--accent-line);background:color-mix(in srgb, var(--accent) 12%, var(--panel));max-width:min(720px,100vw - 32px);color:var(--text);z-index:420;animation:fadeUp var(--dur-3) var(--ease-out);align-items:center;gap:10px;padding:7px 10px 7px 13px;font-size:12.5px;display:flex;position:fixed;top:50px;left:50%;transform:translate(-50%);box-shadow:0 14px 34px -16px #000000d9}.update-banner-dot{background:var(--accent-hi);width:7px;height:7px;animation:dotGlow 2.2s var(--ease) infinite;border-radius:50%;flex:none}.update-banner-text{white-space:nowrap}.update-banner-text strong{color:var(--accent-hi);font-weight:600}.update-banner-sep{color:var(--text-4)}.update-banner-dim{color:var(--text-3)}.update-banner-cmd{font-family:var(--mono);color:var(--accent-hi);background:var(--panel-inset);border:1px solid var(--hairline);border-radius:var(--radius-sm);white-space:nowrap;-webkit-user-select:all;user-select:all;padding:2px 7px;font-size:11.5px}.update-banner-dismiss{width:22px;height:22px;color:var(--text-3);border-radius:var(--radius-sm);cursor:pointer;background:0 0;border:none;flex:none;place-items:center;font-size:16px;line-height:1;display:grid}.update-banner-dismiss:hover{color:var(--text);background:var(--panel-3)}.app-loading{justify-content:center;align-items:center;height:100%;display:flex}.tb-home{cursor:pointer;color:inherit;background:0 0;border:0;align-items:center;gap:9px;padding:0;display:inline-flex}.tb-home:hover .tb-app{color:var(--accent-hi)}.tb-switcher{display:inline-flex;position:relative}.tb-switcher-btn{border-radius:var(--radius);cursor:pointer;height:24px;transition:border-color var(--dur-1), background var(--dur-1);background:0 0;border:1px solid #0000;align-items:center;gap:5px;padding:0 7px;display:inline-flex}.tb-switcher-btn:hover{border-color:var(--hairline);background:var(--panel-3)}.tb-switcher-caret{color:var(--text-4);font-size:9px}.tb-menu{z-index:40;background:var(--panel);border:1px solid var(--hairline);border-radius:var(--radius-lg);min-width:240px;animation:cmdkIn var(--dur-2) var(--ease-out);padding:5px;position:absolute;top:30px;left:0;box-shadow:0 18px 44px -18px #000000d9}.tb-menu-label{letter-spacing:.08em;text-transform:uppercase;color:var(--text-4);padding:6px 8px 4px;font-size:10px}.tb-menu-item{border-radius:var(--radius);cursor:pointer;width:100%;color:var(--text-2);text-align:left;transition:background var(--dur-1), color var(--dur-1);background:0 0;border:0;align-items:center;gap:8px;padding:7px 8px;display:flex}.tb-menu-item:hover{background:var(--panel-3);color:var(--text)}.tb-menu-item.is-current{color:var(--text)}.tb-menu-name{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:13px;overflow:hidden}.tb-menu-branch{color:var(--text-4);font-size:11px}.tb-menu-check{color:var(--accent-hi);font-size:11px}.tb-menu-sep{background:var(--hairline-soft);height:1px;margin:5px 4px}button.tb-runs{cursor:pointer}.home{height:100%;animation:fadeUp var(--dur-3) var(--ease-out);padding:40px clamp(20px,6vw,72px);overflow-y:auto}.home-head{max-width:1100px;margin:0 auto 28px}.home-title{align-items:center;gap:11px;display:flex}.home-title-text{letter-spacing:.01em;font-size:22px;font-weight:600}.home-count{font-family:var(--mono);color:var(--text-3);border:1px solid var(--hairline);border-radius:var(--radius-pill);padding:1px 9px;font-size:12px}.home-sub{color:var(--text-3);max-width:60ch;margin:10px 0 0;font-size:13px}.home-grid{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px;max-width:1100px;margin:0 auto;display:grid}.project-card{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel);transition:border-color var(--dur-2), transform var(--dur-2), box-shadow var(--dur-2);flex-direction:column;display:flex;overflow:hidden}.project-card:hover{border-color:var(--hairline-strong);transform:translateY(-2px);box-shadow:0 16px 34px -20px #000c}.project-card.health-attention{border-left:2px solid var(--needs)}.project-card.health-working{border-left:2px solid var(--ph-implementation)}.project-card.health-steady{border-left:2px solid var(--ok)}.project-card.health-empty{border-left:2px solid var(--hairline-strong)}.pc-main{cursor:pointer;text-align:left;color:inherit;background:0 0;border:0;flex-direction:column;flex:1;gap:5px;padding:16px 16px 14px;display:flex}.pc-head{align-items:center;gap:8px;display:flex}.pc-name{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--text);flex:1;font-size:15px;font-weight:600;overflow:hidden}.pc-rename{background:var(--panel-inset);border:1px solid var(--accent-line);border-radius:var(--radius-sm);min-width:0;height:24px;color:var(--text);flex:1;padding:0 6px;font-size:14px}.pc-health-dot{border-radius:50%;flex:none;width:8px;height:8px}.health-dot-attention{background:var(--needs)}.health-dot-working{background:var(--ph-implementation);animation:1.4s ease-in-out infinite pulse}.health-dot-steady{background:var(--ok)}.health-dot-empty{background:var(--text-4)}.pc-path{color:var(--text-4);text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.pc-branch{color:var(--text-3);font-size:11px}.pc-stats{gap:16px;margin-top:10px;display:flex}.pc-stat{color:var(--text-3);align-items:baseline;gap:5px;display:inline-flex}.pc-stat .spin-ring{align-self:center}.pc-stat-n{font-family:var(--mono);color:var(--text);font-size:16px}.pc-stat-label{font-size:11px}.pc-stat-run .pc-stat-n{color:var(--ph-implementation)}.pc-stat-needs .pc-stat-n{color:var(--needs)}.pc-health-label{letter-spacing:.06em;text-transform:uppercase;color:var(--text-4);margin-top:12px;font-size:10px}.pc-actions{border-top:1px solid var(--hairline-soft);background:var(--panel-2);gap:6px;padding:8px 12px;display:flex}.pc-action{border:1px solid var(--hairline);border-radius:var(--radius);height:24px;color:var(--text-3);cursor:pointer;transition:color var(--dur-1), border-color var(--dur-1);background:0 0;padding:0 10px;font-size:11px}.pc-action:hover:not(:disabled){color:var(--text);border-color:var(--hairline-strong)}.pc-action:disabled{opacity:.4;cursor:not-allowed}.pc-action-danger:hover:not(:disabled){color:var(--danger);border-color:color-mix(in srgb, var(--danger) 45%, var(--hairline))}.open-card{border:1px dashed var(--hairline-strong);border-radius:var(--radius-lg);cursor:pointer;min-height:150px;color:var(--text-3);transition:border-color var(--dur-2), color var(--dur-2), background var(--dur-2);background:0 0;flex-direction:column;justify-content:center;align-items:flex-start;gap:4px;padding:16px;display:flex}.open-card:hover{border-color:var(--accent-line);color:var(--text);background:var(--accent-soft)}.open-card-plus{color:var(--accent-hi);font-size:22px;line-height:1}.open-card-label{font-size:14px;font-weight:600}.open-card-sub{color:var(--text-4);font-size:11px}.open-project{height:100%;animation:fadeUp var(--dur-3) var(--ease-out);justify-content:center;align-items:center;padding:24px;display:flex}.op-card{border:1px solid var(--hairline);border-radius:var(--radius-lg);background:var(--panel);flex-direction:column;gap:6px;width:100%;max-width:460px;padding:28px;display:flex;box-shadow:0 24px 60px -30px #000c}.op-logo{background:var(--accent);width:34px;height:34px;color:var(--accent-ink);border-radius:9px;justify-content:center;align-items:center;margin-bottom:6px;font-weight:700;display:flex}.op-kick{letter-spacing:.1em;text-transform:uppercase;color:var(--accent-hi);font-size:10px}.op-h{font-size:19px;font-weight:600}.op-sub{color:var(--text-3);margin-bottom:8px;font-size:13px;line-height:1.5}.op-label{color:var(--text-2);margin-top:4px;font-size:11px}.op-input{background:var(--panel-inset);border:1px solid var(--hairline);border-radius:var(--radius);height:32px;color:var(--text);transition:border-color var(--dur-1);padding:0 10px;font-size:13px}.op-input:focus{border-color:var(--accent-line);outline:none}.op-hint{color:var(--text-4);font-size:11px}.op-actions{justify-content:flex-end;gap:8px;margin-top:14px;display:flex}.wizard-card{max-width:520px}.wizard-steps{color:var(--text-4);gap:16px;margin:0 0 6px;padding:0;font-size:11px;list-style:none;display:flex}.wizard-step{align-items:center;gap:6px;display:flex}.wizard-step.is-current{color:var(--accent-hi)}.wizard-step.is-done{color:var(--text-2)}.wizard-step-dot{background:var(--hairline);border-radius:50%;width:7px;height:7px}.wizard-step.is-current .wizard-step-dot{background:var(--accent)}.wizard-step.is-done .wizard-step-dot{background:var(--text-3)}.afk-card{flex-direction:column;gap:10px;display:flex}.afk-card-head{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.afk-card-title{font-size:16px;font-weight:600}.afk-card-sub{color:var(--text-3);margin:0;font-size:12.5px;line-height:1.5}.afk-rows{flex-direction:column;gap:8px;display:flex}.afk-row{border:1px solid var(--hairline);border-radius:var(--radius);background:var(--panel-2);flex-direction:column;gap:8px;padding:12px;display:flex}.afk-row.is-ok{opacity:.72}.afk-row-head{align-items:flex-start;gap:9px;display:flex}.afk-dot{border-radius:50%;flex:none;width:8px;height:8px;margin-top:4px}.afk-dot-ok{background:var(--ok,#3fb950)}.afk-dot-warn{background:var(--warn,#d9a441)}.afk-row-text{flex-direction:column;gap:2px;display:flex}.afk-row-label{font-size:13px;font-weight:500}.afk-row-detail{color:var(--text-4);font-size:11px}.afk-row-action{flex-direction:column;gap:8px;padding-left:17px;display:flex}.afk-cmd{background:var(--panel-inset);border:1px solid var(--hairline);border-radius:var(--radius);align-items:center;gap:8px;padding:8px 10px;display:flex}.afk-cmd-text{color:var(--accent-hi);word-break:break-all;flex:1;font-size:12px}.afk-note{color:var(--text-4);font-size:11px}.afk-term{border:1px solid var(--hairline);border-radius:var(--radius);height:280px;overflow:hidden}.afk-term-actions{justify-content:flex-end;gap:8px;display:flex}.afk-verdict{font-size:12px}.afk-verdict.is-ok{color:var(--ok,#3fb950)}.afk-verdict.is-warn{color:var(--warn,#d9a441)}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.32}}@keyframes dotGlow{0%,to{box-shadow:0 0 0 3px #7c6cf638}50%{box-shadow:0 0 0 5px #7c6cf614}}@keyframes fadeUp{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes bodyIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes detailIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}@keyframes lineIn{0%{opacity:0;transform:translate(-4px)}to{opacity:1;transform:translate(0)}}@keyframes popIn{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes cmdkIn{0%{opacity:0;transform:translateY(-10px)scale(.985)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes backdropIn{0%{opacity:0}to{opacity:1}}@keyframes toastIn{0%{opacity:0;transform:translate(16px)scale(.98)}to{opacity:1;transform:translate(0)scale(1)}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition-duration:.001ms!important;animation-duration:.001ms!important;animation-iteration-count:1!important}.btn-solid:hover:not(:disabled){box-shadow:none;transform:none}}