@hanzlaa/rcode 4.1.2 → 4.3.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 (67) hide show
  1. package/cli/install.js +176 -13
  2. package/cli/lib/config.cjs +4 -2
  3. package/cli/lib/fsutil.cjs +13 -2
  4. package/cli/lib/homedir.cjs +21 -0
  5. package/cli/lib/schemas.cjs +6 -1
  6. package/cli/nuke.js +13 -8
  7. package/cli/postinstall.js +14 -4
  8. package/cli/rcode-slash-router.cjs +118 -0
  9. package/cli/uninstall.js +59 -1
  10. package/cli/update.js +10 -5
  11. package/dist/rcode.js +234 -230
  12. package/package.json +1 -1
  13. package/server/dashboard.js +26 -7
  14. package/server/lib/api.js +62 -4
  15. package/server/lib/html/client/agents-data.js +22 -18
  16. package/server/lib/html/client/app.js +3 -0
  17. package/server/lib/html/client/components/AgentCard.js +127 -0
  18. package/server/lib/html/client/components/App.js +104 -39
  19. package/server/lib/html/client/components/CommandPalette.js +133 -0
  20. package/server/lib/html/client/components/FileReader.js +116 -0
  21. package/server/lib/html/client/components/FilterChips.js +94 -0
  22. package/server/lib/html/client/components/NotifyCenter.js +117 -0
  23. package/server/lib/html/client/components/OrchPanel.js +80 -52
  24. package/server/lib/html/client/components/PhaseGraph.js +300 -0
  25. package/server/lib/html/client/components/RejectDialog.js +78 -0
  26. package/server/lib/html/client/components/RunnerPicker.js +190 -0
  27. package/server/lib/html/client/components/Sidebar.js +106 -61
  28. package/server/lib/html/client/components/StatusSummaryBar.js +76 -0
  29. package/server/lib/html/client/components/TaskPipeline.js +83 -0
  30. package/server/lib/html/client/components/Topbar.js +86 -39
  31. package/server/lib/html/client/components/dashboard/Blockers.js +57 -0
  32. package/server/lib/html/client/components/dashboard/CompletedTasks.js +47 -0
  33. package/server/lib/html/client/components/dashboard/CurrentPhase.js +107 -0
  34. package/server/lib/html/client/components/dashboard/InProgress.js +72 -0
  35. package/server/lib/html/client/components/dashboard/ProgressDonut.js +101 -0
  36. package/server/lib/html/client/components/dashboard/ProgressTimeline.js +101 -0
  37. package/server/lib/html/client/components/dashboard/ProjectHealth.js +80 -0
  38. package/server/lib/html/client/components/dashboard/RecentDecisions.js +57 -0
  39. package/server/lib/html/client/components/dashboard/Timeline.js +143 -0
  40. package/server/lib/html/client/components/shared.js +47 -11
  41. package/server/lib/html/client/filter-state.js +72 -0
  42. package/server/lib/html/client/icons-client.js +7 -0
  43. package/server/lib/html/client/notify.js +75 -0
  44. package/server/lib/html/client/orchestrator.js +168 -41
  45. package/server/lib/html/client/preact.js +13 -8
  46. package/server/lib/html/client/store.js +70 -6
  47. package/server/lib/html/client/util.js +78 -0
  48. package/server/lib/html/client/vendor/htm.js +1 -0
  49. package/server/lib/html/client/vendor/preact-hooks.js +2 -0
  50. package/server/lib/html/client/vendor/preact.js +2 -0
  51. package/server/lib/html/client/views/AgentsView.js +144 -51
  52. package/server/lib/html/client/views/FilesView.js +20 -103
  53. package/server/lib/html/client/views/KanbanView.js +40 -21
  54. package/server/lib/html/client/views/MemoryView.js +26 -9
  55. package/server/lib/html/client/views/MilestonesView.js +4 -4
  56. package/server/lib/html/client/views/OrchestrationView.js +154 -19
  57. package/server/lib/html/client/views/OverviewView.js +47 -239
  58. package/server/lib/html/client/views/PhasesView.js +50 -6
  59. package/server/lib/html/client/views/RoadmapView.js +6 -3
  60. package/server/lib/html/client/views/SprintsView.js +50 -6
  61. package/server/lib/html/client/views/TasksView.js +4 -3
  62. package/server/lib/html/client.js +21 -4
  63. package/server/lib/html/css.js +2761 -8
  64. package/server/lib/html/icons.js +7 -0
  65. package/server/lib/html/shell.js +10 -3
  66. package/server/lib/scanner.js +376 -39
  67. package/server/orchestrator.js +329 -5
@@ -104,6 +104,24 @@ function renderCss() {
104
104
  --accent-amber: var(--amber);
105
105
  --accent-red: var(--red);
106
106
  --accent-blue: var(--blue);
107
+
108
+ /* ── Dashboard redesign (mockup) tokens ──────────────────────────
109
+ Exact values from .planning/campaign/MOCKUP-SPEC.md. Namespaced
110
+ --dash-* so the Overview redesign can adopt the deep-navy mockup
111
+ palette without disturbing the existing Linear theme above. */
112
+ --dash-bg: #0F1729; /* deep navy page base */
113
+ --dash-card: #111A2E; /* card surface */
114
+ --dash-border: #1E2A44; /* 1px hairline border */
115
+ --dash-teal: #2DD4BF;
116
+ --dash-purple: #A78BFA;
117
+ --dash-blue: #3B82F6;
118
+ --dash-amber: #F59E0B;
119
+ --dash-sev-high: #F87171; /* red — High */
120
+ --dash-sev-medium: #FBBF24; /* amber — Medium */
121
+ --dash-sev-low: #9CA3AF; /* gray — Low */
122
+ --dash-text: #E6EDF7; /* primary text */
123
+ --dash-text-muted: #8595AD; /* muted text */
124
+ --dash-hover: rgba(255, 255, 255, 0.04); /* row/button hover wash */
107
125
  }
108
126
 
109
127
  /* Light mode */
@@ -123,6 +141,15 @@ function renderCss() {
123
141
  --text-tertiary: #72727e;
124
142
  --text-muted: #9898a4;
125
143
  --accent-bg: rgba(94,106,210,0.08);
144
+
145
+ /* Dashboard mockup tokens — light theme. Surfaces/text flip to light;
146
+ teal/purple/blue/amber accents and severity colors stay the same. */
147
+ --dash-bg: #F4F6FB;
148
+ --dash-card: #FFFFFF;
149
+ --dash-border: #E2E8F0;
150
+ --dash-text: #1A2233;
151
+ --dash-text-muted: #5B6B82;
152
+ --dash-hover: rgba(15, 23, 41, 0.05);
126
153
  }
127
154
 
128
155
  /* ── Reset ─────────────────────────────────────────────────────── */
@@ -1001,11 +1028,6 @@ section .body {
1001
1028
  margin-bottom: 4px;
1002
1029
  line-height: 1.2;
1003
1030
  }
1004
- .agent-card .role {
1005
- font-size: var(--text-2xs);
1006
- color: var(--text-tertiary);
1007
- letter-spacing: -0.006em;
1008
- }
1009
1031
  .real-badge {
1010
1032
  font-size: var(--text-2xs);
1011
1033
  font-weight: 500;
@@ -1422,7 +1444,9 @@ footer {
1422
1444
  .kanban-refresh-btn:hover { background: var(--bg-hover); color: var(--text-primary); }
1423
1445
 
1424
1446
  /* ── Orchestrator side panel ────────────────────────────────────── */
1425
- #orch-panel {
1447
+ /* Selector matches the Preact component's class="orch-panel" — the legacy
1448
+ id="orch-panel" DOM was removed in the Preact migration (Sprint 31.4). */
1449
+ .orch-panel {
1426
1450
  position: fixed;
1427
1451
  top: 0;
1428
1452
  right: 0;
@@ -1439,7 +1463,7 @@ footer {
1439
1463
  transition: transform var(--t-menu) var(--ease);
1440
1464
  box-shadow: -8px 0 32px rgba(0,0,0,0.4);
1441
1465
  }
1442
- #orch-panel.open {
1466
+ .orch-panel.open {
1443
1467
  transform: translateX(0);
1444
1468
  }
1445
1469
 
@@ -1894,7 +1918,7 @@ footer {
1894
1918
  .hamburger-btn { display: flex; }
1895
1919
  .content-area { grid-column: 1; }
1896
1920
  .kanban-board { grid-template-columns: repeat(4, 260px); }
1897
- #orch-panel { max-width: 90vw; min-width: 280px; }
1921
+ .orch-panel { max-width: 90vw; min-width: 280px; }
1898
1922
  }
1899
1923
 
1900
1924
  /* ── Milestones / roadmap dynamic ───────────────────────────── */
@@ -2027,6 +2051,7 @@ footer {
2027
2051
  .term-status-dot.error { background: #ff4444; animation: none; }
2028
2052
  .term-status-dot.stopped { background: var(--accent-amber); animation: none; }
2029
2053
  .term-status-dot.connecting { background: var(--accent-blue); animation: pulse 1s infinite; }
2054
+ .term-status-dot.exited { background: #ff4444; animation: none; }
2030
2055
  .term-btn {
2031
2056
  height: 22px;
2032
2057
  padding: 0 var(--space-3);
@@ -2195,6 +2220,18 @@ footer {
2195
2220
  gap: var(--space-2);
2196
2221
  }
2197
2222
 
2223
+ /* ── Run history panel ── */
2224
+ .hist-panel { margin-top: var(--space-6); }
2225
+ .hist-panel-title { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-md); color: var(--text-primary); margin-bottom: var(--space-4); }
2226
+ .hist-group { margin-bottom: var(--space-5); }
2227
+ .hist-group-title { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin-bottom: var(--space-2); }
2228
+ .hist-date { font-size: var(--text-2xs); color: var(--text-muted); margin: var(--space-3) 0 var(--space-2); }
2229
+ .hist-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-3); background: var(--bg-elev-2); border: 1px solid var(--border-subtle); border-radius: var(--radius-2); margin-bottom: var(--space-2); }
2230
+ .hist-row-id { font-weight: 600; font-size: var(--text-sm); color: var(--text-primary); }
2231
+ .hist-row-cmd { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-secondary); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2232
+ .hist-row-duration { display: flex; align-items: center; gap: var(--space-1); font-size: var(--text-2xs); color: var(--text-muted); white-space: nowrap; }
2233
+ .hist-row-status { margin-left: auto; font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); }
2234
+
2198
2235
  /* ── Icon alignment helpers (for sprint 32.2 SVG icon sweep) ── */
2199
2236
  .ic {
2200
2237
  display: inline-block;
@@ -2278,6 +2315,2722 @@ footer {
2278
2315
  .cmd-runner-btn:hover:not(:disabled) { opacity: 0.85; }
2279
2316
  .cmd-runner-btn:disabled,
2280
2317
  .cmd-runner-btn--busy { opacity: 0.6; cursor: not-allowed; }
2318
+
2319
+ /* ── Dashboard redesign — sidebar + header chrome + project health ──
2320
+ Mockup chrome. Re-declares .sidebar / header layout (later-wins per
2321
+ property; mobile position/transform from the base rule are preserved)
2322
+ and adds prefixed sb-* / tb-* / phealth-* classes. Tokens only. */
2323
+
2324
+ /* Sidebar shell */
2325
+ .sidebar {
2326
+ display: flex;
2327
+ flex-direction: column;
2328
+ gap: 14px;
2329
+ height: 100%;
2330
+ padding: 16px 14px;
2331
+ background: var(--dash-bg);
2332
+ border-right: 1px solid var(--dash-border);
2333
+ box-sizing: border-box;
2334
+ overflow-y: auto;
2335
+ }
2336
+
2337
+ /* Logo badge */
2338
+ .sb-logo { display: flex; align-items: center; gap: 10px; padding: 2px 4px; }
2339
+ .sb-logo-badge {
2340
+ width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0;
2341
+ display: flex; align-items: center; justify-content: center;
2342
+ font-weight: 800; font-size: 16px; color: #06121f;
2343
+ background: linear-gradient(135deg, var(--dash-teal), var(--dash-blue));
2344
+ }
2345
+ .sb-logo-word { font-size: 16px; font-weight: 700; color: var(--dash-text); letter-spacing: -0.01em; }
2346
+
2347
+ /* Project switcher */
2348
+ .sb-switcher {
2349
+ display: flex; align-items: center; gap: 8px; width: 100%;
2350
+ padding: 9px 11px; border-radius: 10px;
2351
+ background: var(--dash-card); border: 1px solid var(--dash-border);
2352
+ color: var(--dash-text); font-size: 13px; font-weight: 600;
2353
+ cursor: pointer; text-align: left;
2354
+ transition: border-color 0.15s, background 0.15s;
2355
+ }
2356
+ .sb-switcher:hover { border-color: var(--dash-teal); }
2357
+ .sb-switcher-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--dash-teal); flex-shrink: 0; }
2358
+ .sb-switcher-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2359
+ .sb-switcher-chev { color: var(--dash-text-muted); font-size: 11px; }
2360
+
2361
+ /* Vertical nav */
2362
+ .sb-nav { display: flex; flex-direction: column; gap: 2px; }
2363
+ .sb-nav-link {
2364
+ display: flex; align-items: center; gap: 11px; width: 100%;
2365
+ padding: 9px 11px; border-radius: 9px;
2366
+ background: transparent; border: 0;
2367
+ color: var(--dash-text-muted); font-size: 13px; font-weight: 500;
2368
+ cursor: pointer; text-align: left;
2369
+ transition: background 0.15s, color 0.15s;
2370
+ }
2371
+ .sb-nav-link:hover { background: rgba(255, 255, 255, 0.04); color: var(--dash-text); }
2372
+ .sb-nav-link.active { background: rgba(45, 212, 191, 0.12); color: var(--dash-text); font-weight: 600; }
2373
+ .sb-nav-link.active .sb-nav-ic { color: var(--dash-teal); }
2374
+ .sb-nav-ic { display: inline-flex; color: var(--dash-text-muted); }
2375
+ .sb-nav-label { flex: 1; }
2376
+
2377
+ /* Health mini-card — pushed toward the bottom above the profile */
2378
+ .sb-health { margin-top: auto; }
2379
+
2380
+ /* Project Health card */
2381
+ .phealth {
2382
+ display: flex; flex-direction: column; gap: 8px;
2383
+ padding: 14px; border-radius: 12px;
2384
+ background: var(--dash-card); border: 1px solid var(--dash-border);
2385
+ }
2386
+ .phealth-title { margin: 0; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--dash-text-muted); }
2387
+ .phealth-head { display: flex; align-items: baseline; gap: 8px; }
2388
+ .phealth-pct { font-size: 26px; font-weight: 800; line-height: 1; color: var(--dash-text); }
2389
+ .phealth-pct-sign { font-size: 14px; font-weight: 700; margin-left: 1px; color: var(--dash-text-muted); }
2390
+ .phealth-label { font-size: 12px; font-weight: 600; }
2391
+ .phealth--good .phealth-label { color: var(--dash-teal); }
2392
+ .phealth--warn .phealth-label { color: var(--dash-sev-medium); }
2393
+ .phealth--risk .phealth-label { color: var(--dash-sev-high); }
2394
+ .phealth-spark { width: 100%; height: 36px; display: block; }
2395
+ .phealth-spark-line { fill: none; stroke-width: 2; vector-effect: non-scaling-stroke; }
2396
+ .phealth--good .phealth-spark-line { stroke: var(--dash-teal); }
2397
+ .phealth--warn .phealth-spark-line { stroke: var(--dash-sev-medium); }
2398
+ .phealth--risk .phealth-spark-line { stroke: var(--dash-sev-high); }
2399
+ .phealth-spark-area { stroke: none; opacity: 0.14; }
2400
+ .phealth--good .phealth-spark-area { fill: var(--dash-teal); }
2401
+ .phealth--warn .phealth-spark-area { fill: var(--dash-sev-medium); }
2402
+ .phealth--risk .phealth-spark-area { fill: var(--dash-sev-high); }
2403
+
2404
+ /* Profile footer */
2405
+ .sb-profile {
2406
+ display: flex; align-items: center; gap: 10px;
2407
+ padding: 10px 8px; border-top: 1px solid var(--dash-border);
2408
+ }
2409
+ .sb-avatar {
2410
+ width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
2411
+ display: flex; align-items: center; justify-content: center;
2412
+ font-size: 12px; font-weight: 700; color: #06121f;
2413
+ background: linear-gradient(135deg, var(--dash-purple), var(--dash-blue));
2414
+ }
2415
+ .sb-profile-meta { display: flex; flex-direction: column; min-width: 0; }
2416
+ .sb-profile-name { font-size: 13px; font-weight: 600; color: var(--dash-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2417
+ .sb-profile-email { font-size: 11px; color: var(--dash-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2418
+
2419
+ /* Header (Topbar) */
2420
+ .topbar {
2421
+ display: flex; align-items: center; gap: 16px; height: 100%;
2422
+ padding: 0 20px;
2423
+ background: var(--dash-bg);
2424
+ border-bottom: 1px solid var(--dash-border);
2425
+ box-sizing: border-box;
2426
+ }
2427
+ .tb-greeting { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
2428
+ .tb-welcome { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.2; color: var(--dash-text); white-space: nowrap; }
2429
+ .tb-wave { display: inline-block; }
2430
+ .tb-sub { margin: 0; font-size: 11px; line-height: 1.2; color: var(--dash-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2431
+ .tb-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
2432
+ .tb-synced {
2433
+ display: flex; align-items: center; gap: 7px;
2434
+ padding: 6px 10px; border-radius: 8px;
2435
+ background: transparent; border: 0; cursor: pointer;
2436
+ font-size: 12px; color: var(--dash-text-muted);
2437
+ }
2438
+ .tb-synced:hover { color: var(--dash-text); }
2439
+ .tb-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dash-teal); box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.18); flex-shrink: 0; }
2440
+ .tb-synced--busy .tb-dot { background: var(--dash-blue); box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18); animation: tb-pulse 0.8s ease-in-out infinite; }
2441
+ @keyframes tb-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
2442
+ .tb-btn {
2443
+ display: inline-flex; align-items: center; gap: 7px;
2444
+ padding: 8px 13px; border-radius: 9px;
2445
+ background: var(--dash-card); border: 1px solid var(--dash-border);
2446
+ color: var(--dash-text); font-size: 13px; font-weight: 600;
2447
+ cursor: pointer; white-space: nowrap;
2448
+ transition: border-color 0.15s, background 0.15s, filter 0.15s;
2449
+ }
2450
+ .tb-btn:hover { border-color: var(--dash-teal); }
2451
+ .tb-btn--primary {
2452
+ background: linear-gradient(135deg, var(--dash-teal), var(--dash-blue));
2453
+ border-color: transparent; color: #06121f;
2454
+ }
2455
+ .tb-btn--primary:hover { filter: brightness(1.05); border-color: transparent; }
2456
+ .tb-btn--icon { padding: 8px 11px; }
2457
+ .tb-kebab { font-size: 16px; line-height: 1; letter-spacing: 1px; }
2458
+
2459
+ @media (max-width: 760px) {
2460
+ .tb-sub { display: none; }
2461
+ .tb-synced { display: none; }
2462
+ }
2463
+
2464
+ /* ════════════════════════════════════════════════════════════════════
2465
+ POLISH — Overview card grid (single source of truth)
2466
+ Replaces the earlier per-agent .dash-grid / .dash-card / donut-* /
2467
+ cp-* / tl-* / ct-* / ip-* / bk-* / rd-* / pt-* blocks, whose
2468
+ interleaved appends left unbalanced braces. ALL dashboard-card CSS
2469
+ lives here — append card changes to this block only.
2470
+ ════════════════════════════════════════════════════════════════════ */
2471
+
2472
+ /* ── Global view normalization — every view on the dash palette ──
2473
+ The pre-redesign views (tasks, decisions, phases, sprints, files,
2474
+ agents, memory, kanban …) consume the legacy Linear tokens. Re-mapping
2475
+ those custom properties on .main-scroll bridges ALL views onto the
2476
+ mockup palette — and onto its light-theme flips — without per-view
2477
+ rules. min-height: 0 lets the 1fr grid row shrink so the area scrolls
2478
+ instead of clipping the bottom card row below the fold. */
2479
+ .main-scroll {
2480
+ min-height: 0;
2481
+ padding: 26px 28px;
2482
+ background: var(--dash-bg);
2483
+ --bg-page: var(--dash-bg);
2484
+ --bg-elev-1: var(--dash-card);
2485
+ --bg-elev-2: var(--dash-card);
2486
+ --bg-elev-3: var(--dash-border);
2487
+ --bg-input: var(--dash-bg);
2488
+ --bg-hover: var(--dash-hover);
2489
+ --bg-active: var(--dash-hover);
2490
+ --border-subtle: var(--dash-border);
2491
+ --border-default: var(--dash-border);
2492
+ --text-primary: var(--dash-text);
2493
+ --text-secondary: var(--dash-text);
2494
+ --text-tertiary: var(--dash-text-muted);
2495
+ --text-muted: var(--dash-text-muted);
2496
+ }
2497
+
2498
+ /* Legacy list panels pick up the card chrome and roomier rows. */
2499
+ .phase-list, .decision-list, .body { border-radius: 14px; }
2500
+ .item { padding: 11px 16px; }
2501
+ .phase-list .item { padding: 13px 16px; }
2502
+
2503
+ /* ── Grid — 12 cols, 20px gaps; wrappers stretch cards to equal row height ── */
2504
+ .dash-grid {
2505
+ display: grid;
2506
+ grid-template-columns: repeat(12, 1fr);
2507
+ gap: 20px;
2508
+ align-items: stretch;
2509
+ }
2510
+ .dash-grid .col-4,
2511
+ .dash-grid .col-6,
2512
+ .dash-grid .col-12 {
2513
+ min-width: 0;
2514
+ display: flex;
2515
+ flex-direction: column;
2516
+ }
2517
+ .dash-grid .col-4 { grid-column: span 4; }
2518
+ .dash-grid .col-6 { grid-column: span 6; }
2519
+ .dash-grid .col-12 { grid-column: span 12; }
2520
+ .dash-grid .col-4 > .dash-card,
2521
+ .dash-grid .col-6 > .dash-card,
2522
+ .dash-grid .col-12 > .dash-card { flex: 1 1 auto; }
2523
+ @media (max-width: 1100px) {
2524
+ .dash-grid .col-4,
2525
+ .dash-grid .col-6 { grid-column: span 12; }
2526
+ }
2527
+
2528
+ /* ── Card surface ── */
2529
+ .dash-card {
2530
+ /* margin: 0 cancels the global "section" margin-top rule — the
2531
+ cards are section elements and grid gap owns the spacing. */
2532
+ margin: 0;
2533
+ background: var(--dash-card);
2534
+ border: 1px solid var(--dash-border);
2535
+ border-radius: 14px;
2536
+ padding: 18px 20px;
2537
+ color: var(--dash-text);
2538
+ display: flex;
2539
+ flex-direction: column;
2540
+ gap: 12px;
2541
+ min-width: 0;
2542
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.02);
2543
+ }
2544
+ .dash-card-title {
2545
+ font-size: 13px;
2546
+ font-weight: 600;
2547
+ color: var(--dash-text);
2548
+ margin: 0;
2549
+ }
2550
+ .dash-card-sub {
2551
+ font-size: 12px;
2552
+ color: var(--dash-text-muted);
2553
+ margin: 0;
2554
+ }
2555
+
2556
+ /* ── Card header row: title left, "View all" link right ── */
2557
+ .ct-head, .ip-head, .bk-head, .rd-head, .pt-head {
2558
+ display: flex;
2559
+ align-items: center;
2560
+ justify-content: space-between;
2561
+ gap: 12px;
2562
+ }
2563
+ .ct-viewall, .ip-viewall, .bk-viewall, .rd-viewall, .pt-viewall {
2564
+ background: none;
2565
+ border: 0;
2566
+ padding: 0;
2567
+ cursor: pointer;
2568
+ font-size: 12px;
2569
+ font-weight: 600;
2570
+ color: var(--dash-teal);
2571
+ white-space: nowrap;
2572
+ }
2573
+ .ct-viewall:hover, .ip-viewall:hover, .bk-viewall:hover,
2574
+ .rd-viewall:hover, .pt-viewall:hover { text-decoration: underline; }
2575
+
2576
+ /* ── Shared list shells + row separators (mockup: subtle hairlines) ── */
2577
+ .ct-list, .ip-list, .bk-list, .rd-list {
2578
+ list-style: none;
2579
+ margin: 0;
2580
+ padding: 0;
2581
+ display: flex;
2582
+ flex-direction: column;
2583
+ min-width: 0;
2584
+ }
2585
+ .ct-row, .ip-row, .bk-row, .rd-row {
2586
+ padding: 9px 0;
2587
+ border-bottom: 1px solid var(--dash-border);
2588
+ }
2589
+ .ct-row:first-child, .ip-row:first-child,
2590
+ .bk-row:first-child, .rd-row:first-child { padding-top: 2px; }
2591
+ .ct-row:last-child, .ip-row:last-child,
2592
+ .bk-row:last-child, .rd-row:last-child {
2593
+ border-bottom: none;
2594
+ padding-bottom: 0;
2595
+ }
2596
+
2597
+ /* ── ProgressDonut — Project Progress (Row 1, Card 1) ── */
2598
+ .donut-body {
2599
+ display: flex;
2600
+ align-items: center;
2601
+ gap: 20px;
2602
+ }
2603
+ .donut-ring {
2604
+ position: relative;
2605
+ flex: 0 0 auto;
2606
+ width: 132px;
2607
+ height: 132px;
2608
+ }
2609
+ .donut-center {
2610
+ position: absolute;
2611
+ inset: 0;
2612
+ display: flex;
2613
+ flex-direction: column;
2614
+ align-items: center;
2615
+ justify-content: center;
2616
+ gap: 2px;
2617
+ }
2618
+ .donut-pct {
2619
+ font-size: 30px;
2620
+ font-weight: 700;
2621
+ line-height: 1;
2622
+ color: var(--dash-text);
2623
+ }
2624
+ .donut-pct-label {
2625
+ font-size: 11px;
2626
+ color: var(--dash-text-muted);
2627
+ }
2628
+ .donut-legend {
2629
+ flex: 1 1 auto;
2630
+ }
2631
+ /* ============================================================
2632
+ CompletedTasks (ct-*) + InProgress (ip-*) cards — Row 2
2633
+ Overview redesign. Appended by tasks agent A6.
2634
+ ============================================================ */
2635
+ /* ── Blockers card (Row 2, Card 3) ───────────────────────────────── */
2636
+ /* ── Dashboard redesign — Recent Decisions (Row 3, Card 1) ───────── */
2637
+ /* Merge repair: the four card-head rules were spliced into each other
2638
+ mid-rule (unclosed braces nested every later rule). They share one
2639
+ header layout — combined into a single rule. */
2640
+ .ct-head,
2641
+ .ip-head,
2642
+ .bk-head,
2643
+ .rd-head {
2644
+ display: flex;
2645
+ align-items: center;
2646
+ justify-content: space-between;
2647
+ gap: 12px;
2648
+ }
2649
+ .ct-viewall,
2650
+ .ip-viewall {
2651
+ background: none;
2652
+ border: none;
2653
+ padding: 0;
2654
+ cursor: pointer;
2655
+ font-size: 12px;
2656
+ font-weight: 500;
2657
+ color: var(--dash-blue);
2658
+ }
2659
+ .ct-viewall:hover,
2660
+ .ip-viewall:hover {
2661
+ text-decoration: underline;
2662
+ }
2663
+ .ct-list,
2664
+ .ip-list {
2665
+ list-style: none;
2666
+ margin: 0;
2667
+ padding: 0;
2668
+ }
2669
+ .bk-viewall {
2670
+ background: none;
2671
+ border: none;
2672
+ padding: 0;
2673
+ }
2674
+ .rd-viewall {
2675
+ background: none;
2676
+ border: none;
2677
+ color: var(--dash-teal);
2678
+ font-size: 12px;
2679
+ font-weight: 600;
2680
+ cursor: pointer;
2681
+ }
2682
+ .bk-viewall:hover { text-decoration: underline; }
2683
+ .bk-list {
2684
+ padding: 0;
2685
+ }
2686
+ .rd-viewall:hover { text-decoration: underline; }
2687
+ .rd-list {
2688
+ list-style: none;
2689
+ margin: 0;
2690
+ padding: 0;
2691
+ display: flex;
2692
+ flex-direction: column;
2693
+ gap: 10px;
2694
+ min-width: 0;
2695
+ }
2696
+ .donut-legend-row {
2697
+ display: flex;
2698
+ align-items: center;
2699
+ gap: 8px;
2700
+ }
2701
+ .donut-dot {
2702
+ flex: 0 0 auto;
2703
+ width: 9px;
2704
+ height: 9px;
2705
+ border-radius: 50%;
2706
+ display: inline-block;
2707
+ }
2708
+ .donut-dot--done { background: var(--dash-teal); }
2709
+ .donut-dot--prog { background: var(--dash-blue); }
2710
+ .donut-dot--idle { background: var(--dash-sev-low); }
2711
+ .donut-legend-label {
2712
+ flex: 1 1 auto;
2713
+ font-size: 13px;
2714
+ color: var(--dash-text-muted);
2715
+ }
2716
+ .donut-legend-pct {
2717
+ flex: 0 0 auto;
2718
+ font-size: 13px;
2719
+ font-weight: 600;
2720
+ color: var(--dash-text);
2721
+ }
2722
+ .donut-summary {
2723
+ font-size: 13px;
2724
+ color: var(--dash-text-muted);
2725
+ margin: 0;
2726
+ }
2727
+ .donut-summary strong {
2728
+ color: var(--dash-text);
2729
+ font-weight: 700;
2730
+ }
2731
+ .donut-bar {
2732
+ display: block;
2733
+ width: 100%;
2734
+ height: 6px;
2735
+ border-radius: 3px;
2736
+ overflow: hidden;
2737
+ }
2738
+
2739
+ /* ── CurrentPhase — phase stepper (Row 1, Card 2) ── */
2740
+ .cp-card { gap: 14px; }
2741
+ .cp-head {
2742
+ display: flex;
2743
+ align-items: flex-start;
2744
+ gap: 12px;
2745
+ }
2746
+ .cp-rocket {
2747
+ flex: 0 0 auto;
2748
+ width: 40px;
2749
+ height: 40px;
2750
+ display: flex;
2751
+ align-items: center;
2752
+ justify-content: center;
2753
+ font-size: 20px;
2754
+ border-radius: 10px;
2755
+ background: rgba(167, 139, 250, 0.12);
2756
+ border: 1px solid rgba(167, 139, 250, 0.25);
2757
+ }
2758
+ .cp-headtext { min-width: 0; }
2759
+ .cp-titlerow {
2760
+ display: flex;
2761
+ align-items: center;
2762
+ flex-wrap: wrap;
2763
+ gap: 8px;
2764
+ }
2765
+ .cp-name {
2766
+ font-size: 16px;
2767
+ font-weight: 700;
2768
+ color: var(--dash-purple);
2769
+ }
2770
+ .cp-pill {
2771
+ display: inline-flex;
2772
+ align-items: center;
2773
+ gap: 4px;
2774
+ font-size: 11px;
2775
+ font-weight: 600;
2776
+ padding: 2px 9px;
2777
+ border-radius: 999px;
2778
+ color: var(--dash-purple);
2779
+ background: rgba(167, 139, 250, 0.12);
2780
+ border: 1px solid rgba(167, 139, 250, 0.3);
2781
+ white-space: nowrap;
2782
+ }
2783
+ .cp-sub {
2784
+ margin: 2px 0 0;
2785
+ font-size: 12px;
2786
+ color: var(--dash-text-muted);
2787
+ }
2788
+ .cp-progress {
2789
+ margin: 0;
2790
+ font-size: 12px;
2791
+ color: var(--dash-text-muted);
2792
+ }
2793
+ .cp-dot { margin: 0 6px; }
2794
+ .cp-pct { color: var(--dash-text); font-weight: 600; }
2795
+ .cp-stepper {
2796
+ list-style: none;
2797
+ margin: 6px 0 0;
2798
+ padding: 0;
2799
+ display: flex;
2800
+ position: relative;
2801
+ }
2802
+ .cp-stepper::before {
2803
+ content: "";
2804
+ position: absolute;
2805
+ top: 11px;
2806
+ left: 0;
2807
+ right: 0;
2808
+ height: 2px;
2809
+ background: var(--dash-border);
2810
+ }
2811
+ .cp-step {
2812
+ position: relative;
2813
+ flex: 1 1 0;
2814
+ display: flex;
2815
+ flex-direction: column;
2816
+ align-items: center;
2817
+ gap: 6px;
2818
+ min-width: 0;
2819
+ }
2820
+ .cp-node {
2821
+ width: 22px;
2822
+ height: 22px;
2823
+ border-radius: 999px;
2824
+ display: flex;
2825
+ align-items: center;
2826
+ justify-content: center;
2827
+ font-size: 12px;
2828
+ font-weight: 700;
2829
+ background: var(--dash-card);
2830
+ border: 2px solid var(--dash-sev-low);
2831
+ color: var(--dash-card);
2832
+ position: relative;
2833
+ z-index: 1;
2834
+ }
2835
+ .cp-done .cp-node {
2836
+ background: var(--dash-teal);
2837
+ border-color: var(--dash-teal);
2838
+ color: var(--dash-bg);
2839
+ }
2840
+ .cp-active .cp-node {
2841
+ background: var(--dash-card);
2842
+ border-color: var(--dash-purple);
2843
+ box-shadow: 0 0 0 4px rgba(167, 139, 250, 0.2);
2844
+ }
2845
+ .cp-label {
2846
+ font-size: 10px;
2847
+ line-height: 1.3;
2848
+ text-align: center;
2849
+ color: var(--dash-text-muted);
2850
+ max-width: 100%;
2851
+ overflow: hidden;
2852
+ text-overflow: ellipsis;
2853
+ white-space: nowrap;
2854
+ }
2855
+ .cp-done .cp-label,
2856
+ .cp-active .cp-label { color: var(--dash-text); }
2857
+
2858
+ /* ── Timeline — projected launch + sparkline (Row 1, Card 3) ── */
2859
+ .tl-card { gap: 6px; }
2860
+ .tl-label {
2861
+ text-transform: uppercase;
2862
+ letter-spacing: 0.06em;
2863
+ }
2864
+ .tl-date {
2865
+ font-size: 26px;
2866
+ font-weight: 700;
2867
+ line-height: 1.1;
2868
+ color: var(--dash-teal);
2869
+ margin: 0;
2870
+ }
2871
+ .tl-days {
2872
+ font-size: 12px;
2873
+ color: var(--dash-text-muted);
2874
+ margin: 0 0 4px 0;
2875
+ }
2876
+ /* flex:1 + preserveAspectRatio="none" → the sparkline stretches to fill
2877
+ whatever height the equal-height row leaves; min-height guards collapse. */
2878
+ .tl-chart {
2879
+ width: 100%;
2880
+ flex: 1 1 auto;
2881
+ min-height: 84px;
2882
+ display: block;
2883
+ overflow: visible;
2884
+ }
2885
+ .tl-footer {
2886
+ display: flex;
2887
+ align-items: center;
2888
+ justify-content: space-between;
2889
+ margin-top: 4px;
2890
+ font-size: 12px;
2891
+ }
2892
+ .tl-status {
2893
+ display: inline-flex;
2894
+ align-items: center;
2895
+ gap: 6px;
2896
+ color: var(--dash-text);
2897
+ font-weight: 600;
2898
+ }
2899
+ .tl-dot-badge {
2900
+ width: 8px;
2901
+ height: 8px;
2902
+ border-radius: 50%;
2903
+ background: var(--dash-teal);
2904
+ display: inline-block;
2905
+ }
2906
+ .tl-status-risk { color: var(--dash-sev-medium); }
2907
+ .tl-status-risk .tl-dot-badge { background: var(--dash-sev-medium); }
2908
+ .tl-note { color: var(--dash-text-muted); }
2909
+
2910
+ /* ── CompletedTasks — check + title + date (Row 2, Card 1) ── */
2911
+ .ct-row {
2912
+ display: flex;
2913
+ align-items: center;
2914
+ gap: 10px;
2915
+ font-size: 13px;
2916
+ color: var(--dash-text);
2917
+ }
2918
+ .ct-check {
2919
+ flex: none;
2920
+ color: var(--accent-green);
2921
+ }
2922
+ .ct-title {
2923
+ flex: 1 1 auto;
2924
+ min-width: 0;
2925
+ overflow: hidden;
2926
+ text-overflow: ellipsis;
2927
+ white-space: nowrap;
2928
+ }
2929
+ .ct-date {
2930
+ flex: none;
2931
+ font-size: 12px;
2932
+ color: var(--dash-text-muted);
2933
+ }
2934
+
2935
+ /* ── InProgress — title + % pill (Row 2, Card 2) ── */
2936
+ .ip-row {
2937
+ display: flex;
2938
+ align-items: center;
2939
+ gap: 10px;
2940
+ font-size: 13px;
2941
+ color: var(--dash-text);
2942
+ }
2943
+ .ip-title {
2944
+ flex: 1 1 auto;
2945
+ min-width: 0;
2946
+ overflow: hidden;
2947
+ text-overflow: ellipsis;
2948
+ white-space: nowrap;
2949
+ }
2950
+ .ip-badge {
2951
+ flex: none;
2952
+ font-size: 11px;
2953
+ font-weight: 600;
2954
+ line-height: 1;
2955
+ padding: 4px 9px;
2956
+ border-radius: 999px;
2957
+ color: var(--dash-blue);
2958
+ background: rgba(59, 130, 246, 0.15);
2959
+ }
2960
+
2961
+ /* ── Blockers — icon + title/desc + severity pill (Row 2, Card 3) ── */
2962
+ .bk-row {
2963
+ display: grid;
2964
+ grid-template-columns: auto 1fr auto;
2965
+ align-items: start;
2966
+ column-gap: 10px;
2967
+ }
2968
+ .bk-icon {
2969
+ font-size: 14px;
2970
+ line-height: 1.4;
2971
+ }
2972
+ .bk-body { min-width: 0; }
2973
+ .bk-title {
2974
+ margin: 0;
2975
+ font-size: 13px;
2976
+ font-weight: 600;
2977
+ color: var(--dash-text);
2978
+ }
2979
+ .bk-desc {
2980
+ margin: 2px 0 0;
2981
+ font-size: 12px;
2982
+ color: var(--dash-text-muted);
2983
+ white-space: nowrap;
2984
+ overflow: hidden;
2985
+ text-overflow: ellipsis;
2986
+ }
2987
+ .bk-pill {
2988
+ align-self: center;
2989
+ font-size: 11px;
2990
+ font-weight: 600;
2991
+ padding: 2px 9px;
2992
+ border-radius: 999px;
2993
+ white-space: nowrap;
2994
+ border: 1px solid transparent;
2995
+ }
2996
+ .bk-sev-high { color: var(--dash-sev-high); }
2997
+ .bk-sev-medium { color: var(--dash-sev-medium); }
2998
+ .bk-sev-low { color: var(--dash-sev-low); }
2999
+ .bk-pill.bk-sev-high {
3000
+ background: rgba(248, 113, 113, 0.12);
3001
+ border-color: rgba(248, 113, 113, 0.35);
3002
+ }
3003
+ .bk-pill.bk-sev-medium {
3004
+ background: rgba(251, 191, 36, 0.12);
3005
+ border-color: rgba(251, 191, 36, 0.35);
3006
+ }
3007
+ .bk-pill.bk-sev-low {
3008
+ background: rgba(156, 163, 175, 0.12);
3009
+ border-color: rgba(156, 163, 175, 0.35);
3010
+ }
3011
+
3012
+ /* ── RecentDecisions — title + status badge + date (Row 3, Card 1) ── */
3013
+ .rd-row {
3014
+ display: flex;
3015
+ align-items: center;
3016
+ gap: 10px;
3017
+ }
3018
+ .rd-title {
3019
+ flex: 1 1 auto;
3020
+ min-width: 0;
3021
+ font-size: 13px;
3022
+ color: var(--dash-text);
3023
+ overflow: hidden;
3024
+ text-overflow: ellipsis;
3025
+ white-space: nowrap;
3026
+ }
3027
+ .rd-badge {
3028
+ flex: none;
3029
+ font-size: 11px;
3030
+ font-weight: 600;
3031
+ padding: 2px 8px;
3032
+ border-radius: 999px;
3033
+ white-space: nowrap;
3034
+ }
3035
+ .rd-badge--approved {
3036
+ color: var(--dash-teal);
3037
+ background: rgba(45, 212, 191, 0.12);
3038
+ }
3039
+ .rd-badge--rejected {
3040
+ color: var(--dash-sev-high);
3041
+ background: rgba(248, 113, 113, 0.12);
3042
+ }
3043
+ .rd-badge--proposed {
3044
+ color: var(--dash-purple);
3045
+ background: rgba(167, 139, 250, 0.12);
3046
+ }
3047
+ .rd-date {
3048
+ flex: none;
3049
+ font-size: 12px;
3050
+ color: var(--dash-text-muted);
3051
+ white-space: nowrap;
3052
+ }
3053
+
3054
+ /* ── ProgressTimeline — horizontal phase segments (Row 3, Card 2) ── */
3055
+ .pt-ticks {
3056
+ display: flex;
3057
+ justify-content: space-between;
3058
+ font-size: 11px;
3059
+ color: var(--dash-text-muted);
3060
+ padding: 0 2px;
3061
+ }
3062
+ .pt-tick { white-space: nowrap; }
3063
+ .pt-track {
3064
+ display: flex;
3065
+ gap: 6px;
3066
+ }
3067
+ .pt-seg {
3068
+ flex: 1;
3069
+ min-width: 0;
3070
+ display: flex;
3071
+ flex-direction: column;
3072
+ gap: 4px;
3073
+ padding: 10px;
3074
+ border-radius: 8px;
3075
+ border: 1px solid var(--dash-border);
3076
+ border-top: 3px solid var(--dash-sev-low);
3077
+ background: rgba(255, 255, 255, 0.02);
3078
+ }
3079
+ .pt-seg--done { border-top-color: var(--dash-teal); }
3080
+ .pt-seg--active { border-top-color: var(--dash-purple); }
3081
+ .pt-seg--todo { border-top-color: var(--dash-sev-low); }
3082
+ .pt-seg-name {
3083
+ font-size: 12px;
3084
+ font-weight: 600;
3085
+ color: var(--dash-text);
3086
+ overflow: hidden;
3087
+ text-overflow: ellipsis;
3088
+ white-space: nowrap;
3089
+ }
3090
+ .ip-badge {
3091
+ flex: none;
3092
+ font-size: 11px;
3093
+ font-weight: 600;
3094
+ line-height: 1;
3095
+ padding: 4px 9px;
3096
+ border-radius: 999px;
3097
+ color: var(--dash-blue);
3098
+ background: rgba(59, 130, 246, 0.15);
3099
+ }
3100
+ .bk-desc {
3101
+ margin: 2px 0 0;
3102
+ font-size: 12px;
3103
+ color: var(--dash-text-muted);
3104
+ white-space: nowrap;
3105
+ overflow: hidden;
3106
+ text-overflow: ellipsis;
3107
+ }
3108
+ .bk-pill {
3109
+ align-self: center;
3110
+ font-size: 11px;
3111
+ font-weight: 600;
3112
+ padding: 2px 9px;
3113
+ border-radius: 999px;
3114
+ white-space: nowrap;
3115
+ border: 1px solid transparent;
3116
+ }
3117
+ .bk-sev-high { color: var(--dash-sev-high); }
3118
+ .bk-sev-medium { color: var(--dash-sev-medium); }
3119
+ .bk-sev-low { color: var(--dash-sev-low); }
3120
+ .bk-pill.bk-sev-high {
3121
+ background: rgba(248, 113, 113, 0.12);
3122
+ border-color: rgba(248, 113, 113, 0.35);
3123
+ }
3124
+ .bk-pill.bk-sev-medium {
3125
+ background: rgba(251, 191, 36, 0.12);
3126
+ border-color: rgba(251, 191, 36, 0.35);
3127
+ }
3128
+ .bk-pill.bk-sev-low {
3129
+ background: rgba(156, 163, 175, 0.12);
3130
+ border-color: rgba(156, 163, 175, 0.35);
3131
+ }
3132
+ .pt-seg-range {
3133
+ font-size: 11px;
3134
+ color: var(--dash-text-muted);
3135
+ white-space: nowrap;
3136
+ }
3137
+ .pt-seg-badge {
3138
+ font-size: 10px;
3139
+ font-weight: 600;
3140
+ padding: 2px 6px;
3141
+ border-radius: 999px;
3142
+ align-self: flex-start;
3143
+ color: var(--dash-sev-low);
3144
+ background: rgba(156, 163, 175, 0.14);
3145
+ }
3146
+ .pt-seg--done .pt-seg-badge {
3147
+ color: var(--dash-teal);
3148
+ background: rgba(45, 212, 191, 0.12);
3149
+ }
3150
+ .pt-seg--active .pt-seg-badge {
3151
+ color: var(--dash-purple);
3152
+ background: rgba(167, 139, 250, 0.12);
3153
+ }
3154
+ @media (max-width: 700px) {
3155
+ .pt-track { flex-direction: column; }
3156
+ }
3157
+
3158
+ /* ── Dashboard redesign — sidebar + header chrome + project health ──
3159
+ Mockup chrome. Re-declares .sidebar / header layout (later-wins per
3160
+ property; mobile position/transform from the base rule are preserved)
3161
+ and adds prefixed sb-* / tb-* / phealth-* classes. Tokens only. */
3162
+
3163
+ /* Sidebar shell */
3164
+ .sidebar {
3165
+ display: flex;
3166
+ flex-direction: column;
3167
+ gap: 14px;
3168
+ height: 100%;
3169
+ padding: 16px 14px;
3170
+ background: var(--dash-bg);
3171
+ border-right: 1px solid var(--dash-border);
3172
+ box-sizing: border-box;
3173
+ overflow-y: auto;
3174
+ }
3175
+
3176
+ /* Logo badge */
3177
+ .sb-logo { display: flex; align-items: center; gap: 10px; padding: 2px 4px; }
3178
+ .sb-logo-badge {
3179
+ width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0;
3180
+ display: flex; align-items: center; justify-content: center;
3181
+ font-weight: 800; font-size: 16px; color: var(--dash-ink);
3182
+ background: linear-gradient(135deg, var(--dash-teal), var(--dash-blue));
3183
+ }
3184
+ .sb-logo-word { font-size: 16px; font-weight: 700; color: var(--dash-text); letter-spacing: -0.01em; }
3185
+
3186
+ /* Project switcher */
3187
+ .sb-switcher {
3188
+ display: flex; align-items: center; gap: 8px; width: 100%;
3189
+ padding: 9px 11px; border-radius: 10px;
3190
+ background: var(--dash-card); border: 1px solid var(--dash-border);
3191
+ color: var(--dash-text); font-size: 13px; font-weight: 600;
3192
+ cursor: pointer; text-align: left;
3193
+ transition: border-color 0.15s, background 0.15s;
3194
+ }
3195
+ .sb-switcher:hover { border-color: var(--dash-teal); }
3196
+ .sb-switcher-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--dash-teal); flex-shrink: 0; }
3197
+ .sb-switcher-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3198
+ .sb-switcher-chev { color: var(--dash-text-muted); font-size: 11px; }
3199
+
3200
+ /* Vertical nav */
3201
+ .sb-nav { display: flex; flex-direction: column; gap: 2px; }
3202
+ .sb-nav-link {
3203
+ display: flex; align-items: center; gap: 11px; width: 100%;
3204
+ padding: 9px 11px; border-radius: 9px;
3205
+ background: transparent; border: 0;
3206
+ color: var(--dash-text-muted); font-size: 13px; font-weight: 500;
3207
+ cursor: pointer; text-align: left;
3208
+ transition: background 0.15s, color 0.15s;
3209
+ }
3210
+ .sb-nav-link:hover { background: var(--dash-hover); color: var(--dash-text); }
3211
+ .sb-nav-link.active { background: rgba(45, 212, 191, 0.12); color: var(--dash-text); font-weight: 600; }
3212
+ .sb-nav-link.active .sb-nav-ic { color: var(--dash-teal); }
3213
+ .sb-nav-ic { display: inline-flex; color: var(--dash-text-muted); }
3214
+ .sb-nav-label { flex: 1; }
3215
+
3216
+ /* Health mini-card — pushed toward the bottom above the profile */
3217
+ .sb-health { margin-top: auto; }
3218
+
3219
+ /* Project Health card */
3220
+ .phealth {
3221
+ display: flex; flex-direction: column; gap: 8px;
3222
+ padding: 14px; border-radius: 12px;
3223
+ background: var(--dash-card); border: 1px solid var(--dash-border);
3224
+ }
3225
+ .phealth-title { margin: 0; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--dash-text-muted); }
3226
+ .phealth-head { display: flex; align-items: baseline; gap: 8px; }
3227
+ .phealth-pct { font-size: 26px; font-weight: 800; line-height: 1; color: var(--dash-text); }
3228
+ .phealth-pct-sign { font-size: 14px; font-weight: 700; margin-left: 1px; color: var(--dash-text-muted); }
3229
+ .phealth-label { font-size: 12px; font-weight: 600; }
3230
+ .phealth--good .phealth-label { color: var(--dash-teal); }
3231
+ .phealth--warn .phealth-label { color: var(--dash-sev-medium); }
3232
+ .phealth--risk .phealth-label { color: var(--dash-sev-high); }
3233
+ .phealth-spark { width: 100%; height: 36px; display: block; }
3234
+ .phealth-spark-line { fill: none; stroke-width: 2; vector-effect: non-scaling-stroke; }
3235
+ .phealth--good .phealth-spark-line { stroke: var(--dash-teal); }
3236
+ .phealth--warn .phealth-spark-line { stroke: var(--dash-sev-medium); }
3237
+ .phealth--risk .phealth-spark-line { stroke: var(--dash-sev-high); }
3238
+ .phealth-spark-area { stroke: none; opacity: 0.14; }
3239
+ .phealth--good .phealth-spark-area { fill: var(--dash-teal); }
3240
+ .phealth--warn .phealth-spark-area { fill: var(--dash-sev-medium); }
3241
+ .phealth--risk .phealth-spark-area { fill: var(--dash-sev-high); }
3242
+
3243
+ /* Profile footer */
3244
+ .sb-profile {
3245
+ display: flex; align-items: center; gap: 10px;
3246
+ padding: 10px 8px; border-top: 1px solid var(--dash-border);
3247
+ }
3248
+ .sb-avatar {
3249
+ width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
3250
+ display: flex; align-items: center; justify-content: center;
3251
+ font-size: 12px; font-weight: 700; color: var(--dash-ink);
3252
+ background: linear-gradient(135deg, var(--dash-purple), var(--dash-blue));
3253
+ }
3254
+ .sb-profile-meta { display: flex; flex-direction: column; min-width: 0; }
3255
+ .sb-profile-name { font-size: 13px; font-weight: 600; color: var(--dash-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3256
+ .sb-profile-email { font-size: 11px; color: var(--dash-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3257
+
3258
+ /* Header (Topbar) */
3259
+ .topbar {
3260
+ display: flex; align-items: center; gap: 16px; height: 100%;
3261
+ padding: 0 20px;
3262
+ background: var(--dash-bg);
3263
+ border-bottom: 1px solid var(--dash-border);
3264
+ box-sizing: border-box;
3265
+ }
3266
+ .tb-greeting { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
3267
+ .tb-welcome { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.2; color: var(--dash-text); white-space: nowrap; }
3268
+ .tb-wave { display: inline-block; }
3269
+ .tb-sub { margin: 0; font-size: 11px; line-height: 1.2; color: var(--dash-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3270
+ .tb-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
3271
+ .tb-synced {
3272
+ display: flex; align-items: center; gap: 7px;
3273
+ padding: 6px 10px; border-radius: 8px;
3274
+ background: transparent; border: 0; cursor: pointer;
3275
+ font-size: 12px; color: var(--dash-text-muted);
3276
+ }
3277
+ .tb-synced:hover { color: var(--dash-text); }
3278
+ .tb-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dash-teal); box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.18); flex-shrink: 0; }
3279
+ .tb-synced--busy .tb-dot { background: var(--dash-blue); box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18); animation: tb-pulse 0.8s ease-in-out infinite; }
3280
+ @keyframes tb-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
3281
+ .tb-btn {
3282
+ display: inline-flex; align-items: center; gap: 7px;
3283
+ padding: 8px 13px; border-radius: 9px;
3284
+ background: var(--dash-card); border: 1px solid var(--dash-border);
3285
+ color: var(--dash-text); font-size: 13px; font-weight: 600;
3286
+ cursor: pointer; white-space: nowrap;
3287
+ transition: border-color 0.15s, background 0.15s, filter 0.15s;
3288
+ }
3289
+ .tb-btn:hover { border-color: var(--dash-teal); }
3290
+ .tb-btn--primary {
3291
+ background: linear-gradient(135deg, var(--dash-teal), var(--dash-blue));
3292
+ border-color: transparent; color: var(--dash-ink);
3293
+ }
3294
+ .tb-btn--primary:hover { filter: brightness(1.05); border-color: transparent; }
3295
+ .tb-btn--icon { padding: 8px 11px; }
3296
+ .tb-kebab { font-size: 16px; line-height: 1; letter-spacing: 1px; }
3297
+
3298
+ @media (max-width: 760px) {
3299
+ .tb-sub { display: none; }
3300
+ .tb-synced { display: none; }
3301
+ }
3302
+
3303
+ /* ════════════════════════════════════════════════════════════════════
3304
+ POLISH — chrome frame (app shell + sidebar + topbar + status bar).
3305
+ Appended LAST so it wins ties against earlier conflicting rules.
3306
+ Owner: p1-chrome agent. Scope: Sidebar / Topbar / App layout only.
3307
+ ════════════════════════════════════════════════════════════════════ */
3308
+
3309
+ :root {
3310
+ /* Sidebar surface — darker sibling of --dash-card per mockup spec
3311
+ ("Card surface: #0E1626 / #111A2E"); kept separate so the sidebar
3312
+ reads one step below the page base. */
3313
+ --dash-sidebar: #0E1626;
3314
+ /* Ink on accent-filled surfaces (logo badge, avatar, primary button,
3315
+ offline banner) — dark navy reads on the teal/blue gradient in both
3316
+ themes, so it has no light override. */
3317
+ --dash-ink: #06121F;
3318
+ /* Subtle hover overlay for nav items — theme-dependent direction
3319
+ (lighten on dark, darken on light). */
3320
+ --dash-hover: rgba(255, 255, 255, 0.04);
3321
+ /* Plain-text log view (OrchPanel) + xterm panel surround. The xterm
3322
+ canvas itself keeps its own dark JS theme — these style the chrome. */
3323
+ --dash-term-bg: #050507;
3324
+ --dash-term-text: #C8D8C8;
3325
+ --dash-term-line: #A0C4A0;
3326
+ --dash-term-tool: #7CB8FF;
3327
+ }
3328
+
3329
+ /* Light theme — same --dash-* tokens, light values. The chrome (and any
3330
+ card CSS built on these tokens) flips with the existing data-theme
3331
+ toggle; accents (teal/purple/blue/amber/severity) stay identical. */
3332
+ [data-theme="light"] {
3333
+ --dash-bg: #F4F6FB;
3334
+ --dash-card: #FFFFFF;
3335
+ --dash-border: #E2E8F0;
3336
+ --dash-text: #1A2233;
3337
+ --dash-text-muted: #5B6B82;
3338
+ --dash-sidebar: #FFFFFF;
3339
+ --dash-hover: rgba(15, 23, 41, 0.05);
3340
+ --dash-term-bg: #F1F5F9;
3341
+ --dash-term-text: #334155;
3342
+ --dash-term-line: #166534;
3343
+ --dash-term-tool: #1D4ED8;
3344
+ }
3345
+
3346
+ /* Frame: deep-navy base behind chrome AND content so the mockup palette
3347
+ is continuous (legacy body bg is near-black #08090a). */
3348
+ .app-shell,
3349
+ .main-scroll { background: var(--dash-bg); }
3350
+
3351
+ /* Content column: 64px header row (greeting + subtitle need the height),
3352
+ scrollable middle, auto-height status bar. Replaces the inline
3353
+ grid-template-rows that previously lived on #main-content in App.js. */
3354
+ .content-area { grid-template-rows: 64px 1fr auto; }
3355
+
3356
+ /* Sidebar surface per mockup. */
3357
+ .sidebar {
3358
+ background: var(--dash-sidebar);
3359
+ border-right: 1px solid var(--dash-border);
3360
+ }
3361
+
3362
+ /* The legacy ".sidebar nav" rule (flex:1 + padding) outranks .sb-nav
3363
+ (element+class beats class) and breaks the chrome nav alignment.
3364
+ Re-assert: nav grows so the health card + profile hug the bottom. */
3365
+ .sidebar nav.sb-nav {
3366
+ flex: 1 0 auto;
3367
+ padding: 0;
3368
+ gap: 2px;
3369
+ }
3370
+
3371
+ /* Topbar: solid navy header — disable the legacy frosted-glass "header"
3372
+ element rule (rgba near-black + backdrop blur) that bleeds through. */
3373
+ header.topbar {
3374
+ background: var(--dash-bg);
3375
+ backdrop-filter: none;
3376
+ -webkit-backdrop-filter: none;
3377
+ border-bottom: 1px solid var(--dash-border);
3378
+ }
3379
+ .tb-welcome { font-size: 17px; letter-spacing: -0.012em; }
3380
+ .tb-sub { font-size: 12px; }
3381
+
3382
+ /* Status bar (was inline styles in App.js StatusBar). */
3383
+ .statusbar {
3384
+ display: flex;
3385
+ align-items: center;
3386
+ gap: var(--space-4);
3387
+ height: 24px;
3388
+ padding: 0 var(--space-4);
3389
+ background: var(--dash-sidebar);
3390
+ border-top: 1px solid var(--dash-border);
3391
+ font-family: var(--font-mono);
3392
+ font-size: var(--text-2xs);
3393
+ color: var(--dash-text-muted);
3394
+ white-space: nowrap;
3395
+ overflow: hidden;
3396
+ }
3397
+ .statusbar-dot {
3398
+ width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
3399
+ background: var(--dash-teal);
3400
+ }
3401
+ .statusbar-dot--offline { background: var(--dash-sev-high); }
3402
+ .statusbar-dot--busy { animation: pulse-dot 1s ease-in-out infinite; }
3403
+ .statusbar-path { overflow: hidden; text-overflow: ellipsis; }
3404
+ .statusbar-version { margin-left: auto; }
3405
+
3406
+ /* Offline banner (was inline styles in App.js OfflineBanner). */
3407
+ .offline-banner {
3408
+ display: flex;
3409
+ align-items: center;
3410
+ gap: var(--space-2);
3411
+ padding: var(--space-2) var(--space-4);
3412
+ background: var(--dash-sev-high);
3413
+ color: var(--dash-ink);
3414
+ font-size: var(--text-sm);
3415
+ font-weight: 600;
3416
+ border-radius: 8px;
3417
+ }
3418
+
3419
+ /* ── Agent Sessions panel (OrchPanel) — themed on --dash-* tokens so it
3420
+ follows the light/dark toggle like the rest of the chrome. */
3421
+ .orch-panel {
3422
+ background: var(--dash-sidebar);
3423
+ border-left: 1px solid var(--dash-border);
3424
+ }
3425
+ .orch-panel-header,
3426
+ .orch-panel-footer,
3427
+ .orch-files,
3428
+ .orch-files-head {
3429
+ background: var(--dash-card);
3430
+ border-color: var(--dash-border);
3431
+ }
3432
+ .orch-panel-title { color: var(--dash-text); }
3433
+ .orch-panel-close { color: var(--dash-text-muted); }
3434
+ .orch-panel-close:hover { background: var(--dash-hover); color: var(--dash-text); }
3435
+ .orch-tabs { background: var(--dash-sidebar); border-color: var(--dash-border); }
3436
+ .orch-tab { color: var(--dash-text-muted); }
3437
+ .orch-tab:hover { background: var(--dash-hover); color: var(--dash-text); }
3438
+ .orch-tab.active { background: var(--dash-card); color: var(--dash-text); }
3439
+ .orch-term-body { background: var(--dash-term-bg); }
3440
+ .orch-term-empty,
3441
+ .orch-empty-tab,
3442
+ .orch-footer-status { color: var(--dash-text-muted); }
3443
+ .kt-line { color: var(--dash-term-line); }
3444
+ .kt-line.tool { color: var(--dash-term-tool); }
3445
+ .kt-line.meta { color: var(--dash-text-muted); }
3446
+ .kt-stream { color: var(--dash-term-text); }
3447
+ .kt-file { color: var(--dash-text-muted); border-color: var(--dash-border); }
3448
+ .orch-footer-btn {
3449
+ background: var(--dash-card);
3450
+ border: 1px solid var(--dash-border);
3451
+ color: var(--dash-text);
3452
+ }
3453
+ .orch-footer-btn:hover { background: var(--dash-card); border-color: var(--dash-teal); color: var(--dash-text); }
3454
+
3455
+ /* ── xterm terminal panel chrome — same treatment. The xterm canvas keeps
3456
+ its own dark JS theme (it is a real terminal); only the surround themes. */
3457
+ .term-panel { background: var(--dash-term-bg); border-top-color: var(--dash-teal); }
3458
+ .term-header { background: var(--dash-card); border-color: var(--dash-border); }
3459
+ .term-title { color: var(--dash-text); }
3460
+ .term-hint {
3461
+ background: var(--dash-card);
3462
+ border-color: var(--dash-border);
3463
+ color: var(--dash-text-muted);
3464
+ }
3465
+ .term-btn {
3466
+ background: var(--dash-card);
3467
+ border-color: var(--dash-border);
3468
+ color: var(--dash-text);
3469
+ }
3470
+ .term-btn:hover { background: var(--dash-card); border-color: var(--dash-teal); color: var(--dash-text); }
3471
+ .term-pill {
3472
+ background: var(--dash-card);
3473
+ border-color: var(--dash-teal);
3474
+ color: var(--dash-text);
3475
+ }
3476
+
3477
+ /* Mobile: the content column owns the full height (legacy 44px first row
3478
+ squashed it). Sidebar open/close uses the canonical .sidebar.open /
3479
+ #sidebar-backdrop.show classes from the base mobile block — App.js
3480
+ toggles those same names. */
3481
+ @media (max-width: 768px) {
3482
+ .app-shell { grid-template-rows: 1fr; }
3483
+ }
3484
+ /* ============================================================
3485
+ TaskPipeline (tpipe-*) — per-task stage stepper
3486
+ Planned → In Progress → Review → Done. Rendered inside task
3487
+ rows (Tasks view via TaskCard) and the Overview In Progress
3488
+ card rows (mini variant). Appended by pipeline agent F1.
3489
+ ============================================================ */
3490
+ .tpipe {
3491
+ display: inline-flex;
3492
+ align-items: center;
3493
+ gap: 3px;
3494
+ flex: none;
3495
+ vertical-align: middle;
3496
+ }
3497
+ .tpipe-node {
3498
+ width: 14px;
3499
+ height: 14px;
3500
+ border-radius: 50%;
3501
+ display: inline-flex;
3502
+ align-items: center;
3503
+ justify-content: center;
3504
+ font-size: 8px;
3505
+ line-height: 1;
3506
+ font-weight: 700;
3507
+ flex: none;
3508
+ color: transparent;
3509
+ background: transparent;
3510
+ border: 1.5px solid var(--dash-sev-low, var(--text-muted));
3511
+ }
3512
+ .tpipe-node--done {
3513
+ background: var(--dash-teal, var(--accent-green));
3514
+ border-color: var(--dash-teal, var(--accent-green));
3515
+ color: var(--dash-bg, var(--bg-page));
3516
+ }
3517
+ .tpipe-node--current {
3518
+ border-color: var(--dash-purple, var(--accent-blue));
3519
+ animation: tpipe-pulse 1.6s ease-in-out infinite;
3520
+ }
3521
+ .tpipe-node--blocked {
3522
+ border-color: var(--dash-sev-high, var(--accent-red));
3523
+ animation: none;
3524
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--dash-sev-high, var(--accent-red)) 20%, transparent);
3525
+ }
3526
+ @keyframes tpipe-pulse {
3527
+ 0%, 100% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--dash-purple, var(--accent-blue)) 45%, transparent); }
3528
+ 50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--dash-purple, var(--accent-blue)) 12%, transparent); }
3529
+ }
3530
+ .tpipe-line {
3531
+ width: 14px;
3532
+ height: 2px;
3533
+ border-radius: 1px;
3534
+ flex: none;
3535
+ background: color-mix(in srgb, var(--dash-sev-low, var(--text-muted)) 45%, transparent);
3536
+ }
3537
+ .tpipe-line--done {
3538
+ background: var(--dash-teal, var(--accent-green));
3539
+ }
3540
+ .tpipe-blocked {
3541
+ flex: none;
3542
+ margin-left: 4px;
3543
+ padding: 2px 7px;
3544
+ border-radius: 999px;
3545
+ font-size: 10px;
3546
+ font-weight: 600;
3547
+ line-height: 1.2;
3548
+ color: var(--dash-sev-high, var(--accent-red));
3549
+ background: color-mix(in srgb, var(--dash-sev-high, var(--accent-red)) 14%, transparent);
3550
+ }
3551
+ /* Mini variant — overview card rows */
3552
+ .tpipe--mini { gap: 2px; }
3553
+ .tpipe--mini .tpipe-node {
3554
+ width: 9px;
3555
+ height: 9px;
3556
+ border-width: 1px;
3557
+ font-size: 6px;
3558
+ }
3559
+ .tpipe--mini .tpipe-line { width: 8px; height: 1.5px; }
3560
+ .tpipe--mini .tpipe-blocked { padding: 1px 5px; font-size: 9px; margin-left: 2px; }
3561
+
3562
+ /* ── Data-honesty states: card empty states + first-run hero ────────
3563
+ Shared by the Overview slot components when a slice is legitimately
3564
+ empty (no blockers, no phases, no decisions…) and by OverviewView's
3565
+ first-run state when no .rcode project exists. Theme variables only —
3566
+ valid in both dark and [data-theme=light]. */
3567
+ .dash-empty {
3568
+ display: flex;
3569
+ flex-direction: column;
3570
+ align-items: center;
3571
+ justify-content: center;
3572
+ gap: 6px;
3573
+ padding: 24px 12px;
3574
+ text-align: center;
3575
+ color: var(--dash-text-muted);
3576
+ font-size: 12px;
3577
+ }
3578
+ .dash-empty-emoji { font-size: 20px; line-height: 1; }
3579
+ .dash-empty-hint {
3580
+ font-family: var(--font-mono);
3581
+ font-size: 11px;
3582
+ color: var(--dash-text);
3583
+ background: var(--dash-hover);
3584
+ border: 1px solid var(--dash-border);
3585
+ border-radius: 6px;
3586
+ padding: 3px 8px;
3587
+ }
3588
+ /* Decision row without a recorded status — muted dash, no fake badge. */
3589
+ .rd-status-none { color: var(--dash-text-muted); font-size: 12px; }
3590
+ /* Sidebar progress card before anything is tracked — neutral tone. */
3591
+ .phealth--none .phealth-label { color: var(--dash-text-muted); }
3592
+ /* Timeline card placeholder when no velocity history is recorded. */
3593
+ .tl-nochart {
3594
+ display: flex;
3595
+ align-items: center;
3596
+ justify-content: center;
3597
+ height: 88px;
3598
+ color: var(--dash-text-muted);
3599
+ font-size: 12px;
3600
+ border: 1px dashed var(--dash-border);
3601
+ border-radius: 8px;
3602
+ }
3603
+ /* First-run hero — Overview when no .rcode project exists. */
3604
+ .firstrun {
3605
+ display: flex;
3606
+ flex-direction: column;
3607
+ align-items: center;
3608
+ justify-content: center;
3609
+ gap: 10px;
3610
+ padding: 64px 24px;
3611
+ text-align: center;
3612
+ background: var(--dash-card);
3613
+ border: 1px solid var(--dash-border);
3614
+ border-radius: 12px;
3615
+ }
3616
+ .firstrun-badge {
3617
+ width: 48px;
3618
+ height: 48px;
3619
+ border-radius: 12px;
3620
+ display: flex;
3621
+ align-items: center;
3622
+ justify-content: center;
3623
+ font-size: 24px;
3624
+ font-weight: 800;
3625
+ color: #fff;
3626
+ background: linear-gradient(135deg, var(--dash-teal), var(--dash-purple));
3627
+ }
3628
+ .firstrun-title { margin: 0; font-size: 18px; font-weight: 700; color: var(--dash-text); }
3629
+ .firstrun-sub { margin: 0; font-size: 13px; color: var(--dash-text-muted); max-width: 440px; line-height: 1.5; }
3630
+ .firstrun-sub code { font-family: var(--font-mono); color: var(--dash-text); }
3631
+ .firstrun-cmd {
3632
+ font-family: var(--font-mono);
3633
+ font-size: 13px;
3634
+ color: var(--dash-teal);
3635
+ background: var(--dash-hover);
3636
+ border: 1px solid var(--dash-border);
3637
+ border-radius: 8px;
3638
+ padding: 6px 12px;
3639
+ }
3640
+ /* ── App loading shell — visible until /js/app.js boots (cleared by app.js) ── */
3641
+ .app-loading {
3642
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
3643
+ gap: 14px; min-height: 100vh; color: var(--dash-text-muted);
3644
+ }
3645
+ .app-loading-spinner {
3646
+ width: 28px; height: 28px; border-radius: 50%;
3647
+ border: 3px solid var(--dash-border); border-top-color: var(--dash-teal);
3648
+ animation: app-loading-spin 0.8s linear infinite;
3649
+ }
3650
+ .app-loading-text { font-size: 13px; margin: 0; }
3651
+ @keyframes app-loading-spin { to { transform: rotate(360deg); } }
3652
+
3653
+ /* ── Inert project switcher — single-project server, no menu to open ── */
3654
+ .sb-switcher--static { cursor: default; }
3655
+ .sb-switcher--static:hover { border-color: var(--dash-border); }
3656
+
3657
+ /* Nav now lists all 12 views — let it scroll on short viewports instead of
3658
+ pushing the health card / profile footer off-screen. */
3659
+ .sb-nav { overflow-y: auto; min-height: 0; }
3660
+ /* ════════════════════════════════════════════════════════════════════
3661
+ R3 — accessibility baseline + failure visibility + mobile pass.
3662
+ Owner: r3-access agent. Appended last so it wins ties.
3663
+ ════════════════════════════════════════════════════════════════════ */
3664
+
3665
+ /* ── Focus indicators — keyboard-only (:focus-visible) for all interactive
3666
+ chrome. Both themes define --dash-teal, so the ring is visible on the
3667
+ dark and light surfaces alike. */
3668
+ button:focus-visible,
3669
+ a:focus-visible,
3670
+ select:focus-visible,
3671
+ input:focus-visible,
3672
+ summary:focus-visible,
3673
+ [role="button"]:focus-visible {
3674
+ outline: 2px solid var(--dash-teal, #2DD4BF);
3675
+ outline-offset: 2px;
3676
+ border-radius: 4px;
3677
+ }
3678
+ /* Clickable rows/cards get the ring inside their own radius. */
3679
+ .item-clickable:focus-visible,
3680
+ .cmd-hint-item:focus-visible {
3681
+ outline-offset: -2px;
3682
+ }
3683
+
3684
+ /* ── Disabled run buttons (orchestrator unreachable) ── */
3685
+ .card-run-btn:disabled,
3686
+ .kanban-run-btn:disabled,
3687
+ .cmd-runner-btn:disabled {
3688
+ opacity: 0.45;
3689
+ cursor: not-allowed;
3690
+ }
3691
+
3692
+ /* ── state.json parse-error banner (dismissible, role=alert) ── */
3693
+ .parse-error-banner {
3694
+ display: flex;
3695
+ align-items: center;
3696
+ justify-content: space-between;
3697
+ gap: var(--space-3);
3698
+ padding: var(--space-2) var(--space-4);
3699
+ margin-bottom: var(--space-3);
3700
+ background: var(--accent-amber, #F59E0B);
3701
+ color: var(--dash-ink, #06121F);
3702
+ font-size: var(--text-sm);
3703
+ font-weight: 600;
3704
+ border-radius: 8px;
3705
+ }
3706
+ .banner-dismiss {
3707
+ flex: none;
3708
+ background: none;
3709
+ border: none;
3710
+ cursor: pointer;
3711
+ color: inherit;
3712
+ font-size: var(--text-sm);
3713
+ font-weight: 700;
3714
+ padding: 2px 6px;
3715
+ border-radius: 4px;
3716
+ }
3717
+ .banner-dismiss:hover { background: rgba(0,0,0,0.12); /* intentional: dim overlay on amber; alpha can't be a theme token */ }
3718
+
3719
+ /* ── Orchestrator-down banner (Orchestration view) ── */
3720
+ .orch-down-banner {
3721
+ display: flex;
3722
+ align-items: center;
3723
+ gap: var(--space-2);
3724
+ padding: var(--space-2) var(--space-4);
3725
+ margin: var(--space-3) 0;
3726
+ background: color-mix(in srgb, var(--dash-sev-high, var(--accent-red)) 14%, transparent);
3727
+ border: 1px solid var(--dash-sev-high, var(--accent-red));
3728
+ color: var(--dash-text, var(--text-primary));
3729
+ font-size: var(--text-sm);
3730
+ font-weight: 600;
3731
+ border-radius: 8px;
3732
+ }
3733
+
3734
+ /* ── Mobile pass (≤768px) — redesigned chrome + overview grid ──
3735
+ Cards already stack via the ≤1100px .dash-grid rule; this tightens
3736
+ spacing and keeps the topbar on one row without horizontal scroll. */
3737
+ @media (max-width: 768px) {
3738
+ .main-scroll { padding: 14px 12px; }
3739
+ .dash-grid { gap: 14px; }
3740
+ header { padding: 0 var(--space-4); }
3741
+ .tb-greeting { min-width: 0; }
3742
+ .tb-welcome { font-size: 14px; overflow: hidden; text-overflow: ellipsis; }
3743
+ .tb-actions { gap: 6px; }
3744
+ .tb-btn--share { display: none; }
3745
+ /* Slide-in sidebar sits above the backdrop; backdrop above content. */
3746
+ .sidebar { z-index: 30; }
3747
+ #sidebar-backdrop { z-index: 25; }
3748
+ }
3749
+
3750
+ /* ══════════════════════════════════════════════════════════════════
3751
+ FILE READER — shared slide-over for Files + Memory views
3752
+ (components/FileReader.js)
3753
+ ══════════════════════════════════════════════════════════════════ */
3754
+ .reader-backdrop {
3755
+ position: fixed;
3756
+ inset: 0;
3757
+ background: rgba(0,0,0,0.45); /* intentional: one-off overlay tint; translucency can't be expressed as a theme token */
3758
+ z-index: 220;
3759
+ }
3760
+ .reader-panel {
3761
+ position: fixed;
3762
+ top: 0;
3763
+ right: 0;
3764
+ bottom: 0;
3765
+ width: min(720px, 92vw);
3766
+ display: flex;
3767
+ flex-direction: column;
3768
+ background: var(--bg-elev-2);
3769
+ border-left: 1px solid var(--border-default);
3770
+ box-shadow: -12px 0 32px rgba(0,0,0,0.35); /* intentional: overlay shadow; alpha can't be a theme token */
3771
+ z-index: 221;
3772
+ }
3773
+ /* ════════════════════════════════════════════════════════════════════
3774
+ AGENTS VIEW v2 — sectioned card grid + agent detail drawer
3775
+ (appended block — theme variables only, valid in dark and
3776
+ [data-theme=light]. Per-role color comes from --agent-accent, set by
3777
+ the agent-accent--<type> variants on the card/drawer root.)
3778
+ ════════════════════════════════════════════════════════════════════ */
3779
+
3780
+ /* Per-role accent variants — hue tokens are theme-stable in both modes. */
3781
+ .agent-accent--leadership { --agent-accent: var(--accent-primary); }
3782
+ .agent-accent--engineering { --agent-accent: var(--accent-green); }
3783
+ .agent-accent--product { --agent-accent: var(--accent-blue); }
3784
+ .agent-accent--design { --agent-accent: var(--violet); }
3785
+ .agent-accent--quality { --agent-accent: var(--accent-amber); }
3786
+ .agent-accent--support { --agent-accent: var(--dash-teal); }
3787
+ .agent-accent--system { --agent-accent: var(--dash-sev-low); }
3788
+
3789
+ /* ── Search bar (same chrome as Files) + result count ── */
3790
+ .agent-filter-bar {
3791
+ display: flex;
3792
+ align-items: center;
3793
+ gap: var(--space-4);
3794
+ }
3795
+ .agent-count {
3796
+ flex-shrink: 0;
3797
+ font-family: var(--font-mono);
3798
+ font-size: var(--text-2xs);
3799
+ color: var(--text-muted);
3800
+ white-space: nowrap;
3801
+ }
3802
+
3803
+ /* ── Category sections with sticky headers ── */
3804
+ .agent-section-head {
3805
+ position: sticky;
3806
+ top: 0;
3807
+ z-index: 5;
3808
+ display: flex;
3809
+ align-items: baseline;
3810
+ gap: var(--space-3);
3811
+ padding: var(--space-3) var(--space-2);
3812
+ margin-top: var(--space-4);
3813
+ background: var(--bg-page);
3814
+ border-bottom: 1px solid var(--border-subtle);
3815
+ font-size: var(--text-xs);
3816
+ font-weight: 600;
3817
+ color: var(--text-primary);
3818
+ text-transform: uppercase;
3819
+ letter-spacing: 0.07em;
3820
+ }
3821
+ .agent-section-count {
3822
+ font-family: var(--font-mono);
3823
+ font-size: var(--text-2xs);
3824
+ font-weight: 400;
3825
+ color: var(--text-muted);
3826
+ }
3827
+
3828
+ /* ── Card grid ── */
3829
+ .agent-grid {
3830
+ display: grid;
3831
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
3832
+ gap: var(--space-4);
3833
+ padding: var(--space-4) 0 var(--space-3);
3834
+ }
3835
+
3836
+ /* ── Card — overrides the base .agent-card block: hover lift + accent ── */
3837
+ .agent-card {
3838
+ cursor: pointer;
3839
+ display: flex;
3840
+ flex-direction: column;
3841
+ transition: transform 0.15s var(--ease), box-shadow 0.15s var(--ease),
3842
+ border-color 0.15s var(--ease), background 0.15s var(--ease);
3843
+ }
3844
+ .agent-card:hover {
3845
+ transform: translateY(-2px);
3846
+ box-shadow: 0 8px 24px rgba(0,0,0,0.30); /* intentional: shadows stay dark in both themes, like --shadow-lg */
3847
+ border-color: color-mix(in srgb, var(--agent-accent, var(--accent-primary)) 45%, var(--border-default));
3848
+ }
3849
+ .agent-card:focus-visible {
3850
+ outline: none;
3851
+ border-color: var(--agent-accent, var(--accent-primary));
3852
+ }
3853
+ .agent-card-top {
3854
+ display: flex;
3855
+ align-items: center;
3856
+ gap: var(--space-4);
3857
+ min-width: 0;
3858
+ }
3859
+ .agent-card-id {
3860
+ flex: 1;
3861
+ min-width: 0;
3862
+ display: flex;
3863
+ flex-direction: column;
3864
+ align-items: flex-start;
3865
+ gap: 3px;
3866
+ }
3867
+ .agent-card-name {
3868
+ display: flex;
3869
+ align-items: center;
3870
+ flex-wrap: wrap;
3871
+ gap: 6px;
3872
+ font-size: var(--text-xs);
3873
+ font-weight: 600;
3874
+ color: var(--text-primary);
3875
+ letter-spacing: -0.006em;
3876
+ }
3877
+ .agent-card-arabic {
3878
+ align-self: flex-start;
3879
+ font-size: var(--text-md);
3880
+ color: color-mix(in srgb, var(--agent-accent, var(--accent-primary)) 75%, var(--text-tertiary));
3881
+ line-height: 1.2;
3882
+ }
3883
+ .agent-card-desc {
3884
+ display: -webkit-box;
3885
+ -webkit-line-clamp: 2;
3886
+ -webkit-box-orient: vertical;
3887
+ overflow: hidden;
3888
+ margin: var(--space-3) 0 0;
3889
+ font-size: var(--text-2xs);
3890
+ line-height: 1.45;
3891
+ color: var(--text-tertiary);
3892
+ }
3893
+
3894
+ /* ── Avatar circle with initials ── */
3895
+ .agent-avatar {
3896
+ flex-shrink: 0;
3897
+ width: 36px;
3898
+ height: 36px;
3899
+ display: inline-flex;
3900
+ align-items: center;
3901
+ justify-content: center;
3902
+ border-radius: var(--radius-full);
3903
+ font-size: var(--text-xs);
3904
+ font-weight: 600;
3905
+ letter-spacing: 0.02em;
3906
+ background: color-mix(in srgb, var(--agent-accent, var(--accent-primary)) 16%, transparent);
3907
+ color: var(--agent-accent, var(--accent-primary));
3908
+ border: 1px solid color-mix(in srgb, var(--agent-accent, var(--accent-primary)) 32%, transparent);
3909
+ }
3910
+ .agent-avatar--lg {
3911
+ width: 44px;
3912
+ height: 44px;
3913
+ font-size: var(--text-sm);
3914
+ }
3915
+
3916
+ /* ── Role badge — tinted by the per-role accent ── */
3917
+ .role-badge {
3918
+ display: inline-block;
3919
+ max-width: 100%;
3920
+ overflow: hidden;
3921
+ text-overflow: ellipsis;
3922
+ white-space: nowrap;
3923
+ font-size: var(--text-2xs);
3924
+ font-weight: 500;
3925
+ padding: 1px 6px;
3926
+ border-radius: var(--radius-1);
3927
+ background: color-mix(in srgb, var(--agent-accent, var(--accent-primary)) 12%, transparent);
3928
+ color: color-mix(in srgb, var(--agent-accent, var(--accent-primary)) 80%, var(--text-primary));
3929
+ border: 1px solid color-mix(in srgb, var(--agent-accent, var(--accent-primary)) 28%, transparent);
3930
+ letter-spacing: -0.006em;
3931
+ }
3932
+
3933
+ /* ── Frontmatter chips — model + tools, shared by cards and drawer ── */
3934
+ .agent-chips {
3935
+ display: flex;
3936
+ flex-wrap: wrap;
3937
+ gap: 4px;
3938
+ margin-top: var(--space-3);
3939
+ }
3940
+ .agent-chip {
3941
+ font-size: var(--text-2xs);
3942
+ font-family: var(--font-mono);
3943
+ padding: 1px 6px;
3944
+ border-radius: var(--radius-full);
3945
+ background: var(--bg-hover);
3946
+ color: var(--text-secondary);
3947
+ border: 1px solid var(--border-subtle);
3948
+ white-space: nowrap;
3949
+ }
3950
+ .agent-chip--model {
3951
+ color: var(--accent-hover);
3952
+ border-color: var(--accent-border);
3953
+ }
3954
+ .agent-chip--more { color: var(--text-muted); }
3955
+
3956
+ /* ── Detail drawer — fixed right panel above the mobile sidebar (z 30) ── */
3957
+ .agent-drawer-backdrop {
3958
+ position: fixed;
3959
+ inset: 0;
3960
+ background: rgba(0,0,0,0.45); /* intentional: one-off overlay tint; translucency can't be expressed as a theme token */
3961
+ z-index: 50;
3962
+ }
3963
+ .agent-drawer {
3964
+ position: fixed;
3965
+ top: 0;
3966
+ right: 0;
3967
+ bottom: 0;
3968
+ width: min(720px, 92vw);
3969
+ display: flex;
3970
+ flex-direction: column;
3971
+ background: var(--bg-elev-2);
3972
+ border-left: 1px solid var(--border-default);
3973
+ box-shadow: -12px 0 32px rgba(0,0,0,0.35); /* intentional: overlay shadow; alpha can't be a theme token */
3974
+ z-index: 221;
3975
+ }
3976
+ .reader-header {
3977
+ display: flex;
3978
+ align-items: center;
3979
+ justify-content: space-between;
3980
+ gap: var(--space-3);
3981
+ padding: var(--space-3) var(--space-5);
3982
+ border-bottom: 1px solid var(--border-subtle);
3983
+ flex-shrink: 0;
3984
+ }
3985
+ .reader-heading { min-width: 0; }
3986
+ .reader-title {
3987
+ font-size: var(--text-sm);
3988
+ font-weight: 600;
3989
+ color: var(--text-primary);
3990
+ white-space: nowrap;
3991
+ overflow: hidden;
3992
+ text-overflow: ellipsis;
3993
+ }
3994
+ .reader-path {
3995
+ font-family: var(--font-mono);
3996
+ font-size: var(--text-2xs);
3997
+ color: var(--text-muted);
3998
+ white-space: nowrap;
3999
+ overflow: hidden;
4000
+ text-overflow: ellipsis;
4001
+ letter-spacing: 0;
4002
+ }
4003
+ .reader-actions {
4004
+ display: flex;
4005
+ align-items: center;
4006
+ gap: var(--space-2);
4007
+ flex-shrink: 0;
4008
+ }
4009
+ .reader-copy {
4010
+ font-size: var(--text-2xs);
4011
+ font-family: var(--font-mono);
4012
+ padding: var(--space-1) var(--space-3);
4013
+ background: var(--bg-elev-3);
4014
+ border: 1px solid var(--border-default);
4015
+ border-radius: var(--radius-3);
4016
+ color: var(--text-secondary);
4017
+ cursor: pointer;
4018
+ letter-spacing: 0;
4019
+ transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
4020
+ }
4021
+ .reader-copy:hover { background: var(--bg-hover); color: var(--text-primary); }
4022
+ .reader-close {
4023
+ width: 28px;
4024
+ height: 28px;
4025
+ display: inline-flex;
4026
+ align-items: center;
4027
+ justify-content: center;
4028
+ background: transparent;
4029
+ border: 1px solid var(--border-subtle);
4030
+ border-radius: var(--radius-3);
4031
+ color: var(--text-secondary);
4032
+ font-size: var(--text-md);
4033
+ line-height: 1;
4034
+ cursor: pointer;
4035
+ transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
4036
+ }
4037
+ .reader-close:hover { background: var(--bg-hover); color: var(--text-primary); }
4038
+ .reader-body {
4039
+ flex: 1;
4040
+ overflow-y: auto;
4041
+ padding: var(--space-5);
4042
+ }
4043
+ .reader-error {
4044
+ color: var(--accent-red);
4045
+ font-size: var(--text-xs);
4046
+ padding: var(--space-4);
4047
+ }
4048
+ .reader-skel-line { margin-bottom: var(--space-3); }
4049
+ .reader-skel-block { height: 200px; }
4050
+ @media (max-width: 768px) {
4051
+ .reader-panel { width: 100vw; border-left: none; }
4052
+ }
4053
+ .agent-drawer {
4054
+ position: fixed;
4055
+ top: 0;
4056
+ right: 0;
4057
+ bottom: 0;
4058
+ width: min(560px, 92vw);
4059
+ display: flex;
4060
+ flex-direction: column;
4061
+ background: var(--bg-elev-1);
4062
+ border-left: 1px solid var(--border-default);
4063
+ box-shadow: var(--shadow-lg);
4064
+ z-index: 51;
4065
+ animation: agent-drawer-in 0.18s var(--ease);
4066
+ }
4067
+ @keyframes agent-drawer-in {
4068
+ from { transform: translateX(24px); opacity: 0; }
4069
+ to { transform: translateX(0); opacity: 1; }
4070
+ }
4071
+ .agent-drawer-head {
4072
+ display: flex;
4073
+ align-items: flex-start;
4074
+ gap: var(--space-4);
4075
+ padding: var(--space-5) var(--space-5) var(--space-4);
4076
+ border-bottom: 1px solid var(--border-subtle);
4077
+ }
4078
+ .agent-drawer-titles {
4079
+ flex: 1;
4080
+ min-width: 0;
4081
+ display: flex;
4082
+ flex-direction: column;
4083
+ align-items: flex-start;
4084
+ gap: var(--space-2);
4085
+ }
4086
+ .agent-drawer-name {
4087
+ display: flex;
4088
+ align-items: center;
4089
+ flex-wrap: wrap;
4090
+ gap: 6px;
4091
+ font-size: var(--text-md);
4092
+ font-weight: 600;
4093
+ color: var(--text-primary);
4094
+ }
4095
+ .agent-drawer-arabic {
4096
+ font-size: var(--text-md);
4097
+ color: var(--agent-accent, var(--accent-primary));
4098
+ font-weight: 400;
4099
+ }
4100
+ .agent-drawer-close {
4101
+ flex-shrink: 0;
4102
+ width: var(--size-icon-btn, 28px);
4103
+ height: var(--size-icon-btn, 28px);
4104
+ display: flex;
4105
+ align-items: center;
4106
+ justify-content: center;
4107
+ font-size: var(--text-lg);
4108
+ line-height: 1;
4109
+ color: var(--text-muted);
4110
+ background: transparent;
4111
+ border: 1px solid var(--border-subtle);
4112
+ border-radius: var(--radius-2);
4113
+ cursor: pointer;
4114
+ transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
4115
+ }
4116
+ .agent-drawer-close:hover {
4117
+ color: var(--text-primary);
4118
+ border-color: var(--border-default);
4119
+ }
4120
+
4121
+ /* Meta row — file path + copy + jump-to-Files actions */
4122
+ .agent-drawer-meta {
4123
+ display: flex;
4124
+ align-items: center;
4125
+ gap: var(--space-3);
4126
+ padding: var(--space-2) var(--space-5);
4127
+ border-bottom: 1px solid var(--border-subtle);
4128
+ background: var(--bg-elev-2);
4129
+ }
4130
+ .agent-drawer-meta-path {
4131
+ flex: 1;
4132
+ min-width: 0;
4133
+ overflow: hidden;
4134
+ text-overflow: ellipsis;
4135
+ white-space: nowrap;
4136
+ font-family: var(--font-mono);
4137
+ font-size: var(--text-2xs);
4138
+ color: var(--text-muted);
4139
+ }
4140
+ .agent-drawer-btn {
4141
+ flex-shrink: 0;
4142
+ padding: 2px 8px;
4143
+ font-size: var(--text-2xs);
4144
+ font-family: var(--font-sans);
4145
+ color: var(--text-secondary);
4146
+ background: transparent;
4147
+ border: 1px solid var(--border-default);
4148
+ border-radius: var(--radius-2);
4149
+ cursor: pointer;
4150
+ white-space: nowrap;
4151
+ transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
4152
+ }
4153
+ .agent-drawer-btn:hover {
4154
+ color: var(--text-primary);
4155
+ border-color: var(--border-strong);
4156
+ }
4157
+ .agent-drawer-btn--link {
4158
+ color: var(--accent-hover);
4159
+ border-color: var(--accent-border);
4160
+ }
4161
+ .agent-drawer-btn--link:hover {
4162
+ color: var(--accent-hover);
4163
+ border-color: var(--accent-hover);
4164
+ }
4165
+
4166
+ .agent-drawer-body {
4167
+ flex: 1;
4168
+ min-height: 0;
4169
+ overflow-y: auto;
4170
+ padding: var(--space-4) var(--space-5);
4171
+ }
4172
+ .agent-drawer-skeleton { height: 200px; }
4173
+ .agent-drawer-empty,
4174
+ .agent-drawer-error {
4175
+ padding: var(--space-4);
4176
+ font-size: var(--text-sm);
4177
+ color: var(--text-tertiary);
4178
+ }
4179
+ .agent-drawer-error { color: var(--accent-red); }
4180
+ /* ════════ RunnerPicker — runner + model picker popover (BEGIN) ════════
4181
+ Anchored under the clicked Run button via --rp-x/--rp-y custom
4182
+ properties set from the component ref (no inline style attribute).
4183
+ Built entirely on theme tokens, so it follows dark and
4184
+ [data-theme="light"] automatically. z-index sits above the terminal
4185
+ panel (201) and below the toast (1000). */
4186
+ .runner-picker {
4187
+ position: fixed;
4188
+ /* Default off-screen until the component measures + clamps to viewport. */
4189
+ left: var(--rp-x, -9999px);
4190
+ top: var(--rp-y, -9999px);
4191
+ z-index: 900;
4192
+ width: 248px;
4193
+ display: flex;
4194
+ flex-direction: column;
4195
+ gap: var(--space-3);
4196
+ padding: var(--space-4);
4197
+ background: var(--bg-elev-3);
4198
+ border: 1px solid var(--border-default);
4199
+ border-radius: var(--radius-4);
4200
+ box-shadow: var(--shadow-lg);
4201
+ }
4202
+ .runner-picker-title {
4203
+ font-size: var(--text-sm);
4204
+ font-weight: 600;
4205
+ color: var(--text-primary);
4206
+ overflow: hidden;
4207
+ text-overflow: ellipsis;
4208
+ white-space: nowrap;
4209
+ }
4210
+ .runner-picker-hint {
4211
+ font-size: var(--text-xs);
4212
+ color: var(--text-tertiary);
4213
+ }
4214
+ .runner-picker-field {
4215
+ display: flex;
4216
+ flex-direction: column;
4217
+ gap: 4px;
4218
+ }
4219
+ .runner-picker-label {
4220
+ font-size: var(--text-xs);
4221
+ font-weight: 500;
4222
+ color: var(--text-tertiary);
4223
+ }
4224
+ .runner-picker-select {
4225
+ width: 100%;
4226
+ padding: 6px 8px;
4227
+ background: var(--bg-input);
4228
+ border: 1px solid var(--border-default);
4229
+ border-radius: var(--radius-3);
4230
+ color: var(--text-primary);
4231
+ font-family: var(--font-sans);
4232
+ font-size: var(--text-xs);
4233
+ }
4234
+ .runner-picker-select:focus {
4235
+ outline: none;
4236
+ border-color: var(--accent-border);
4237
+ }
4238
+
4239
+ /* Runner option list — buttons instead of a <select> so each row can carry
4240
+ a Beta pill and unavailable rows can show their reason inline. */
4241
+ .runner-picker-list {
4242
+ display: flex;
4243
+ flex-direction: column;
4244
+ gap: 2px;
4245
+ max-height: 220px;
4246
+ overflow-y: auto;
4247
+ border: 1px solid var(--border-default);
4248
+ border-radius: var(--radius-3);
4249
+ background: var(--bg-input);
4250
+ padding: 3px;
4251
+ }
4252
+ .runner-picker-option {
4253
+ display: flex;
4254
+ align-items: center;
4255
+ gap: var(--space-2);
4256
+ width: 100%;
4257
+ padding: 5px 8px;
4258
+ background: transparent;
4259
+ border: none;
4260
+ border-radius: var(--radius-2);
4261
+ color: var(--text-secondary);
4262
+ font-family: var(--font-sans);
4263
+ font-size: var(--text-xs);
4264
+ text-align: left;
4265
+ cursor: pointer;
4266
+ }
4267
+ .runner-picker-option:hover:not(:disabled) {
4268
+ background: var(--bg-hover);
4269
+ color: var(--text-primary);
4270
+ }
4271
+ .runner-picker-option.selected {
4272
+ background: var(--accent-bg);
4273
+ color: var(--text-primary);
4274
+ }
4275
+ .runner-picker-option:disabled {
4276
+ opacity: 0.5;
4277
+ cursor: not-allowed;
4278
+ }
4279
+ .runner-picker-option-label {
4280
+ flex: 0 1 auto;
4281
+ overflow: hidden;
4282
+ text-overflow: ellipsis;
4283
+ white-space: nowrap;
4284
+ }
4285
+ .runner-picker-option-hint {
4286
+ margin-left: auto;
4287
+ color: var(--text-muted);
4288
+ font-size: 10px;
4289
+ white-space: nowrap;
4290
+ }
4291
+ /* "Beta" pill — every runner except claude (the first-class default). */
4292
+ .runner-beta-pill {
4293
+ flex: 0 0 auto;
4294
+ padding: 0 5px;
4295
+ background: color-mix(in srgb, var(--amber) 16%, transparent);
4296
+ border: 1px solid color-mix(in srgb, var(--amber) 45%, transparent);
4297
+ border-radius: var(--radius-full);
4298
+ color: var(--amber);
4299
+ font-size: 9px;
4300
+ font-weight: 600;
4301
+ line-height: 14px;
4302
+ letter-spacing: 0.04em;
4303
+ text-transform: uppercase;
4304
+ }
4305
+ .runner-picker-actions {
4306
+ display: flex;
4307
+ justify-content: flex-end;
4308
+ gap: var(--space-2);
4309
+ }
4310
+ .runner-picker-btn {
4311
+ padding: 5px 12px;
4312
+ background: var(--bg-elev-2);
4313
+ border: 1px solid var(--border-default);
4314
+ border-radius: var(--radius-3);
4315
+ color: var(--text-secondary);
4316
+ font-family: var(--font-sans);
4317
+ font-size: var(--text-xs);
4318
+ font-weight: 500;
4319
+ cursor: pointer;
4320
+ }
4321
+ .runner-picker-btn:hover {
4322
+ background: var(--bg-hover);
4323
+ color: var(--text-primary);
4324
+ }
4325
+ .runner-picker-btn--run {
4326
+ background: var(--accent-primary);
4327
+ border-color: var(--accent-primary);
4328
+ color: #fff;
4329
+ }
4330
+ .runner-picker-btn--run:hover {
4331
+ background: var(--accent-hover);
4332
+ color: #fff;
4333
+ }
4334
+ .runner-picker-btn--run:disabled {
4335
+ opacity: 0.5;
4336
+ cursor: not-allowed;
4337
+ }
4338
+
4339
+ /* Runner badge — which CLI/model launched a session (Orchestration cards). */
4340
+ .runner-badge {
4341
+ display: inline-flex;
4342
+ align-items: center;
4343
+ max-width: 140px;
4344
+ overflow: hidden;
4345
+ text-overflow: ellipsis;
4346
+ white-space: nowrap;
4347
+ padding: 1px 7px;
4348
+ background: var(--accent-bg);
4349
+ border: 1px solid var(--accent-border);
4350
+ border-radius: var(--radius-full);
4351
+ color: var(--text-secondary);
4352
+ font-family: var(--font-mono);
4353
+ font-size: 10px;
4354
+ line-height: 16px;
4355
+ }
4356
+ /* ════════ RunnerPicker (END) ════════ */
4357
+
4358
+ /* ── Status summary bar ────────────────────────────────────────── */
4359
+ .summary-bar {
4360
+ display: flex;
4361
+ flex-direction: row;
4362
+ gap: var(--space-4);
4363
+ flex-wrap: wrap;
4364
+ padding: var(--space-3) var(--space-4);
4365
+ border-bottom: 1px solid var(--border-subtle);
4366
+ }
4367
+ .summary-group {
4368
+ display: flex;
4369
+ flex-direction: row;
4370
+ align-items: center;
4371
+ gap: var(--space-2);
4372
+ }
4373
+ .summary-group-label {
4374
+ font-size: var(--text-2xs);
4375
+ color: var(--text-muted);
4376
+ text-transform: uppercase;
4377
+ letter-spacing: 0.04em;
4378
+ }
4379
+ .summary-count-chip {
4380
+ display: inline-flex;
4381
+ gap: 4px;
4382
+ font-size: var(--text-2xs);
4383
+ padding: 2px var(--space-2);
4384
+ border-radius: var(--radius-3);
4385
+ background: var(--bg-elev-3);
4386
+ border: 1px solid var(--border-subtle);
4387
+ }
4388
+ .summary-count-chip.complete { color: var(--accent-green); }
4389
+ .summary-count-chip.active { color: var(--accent-blue); }
4390
+ .summary-count-chip.blocked { color: var(--accent-red); }
4391
+ .summary-count-chip.planned,
4392
+ .summary-count-chip.todo { color: var(--text-secondary); }
4393
+
4394
+ /* ── Filter chips ────────────────────────────────────────────────── */
4395
+ .filter-chips {
4396
+ display: flex;
4397
+ flex-direction: row;
4398
+ gap: var(--space-3);
4399
+ flex-wrap: wrap;
4400
+ padding: var(--space-3) var(--space-4);
4401
+ border-bottom: 1px solid var(--border-subtle);
4402
+ }
4403
+ .filter-chip-group {
4404
+ display: flex;
4405
+ flex-direction: row;
4406
+ gap: var(--space-1);
4407
+ align-items: center;
4408
+ }
4409
+ .filter-chip {
4410
+ font-size: var(--text-2xs);
4411
+ padding: 3px var(--space-3);
4412
+ border-radius: var(--radius-4);
4413
+ border: 1px solid var(--border-default);
4414
+ background: var(--bg-input);
4415
+ color: var(--text-secondary);
4416
+ cursor: pointer;
4417
+ transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
4418
+ }
4419
+ .filter-chip:hover { border-color: var(--accent-primary); }
4420
+ .filter-chip.active {
4421
+ background: var(--accent-primary);
4422
+ color: #fff;
4423
+ border-color: var(--accent-primary);
4424
+ }
4425
+ .filter-chip-clear {
4426
+ font-size: var(--text-2xs);
4427
+ padding: 3px var(--space-3);
4428
+ border-radius: var(--radius-4);
4429
+ border: 1px solid var(--border-default);
4430
+ background: var(--bg-input);
4431
+ color: var(--text-muted);
4432
+ cursor: pointer;
4433
+ transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
4434
+ }
4435
+ .filter-chip-clear:disabled { opacity: 0.4; cursor: default; }
4436
+
4437
+ /* ── Command palette (Sprint 36.1 — DSH-4) ─────────────────────────────────
4438
+ z-index reference: #orch-panel slide-in = 50, xterm term-backdrop = 200,
4439
+ xterm term-panel/term-pill = 201, .toast notification layer = 1000.
4440
+ 1100 places the palette overlay above every stacking context, including
4441
+ the toast layer (pointer-events:none but must still paint beneath us). */
4442
+ .cmd-palette-overlay {
4443
+ position: fixed;
4444
+ inset: 0;
4445
+ z-index: 1100;
4446
+ display: flex;
4447
+ justify-content: center;
4448
+ align-items: flex-start;
4449
+ padding-top: 15vh;
4450
+ background: rgba(0, 0, 0, 0.45);
4451
+ }
4452
+ .cmd-palette {
4453
+ width: 90%;
4454
+ max-width: 560px;
4455
+ background: var(--bg-card);
4456
+ border: 1px solid var(--border);
4457
+ border-radius: var(--radius-md);
4458
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
4459
+ overflow: hidden;
4460
+ }
4461
+ .cmd-palette-search {
4462
+ display: flex;
4463
+ align-items: center;
4464
+ gap: var(--space-3);
4465
+ padding: var(--space-3) var(--space-4);
4466
+ border-bottom: 1px solid var(--border);
4467
+ }
4468
+ .cmd-palette-search-icon {
4469
+ color: var(--text-muted);
4470
+ flex-shrink: 0;
4471
+ }
4472
+ .cmd-palette-input {
4473
+ flex: 1;
4474
+ background: transparent;
4475
+ border: none;
4476
+ outline: none;
4477
+ color: var(--text-primary);
4478
+ font-size: var(--text-sm);
4479
+ }
4480
+ .cmd-palette-list {
4481
+ max-height: 50vh;
4482
+ overflow-y: auto;
4483
+ }
4484
+ .cmd-palette-group {
4485
+ font-size: var(--text-2xs);
4486
+ text-transform: uppercase;
4487
+ letter-spacing: 0.08em;
4488
+ color: var(--text-muted);
4489
+ padding: var(--space-3) var(--space-4) var(--space-1);
4490
+ }
4491
+ .cmd-palette-item {
4492
+ display: flex;
4493
+ justify-content: space-between;
4494
+ align-items: center;
4495
+ width: 100%;
4496
+ background: transparent;
4497
+ border: none;
4498
+ color: var(--text-primary);
4499
+ text-align: left;
4500
+ cursor: pointer;
4501
+ padding: var(--space-2) var(--space-4);
4502
+ font-size: var(--text-sm);
4503
+ }
4504
+ .cmd-palette-item:hover,
4505
+ .cmd-palette-item.active { background: var(--bg-hover); }
4506
+ .cmd-palette-cmd {
4507
+ font-size: var(--text-2xs);
4508
+ color: var(--text-muted);
4509
+ font-family: var(--font-mono);
4510
+ }
4511
+ .cmd-palette-empty {
4512
+ text-align: center;
4513
+ color: var(--text-muted);
4514
+ padding: var(--space-6) var(--space-4);
4515
+ font-size: var(--text-sm);
4516
+ }
4517
+ /* ════════ Command palette (END) ════════ */
4518
+
4519
+ /* ── Reject dialog ── */
4520
+ .reject-overlay {
4521
+ position: fixed;
4522
+ inset: 0;
4523
+ background: rgba(0,0,0,0.5);
4524
+ z-index: 40;
4525
+ display: flex;
4526
+ align-items: center;
4527
+ justify-content: center;
4528
+ }
4529
+ .reject-dialog {
4530
+ background: var(--bg-elev-2);
4531
+ border: 1px solid var(--border);
4532
+ border-radius: var(--radius-3);
4533
+ box-shadow: var(--shadow-lg);
4534
+ padding: var(--space-5);
4535
+ width: min(480px, 90vw);
4536
+ }
4537
+ .reject-dialog-title {
4538
+ font-size: var(--text-md);
4539
+ font-weight: 600;
4540
+ color: var(--text-primary);
4541
+ margin-bottom: var(--space-3);
4542
+ }
4543
+ .reject-dialog-input {
4544
+ width: 100%;
4545
+ min-height: 96px;
4546
+ background: var(--bg-input);
4547
+ color: var(--text-primary);
4548
+ border: 1px solid var(--border);
4549
+ border-radius: var(--radius-2);
4550
+ padding: var(--space-2);
4551
+ font-family: var(--font-sans);
4552
+ font-size: var(--text-xs);
4553
+ resize: vertical;
4554
+ box-sizing: border-box;
4555
+ }
4556
+ .reject-dialog-input:focus { outline: none; border-color: var(--accent-primary); }
4557
+ .reject-dialog-actions {
4558
+ display: flex;
4559
+ justify-content: flex-end;
4560
+ gap: var(--space-2);
4561
+ margin-top: var(--space-4);
4562
+ }
4563
+ .reject-cancel {
4564
+ display: inline-flex;
4565
+ align-items: center;
4566
+ height: 28px;
4567
+ padding: 0 var(--space-4);
4568
+ background: transparent;
4569
+ border: 1px solid var(--border);
4570
+ border-radius: var(--radius-3);
4571
+ color: var(--text-secondary);
4572
+ font-size: var(--text-xs);
4573
+ font-weight: 500;
4574
+ font-family: var(--font-sans);
4575
+ cursor: pointer;
4576
+ transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
4577
+ }
4578
+ .reject-cancel:hover { background: var(--bg-hover); color: var(--text-primary); }
4579
+ .reject-submit {
4580
+ display: inline-flex;
4581
+ align-items: center;
4582
+ height: 28px;
4583
+ padding: 0 var(--space-4);
4584
+ background: transparent;
4585
+ border: 1px solid rgba(255,107,107,0.4);
4586
+ border-radius: var(--radius-3);
4587
+ color: #ff6b6b;
4588
+ font-size: var(--text-xs);
4589
+ font-weight: 500;
4590
+ font-family: var(--font-sans);
4591
+ cursor: pointer;
4592
+ transition: background var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
4593
+ }
4594
+ .reject-submit:hover:not(:disabled) { background: rgba(255,107,107,0.12); }
4595
+ .reject-submit:disabled { opacity: 0.5; cursor: not-allowed; }
4596
+ .orch-card-rejection {
4597
+ margin-top: var(--space-2);
4598
+ font-size: var(--text-xs);
4599
+ color: var(--accent-red);
4600
+ border-left: 2px solid var(--accent-red);
4601
+ padding-left: var(--space-2);
4602
+ }
4603
+ /* ── Reject dialog (END) ── */
4604
+
4605
+ /* ════════ Sidebar health badges (36-2) ════════ */
4606
+ .sidebar-health {
4607
+ display: flex;
4608
+ flex-direction: row;
4609
+ gap: var(--space-2);
4610
+ padding: var(--space-2) var(--space-4);
4611
+ border-bottom: 1px solid var(--border-subtle);
4612
+ flex-wrap: wrap;
4613
+ }
4614
+ .health-badge {
4615
+ display: inline-flex;
4616
+ align-items: center;
4617
+ gap: 4px;
4618
+ font-size: var(--text-2xs);
4619
+ padding: 2px var(--space-2);
4620
+ border-radius: var(--radius-2);
4621
+ background: var(--bg-elev-2);
4622
+ color: var(--text-secondary);
4623
+ white-space: nowrap;
4624
+ user-select: none;
4625
+ }
4626
+ /* Non-zero blocker state — flag with amber to draw attention */
4627
+ .health-badge--alert {
4628
+ color: var(--accent-amber);
4629
+ }
4630
+ /* Zero count — de-emphasise so it reads as "all clear", not an alarm */
4631
+ .health-badge--zero {
4632
+ color: var(--text-muted);
4633
+ opacity: 0.6;
4634
+ }
4635
+ /* ════════ Sidebar health badges (END) ════════ */
4636
+
4637
+ /* ════════ Live session join — tasks/kanban/overview (l1-livetasks) ════════ */
4638
+ /* Self-contained: own keyframes, no dependencies on other blocks. */
4639
+ @keyframes live-session-pulse {
4640
+ 0%, 100% { opacity: 1; transform: scale(1); }
4641
+ 50% { opacity: 0.35; transform: scale(0.75); }
4642
+ }
4643
+ /* Pulsing green dot — marks anything backed by a live orchestrator session */
4644
+ .live-dot {
4645
+ display: inline-block;
4646
+ width: 7px;
4647
+ height: 7px;
4648
+ border-radius: 50%;
4649
+ background: var(--accent-green);
4650
+ animation: live-session-pulse 1.1s ease-in-out infinite;
4651
+ flex-shrink: 0;
4652
+ }
4653
+ /* Overview In Progress card — clickable live-session rows (above scanned tasks) */
4654
+ .ip-live-row {
4655
+ cursor: pointer;
4656
+ border-radius: var(--radius-2);
4657
+ }
4658
+ .ip-live-row:hover,
4659
+ .ip-live-row:focus-visible {
4660
+ background: rgba(63, 185, 80, 0.08);
4661
+ }
4662
+ .ip-live-title {
4663
+ font-weight: 500;
4664
+ color: var(--accent-green);
4665
+ }
4666
+ .ip-live-elapsed {
4667
+ flex: none;
4668
+ font-size: 11px;
4669
+ font-variant-numeric: tabular-nums;
4670
+ color: var(--text-muted);
4671
+ }
4672
+ /* TaskPipeline current node pulses while a live session runs for the task */
4673
+ .tpipe-node--live {
4674
+ animation: live-session-pulse 1.1s ease-in-out infinite;
4675
+ }
4676
+ /* Donut subtitle "· N running now" fragment */
4677
+ .donut-live {
4678
+ color: var(--accent-green);
4679
+ font-weight: 600;
4680
+ }
4681
+ /* ════════ Live session join (END) ════════ */
4682
+ /* ════════ Blocked-session notifications (l2-notify) (BEGIN) ════════
4683
+ Self-contained block: status-dot palette (teal running / amber blocked /
4684
+ gray exited), topbar bell + dropdown, persistent blocked toasts.
4685
+ Theme variables only — valid in dark and [data-theme=light]. */
4686
+
4687
+ @keyframes nb-pulse {
4688
+ 0% { opacity: 1; }
4689
+ 50% { opacity: 0.35; }
4690
+ 100% { opacity: 1; }
4691
+ }
4692
+
4693
+ /* Status dots — teal pulse running, amber blocked, gray exited. Overrides the
4694
+ earlier .term-status-dot palette via cascade (this block loads last). */
4695
+ .term-status-dot.running { background: var(--dash-teal); animation: nb-pulse 1.5s infinite; }
4696
+ .term-status-dot.blocked { background: var(--accent-amber); animation: nb-pulse 1s infinite; }
4697
+ .term-status-dot.waiting { background: var(--accent-amber); animation: nb-pulse 1s infinite; }
4698
+ .term-status-dot.exited { background: var(--text-muted); animation: none; }
4699
+ .tab-status-dot.blocked { background: var(--accent-amber); animation: nb-pulse 1s infinite; }
4700
+
4701
+ /* Blocked session card accent in the Orchestration grid */
4702
+ .orch-card.orch-blocked {
4703
+ border-color: var(--accent-amber);
4704
+ box-shadow: 0 0 0 1px var(--accent-amber) inset;
4705
+ }
4706
+
4707
+ /* ── Topbar bell ── */
4708
+ .nb-bell-wrap { position: relative; display: inline-flex; }
4709
+ .nb-bell { position: relative; }
4710
+ .nb-bell--alert { color: var(--accent-amber); }
4711
+ .nb-bell-count {
4712
+ position: absolute;
4713
+ top: -4px;
4714
+ right: -4px;
4715
+ min-width: 14px;
4716
+ height: 14px;
4717
+ padding: 0 3px;
4718
+ border-radius: var(--radius-full);
4719
+ background: var(--accent-amber);
4720
+ color: var(--bg-page);
4721
+ font-size: 10px;
4722
+ font-weight: 700;
4723
+ line-height: 14px;
4724
+ text-align: center;
4725
+ pointer-events: none;
4726
+ }
4727
+ .nb-bell-dropdown {
4728
+ position: absolute;
4729
+ top: calc(100% + var(--space-2));
4730
+ right: 0;
4731
+ z-index: 1100;
4732
+ min-width: 260px;
4733
+ max-width: 360px;
4734
+ background: var(--bg-elev-2);
4735
+ border: 1px solid var(--border-default);
4736
+ border-radius: var(--radius-4);
4737
+ box-shadow: var(--shadow-lg);
4738
+ padding: var(--space-2);
4739
+ }
4740
+ .nb-bell-title {
4741
+ font-size: var(--text-2xs);
4742
+ font-weight: 600;
4743
+ text-transform: uppercase;
4744
+ letter-spacing: 0.04em;
4745
+ color: var(--text-tertiary);
4746
+ padding: var(--space-2) var(--space-3);
4747
+ }
4748
+ .nb-bell-item {
4749
+ display: flex;
4750
+ align-items: center;
4751
+ gap: var(--space-3);
4752
+ width: 100%;
4753
+ padding: var(--space-2) var(--space-3);
4754
+ background: transparent;
4755
+ border: none;
4756
+ border-radius: var(--radius-2);
4757
+ color: var(--text-primary);
4758
+ font-size: var(--text-xs);
4759
+ font-family: var(--font-sans);
4760
+ text-align: left;
4761
+ cursor: pointer;
4762
+ }
4763
+ .nb-bell-item:hover { background: var(--bg-hover); }
4764
+ .nb-bell-item-id { font-weight: 600; white-space: nowrap; }
4765
+ .nb-bell-item-cmd {
4766
+ color: var(--text-muted);
4767
+ font-family: var(--font-mono);
4768
+ font-size: var(--text-2xs);
4769
+ overflow: hidden;
4770
+ text-overflow: ellipsis;
4771
+ white-space: nowrap;
4772
+ }
4773
+
4774
+ /* ── Persistent blocked toasts ── */
4775
+ .nb-toasts {
4776
+ position: fixed;
4777
+ bottom: var(--space-6);
4778
+ right: var(--space-6);
4779
+ z-index: 1200;
4780
+ display: flex;
4781
+ flex-direction: column;
4782
+ gap: var(--space-3);
4783
+ max-width: 380px;
4784
+ }
4785
+ .nb-toast {
4786
+ display: flex;
4787
+ align-items: center;
4788
+ gap: var(--space-3);
4789
+ padding: var(--space-3) var(--space-4);
4790
+ background: var(--bg-elev-3);
4791
+ border: 1px solid var(--accent-amber);
4792
+ border-radius: var(--radius-4);
4793
+ box-shadow: var(--shadow-lg);
4794
+ color: var(--text-primary);
4795
+ font-size: var(--text-xs);
4796
+ cursor: pointer;
4797
+ }
4798
+ .nb-toast:hover { background: var(--bg-hover); }
4799
+ .nb-toast-dot {
4800
+ width: 8px;
4801
+ height: 8px;
4802
+ border-radius: 50%;
4803
+ background: var(--accent-amber);
4804
+ animation: nb-pulse 1s infinite;
4805
+ flex-shrink: 0;
4806
+ }
4807
+ .nb-toast-text { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
4808
+ .nb-toast-cmd {
4809
+ color: var(--text-muted);
4810
+ font-family: var(--font-mono);
4811
+ font-size: var(--text-2xs);
4812
+ overflow: hidden;
4813
+ text-overflow: ellipsis;
4814
+ white-space: nowrap;
4815
+ }
4816
+ .nb-toast-dismiss {
4817
+ margin-left: auto;
4818
+ background: transparent;
4819
+ border: none;
4820
+ color: var(--text-tertiary);
4821
+ cursor: pointer;
4822
+ padding: var(--space-1);
4823
+ border-radius: var(--radius-1);
4824
+ flex-shrink: 0;
4825
+ }
4826
+ .nb-toast-dismiss:hover { color: var(--text-primary); background: var(--bg-active); }
4827
+ /* ════════ Blocked-session notifications (l2-notify) (END) ════════ */
4828
+ /* ════════ Living overview cards (l3-cards) ════════ */
4829
+ /* Hover/keyboard affordance for clickable card rows + timeline segments.
4830
+ Applied alongside existing row classes; self-contained — only .ovr-link
4831
+ selectors live here. */
4832
+ .ovr-link {
4833
+ cursor: pointer;
4834
+ border-radius: var(--radius-2);
4835
+ transition: background var(--t-fast) var(--ease);
4836
+ }
4837
+ .ovr-link:hover { background: var(--bg-hover); }
4838
+ .ovr-link:focus-visible {
4839
+ outline: 2px solid var(--accent-primary);
4840
+ outline-offset: 1px;
4841
+ }
4842
+ /* "Up Next" pill on the Current Phase card — amber, distinct from the
4843
+ active-phase pill, so an upcoming phase never reads as in-flight. */
4844
+ .cp-pill--next {
4845
+ color: var(--accent-amber);
4846
+ border-color: var(--accent-amber);
4847
+ }
4848
+ /* Milestone outlook (Target Launch card without a configured launch_date). */
4849
+ .tl-outlook-name {
4850
+ font-size: var(--text-lg);
4851
+ font-weight: 600;
4852
+ color: var(--text-primary);
4853
+ margin: 0 0 var(--space-2);
4854
+ }
4855
+ .tl-outlook {
4856
+ list-style: none;
4857
+ margin: 0 0 var(--space-2);
4858
+ padding: 0;
4859
+ display: flex;
4860
+ flex-direction: column;
4861
+ gap: var(--space-1);
4862
+ }
4863
+ .tl-outlook-row {
4864
+ display: flex;
4865
+ justify-content: space-between;
4866
+ gap: var(--space-3);
4867
+ font-size: var(--text-xs);
4868
+ }
4869
+ .tl-outlook-key { color: var(--text-muted); }
4870
+ .tl-outlook-val { color: var(--text-secondary); font-weight: 500; }
4871
+ .tl-outlook-hint {
4872
+ margin: var(--space-2) 0 0;
4873
+ font-size: var(--text-2xs);
4874
+ color: var(--text-muted);
4875
+ }
4876
+ .tl-outlook-hint code {
4877
+ font-family: var(--font-mono);
4878
+ font-size: var(--text-2xs);
4879
+ color: var(--text-secondary);
4880
+ }
4881
+ /* ════════ Living overview cards (END) ════════ */
4882
+
4883
+ /* ════════ Phase dependency graph (PhaseGraph.js) ════════
4884
+ Status colors are --pg-* tokens scoped to the panel so both themes flip
4885
+ them without touching the global token block. */
4886
+ .pg-panel {
4887
+ --pg-done: #2dd4bf; /* teal */
4888
+ --pg-active: #a78bfa; /* purple */
4889
+ --pg-todo: var(--text-muted);
4890
+ --pg-blocked: var(--amber);
4891
+ margin-bottom: var(--space-4);
4892
+ border: 1px solid var(--border-default);
4893
+ border-radius: var(--radius-4);
4894
+ background: var(--bg-elev-1);
4895
+ }
4896
+ [data-theme="light"] .pg-panel {
4897
+ --pg-done: #0d9488;
4898
+ --pg-active: #7c3aed;
4899
+ }
4900
+ .pg-panel summary {
4901
+ padding: var(--space-3) var(--space-5);
4902
+ font-size: var(--text-xs);
4903
+ color: var(--text-secondary);
4904
+ cursor: pointer;
4905
+ user-select: none;
4906
+ display: flex;
4907
+ align-items: center;
4908
+ gap: var(--space-2);
4909
+ }
4910
+ .pg-panel summary:hover { background: var(--bg-hover); }
4911
+ .pg-count {
4912
+ margin-left: auto;
4913
+ font-size: var(--text-2xs);
4914
+ color: var(--text-muted);
4915
+ }
4916
+ .pg-legend {
4917
+ display: flex;
4918
+ align-items: center;
4919
+ gap: var(--space-5);
4920
+ padding: 0 var(--space-5) var(--space-3);
4921
+ font-size: var(--text-2xs);
4922
+ color: var(--text-tertiary);
4923
+ }
4924
+ .pg-legend-item {
4925
+ display: inline-flex;
4926
+ align-items: center;
4927
+ gap: var(--space-2);
4928
+ }
4929
+ .pg-swatch {
4930
+ width: 10px;
4931
+ height: 10px;
4932
+ border-radius: var(--radius-1);
4933
+ background: var(--bg-elev-3);
4934
+ border: 1.5px solid var(--pg-todo);
4935
+ }
4936
+ .pg-swatch.pg-done { border-color: var(--pg-done); }
4937
+ .pg-swatch.pg-active { border-color: var(--pg-active); }
4938
+ .pg-swatch.pg-blocked { border-color: var(--pg-blocked); }
4939
+
4940
+ /* DAG mode — horizontal scroll when the graph is wider than the panel. */
4941
+ .pg-scroll {
4942
+ overflow-x: auto;
4943
+ padding: 0 var(--space-3) var(--space-3);
4944
+ }
4945
+ .pg-svg { display: block; }
4946
+ .pg-node { cursor: pointer; }
4947
+ .pg-node rect {
4948
+ fill: var(--bg-elev-2);
4949
+ stroke: var(--pg-todo);
4950
+ stroke-width: 1.5;
4951
+ transition: opacity var(--t-fast) var(--ease);
4952
+ }
4953
+ .pg-node.pg-done rect { stroke: var(--pg-done); }
4954
+ .pg-node.pg-active rect { stroke: var(--pg-active); animation: pg-pulse 2s var(--ease) infinite; }
4955
+ .pg-node.pg-blocked rect { stroke: var(--pg-blocked); }
4956
+ @keyframes pg-pulse {
4957
+ 0%, 100% { stroke-opacity: 1; stroke-width: 1.5; }
4958
+ 50% { stroke-opacity: 0.45; stroke-width: 2.5; }
4959
+ }
4960
+ .pg-label {
4961
+ fill: var(--text-primary);
4962
+ font-size: var(--text-2xs);
4963
+ font-weight: 600;
4964
+ pointer-events: none;
4965
+ }
4966
+ .pg-sublabel {
4967
+ fill: var(--text-secondary);
4968
+ font-size: 10px;
4969
+ pointer-events: none;
4970
+ }
4971
+ .pg-edge {
4972
+ stroke: var(--text-tertiary);
4973
+ stroke-width: 1.5;
4974
+ fill: none;
4975
+ transition: opacity var(--t-fast) var(--ease);
4976
+ }
4977
+ .pg-arrow { fill: var(--text-tertiary); }
4978
+ /* Hovering a node spotlights its ancestors + descendants, dims the rest. */
4979
+ .pg-hovering .pg-node:not(.pg-related) { opacity: 0.22; }
4980
+ .pg-hovering .pg-edge:not(.pg-related) { opacity: 0.12; }
4981
+ .pg-edge.pg-related { stroke: var(--accent-primary); stroke-width: 2; }
4982
+ .pg-tip rect {
4983
+ fill: var(--bg-elev-3);
4984
+ stroke: var(--border-strong);
4985
+ stroke-width: 1;
4986
+ }
4987
+ .pg-tip text { font-size: var(--text-2xs); fill: var(--text-secondary); pointer-events: none; }
4988
+ .pg-tip .pg-tip-title { fill: var(--text-primary); font-weight: 600; }
4989
+
4990
+ /* Flow-row mode — no cross-phase dependencies: wrapped chip sequence. */
4991
+ .pg-flow {
4992
+ display: flex;
4993
+ flex-wrap: wrap;
4994
+ gap: var(--space-3);
4995
+ padding: 0 var(--space-5) var(--space-2);
4996
+ }
4997
+ .pg-chip {
4998
+ display: inline-flex;
4999
+ align-items: center;
5000
+ gap: var(--space-2);
5001
+ max-width: 220px;
5002
+ padding: var(--space-2) var(--space-3);
5003
+ border: 1.5px solid var(--pg-todo);
5004
+ border-radius: var(--radius-3);
5005
+ background: var(--bg-elev-2);
5006
+ color: var(--text-secondary);
5007
+ font-size: var(--text-2xs);
5008
+ font-family: var(--font-sans);
5009
+ cursor: pointer;
5010
+ transition: background var(--t-fast) var(--ease);
5011
+ }
5012
+ .pg-chip:hover { background: var(--bg-hover); }
5013
+ .pg-chip.pg-done { border-color: var(--pg-done); }
5014
+ .pg-chip.pg-active { border-color: var(--pg-active); animation: pg-chip-pulse 2s var(--ease) infinite; }
5015
+ .pg-chip.pg-blocked { border-color: var(--pg-blocked); }
5016
+ @keyframes pg-chip-pulse {
5017
+ 0%, 100% { box-shadow: 0 0 0 0 transparent; }
5018
+ 50% { box-shadow: 0 0 6px 0 var(--pg-active); }
5019
+ }
5020
+ .pg-chip-id { font-weight: 600; color: var(--text-primary); }
5021
+ .pg-chip-name {
5022
+ overflow: hidden;
5023
+ text-overflow: ellipsis;
5024
+ white-space: nowrap;
5025
+ }
5026
+ .pg-hint, .pg-empty {
5027
+ padding: 0 var(--space-5) var(--space-3);
5028
+ font-size: var(--text-2xs);
5029
+ color: var(--text-muted);
5030
+ }
5031
+ .pg-empty { padding-top: var(--space-2); }
5032
+ .pg-empty code { font-family: var(--font-mono); color: var(--text-secondary); }
5033
+ /* ════════ Phase dependency graph (END) ════════ */
2281
5034
  </style>`;
2282
5035
  }
2283
5036