botmux 2.85.1 → 2.87.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 (236) hide show
  1. package/README.en.md +26 -0
  2. package/README.md +26 -0
  3. package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
  4. package/dist/adapters/backend/herdr-backend.js +12 -1
  5. package/dist/adapters/backend/herdr-backend.js.map +1 -1
  6. package/dist/adapters/backend/pty-backend.d.ts.map +1 -1
  7. package/dist/adapters/backend/pty-backend.js +4 -1
  8. package/dist/adapters/backend/pty-backend.js.map +1 -1
  9. package/dist/adapters/backend/tmux-backend.d.ts +1 -1
  10. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  11. package/dist/adapters/backend/tmux-backend.js +22 -9
  12. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  13. package/dist/adapters/backend/tmux-pipe-backend.js +1 -1
  14. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  15. package/dist/adapters/backend/types.d.ts +9 -0
  16. package/dist/adapters/backend/types.d.ts.map +1 -1
  17. package/dist/adapters/backend/types.js.map +1 -1
  18. package/dist/adapters/backend/zellij-backend.js +1 -1
  19. package/dist/adapters/backend/zellij-backend.js.map +1 -1
  20. package/dist/adapters/cli/codex.d.ts.map +1 -1
  21. package/dist/adapters/cli/codex.js +8 -5
  22. package/dist/adapters/cli/codex.js.map +1 -1
  23. package/dist/adapters/cli/shared-hints.d.ts +2 -1
  24. package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
  25. package/dist/adapters/cli/shared-hints.js +25 -3
  26. package/dist/adapters/cli/shared-hints.js.map +1 -1
  27. package/dist/bot-registry.d.ts +10 -0
  28. package/dist/bot-registry.d.ts.map +1 -1
  29. package/dist/bot-registry.js +6 -0
  30. package/dist/bot-registry.js.map +1 -1
  31. package/dist/cli.d.ts.map +1 -1
  32. package/dist/cli.js +362 -16
  33. package/dist/cli.js.map +1 -1
  34. package/dist/core/command-handler.d.ts.map +1 -1
  35. package/dist/core/command-handler.js +215 -5
  36. package/dist/core/command-handler.js.map +1 -1
  37. package/dist/core/cost-calculator.d.ts.map +1 -1
  38. package/dist/core/cost-calculator.js +7 -106
  39. package/dist/core/cost-calculator.js.map +1 -1
  40. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  41. package/dist/core/dashboard-ipc-server.js +285 -2
  42. package/dist/core/dashboard-ipc-server.js.map +1 -1
  43. package/dist/core/maintenance.d.ts +18 -0
  44. package/dist/core/maintenance.d.ts.map +1 -1
  45. package/dist/core/maintenance.js +58 -30
  46. package/dist/core/maintenance.js.map +1 -1
  47. package/dist/core/passthrough-commands.d.ts.map +1 -1
  48. package/dist/core/passthrough-commands.js +1 -1
  49. package/dist/core/passthrough-commands.js.map +1 -1
  50. package/dist/core/per-bot-env.d.ts +38 -0
  51. package/dist/core/per-bot-env.d.ts.map +1 -0
  52. package/dist/core/per-bot-env.js +79 -0
  53. package/dist/core/per-bot-env.js.map +1 -0
  54. package/dist/core/role-resolver.d.ts +1 -0
  55. package/dist/core/role-resolver.d.ts.map +1 -1
  56. package/dist/core/role-resolver.js +14 -0
  57. package/dist/core/role-resolver.js.map +1 -1
  58. package/dist/core/session-manager.d.ts +3 -0
  59. package/dist/core/session-manager.d.ts.map +1 -1
  60. package/dist/core/session-manager.js +70 -6
  61. package/dist/core/session-manager.js.map +1 -1
  62. package/dist/core/skills/discovery.d.ts +7 -0
  63. package/dist/core/skills/discovery.d.ts.map +1 -1
  64. package/dist/core/skills/discovery.js +51 -0
  65. package/dist/core/skills/discovery.js.map +1 -1
  66. package/dist/core/trigger-session.d.ts.map +1 -1
  67. package/dist/core/trigger-session.js +5 -2
  68. package/dist/core/trigger-session.js.map +1 -1
  69. package/dist/core/update-check.d.ts +67 -0
  70. package/dist/core/update-check.d.ts.map +1 -0
  71. package/dist/core/update-check.js +159 -0
  72. package/dist/core/update-check.js.map +1 -0
  73. package/dist/core/worker-pool.d.ts.map +1 -1
  74. package/dist/core/worker-pool.js +4 -0
  75. package/dist/core/worker-pool.js.map +1 -1
  76. package/dist/daemon.d.ts.map +1 -1
  77. package/dist/daemon.js +29 -6
  78. package/dist/daemon.js.map +1 -1
  79. package/dist/dashboard/bot-payload.d.ts +1 -0
  80. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  81. package/dist/dashboard/bot-payload.js +1 -0
  82. package/dist/dashboard/bot-payload.js.map +1 -1
  83. package/dist/dashboard/skill-install-request.d.ts +10 -0
  84. package/dist/dashboard/skill-install-request.d.ts.map +1 -1
  85. package/dist/dashboard/skill-install-request.js +17 -0
  86. package/dist/dashboard/skill-install-request.js.map +1 -1
  87. package/dist/dashboard/web/app.d.ts.map +1 -1
  88. package/dist/dashboard/web/app.js +43 -4
  89. package/dist/dashboard/web/app.js.map +1 -1
  90. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  91. package/dist/dashboard/web/bot-defaults.js +178 -1
  92. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  93. package/dist/dashboard/web/groups.d.ts +2 -0
  94. package/dist/dashboard/web/groups.d.ts.map +1 -1
  95. package/dist/dashboard/web/groups.js +419 -3
  96. package/dist/dashboard/web/groups.js.map +1 -1
  97. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  98. package/dist/dashboard/web/i18n.js +745 -3
  99. package/dist/dashboard/web/i18n.js.map +1 -1
  100. package/dist/dashboard/web/insights.d.ts +2 -0
  101. package/dist/dashboard/web/insights.d.ts.map +1 -0
  102. package/dist/dashboard/web/insights.js +1523 -0
  103. package/dist/dashboard/web/insights.js.map +1 -0
  104. package/dist/dashboard/web/role-profile-match.d.ts +31 -0
  105. package/dist/dashboard/web/role-profile-match.d.ts.map +1 -0
  106. package/dist/dashboard/web/role-profile-match.js +58 -0
  107. package/dist/dashboard/web/role-profile-match.js.map +1 -0
  108. package/dist/dashboard/web/roles.d.ts +1 -0
  109. package/dist/dashboard/web/roles.d.ts.map +1 -1
  110. package/dist/dashboard/web/roles.js +520 -27
  111. package/dist/dashboard/web/roles.js.map +1 -1
  112. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  113. package/dist/dashboard/web/sessions.js +84 -0
  114. package/dist/dashboard/web/sessions.js.map +1 -1
  115. package/dist/dashboard/web/settings.d.ts.map +1 -1
  116. package/dist/dashboard/web/settings.js +289 -0
  117. package/dist/dashboard/web/settings.js.map +1 -1
  118. package/dist/dashboard/web/skills.d.ts.map +1 -1
  119. package/dist/dashboard/web/skills.js +183 -10
  120. package/dist/dashboard/web/skills.js.map +1 -1
  121. package/dist/dashboard/web/whiteboards.d.ts +2 -0
  122. package/dist/dashboard/web/whiteboards.d.ts.map +1 -0
  123. package/dist/dashboard/web/whiteboards.js +267 -0
  124. package/dist/dashboard/web/whiteboards.js.map +1 -0
  125. package/dist/dashboard-web/app.js +1406 -833
  126. package/dist/dashboard-web/index.html +3 -1
  127. package/dist/dashboard-web/style.css +1382 -30
  128. package/dist/dashboard.js +474 -6
  129. package/dist/dashboard.js.map +1 -1
  130. package/dist/global-config.d.ts +6 -0
  131. package/dist/global-config.d.ts.map +1 -1
  132. package/dist/global-config.js +12 -0
  133. package/dist/global-config.js.map +1 -1
  134. package/dist/i18n/en.d.ts.map +1 -1
  135. package/dist/i18n/en.js +34 -1
  136. package/dist/i18n/en.js.map +1 -1
  137. package/dist/i18n/zh.d.ts.map +1 -1
  138. package/dist/i18n/zh.js +34 -1
  139. package/dist/i18n/zh.js.map +1 -1
  140. package/dist/im/lark/card-handler.d.ts.map +1 -1
  141. package/dist/im/lark/card-handler.js +7 -3
  142. package/dist/im/lark/card-handler.js.map +1 -1
  143. package/dist/services/bot-config-store.d.ts.map +1 -1
  144. package/dist/services/bot-config-store.js +19 -0
  145. package/dist/services/bot-config-store.js.map +1 -1
  146. package/dist/services/group-creator.d.ts +6 -0
  147. package/dist/services/group-creator.d.ts.map +1 -1
  148. package/dist/services/group-creator.js +54 -5
  149. package/dist/services/group-creator.js.map +1 -1
  150. package/dist/services/insight/antigravity-span-reader.d.ts +3 -0
  151. package/dist/services/insight/antigravity-span-reader.d.ts.map +1 -0
  152. package/dist/services/insight/antigravity-span-reader.js +249 -0
  153. package/dist/services/insight/antigravity-span-reader.js.map +1 -0
  154. package/dist/services/insight/classify.d.ts +7 -0
  155. package/dist/services/insight/classify.d.ts.map +1 -0
  156. package/dist/services/insight/classify.js +46 -0
  157. package/dist/services/insight/classify.js.map +1 -0
  158. package/dist/services/insight/claude-span-reader.d.ts +3 -0
  159. package/dist/services/insight/claude-span-reader.d.ts.map +1 -0
  160. package/dist/services/insight/claude-span-reader.js +257 -0
  161. package/dist/services/insight/claude-span-reader.js.map +1 -0
  162. package/dist/services/insight/codex-span-reader.d.ts +3 -0
  163. package/dist/services/insight/codex-span-reader.d.ts.map +1 -0
  164. package/dist/services/insight/codex-span-reader.js +290 -0
  165. package/dist/services/insight/codex-span-reader.js.map +1 -0
  166. package/dist/services/insight/intent.d.ts +5 -0
  167. package/dist/services/insight/intent.d.ts.map +1 -0
  168. package/dist/services/insight/intent.js +145 -0
  169. package/dist/services/insight/intent.js.map +1 -0
  170. package/dist/services/insight/jsonl.d.ts +10 -0
  171. package/dist/services/insight/jsonl.d.ts.map +1 -0
  172. package/dist/services/insight/jsonl.js +36 -0
  173. package/dist/services/insight/jsonl.js.map +1 -0
  174. package/dist/services/insight/prompt.d.ts +3 -0
  175. package/dist/services/insight/prompt.d.ts.map +1 -0
  176. package/dist/services/insight/prompt.js +99 -0
  177. package/dist/services/insight/prompt.js.map +1 -0
  178. package/dist/services/insight/redact.d.ts +4 -0
  179. package/dist/services/insight/redact.d.ts.map +1 -0
  180. package/dist/services/insight/redact.js +67 -0
  181. package/dist/services/insight/redact.js.map +1 -0
  182. package/dist/services/insight/report.d.ts +29 -0
  183. package/dist/services/insight/report.d.ts.map +1 -0
  184. package/dist/services/insight/report.js +1126 -0
  185. package/dist/services/insight/report.js.map +1 -0
  186. package/dist/services/insight/safe-detail.d.ts +5 -0
  187. package/dist/services/insight/safe-detail.d.ts.map +1 -0
  188. package/dist/services/insight/safe-detail.js +59 -0
  189. package/dist/services/insight/safe-detail.js.map +1 -0
  190. package/dist/services/insight/scrub.d.ts +22 -0
  191. package/dist/services/insight/scrub.d.ts.map +1 -0
  192. package/dist/services/insight/scrub.js +70 -0
  193. package/dist/services/insight/scrub.js.map +1 -0
  194. package/dist/services/insight/types.d.ts +394 -0
  195. package/dist/services/insight/types.d.ts.map +1 -0
  196. package/dist/services/insight/types.js +2 -0
  197. package/dist/services/insight/types.js.map +1 -0
  198. package/dist/services/resumable-session-discovery.d.ts.map +1 -1
  199. package/dist/services/resumable-session-discovery.js +21 -4
  200. package/dist/services/resumable-session-discovery.js.map +1 -1
  201. package/dist/services/role-profile-store.d.ts +25 -0
  202. package/dist/services/role-profile-store.d.ts.map +1 -0
  203. package/dist/services/role-profile-store.js +171 -0
  204. package/dist/services/role-profile-store.js.map +1 -0
  205. package/dist/services/skill-registry-store.d.ts +1 -0
  206. package/dist/services/skill-registry-store.d.ts.map +1 -1
  207. package/dist/services/skill-registry-store.js +32 -0
  208. package/dist/services/skill-registry-store.js.map +1 -1
  209. package/dist/services/transcript-resolver.d.ts +26 -0
  210. package/dist/services/transcript-resolver.d.ts.map +1 -0
  211. package/dist/services/transcript-resolver.js +111 -0
  212. package/dist/services/transcript-resolver.js.map +1 -0
  213. package/dist/services/whiteboard-store.d.ts +67 -0
  214. package/dist/services/whiteboard-store.d.ts.map +1 -0
  215. package/dist/services/whiteboard-store.js +450 -0
  216. package/dist/services/whiteboard-store.js.map +1 -0
  217. package/dist/setup/bot-config-editor.d.ts +8 -0
  218. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  219. package/dist/setup/bot-config-editor.js +9 -0
  220. package/dist/setup/bot-config-editor.js.map +1 -1
  221. package/dist/skills/definitions.d.ts.map +1 -1
  222. package/dist/skills/definitions.js +118 -0
  223. package/dist/skills/definitions.js.map +1 -1
  224. package/dist/types.d.ts +3 -0
  225. package/dist/types.d.ts.map +1 -1
  226. package/dist/utils/install-diagnostics.d.ts +52 -0
  227. package/dist/utils/install-diagnostics.d.ts.map +1 -0
  228. package/dist/utils/install-diagnostics.js +155 -0
  229. package/dist/utils/install-diagnostics.js.map +1 -0
  230. package/dist/utils/install-info.d.ts +4 -0
  231. package/dist/utils/install-info.d.ts.map +1 -1
  232. package/dist/utils/install-info.js +6 -0
  233. package/dist/utils/install-info.js.map +1 -1
  234. package/dist/worker.js +12 -0
  235. package/dist/worker.js.map +1 -1
  236. package/package.json +1 -1
@@ -157,6 +157,20 @@ a { color: inherit; }
157
157
  color: var(--accent-strong);
158
158
  }
159
159
 
160
+ /* Red dot on the Settings nav when a newer botmux version is available. */
161
+ .sidebar-nav a.nav-has-update { position: relative; }
162
+ .sidebar-nav a.nav-has-update::after {
163
+ content: "";
164
+ position: absolute;
165
+ top: 7px;
166
+ right: 8px;
167
+ width: 7px;
168
+ height: 7px;
169
+ border-radius: 50%;
170
+ background: var(--danger);
171
+ box-shadow: 0 0 0 2px var(--surface);
172
+ }
173
+
160
174
  .sidebar-foot {
161
175
  margin-top: auto;
162
176
  padding: 10px 8px 4px;
@@ -2228,6 +2242,21 @@ input.row-select,
2228
2242
  }
2229
2243
  .bd-section-note { margin: 6px 0 0; color: var(--muted); font-size: 12px; line-height: 1.5; }
2230
2244
 
2245
+ /* ── Version & update card ── */
2246
+ .update-version { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
2247
+ .update-badge { font-size: 12px; font-weight: 600; padding: 2px 8px; border-radius: 999px; }
2248
+ .update-badge-new { color: var(--accent-strong); background: var(--accent-soft); }
2249
+ .update-badge-ok { color: var(--success); background: var(--success-soft); }
2250
+ .update-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
2251
+ .update-install-list { margin: 6px 0 0; padding-left: 18px; font-size: 12px; line-height: 1.6; }
2252
+ .update-install-list code { font-size: 11px; }
2253
+ .update-install-list small { color: var(--muted); }
2254
+ .update-changelog { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; }
2255
+ .update-release { border: 1px solid var(--border-soft); border-radius: 8px; padding: 8px 12px; background: var(--surface-muted); }
2256
+ .update-release > summary { cursor: pointer; font-size: 13px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
2257
+ .update-release > summary small { color: var(--muted); font-size: 11px; }
2258
+ .update-release-body { margin: 8px 0 0; white-space: pre-wrap; word-break: break-word; font-size: 12px; line-height: 1.5; max-height: 320px; overflow: auto; color: var(--fg); }
2259
+
2231
2260
  /* A lighter sub-group inside a bd-section (e.g. 主动开工 lives under 新群 Oncall).
2232
2261
  Separated by a soft top rule + indent so it reads as "part of this block". */
2233
2262
  .bd-subsection {
@@ -2378,6 +2407,13 @@ input.row-select,
2378
2407
  }
2379
2408
 
2380
2409
  /* ─── Roles Page ─── */
2410
+ .roles-heading {
2411
+ align-items: flex-start;
2412
+ gap: 16px;
2413
+ }
2414
+ .roles-tabs {
2415
+ flex: 0 0 auto;
2416
+ }
2381
2417
  .roles-page .roles-layout {
2382
2418
  display: grid;
2383
2419
  grid-template-columns: 320px 1fr;
@@ -2385,6 +2421,7 @@ input.row-select,
2385
2421
  height: calc(100vh - 160px);
2386
2422
  min-height: 400px;
2387
2423
  }
2424
+ .roles-page .roles-layout[hidden] { display: none !important; }
2388
2425
 
2389
2426
  /* ─── Tree Panel (left) ─── */
2390
2427
  .roles-tree-panel {
@@ -2402,6 +2439,12 @@ input.row-select,
2402
2439
  gap: 8px;
2403
2440
  }
2404
2441
  .roles-tree-header input { flex: 1; }
2442
+ .roles-profile-create {
2443
+ align-items: stretch;
2444
+ }
2445
+ .roles-profile-create input {
2446
+ min-width: 0;
2447
+ }
2405
2448
  .roles-tree {
2406
2449
  flex: 1;
2407
2450
  overflow-y: auto;
@@ -2512,6 +2555,61 @@ input.row-select,
2512
2555
  background: var(--bg-soft);
2513
2556
  color: var(--faint);
2514
2557
  }
2558
+ .roles-profile-match {
2559
+ display: inline-flex;
2560
+ max-width: 100%;
2561
+ margin-top: 5px;
2562
+ padding: 2px 7px;
2563
+ border-radius: 999px;
2564
+ border: 1px solid var(--border-soft);
2565
+ background: var(--surface-muted);
2566
+ color: var(--muted);
2567
+ font-size: 10.5px;
2568
+ font-weight: 700;
2569
+ line-height: 1.45;
2570
+ white-space: normal;
2571
+ overflow-wrap: anywhere;
2572
+ }
2573
+ .roles-profile-match.full {
2574
+ border-color: color-mix(in srgb, var(--success) 35%, var(--border-soft));
2575
+ background: color-mix(in srgb, var(--success) 10%, var(--surface));
2576
+ color: var(--success);
2577
+ }
2578
+ .roles-profile-match.partial {
2579
+ border-color: color-mix(in srgb, var(--warning) 35%, var(--border-soft));
2580
+ background: color-mix(in srgb, var(--warning) 12%, var(--surface));
2581
+ color: var(--warning);
2582
+ }
2583
+ .roles-profile-match.muted {
2584
+ font-weight: 600;
2585
+ color: var(--muted);
2586
+ }
2587
+ .roles-profile-row {
2588
+ display: flex;
2589
+ align-items: center;
2590
+ gap: 10px;
2591
+ padding: 10px 12px;
2592
+ cursor: pointer;
2593
+ border-bottom: 1px solid var(--border-soft);
2594
+ transition: background 0.12s;
2595
+ }
2596
+ .roles-profile-row:hover { background: var(--bg-soft); }
2597
+ .roles-profile-row.selected {
2598
+ background: var(--accent-soft);
2599
+ border-left: 3px solid var(--accent);
2600
+ padding-left: 9px;
2601
+ }
2602
+ .roles-profile-row-main {
2603
+ min-width: 0;
2604
+ flex: 1;
2605
+ }
2606
+ .roles-profile-name {
2607
+ font-size: 13px;
2608
+ font-weight: 650;
2609
+ white-space: nowrap;
2610
+ overflow: hidden;
2611
+ text-overflow: ellipsis;
2612
+ }
2515
2613
 
2516
2614
  /* ─── Editor Panel (right) ─── */
2517
2615
  .roles-editor-panel {
@@ -2560,10 +2658,76 @@ input.row-select,
2560
2658
  color: var(--faint);
2561
2659
  font-family: var(--mono);
2562
2660
  }
2661
+ .roles-profile-detail {
2662
+ gap: 16px;
2663
+ min-height: 0;
2664
+ overflow: hidden;
2665
+ }
2666
+ .roles-profile-title {
2667
+ flex: 0 0 auto;
2668
+ display: flex;
2669
+ align-items: flex-start;
2670
+ justify-content: space-between;
2671
+ gap: 12px;
2672
+ }
2673
+ .roles-profile-grid {
2674
+ flex: 1 1 auto;
2675
+ display: grid;
2676
+ grid-template-columns: minmax(240px, 320px) minmax(0, 1fr);
2677
+ gap: 16px;
2678
+ align-items: stretch;
2679
+ min-height: 0;
2680
+ overflow: hidden;
2681
+ }
2682
+ .roles-profile-bots,
2683
+ .roles-profile-editor,
2684
+ .roles-profile-apply {
2685
+ min-width: 0;
2686
+ }
2687
+ .roles-profile-bots {
2688
+ display: flex;
2689
+ flex-direction: column;
2690
+ min-height: 0;
2691
+ }
2692
+ .roles-profile-editor {
2693
+ display: flex;
2694
+ flex-direction: column;
2695
+ gap: 10px;
2696
+ min-height: 0;
2697
+ }
2698
+ .roles-profile-section-title {
2699
+ color: var(--muted);
2700
+ font-size: 12px;
2701
+ font-weight: 700;
2702
+ margin-bottom: 8px;
2703
+ text-transform: uppercase;
2704
+ }
2705
+ .roles-profile-bot-list {
2706
+ flex: 1 1 auto;
2707
+ min-height: 0;
2708
+ border: 1px solid var(--border-soft);
2709
+ border-radius: var(--radius);
2710
+ overflow: auto;
2711
+ }
2712
+ .roles-profile-bot-row {
2713
+ padding-left: 12px;
2714
+ }
2715
+ .roles-profile-bot-row.selected {
2716
+ padding-left: 9px;
2717
+ }
2718
+ .roles-profile-inline-empty {
2719
+ flex: 1 1 auto;
2720
+ min-height: 220px;
2721
+ border: 1px dashed var(--border);
2722
+ border-radius: var(--radius);
2723
+ }
2563
2724
 
2564
2725
  /* ─── Editor textarea ─── */
2565
- #roles-editor-textarea {
2566
- flex: 1;
2726
+ #roles-editor-textarea,
2727
+ #roles-profile-textarea {
2728
+ width: 100%;
2729
+ box-sizing: border-box;
2730
+ flex: 0 0 auto;
2567
2731
  min-height: 220px;
2568
2732
  font-family: var(--mono);
2569
2733
  font-size: 13px;
@@ -2576,7 +2740,13 @@ input.row-select,
2576
2740
  color: var(--fg);
2577
2741
  tab-size: 2;
2578
2742
  }
2579
- #roles-editor-textarea:focus {
2743
+ #roles-profile-textarea {
2744
+ flex: 1 1 260px;
2745
+ min-height: 180px;
2746
+ max-height: min(44vh, 420px);
2747
+ }
2748
+ #roles-editor-textarea:focus,
2749
+ #roles-profile-textarea:focus {
2580
2750
  outline: none;
2581
2751
  border-color: var(--accent);
2582
2752
  box-shadow: 0 0 0 3px var(--accent-soft);
@@ -2596,6 +2766,44 @@ input.row-select,
2596
2766
  .roles-bytecount.warn { color: var(--warning); }
2597
2767
  .roles-bytecount.over { color: var(--danger); font-weight: 700; }
2598
2768
  .roles-editor-actions { display: flex; gap: 8px; }
2769
+ .roles-profile-editor .roles-editor-actions,
2770
+ .roles-profile-apply .roles-editor-actions {
2771
+ justify-content: flex-end;
2772
+ flex-wrap: wrap;
2773
+ }
2774
+ .roles-profile-apply {
2775
+ flex: 0 0 auto;
2776
+ max-height: 34%;
2777
+ overflow: auto;
2778
+ border-top: 1px solid var(--border-soft);
2779
+ padding-top: 14px;
2780
+ }
2781
+ .roles-profile-apply-controls {
2782
+ display: grid;
2783
+ grid-template-columns: minmax(180px, 1fr) auto;
2784
+ gap: 10px;
2785
+ align-items: center;
2786
+ margin-bottom: 10px;
2787
+ }
2788
+ .roles-profile-apply-controls select {
2789
+ min-width: 0;
2790
+ }
2791
+ .roles-profile-force {
2792
+ display: flex;
2793
+ align-items: center;
2794
+ gap: 6px;
2795
+ color: var(--muted);
2796
+ font-size: 12px;
2797
+ }
2798
+ .roles-profile-apply-bot {
2799
+ margin-bottom: 6px;
2800
+ }
2801
+ .roles-profile-status {
2802
+ color: var(--muted);
2803
+ font-size: 12px;
2804
+ line-height: 1.6;
2805
+ min-height: 18px;
2806
+ }
2599
2807
 
2600
2808
  /* ─── Saved flash ─── */
2601
2809
  .roles-saved-flash {
@@ -2624,9 +2832,15 @@ input.row-select,
2624
2832
  max-height: 140px;
2625
2833
  overflow-y: auto;
2626
2834
  }
2835
+ .roles-profile-editor .roles-preview {
2836
+ flex: 1 1 auto;
2837
+ min-height: 160px;
2838
+ max-height: none;
2839
+ }
2627
2840
  .roles-preview pre {
2628
2841
  margin: 8px 0 0 0;
2629
2842
  white-space: pre-wrap;
2843
+ overflow-wrap: anywhere;
2630
2844
  font-family: var(--mono);
2631
2845
  font-size: 12px;
2632
2846
  line-height: 1.5;
@@ -2644,6 +2858,21 @@ input.row-select,
2644
2858
  grid-template-columns: 1fr;
2645
2859
  height: auto;
2646
2860
  }
2861
+ .roles-heading {
2862
+ flex-direction: column;
2863
+ }
2864
+ .roles-tabs {
2865
+ width: 100%;
2866
+ }
2867
+ .roles-tabs button {
2868
+ flex: 1;
2869
+ }
2870
+ .roles-profile-grid {
2871
+ grid-template-columns: 1fr;
2872
+ }
2873
+ .roles-profile-apply-controls {
2874
+ grid-template-columns: 1fr;
2875
+ }
2647
2876
  }
2648
2877
 
2649
2878
  /* ─── Workflow runtime: list, detail, parallel timeline, IO cards ─── */
@@ -3000,36 +3229,275 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
3000
3229
  background: radial-gradient(circle at 32% 28%, #d8fbff, var(--c1, #5be3ff) 38%, var(--c2, #4f8bff) 72%, #060d1c 105%);
3001
3230
  box-shadow: 0 0 16px color-mix(in srgb, var(--c1, #5be3ff) 32%, transparent), inset 0 0 9px rgba(255, 255, 255, 0.28);
3002
3231
  }
3003
- .orb-avatar-sm {
3004
- width: 24px;
3005
- height: 24px;
3006
- box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.28);
3232
+ .orb-avatar-sm {
3233
+ width: 24px;
3234
+ height: 24px;
3235
+ box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.28);
3236
+ }
3237
+ /* 有真实头像时,把渐变球底色换成中性占位,避免"先亮球后头像"的闪烁;
3238
+ 渐变球只在头像加载失败(onerror 移除 .orb-has-img)时作为兜底重新露出。 */
3239
+ .orb-avatar.orb-has-img {
3240
+ background: var(--surface-muted);
3241
+ box-shadow: inset 0 0 0 1px var(--border);
3242
+ }
3243
+ /* 真实头像盖在数字生命球上;onerror 时移除自身,露出下面的渐变球兜底。
3244
+ 不加淡入动画——innerHTML 每次重绘都会重建 <img>,动画会跟着重放,看起来就是
3245
+ 头像在"刷新"。图本身有 HTTP 缓存 + URL 走 localStorage,重建即同步出图。 */
3246
+ .orb-img {
3247
+ position: absolute;
3248
+ inset: 0;
3249
+ width: 100%;
3250
+ height: 100%;
3251
+ border-radius: 50%;
3252
+ object-fit: cover;
3253
+ }
3254
+ /* 飞书群头像:圆角方形,和圆形的 bot 头像一眼区分开。 */
3255
+ .orb-avatar.orb-square,
3256
+ .orb-avatar.orb-square .orb-img { border-radius: 9px; }
3257
+ .orb-avatar.orb-square.orb-avatar-sm,
3258
+ .orb-avatar.orb-square.orb-avatar-sm .orb-img { border-radius: 6px; }
3259
+ /* 群列表名称单元格:群头像 + 群名/ID 横向排列。 */
3260
+ .g-chat-cell { display: flex; align-items: center; gap: 8px; }
3261
+ .g-chat-meta { min-width: 0; }
3262
+ .g-profile-status {
3263
+ display: inline-flex;
3264
+ align-items: center;
3265
+ max-width: 240px;
3266
+ margin-top: 5px;
3267
+ padding: 2px 7px;
3268
+ border-radius: 999px;
3269
+ border: 1px solid var(--border-soft);
3270
+ background: var(--surface-muted);
3271
+ color: var(--muted);
3272
+ font-size: 11px;
3273
+ font-weight: 700;
3274
+ line-height: 1.5;
3275
+ white-space: normal;
3276
+ overflow-wrap: anywhere;
3277
+ }
3278
+ .g-profile-status.full {
3279
+ border-color: color-mix(in srgb, var(--success) 35%, var(--border-soft));
3280
+ background: color-mix(in srgb, var(--success) 10%, var(--surface));
3281
+ color: var(--success);
3282
+ }
3283
+ .g-profile-status.partial {
3284
+ border-color: color-mix(in srgb, var(--warning) 35%, var(--border-soft));
3285
+ background: color-mix(in srgb, var(--warning) 12%, var(--surface));
3286
+ color: var(--warning);
3287
+ }
3288
+ .g-profile-status.muted { font-weight: 600; }
3289
+ .g-save-profile-dialog {
3290
+ display: grid;
3291
+ gap: 12px;
3292
+ }
3293
+ .g-save-profile-dialog [hidden] {
3294
+ display: none !important;
3295
+ }
3296
+ .g-save-profile-panel {
3297
+ display: grid;
3298
+ gap: 10px;
3299
+ padding: 12px;
3300
+ border: 1px solid var(--border-soft);
3301
+ border-radius: var(--radius);
3302
+ background: var(--surface-muted);
3303
+ }
3304
+ .g-save-profile-section-head {
3305
+ display: flex;
3306
+ justify-content: space-between;
3307
+ gap: 12px;
3308
+ align-items: baseline;
3309
+ }
3310
+ .g-save-profile-section-head > span {
3311
+ color: var(--fg);
3312
+ font-weight: 700;
3313
+ }
3314
+ .g-save-profile-section-head > small {
3315
+ color: var(--muted);
3316
+ font-size: 12px;
3317
+ }
3318
+ .g-save-profile-stats {
3319
+ display: flex;
3320
+ flex-wrap: wrap;
3321
+ gap: 6px;
3322
+ }
3323
+ .g-save-profile-stats span {
3324
+ display: inline-flex;
3325
+ gap: 5px;
3326
+ align-items: center;
3327
+ padding: 3px 8px;
3328
+ border: 1px solid var(--border-soft);
3329
+ border-radius: 999px;
3330
+ background: var(--surface);
3331
+ color: var(--muted);
3332
+ font-size: 12px;
3333
+ }
3334
+ .g-save-profile-stats strong {
3335
+ color: var(--fg);
3336
+ }
3337
+ .g-save-profile-stats .warn {
3338
+ color: var(--danger);
3339
+ background: var(--danger-soft);
3340
+ }
3341
+ .g-save-profile-entry-list {
3342
+ display: grid;
3343
+ gap: 6px;
3344
+ max-height: 170px;
3345
+ overflow: auto;
3346
+ }
3347
+ .g-save-profile-entry {
3348
+ display: grid;
3349
+ grid-template-columns: minmax(0, 1fr) auto;
3350
+ gap: 10px;
3351
+ align-items: center;
3352
+ padding: 8px 10px;
3353
+ border: 1px solid var(--border-soft);
3354
+ border-radius: var(--radius-sm);
3355
+ background: var(--surface);
3356
+ }
3357
+ .g-save-profile-entry > div {
3358
+ min-width: 0;
3359
+ display: grid;
3360
+ gap: 2px;
3361
+ }
3362
+ .g-save-profile-entry strong,
3363
+ .g-save-profile-entry code {
3364
+ min-width: 0;
3365
+ overflow: hidden;
3366
+ text-overflow: ellipsis;
3367
+ white-space: nowrap;
3368
+ }
3369
+ .g-save-profile-entry code {
3370
+ color: var(--muted);
3371
+ background: transparent;
3372
+ padding: 0;
3373
+ }
3374
+ .g-save-profile-entry.error {
3375
+ border-color: color-mix(in srgb, var(--danger) 35%, var(--border-soft));
3376
+ }
3377
+ .g-save-profile-entry-status {
3378
+ display: inline-flex;
3379
+ align-items: center;
3380
+ min-height: 22px;
3381
+ padding: 2px 8px;
3382
+ border-radius: 999px;
3383
+ background: var(--surface-muted);
3384
+ color: var(--muted);
3385
+ font-size: 12px;
3386
+ font-weight: 700;
3387
+ white-space: nowrap;
3388
+ }
3389
+ .g-save-profile-entry-status.ok {
3390
+ color: var(--success);
3391
+ background: color-mix(in srgb, var(--success) 12%, var(--surface));
3392
+ }
3393
+ .g-save-profile-entry-status.error {
3394
+ color: var(--danger);
3395
+ background: var(--danger-soft);
3396
+ }
3397
+ .g-save-profile-empty {
3398
+ color: var(--muted);
3399
+ font-size: 13px;
3400
+ }
3401
+ .g-save-profile-switch {
3402
+ display: grid;
3403
+ grid-template-columns: repeat(2, minmax(0, 1fr));
3404
+ gap: 4px;
3405
+ padding: 4px;
3406
+ border: 1px solid var(--border-soft);
3407
+ border-radius: 999px;
3408
+ background: var(--surface-muted);
3409
+ }
3410
+ .g-save-profile-switch button {
3411
+ min-width: 0;
3412
+ border-color: transparent;
3413
+ background: transparent;
3414
+ box-shadow: none;
3415
+ }
3416
+ .g-save-profile-switch button.active {
3417
+ background: var(--surface);
3418
+ border-color: color-mix(in srgb, var(--accent) 40%, var(--border-soft));
3419
+ color: var(--accent-strong);
3420
+ box-shadow: 0 3px 12px color-mix(in srgb, var(--accent) 16%, transparent);
3421
+ }
3422
+ .g-save-profile-picker {
3423
+ display: grid;
3424
+ gap: 8px;
3425
+ max-height: 220px;
3426
+ overflow: auto;
3427
+ }
3428
+ .g-save-profile-pick {
3429
+ display: grid;
3430
+ grid-template-columns: minmax(0, 1fr) auto;
3431
+ gap: 10px;
3432
+ align-items: center;
3433
+ justify-content: stretch;
3434
+ min-height: 38px;
3435
+ width: 100%;
3436
+ border-radius: var(--radius-sm);
3437
+ background: var(--surface-muted);
3438
+ box-shadow: none;
3439
+ text-align: left;
3440
+ }
3441
+ .g-save-profile-pick.selected {
3442
+ border-color: color-mix(in srgb, var(--accent) 55%, var(--border-soft));
3443
+ background: color-mix(in srgb, var(--accent) 8%, var(--surface));
3444
+ color: var(--accent-strong);
3445
+ }
3446
+ .g-save-profile-pick span {
3447
+ min-width: 0;
3448
+ overflow: hidden;
3449
+ text-overflow: ellipsis;
3450
+ white-space: nowrap;
3451
+ }
3452
+ .g-save-profile-pick small,
3453
+ .g-save-profile-summary,
3454
+ .g-save-profile-status,
3455
+ .form-row small {
3456
+ color: var(--muted);
3457
+ font-size: 12px;
3458
+ line-height: 1.55;
3459
+ }
3460
+ .g-save-profile-target {
3461
+ display: grid;
3462
+ grid-template-columns: auto minmax(0, 1fr);
3463
+ gap: 4px 10px;
3464
+ align-items: center;
3465
+ padding: 9px 10px;
3466
+ border: 1px solid var(--border-soft);
3467
+ border-radius: var(--radius-sm);
3468
+ background: var(--surface-muted);
3469
+ }
3470
+ .g-save-profile-target > span {
3471
+ color: var(--muted);
3472
+ font-size: 12px;
3473
+ font-weight: 700;
3474
+ }
3475
+ .g-save-profile-target code {
3476
+ min-width: 0;
3477
+ overflow: hidden;
3478
+ text-overflow: ellipsis;
3479
+ }
3480
+ .g-save-profile-target small {
3481
+ grid-column: 2;
3482
+ color: var(--muted);
3483
+ font-size: 12px;
3007
3484
  }
3008
- /* 有真实头像时,把渐变球底色换成中性占位,避免"先亮球后头像"的闪烁;
3009
- 渐变球只在头像加载失败(onerror 移除 .orb-has-img)时作为兜底重新露出。 */
3010
- .orb-avatar.orb-has-img {
3485
+ .g-save-profile-summary {
3486
+ padding: 8px 10px;
3487
+ border-radius: var(--radius-sm);
3011
3488
  background: var(--surface-muted);
3012
- box-shadow: inset 0 0 0 1px var(--border);
3013
3489
  }
3014
- /* 真实头像盖在数字生命球上;onerror 时移除自身,露出下面的渐变球兜底。
3015
- 不加淡入动画——innerHTML 每次重绘都会重建 <img>,动画会跟着重放,看起来就是
3016
- 头像在"刷新"。图本身有 HTTP 缓存 + URL 走 localStorage,重建即同步出图。 */
3017
- .orb-img {
3018
- position: absolute;
3019
- inset: 0;
3020
- width: 100%;
3021
- height: 100%;
3022
- border-radius: 50%;
3023
- object-fit: cover;
3490
+ .g-save-profile-summary.warn,
3491
+ .g-save-profile-status.error {
3492
+ color: var(--danger);
3493
+ background: var(--danger-soft);
3494
+ }
3495
+ .g-save-profile-status {
3496
+ min-height: 20px;
3497
+ }
3498
+ .g-save-profile-status.ok {
3499
+ color: var(--success);
3024
3500
  }
3025
- /* 飞书群头像:圆角方形,和圆形的 bot 头像一眼区分开。 */
3026
- .orb-avatar.orb-square,
3027
- .orb-avatar.orb-square .orb-img { border-radius: 9px; }
3028
- .orb-avatar.orb-square.orb-avatar-sm,
3029
- .orb-avatar.orb-square.orb-avatar-sm .orb-img { border-radius: 6px; }
3030
- /* 群列表名称单元格:群头像 + 群名/ID 横向排列。 */
3031
- .g-chat-cell { display: flex; align-items: center; gap: 8px; }
3032
- .g-chat-meta { min-width: 0; }
3033
3501
  .orb-dot {
3034
3502
  position: absolute;
3035
3503
  right: -1px;
@@ -3740,6 +4208,19 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
3740
4208
  min-width: 0;
3741
4209
  }
3742
4210
 
4211
+ .skills-source-control {
4212
+ display: grid;
4213
+ grid-template-columns: minmax(0, 1fr) auto;
4214
+ gap: 8px;
4215
+ align-items: center;
4216
+ }
4217
+
4218
+ .skills-source-control button {
4219
+ min-height: 36px;
4220
+ padding: 0 13px;
4221
+ white-space: nowrap;
4222
+ }
4223
+
3743
4224
  .skills-main-panel,
3744
4225
  .skills-bot-grid {
3745
4226
  display: grid;
@@ -3884,7 +4365,27 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
3884
4365
  line-height: 1.45;
3885
4366
  overflow-wrap: anywhere;
3886
4367
  }
3887
- .skills-row small { color: var(--muted); font-family: var(--mono); font-size: 11px; overflow-wrap: anywhere; }
4368
+ .skills-row small {
4369
+ color: var(--muted);
4370
+ font-family: var(--mono);
4371
+ font-size: 11px;
4372
+ overflow-wrap: anywhere;
4373
+ }
4374
+
4375
+ .skills-source-badge {
4376
+ display: inline-flex;
4377
+ align-items: center;
4378
+ width: fit-content;
4379
+ max-width: 100%;
4380
+ min-height: 22px;
4381
+ margin-top: 4px;
4382
+ padding: 2px 7px;
4383
+ border: 1px solid var(--border-soft);
4384
+ border-radius: 999px;
4385
+ background: var(--surface-muted);
4386
+ overflow: hidden;
4387
+ text-overflow: ellipsis;
4388
+ }
3888
4389
 
3889
4390
  .skills-card-actions {
3890
4391
  display: grid;
@@ -4319,6 +4820,213 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
4319
4820
  align-self: start;
4320
4821
  }
4321
4822
 
4823
+ .skills-discovery-dialog {
4824
+ width: min(860px, calc(100vw - 44px));
4825
+ max-height: min(760px, calc(100vh - 64px));
4826
+ padding: 0;
4827
+ border: 1px solid var(--border-soft);
4828
+ border-radius: 14px;
4829
+ background: var(--surface);
4830
+ box-shadow: var(--modal-shadow);
4831
+ color: var(--fg);
4832
+ }
4833
+
4834
+ .skills-discovery-dialog::backdrop {
4835
+ background: color-mix(in srgb, #0b1524 42%, transparent);
4836
+ backdrop-filter: blur(4px);
4837
+ }
4838
+
4839
+ .skills-discovery-dialog article {
4840
+ display: grid;
4841
+ grid-template-rows: auto minmax(0, 1fr) auto;
4842
+ max-height: inherit;
4843
+ }
4844
+
4845
+ .skills-discovery-dialog header {
4846
+ display: grid;
4847
+ gap: 5px;
4848
+ padding: 18px 20px 12px;
4849
+ border-bottom: 1px solid var(--border-soft);
4850
+ }
4851
+
4852
+ .skills-discovery-dialog h3,
4853
+ .skills-discovery-dialog p {
4854
+ margin: 0;
4855
+ }
4856
+
4857
+ .skills-discovery-dialog h3 {
4858
+ font-size: 17px;
4859
+ }
4860
+
4861
+ .skills-discovery-dialog p {
4862
+ color: var(--muted);
4863
+ font-size: 12.5px;
4864
+ line-height: 1.5;
4865
+ }
4866
+
4867
+ .skills-discovery-body {
4868
+ display: grid;
4869
+ gap: 12px;
4870
+ min-height: 0;
4871
+ max-height: 520px;
4872
+ overflow: auto;
4873
+ padding: 16px 20px;
4874
+ }
4875
+
4876
+ .skills-discovery-tabs {
4877
+ display: flex;
4878
+ gap: 8px;
4879
+ align-items: center;
4880
+ min-height: 40px;
4881
+ overflow-x: auto;
4882
+ overflow-y: hidden;
4883
+ padding-bottom: 2px;
4884
+ scrollbar-width: thin;
4885
+ }
4886
+
4887
+ .skills-discovery-tabs button {
4888
+ display: grid;
4889
+ grid-template-columns: auto auto;
4890
+ gap: 8px;
4891
+ align-items: center;
4892
+ flex: 0 0 auto;
4893
+ min-height: 38px;
4894
+ padding: 0 12px;
4895
+ border-radius: 999px;
4896
+ text-transform: uppercase;
4897
+ }
4898
+
4899
+ .skills-discovery-tabs button.selected {
4900
+ border-color: color-mix(in srgb, var(--accent) 72%, var(--border-soft));
4901
+ background: color-mix(in srgb, var(--accent) 10%, var(--surface));
4902
+ color: var(--fg);
4903
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
4904
+ }
4905
+
4906
+ .skills-discovery-tabs strong {
4907
+ font-size: 12px;
4908
+ }
4909
+
4910
+ .skills-discovery-tabs small {
4911
+ color: var(--muted);
4912
+ font-size: 11px;
4913
+ font-weight: 700;
4914
+ text-transform: none;
4915
+ }
4916
+
4917
+ .skills-discovery-path {
4918
+ min-width: 0;
4919
+ padding: 7px 10px;
4920
+ border-radius: 8px;
4921
+ background: color-mix(in srgb, var(--surface-muted) 70%, transparent);
4922
+ }
4923
+
4924
+ .skills-discovery-path code {
4925
+ display: block;
4926
+ overflow: hidden;
4927
+ color: var(--muted);
4928
+ font-size: 12px;
4929
+ text-overflow: ellipsis;
4930
+ white-space: nowrap;
4931
+ }
4932
+
4933
+ .skills-discovery-group {
4934
+ display: grid;
4935
+ gap: 8px;
4936
+ }
4937
+
4938
+ .skills-discovery-group[hidden] {
4939
+ display: none;
4940
+ }
4941
+
4942
+ .skills-discovery-group header {
4943
+ display: grid;
4944
+ grid-template-columns: auto minmax(0, 1fr);
4945
+ gap: 8px;
4946
+ align-items: center;
4947
+ padding: 0;
4948
+ border: 0;
4949
+ }
4950
+
4951
+ .skills-discovery-group strong {
4952
+ text-transform: uppercase;
4953
+ color: var(--fg);
4954
+ font-size: 12px;
4955
+ }
4956
+
4957
+ .skills-discovery-group code {
4958
+ overflow: hidden;
4959
+ color: var(--muted);
4960
+ font-size: 11px;
4961
+ text-overflow: ellipsis;
4962
+ white-space: nowrap;
4963
+ }
4964
+
4965
+ .skills-discovery-list {
4966
+ display: grid;
4967
+ gap: 7px;
4968
+ }
4969
+
4970
+ .skills-discovery-row {
4971
+ display: grid;
4972
+ grid-template-columns: auto minmax(0, 1fr) auto;
4973
+ gap: 10px;
4974
+ align-items: start;
4975
+ min-height: 54px;
4976
+ padding: 10px 12px;
4977
+ border: 1px solid var(--border-soft);
4978
+ border-radius: 8px;
4979
+ background: var(--surface-muted);
4980
+ cursor: pointer;
4981
+ }
4982
+
4983
+ .skills-discovery-row input {
4984
+ margin-top: 3px;
4985
+ }
4986
+
4987
+ .skills-discovery-row span {
4988
+ display: grid;
4989
+ gap: 3px;
4990
+ min-width: 0;
4991
+ }
4992
+
4993
+ .skills-discovery-row strong {
4994
+ overflow: hidden;
4995
+ color: var(--fg);
4996
+ font-size: 13px;
4997
+ text-overflow: ellipsis;
4998
+ white-space: nowrap;
4999
+ }
5000
+
5001
+ .skills-discovery-row small {
5002
+ display: -webkit-box;
5003
+ -webkit-line-clamp: 2;
5004
+ -webkit-box-orient: vertical;
5005
+ overflow: hidden;
5006
+ color: var(--muted);
5007
+ font-size: 12px;
5008
+ line-height: 1.4;
5009
+ }
5010
+
5011
+ .skills-discovery-row em {
5012
+ align-self: center;
5013
+ color: var(--muted);
5014
+ font-size: 11px;
5015
+ font-style: normal;
5016
+ font-weight: 700;
5017
+ }
5018
+
5019
+ .skills-discovery-row.installed {
5020
+ opacity: 0.68;
5021
+ cursor: default;
5022
+ }
5023
+
5024
+ .skills-discovery-dialog footer {
5025
+ justify-content: end;
5026
+ padding: 12px 20px 16px;
5027
+ border-top: 1px solid var(--border-soft);
5028
+ }
5029
+
4322
5030
  .skills-policy-controls [data-bot-status] {
4323
5031
  grid-column: 1 / -1;
4324
5032
  }
@@ -4364,6 +5072,7 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
4364
5072
  }
4365
5073
  .skills-side-rail,
4366
5074
  .skills-install-grid,
5075
+ .skills-source-control,
4367
5076
  .skills-section-head-row,
4368
5077
  .skills-overview,
4369
5078
  .skills-metric-strip,
@@ -4471,6 +5180,43 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
4471
5180
  .toggle-row .switch, .toggle-row .switch::after { transition: none; }
4472
5181
  }
4473
5182
 
5183
+ .bd-profile-roles {
5184
+ margin-top: 12px;
5185
+ padding-top: 12px;
5186
+ border-top: 1px solid var(--border-soft);
5187
+ }
5188
+ .bd-profile-role-entry > summary {
5189
+ cursor: pointer;
5190
+ color: var(--fg);
5191
+ font-weight: 700;
5192
+ }
5193
+ .bd-profile-roles .bd-subsection-title {
5194
+ margin: 0 0 4px;
5195
+ }
5196
+ .bd-profile-role-list {
5197
+ display: grid;
5198
+ gap: 8px;
5199
+ margin-top: 10px;
5200
+ }
5201
+ .bd-profile-role-entry {
5202
+ padding: 8px 10px;
5203
+ border: 1px solid var(--border-soft);
5204
+ border-radius: var(--radius-sm);
5205
+ background: var(--surface-muted);
5206
+ }
5207
+ .bd-profile-role-content pre {
5208
+ margin: 8px 0 0;
5209
+ padding: 10px;
5210
+ max-height: 220px;
5211
+ overflow: auto;
5212
+ white-space: pre-wrap;
5213
+ overflow-wrap: anywhere;
5214
+ border-radius: var(--radius-sm);
5215
+ background: var(--surface-raised);
5216
+ color: var(--fg);
5217
+ font: 12px/1.5 var(--mono);
5218
+ }
5219
+
4474
5220
  .bd-tile textarea,
4475
5221
  .bd-tile input[type=text],
4476
5222
  .bd-tile input[type=number] {
@@ -6017,3 +6763,609 @@ body.cp-fx-slice main { animation: cp-fx-slice 0.32s steps(2, end); }
6017
6763
  @media (prefers-reduced-motion: reduce) {
6018
6764
  .skin-intro { display: none; }
6019
6765
  }
6766
+
6767
+ /* ── Insight workbench (owner-only #/insights page) ───────────────────────────
6768
+ Visual layer ported from the reference app (agent-session-insights, html.ts
6769
+ STYLE) so this page reads as that read-only "工作台", not generic dashboard
6770
+ cards. The reference is dark-only with hardcoded hexes; here its variables
6771
+ (--panel/--line/--mut/--acc/--good/--warn/--bad) and stray hexes are remapped
6772
+ to the dashboard's light/dark design tokens and SCOPED under .insights-page,
6773
+ so the workbench look carries over while still respecting the active theme.
6774
+ Phase colors match the reference exactly: edit=green research=blue run=amber
6775
+ delegate=purple discuss=gray. */
6776
+ .insights-page {
6777
+ --panel: var(--surface);
6778
+ --line: var(--border);
6779
+ --mut: var(--muted);
6780
+ --acc: var(--accent);
6781
+ --good: var(--success);
6782
+ --warn: var(--warning);
6783
+ --bad: var(--danger);
6784
+ --ins-inner: var(--surface-muted);
6785
+ --ins-recess: var(--bg-soft);
6786
+ --ins-faint: var(--faint);
6787
+ --ph-edit: var(--success);
6788
+ --ph-research: var(--accent);
6789
+ --ph-run: var(--warning);
6790
+ --ph-delegate: #a06fd6;
6791
+ --ph-discuss: var(--muted);
6792
+ --ph-unknown: var(--border);
6793
+ color: var(--fg);
6794
+ font-size: 14px;
6795
+ line-height: 1.5;
6796
+ }
6797
+ .insight-page-status { color: var(--mut); font-size: 12px; margin: 4px 0 14px; min-height: 14px; }
6798
+
6799
+ /* section labels (uppercase eyebrow) — reference h3 */
6800
+ .insights-page .block h3,
6801
+ .insights-page .insight-detail h3,
6802
+ .insights-page .insight-section-label {
6803
+ font-size: 12px; color: var(--mut); font-weight: 600; letter-spacing: .06em;
6804
+ text-transform: uppercase; margin: 0 0 10px;
6805
+ }
6806
+
6807
+ /* metric cards (reference .cards/.card/.cv/.cl/.cs) */
6808
+ .insights-page .cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
6809
+ .insights-page .insights-metrics { margin-bottom: 16px; }
6810
+ .insights-page .card { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; }
6811
+ .insights-page .cv { font-size: 20px; font-weight: 600; line-height: 1.2; }
6812
+ .insights-page .cl { color: var(--mut); font-size: 12px; margin-top: 4px; }
6813
+ .insights-page .cs { color: var(--mut); font-size: 11px; margin-top: 2px; }
6814
+
6815
+ /* overview blocks (reference .block/.grid2col/.recblock) */
6816
+ .insights-page .block { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; }
6817
+ .insights-page .recblock { background: var(--ins-inner); }
6818
+ .insights-overview-grid { display: grid; grid-template-columns: 1.25fr 1fr; gap: 14px; margin: 16px 0 18px; }
6819
+ @media (max-width: 900px) { .insights-overview-grid { grid-template-columns: 1fr; } }
6820
+
6821
+ /* recommendations (reference .reclist/.rec/.rectop/.recev/.recact) */
6822
+ .insights-page .reclist { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 8px; }
6823
+ .insights-page .insight-detail .reclist { grid-template-columns: 1fr; }
6824
+ .insights-page .rec {
6825
+ display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; border: 1px solid var(--line); border-left: 3px solid var(--mut);
6826
+ border-radius: 7px; background: var(--panel); padding: 9px 11px;
6827
+ }
6828
+ /* <button class="rec"> carries UA defaults (justify-content + text-align: center)
6829
+ that centre the card body. The non-clickable rec (no evidence ⇒ no .rec-clickable,
6830
+ which is the only place text-align:left lived) hit exactly that — its impact/actions
6831
+ rendered centred. Reset on every rec button so clickable/non-clickable align identically. */
6832
+ .insights-page button.rec { justify-items: stretch; justify-content: stretch; text-align: left; width: 100%; font: inherit; color: inherit; appearance: none; -webkit-appearance: none; }
6833
+ .insights-page .recblock .rec { background: var(--ins-recess); }
6834
+ .insights-page .rec.bad { border-left-color: var(--bad); }
6835
+ .insights-page .rec.warn { border-left-color: var(--warn); }
6836
+ .insights-page .rec.info { border-left-color: var(--acc); }
6837
+ .insights-page .rectop { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
6838
+ .insights-page .rectop b { font-size: 13px; line-height: 1.35; }
6839
+ .insights-page .rectop span { flex: 0 0 auto; color: var(--mut); border: 1px solid var(--line); border-radius: 999px; padding: 1px 8px; font-size: 11px; white-space: nowrap; }
6840
+ .insights-page .rec.bad .rectop span { color: var(--bad); border-color: var(--bad); }
6841
+ .insights-page .rec.warn .rectop span { color: var(--warn); border-color: var(--warn); }
6842
+ .insights-page .rec.info .rectop span { color: var(--acc); border-color: var(--acc); }
6843
+ .insights-page .recev { color: var(--fg); font-size: 12px; line-height: 1.45; }
6844
+ .insights-page .recact { color: var(--mut); font-size: 12px; line-height: 1.45; }
6845
+
6846
+ /* top failed tools — horizontal bars (reference .hbrow/.hbtrack/.hbfill/.hbval) */
6847
+ .insights-page .hbars { display: grid; gap: 4px; }
6848
+ .insights-page .hbrow { display: grid; grid-template-columns: 116px 1fr 64px; align-items: center; gap: 10px; padding: 4px 4px; border-radius: 6px; }
6849
+ .insights-page .hblabel { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: var(--mono); }
6850
+ .insights-page .hbtrack { background: var(--ins-inner); border-radius: 6px; height: 14px; overflow: hidden; }
6851
+ .insights-page .hbfill { height: 100%; background: linear-gradient(90deg, var(--danger-soft), var(--bad)); border-radius: 6px; min-width: 3px; transform-origin: left; animation: insight-bar-grow .55s ease both; }
6852
+ .insights-page .hbval { font-size: 12px; color: var(--mut); text-align: right; white-space: nowrap; }
6853
+
6854
+ /* workbench: session list | detail (master-detail) */
6855
+ .insight-workbench { display: grid; grid-template-columns: minmax(260px, 320px) minmax(0, 1fr); gap: 14px; align-items: start; }
6856
+ @media (max-width: 900px) { .insight-workbench { grid-template-columns: 1fr; } }
6857
+ .insight-workbench > *, .insight-list-panel, .insight-detail { min-width: 0; }
6858
+ .insight-list-panel, .insight-detail { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; }
6859
+ .insight-list-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
6860
+ .insight-list-head h3 { font-size: 13px; margin: 0; }
6861
+ .insight-list-head span { font-size: 11px; color: var(--mut); }
6862
+
6863
+ /* session rows (reference .slist/.srow/.srmain/.srstats) */
6864
+ .insights-page .slist { display: grid; gap: 8px; max-height: 72vh; overflow: auto; }
6865
+ .insights-page .srow {
6866
+ display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; width: 100%; box-sizing: border-box;
6867
+ background: var(--ins-inner); border: 1px solid var(--line); border-left: 3px solid transparent;
6868
+ border-radius: 8px; padding: 9px 11px; color: inherit; text-align: left; cursor: pointer;
6869
+ transition: background .12s ease, border-color .12s ease, transform .12s ease, box-shadow .15s ease;
6870
+ }
6871
+ .insights-page .srow:hover { background: var(--ins-recess); transform: translateY(-1px); box-shadow: var(--shadow); }
6872
+ .insights-page .srow.on { border-left-color: var(--acc); background: var(--accent-soft); }
6873
+ .insights-page .srow.review { border-left-color: var(--bad); }
6874
+ .insights-page .srmain { display: grid; gap: 5px; min-width: 0; }
6875
+ .insights-page .srmain strong { font-size: 13px; font-weight: 600; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
6876
+ .insights-page .srmain small { font-size: 11px; color: var(--mut); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
6877
+ .insights-page .srstats { display: flex; flex-wrap: wrap; gap: 4px 6px; }
6878
+ .insights-page .srstats b { font-size: 11px; color: var(--mut); font-weight: 500; background: var(--panel); border: 1px solid var(--line); border-radius: 999px; padding: 1px 8px; white-space: nowrap; }
6879
+ .insights-page .srstats b em { font-style: normal; color: var(--fg); font-weight: 600; margin-left: 4px; }
6880
+ .insights-page .srstats b.bad em { color: var(--bad); }
6881
+ .insights-page .srmsg { font-size: 11px; color: var(--mut); }
6882
+
6883
+ /* phase-mix mini bar (reference .mph) + proportional bar (reference .pmx) */
6884
+ .insights-page .mph { display: flex; gap: 1px; height: 7px; overflow: hidden; border-radius: 3px; margin-top: 1px; background: var(--ins-recess); }
6885
+ .insights-page .mph i { display: block; height: 100%; min-width: 1px; }
6886
+ .insights-page .pmx { display: flex; height: 11px; border-radius: 5px; overflow: hidden; background: var(--ins-inner); }
6887
+ .insights-page .pmx i { display: block; height: 100%; }
6888
+ .insights-page i.phase-research { background: var(--ph-research); }
6889
+ .insights-page i.phase-edit { background: var(--ph-edit); }
6890
+ .insights-page i.phase-run { background: var(--ph-run); }
6891
+ .insights-page i.phase-delegate { background: var(--ph-delegate); }
6892
+ .insights-page i.phase-discuss { background: var(--ph-discuss); }
6893
+ .insights-page i.phase-unknown { background: var(--ph-unknown); }
6894
+ .insights-page .leg { font-size: 11px; color: var(--mut); margin-top: 6px; }
6895
+ .insights-page .ld { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin: 0 4px 0 10px; vertical-align: middle; }
6896
+
6897
+ /* detail head (reference .shead/.smeta) */
6898
+ .insights-page .shead h2 { font-size: 16px; margin: 0 0 4px; }
6899
+ .insights-page .smeta { color: var(--mut); font-size: 12px; margin: 0 0 12px; }
6900
+ .insights-page .smeta code { font-family: var(--mono); }
6901
+ .insights-page .insight-detail-metrics { margin-bottom: 10px; }
6902
+ .insights-page .insight-meta { font-size: 12px; color: var(--mut); margin: 8px 0; }
6903
+ .insights-page .insight-empty { color: var(--mut); padding: 24px; text-align: center; }
6904
+ .insights-page .mut { color: var(--ins-faint); }
6905
+ .insights-page .note { color: var(--mut); font-size: 12px; margin-top: 8px; }
6906
+
6907
+ /* detail tabs: 动作 span / 逐轮对账 (reference .detailtabbar) */
6908
+ .insights-page .detailtabs { margin-top: 16px; }
6909
+ .insights-page .detailtabbar { display: flex; gap: 6px; align-items: center; border-bottom: 1px solid var(--line); margin-bottom: 12px; }
6910
+ .insights-page .detailtabbar button {
6911
+ background: transparent; color: var(--mut); border: 1px solid transparent; border-bottom: 0;
6912
+ border-radius: 7px 7px 0 0; padding: 7px 13px; font: inherit; font-size: 12px; cursor: pointer; margin-bottom: -1px;
6913
+ }
6914
+ .insights-page .detailtabbar button:hover { color: var(--fg); }
6915
+ .insights-page .detailtabbar button.on { color: var(--fg); background: var(--panel); border-color: var(--line); font-weight: 600; }
6916
+ .insights-page .detailtabbar b { font-weight: 500; color: var(--acc); margin-left: 5px; }
6917
+ .insights-page .insight-tab-panel[hidden] { display: none; }
6918
+
6919
+ /* 动作 span — trace (reference .tracebox/.spanlist/.spanrow/.spanst/.spanline) */
6920
+ .insights-page .tracebox { background: var(--ins-inner); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }
6921
+ .insights-page .tracehead { display: flex; align-items: center; justify-content: space-between; gap: 10px; color: var(--mut); font-size: 12px; margin-bottom: 8px; }
6922
+ .insights-page .tracehead b { color: var(--fg); }
6923
+ .insights-page .tracebad { color: var(--bad); }
6924
+ .insights-page .spanlist { display: grid; gap: 5px; max-height: 62vh; overflow: auto; }
6925
+ .insights-page .spanrow {
6926
+ display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 9px;
6927
+ background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--line);
6928
+ border-radius: 7px; padding: 7px 9px;
6929
+ }
6930
+ .insights-page .spanrow.ph-research { border-left-color: var(--ph-research); }
6931
+ .insights-page .spanrow.ph-edit { border-left-color: var(--ph-edit); }
6932
+ .insights-page .spanrow.ph-run { border-left-color: var(--ph-run); }
6933
+ .insights-page .spanrow.ph-delegate { border-left-color: var(--ph-delegate); }
6934
+ .insights-page .spanrow.ph-discuss { border-left-color: var(--ph-discuss); }
6935
+ .insights-page .spanrow.error { background: var(--danger-soft); border-color: var(--bad); border-left-color: var(--bad); }
6936
+ .insights-page .spanrail { display: flex; flex-direction: column; gap: 3px; color: var(--ins-faint); font-size: 11px; font-family: var(--mono); white-space: nowrap; }
6937
+ .insights-page .spanrail .sr-turn { color: var(--mut); }
6938
+ .insights-page .spanbody { display: grid; gap: 4px; min-width: 0; }
6939
+ .insights-page .spantop { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; color: var(--mut); font-size: 11px; }
6940
+ .insights-page .spantop b { font-family: var(--mono); color: var(--fg); font-size: 12px; }
6941
+ .insights-page .spanst { border-radius: 999px; background: var(--ins-inner); border: 1px solid var(--line); padding: 1px 8px; font-size: 10px; font-weight: 700; }
6942
+ .insights-page .spanst.ok { color: var(--good); border-color: var(--good); }
6943
+ .insights-page .spanst.error { color: var(--bad); border-color: var(--bad); }
6944
+ .insights-page .spanst.running { color: var(--warn); border-color: var(--warn); }
6945
+ .insights-page .spanline { display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: 8px; align-items: start; }
6946
+ .insights-page .spanline > span { color: var(--ins-faint); font-size: 11px; text-align: right; line-height: 1.6; }
6947
+ .insights-page .spanline code, .insights-page .spanline em {
6948
+ min-width: 0; overflow-wrap: anywhere; background: var(--bg); border: 1px solid var(--line);
6949
+ border-radius: 5px; padding: 3px 7px; font-family: var(--mono); font-size: 11px; line-height: 1.45; color: var(--fg); font-style: normal;
6950
+ }
6951
+ .insights-page .spanline em { color: var(--mut); }
6952
+
6953
+ /* 逐轮对账 — ledger (reference .ledger/.lrow/.lhead/.lstat) */
6954
+ .insights-page .ledger { display: grid; gap: 6px; max-height: 62vh; overflow: auto; }
6955
+ .insights-page .lrow { background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--line); border-radius: 8px; padding: 8px 12px; }
6956
+ .insights-page .lrow.dom-research { border-left-color: var(--ph-research); }
6957
+ .insights-page .lrow.dom-edit { border-left-color: var(--ph-edit); }
6958
+ .insights-page .lrow.dom-run { border-left-color: var(--ph-run); }
6959
+ .insights-page .lrow.dom-delegate { border-left-color: var(--ph-delegate); }
6960
+ .insights-page .lrow.dom-discuss { border-left-color: var(--ph-discuss); }
6961
+ .insights-page .lhead { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
6962
+ .insights-page .lno { color: var(--mut); font-size: 12px; font-family: var(--mono); font-weight: 700; flex: 0 0 auto; }
6963
+ .insights-page .lphases { display: flex; flex-wrap: wrap; gap: 5px; }
6964
+ .insights-page .lphase { display: inline-flex; align-items: center; gap: 5px; background: var(--ins-inner); border-radius: 999px; padding: 2px 8px; font-size: 11px; color: var(--fg); }
6965
+ .insights-page .lphase::before { content: ''; width: 6px; height: 6px; border-radius: 999px; background: var(--mut); }
6966
+ .insights-page .lphase.phase-research::before { background: var(--ph-research); }
6967
+ .insights-page .lphase.phase-edit::before { background: var(--ph-edit); }
6968
+ .insights-page .lphase.phase-run::before { background: var(--ph-run); }
6969
+ .insights-page .lphase.phase-delegate::before { background: var(--ph-delegate); }
6970
+ .insights-page .lphase.phase-discuss::before { background: var(--ph-discuss); }
6971
+ .insights-page .lstat { display: flex; gap: 14px; align-items: center; margin-top: 6px; font-size: 11px; color: var(--mut); flex-wrap: wrap; }
6972
+ .insights-page .lstat b { color: var(--fg); font-weight: 600; }
6973
+ .insights-page .lerr { color: var(--bad); font-weight: 600; }
6974
+ .insights-page .lcontent { display: grid; gap: 6px; margin-top: 8px; min-width: 0; }
6975
+ .insights-page .lcontent-preview,
6976
+ .insights-page .lcontent-more { display: grid; gap: 5px; min-width: 0; }
6977
+ .insights-page .lcontent-line {
6978
+ display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: 8px; align-items: start;
6979
+ background: var(--ins-inner); border: 1px solid var(--line); border-radius: 6px; padding: 5px 8px; min-width: 0;
6980
+ }
6981
+ .insights-page .lcontent-line.error { border-color: rgba(248, 81, 73, .35); background: rgba(248, 81, 73, .07); }
6982
+ .insights-page .lcontent-line b {
6983
+ min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
6984
+ color: var(--mut); font-family: var(--mono); font-size: 11px; font-weight: 650;
6985
+ }
6986
+ .insights-page .lcontent-line span {
6987
+ min-width: 0; color: var(--fg); font-family: var(--mono); font-size: 11px; line-height: 1.45;
6988
+ display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere;
6989
+ }
6990
+ .insights-page .lcontent details { color: var(--mut); font-size: 11px; }
6991
+ .insights-page .lcontent summary {
6992
+ cursor: pointer; user-select: none; display: inline-flex; width: fit-content;
6993
+ border: 1px dashed var(--line); border-radius: 999px; padding: 2px 8px; background: var(--bg);
6994
+ }
6995
+ .insights-page .lcontent summary:hover { color: var(--fg); border-color: var(--acc); }
6996
+ .insights-page .lcontent details[open] .lcontent-more { margin-top: 6px; max-height: 260px; overflow: auto; padding-right: 2px; }
6997
+ .insights-page .lcontent details[open] .lcontent-line span {
6998
+ display: block; max-height: 96px; overflow: auto; white-space: pre-wrap;
6999
+ }
7000
+ .insights-page .lcontent-omitted,
7001
+ .insights-page .lcontent-empty { color: var(--mut); font-size: 11px; }
7002
+
7003
+ /* diagnosis-driven: recommendations as evidence entry points + focus/highlight */
7004
+ .insights-page .rec.rec-clickable {
7005
+ cursor: pointer; width: 100%; text-align: left; font: inherit; color: inherit;
7006
+ appearance: none; -webkit-appearance: none; transition: border-color .15s, box-shadow .15s, transform .04s;
7007
+ }
7008
+ .insights-page .rec.rec-clickable:hover { border-color: var(--acc); }
7009
+ .insights-page .rec.rec-clickable:active { transform: translateY(1px); }
7010
+ .insights-page .rec.active { border-color: var(--acc); box-shadow: 0 0 0 1px var(--acc) inset; }
7011
+ .insights-page .rec-cta { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 650; color: var(--acc); }
7012
+ .insights-page .rec.active .rec-cta::before { content: ''; width: 6px; height: 6px; border-radius: 999px; background: var(--acc); }
7013
+ .insights-page .spanrow.hot { border-left-width: 4px; box-shadow: 0 0 0 1px var(--acc) inset; }
7014
+ .insights-page .tracehead .ev-toggle {
7015
+ cursor: pointer; font: inherit; font-size: 11px; color: var(--mut); background: var(--bg);
7016
+ border: 1px dashed var(--line); border-radius: 999px; padding: 2px 10px; white-space: nowrap;
7017
+ }
7018
+ .insights-page .tracehead .ev-toggle:hover { color: var(--fg); border-color: var(--acc); }
7019
+ .insights-page .ev-reason { margin: 0 0 8px; font-size: 12px; color: var(--mut); line-height: 1.45; }
7020
+
7021
+ /* per-turn efficiency metrics (read/edit/run/fail/time + dominant phase) */
7022
+ .insights-page .ldom { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 650; color: var(--fg); flex: 0 0 auto; }
7023
+ .insights-page .ldom::before { content: ''; width: 7px; height: 7px; border-radius: 999px; background: var(--mut); }
7024
+ .insights-page .ldom.phase-research::before { background: var(--ph-research); }
7025
+ .insights-page .ldom.phase-edit::before { background: var(--ph-edit); }
7026
+ .insights-page .ldom.phase-run::before { background: var(--ph-run); }
7027
+ .insights-page .ldom.phase-delegate::before { background: var(--ph-delegate); }
7028
+ .insights-page .ldom.phase-discuss::before { background: var(--ph-discuss); }
7029
+ .insights-page .lmets { display: inline-flex; flex-wrap: wrap; gap: 6px; margin-left: auto; align-items: center; }
7030
+ .insights-page .lmet {
7031
+ display: inline-flex; align-items: baseline; gap: 5px; font-size: 11px; color: var(--mut);
7032
+ background: var(--ins-inner); border-radius: 6px; padding: 2px 7px; border-left: 2px solid var(--line);
7033
+ }
7034
+ .insights-page .lmet i { font-style: normal; }
7035
+ .insights-page .lmet b { color: var(--fg); font-weight: 700; font-family: var(--mono); }
7036
+ .insights-page .lmet.zero { opacity: .4; }
7037
+ .insights-page .lmet.phase-research { border-left-color: var(--ph-research); }
7038
+ .insights-page .lmet.phase-edit { border-left-color: var(--ph-edit); }
7039
+ .insights-page .lmet.phase-run { border-left-color: var(--ph-run); }
7040
+ .insights-page .lmet.phase-delegate { border-left-color: var(--ph-delegate); }
7041
+ .insights-page .lmet.phase-discuss { border-left-color: var(--ph-discuss); }
7042
+ .insights-page .lmet-bad { border-left-color: var(--bad); color: var(--bad); }
7043
+ .insights-page .lmet-bad b { color: var(--bad); }
7044
+ .insights-page .lmet-dur { border-left-color: var(--acc); }
7045
+ .insights-page .lrow.hot { border-left-width: 4px; box-shadow: 0 0 0 1px var(--acc) inset; }
7046
+
7047
+ /* enriched evidence: intent→result span rows */
7048
+ .insights-page .span-subj { font-family: var(--mono); font-size: 11px; color: var(--fg); background: var(--ins-recess); border-radius: 5px; padding: 1px 6px; }
7049
+ .insights-page .span-dur { margin-left: auto; color: var(--mut); font-size: 11px; font-family: var(--mono); flex: 0 0 auto; }
7050
+ .insights-page .span-outcome { margin-top: 4px; }
7051
+ .insights-page .span-res { display: inline-flex; align-items: center; font-size: 11px; border-radius: 999px; padding: 1px 8px; border: 1px solid var(--line); }
7052
+ .insights-page .span-res.rc-bad { color: var(--bad); border-color: var(--bad); background: var(--danger-soft); }
7053
+ /* evidence groups (失败/慢/返工) */
7054
+ .insights-page .evidence { display: grid; gap: 12px; }
7055
+ .insights-page .evgroup { display: grid; gap: 6px; }
7056
+ .insights-page .evgroup-head { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--fg); }
7057
+ .insights-page .evgroup-head b { font-weight: 700; }
7058
+ .insights-page .evgroup-head span { color: var(--mut); background: var(--ins-inner); border-radius: 999px; padding: 0 8px; font-size: 11px; }
7059
+ .insights-page .evgroup-failure .evgroup-head b { color: var(--bad); }
7060
+ .insights-page .evgroup-slow .evgroup-head b { color: var(--warn); }
7061
+ .insights-page .ev-timeline > summary { cursor: pointer; user-select: none; color: var(--mut); font-size: 12px; padding: 4px 0; list-style-position: inside; }
7062
+ .insights-page .ev-timeline > summary:hover { color: var(--fg); }
7063
+ .insights-page .ev-timeline[open] { display: grid; gap: 5px; margin-top: 2px; }
7064
+ /* 轮次效率 cards */
7065
+ .insights-page .turnlist { display: grid; gap: 8px; max-height: 62vh; overflow: auto; }
7066
+ .insights-page .turncard { background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--mut); border-radius: 8px; padding: 9px 12px; }
7067
+ .insights-page .turncard.sev-bad { border-left-color: var(--bad); }
7068
+ .insights-page .turncard.sev-warn { border-left-color: var(--warn); }
7069
+ .insights-page .turncard.sev-info { border-left-color: var(--acc); }
7070
+ .insights-page .turncard.hot { box-shadow: 0 0 0 1px var(--acc) inset; }
7071
+ .insights-page .turncard-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
7072
+ .insights-page .turn-no { color: var(--mut); font-family: var(--mono); font-size: 12px; font-weight: 700; flex: 0 0 auto; }
7073
+ .insights-page .turn-headline { font-size: 13px; font-weight: 650; color: var(--fg); }
7074
+ .insights-page .turn-metrics { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
7075
+ .insights-page .tm { display: inline-flex; align-items: baseline; gap: 4px; font-size: 11px; color: var(--mut); background: var(--ins-inner); border-radius: 6px; padding: 2px 7px; }
7076
+ .insights-page .tm b { color: var(--fg); font-weight: 700; font-family: var(--mono); }
7077
+ .insights-page .tm.bad { color: var(--bad); }
7078
+ .insights-page .tm.bad b { color: var(--bad); }
7079
+ .insights-page .turn-ev { margin-top: 8px; }
7080
+ .insights-page .turn-ev > summary { cursor: pointer; user-select: none; color: var(--mut); font-size: 11px; border: 1px dashed var(--line); border-radius: 999px; padding: 2px 8px; width: fit-content; list-style-position: inside; }
7081
+ .insights-page .turn-ev > summary:hover { color: var(--fg); border-color: var(--acc); }
7082
+ .insights-page .turn-ev[open] .spanlist { margin-top: 6px; }
7083
+ .insights-page .turn-hidden { padding: 6px 2px 0; font-size: 11px; }
7084
+
7085
+ /* ── v3: actionable recommendations + compact evidence rows + 详情 drawer + per-turn timeline ── */
7086
+ .insights-page .rec-impact { font-size: 12px; color: var(--fg); line-height: 1.45; }
7087
+ .insights-page .rec-actions { margin: 2px 0 0; padding-left: 16px; display: grid; gap: 3px; }
7088
+ .insights-page .rec-actions li { font-size: 12px; color: var(--fg); line-height: 1.4; }
7089
+ .insights-page .rec-why { font-size: 11px; color: var(--mut); line-height: 1.4; }
7090
+
7091
+ /* compact span row: one dense flex line (.sprow-line) + optional 详情 drawer (.spandetail) */
7092
+ .insights-page .spanrow { display: block; grid-template-columns: none; padding: 0; overflow: hidden; }
7093
+ .insights-page .sprow-line { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; padding: 6px 9px; font-size: 12px; }
7094
+ .insights-page .sprow-line.clickable { cursor: pointer; }
7095
+ .insights-page .sprow-line.clickable:hover { background: var(--ins-inner); }
7096
+ .insights-page .spanrow.open > .sprow-line { background: var(--ins-inner); }
7097
+ .insights-page .sprow-line.clickable:focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }
7098
+ .insights-page .span-turn { color: var(--mut); font-family: var(--mono); font-size: 11px; font-weight: 700; flex: 0 0 auto; }
7099
+ .insights-page .span-what { color: var(--fg); font-weight: 600; flex: 0 0 auto; }
7100
+ .insights-page .span-tags { display: inline-flex; gap: 4px; flex-wrap: wrap; }
7101
+ .insights-page .span-tag { font-size: 10px; color: var(--mut); background: var(--ins-inner); border: 1px solid var(--line); border-radius: 999px; padding: 0 7px; }
7102
+ .insights-page .span-tag.tg-failure { color: var(--bad); border-color: var(--bad); }
7103
+ .insights-page .span-tag.tg-slow { color: var(--warn); border-color: var(--warn); }
7104
+ .insights-page .span-tag.tg-retry { color: var(--ph-delegate); border-color: var(--ph-delegate); }
7105
+ .insights-page .span-detail-btn {
7106
+ flex: 0 0 auto; cursor: pointer; font: inherit; font-size: 11px; color: var(--mut);
7107
+ background: var(--bg); border: 1px solid var(--line); border-radius: 999px; padding: 1px 10px;
7108
+ }
7109
+ .insights-page .span-detail-btn:hover { color: var(--fg); border-color: var(--acc); }
7110
+ .insights-page .spanrow.open .span-detail-btn { color: var(--acc); border-color: var(--acc); }
7111
+
7112
+ .insights-page .spandetail { border-top: 1px dashed var(--line); background: var(--ins-recess); padding: 9px 11px; display: grid; gap: 9px; }
7113
+ .insights-page .span-kv { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 7px 14px; margin: 0; }
7114
+ .insights-page .span-kv > div { display: grid; gap: 1px; min-width: 0; }
7115
+ .insights-page .span-kv dt { color: var(--mut); font-size: 10px; text-transform: uppercase; letter-spacing: .04em; }
7116
+ .insights-page .span-kv dd { margin: 0; color: var(--fg); font-size: 12px; font-family: var(--mono); overflow-wrap: anywhere; }
7117
+ .insights-page .span-flank { display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 11px; color: var(--mut); font-family: var(--mono); }
7118
+ .insights-page .span-ctx { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
7119
+ .insights-page .span-ctx-label { font-size: 10px; color: var(--mut); text-transform: uppercase; letter-spacing: .04em; flex: 0 0 auto; }
7120
+
7121
+ /* operation strip — phase-coloured timeline glyphs (shared by drawer + per-turn rows) */
7122
+ .insights-page .opstrip { display: inline-flex; gap: 3px; flex-wrap: wrap; align-items: center; }
7123
+ .insights-page .op { width: 9px; height: 9px; border-radius: 2px; background: var(--ph-discuss); position: relative; opacity: .9; }
7124
+ .insights-page .op.ph-research { background: var(--ph-research); }
7125
+ .insights-page .op.ph-edit { background: var(--ph-edit); }
7126
+ .insights-page .op.ph-run { background: var(--ph-run); }
7127
+ .insights-page .op.ph-delegate { background: var(--ph-delegate); }
7128
+ .insights-page .op.ph-discuss { background: var(--ph-discuss); }
7129
+ .insights-page .op.bad { outline: 1.5px solid var(--bad); outline-offset: 1px; }
7130
+ .insights-page .op.cur { outline: 2px solid var(--acc); outline-offset: 1px; transform: scale(1.2); z-index: 1; }
7131
+
7132
+ /* 动作 span — filter chips + table */
7133
+ .insights-page .spanfilter { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
7134
+ .insights-page .spanchip {
7135
+ cursor: pointer; font: inherit; font-size: 12px; color: var(--mut);
7136
+ background: var(--ins-inner); border: 1px solid var(--line); border-radius: 999px; padding: 3px 11px;
7137
+ }
7138
+ .insights-page .spanchip b { color: var(--fg); font-family: var(--mono); margin-left: 4px; }
7139
+ .insights-page .spanchip:hover { color: var(--fg); border-color: var(--acc); }
7140
+ .insights-page .spanchip.on { color: var(--fg); border-color: var(--acc); background: var(--accent-soft); }
7141
+ .insights-page .spanchip.tg-failure.on { border-color: var(--bad); color: var(--bad); }
7142
+ .insights-page .spanchip.tg-slow.on { border-color: var(--warn); color: var(--warn); }
7143
+ /* block (not grid): grid items with overflow:hidden collapse their auto-row to the border height */
7144
+ .insights-page .spantable { display: block; max-height: 60vh; overflow: auto; padding-right: 2px; }
7145
+ .insights-page .spantable > .spanrow { margin-bottom: 5px; }
7146
+ .insights-page .spantable > .spanrow:last-child { margin-bottom: 0; }
7147
+
7148
+ /* 逐轮对账 — per-turn timeline (all turns; normal collapsed, flagged severity-coloured) */
7149
+ /* block (not grid): grid items with overflow:hidden collapse their auto-row to the border height */
7150
+ .insights-page .turnlist { display: block; max-height: 62vh; overflow: auto; padding-right: 2px; }
7151
+ .insights-page .turnlist > .turnrow { margin-bottom: 8px; }
7152
+ .insights-page .turnlist > .turnrow:last-child { margin-bottom: 0; }
7153
+ .insights-page .turn-sum { padding: 0 2px 4px; font-size: 11px; }
7154
+ /* 会话轨迹 turn-rail */
7155
+ .insights-page .turnrail-block { background: var(--ins-inner); }
7156
+ .insights-page .turnrail-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
7157
+ .insights-page .turnrail-legend { display: flex; gap: 11px; flex-wrap: wrap; font-size: 11px; color: var(--mut); }
7158
+ .insights-page .rl-item { display: inline-flex; align-items: center; gap: 4px; }
7159
+ .insights-page .rl-item i { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
7160
+ .insights-page .turnrail { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 10px; }
7161
+ /* filled phase-color nodes on a serial main line (mirrors reference design) */
7162
+ .insights-page .railnode { position: relative; min-width: 27px; height: 27px; padding: 0 7px; border: none; border-radius: 7px; background: var(--ph-discuss); color: #fff; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: transform .1s ease, box-shadow .1s ease; }
7163
+ .insights-page .railnode > span { text-shadow: 0 1px 2px rgba(0, 0, 0, .35); }
7164
+ .insights-page .railnode:hover { transform: translateY(-2px); box-shadow: 0 3px 10px rgba(0, 0, 0, .3); }
7165
+ .insights-page .railnode.phase-research { background: var(--ph-research); }
7166
+ .insights-page .railnode.phase-edit { background: var(--ph-edit); }
7167
+ .insights-page .railnode.phase-run { background: var(--ph-run); }
7168
+ .insights-page .railnode.phase-delegate { background: var(--ph-delegate); }
7169
+ .insights-page .railnode.phase-discuss { background: var(--ph-discuss); }
7170
+ .insights-page .railnode.phase-unknown { background: var(--ph-unknown); }
7171
+ .insights-page .railnode.hot { outline: 2px solid var(--acc); outline-offset: 1px; }
7172
+ .insights-page .railnode.dim { opacity: .3; }
7173
+ .insights-page .railnode .rb { position: absolute; width: 7px; height: 7px; border-radius: 50%; border: 1px solid var(--ins-inner); }
7174
+ .insights-page .railnode .rb-fail { top: -3px; right: -3px; background: var(--bad); }
7175
+ .insights-page .railnode .rb-slow { bottom: -3px; right: -3px; background: var(--warn); }
7176
+ .insights-page .railnode .rb-rec { top: -3px; left: -3px; background: var(--acc); }
7177
+ /* 委派分支 — subagent branch dots between main-line nodes */
7178
+ .insights-page .railbranch { display: inline-flex; align-items: center; gap: 2px; padding: 0 2px; }
7179
+ .insights-page .rbr-sub { width: 6px; height: 6px; border-radius: 50%; background: #2bb6c4; display: inline-block; }
7180
+ .insights-page .rl-sep { border-left: 1px solid var(--line); padding-left: 11px; }
7181
+ /* 工作时序 Gantt */
7182
+ .insights-page .gantt-block { background: var(--ins-inner); }
7183
+ .insights-page .gantt-cap { font-size: 11px; color: var(--mut); font-variant-numeric: tabular-nums; }
7184
+ .insights-page .gantt { margin-top: 10px; }
7185
+ .insights-page .gtrack { position: relative; height: 34px; background: var(--ins-recess); border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
7186
+ .insights-page .gbar { position: absolute; top: 5px; height: 24px; min-width: 2px; padding: 0; border: none; border-radius: 2px; background: var(--ph-discuss); opacity: .8; cursor: pointer; }
7187
+ .insights-page .gbar:hover { opacity: 1; box-shadow: 0 0 0 1px var(--fg); z-index: 2; }
7188
+ .insights-page .gbar.phase-research { background: var(--ph-research); }
7189
+ .insights-page .gbar.phase-edit { background: var(--ph-edit); }
7190
+ .insights-page .gbar.phase-run { background: var(--ph-run); }
7191
+ .insights-page .gbar.phase-delegate { background: var(--ph-delegate); }
7192
+ .insights-page .gbar.phase-discuss { background: var(--ph-discuss); }
7193
+ .insights-page .gbar.phase-unknown { background: var(--ph-unknown); }
7194
+ .insights-page .gbar.gbar-slow { top: 1px; height: 32px; }
7195
+ .insights-page .gbar.gbar-fail { background: var(--bad); box-shadow: 0 0 0 1px var(--bad); opacity: 1; }
7196
+ /* 上下文曲线 context curve */
7197
+ .insights-page .ctxcurve-block { background: var(--ins-inner); }
7198
+ .insights-page .ctxchart { display: flex; gap: 8px; margin-top: 10px; }
7199
+ .insights-page .ctxyaxis { display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end; width: 52px; padding-bottom: 16px; font-size: 10px; color: var(--mut); font-variant-numeric: tabular-nums; }
7200
+ .insights-page .ctxplot { flex: 1; min-width: 0; }
7201
+ .insights-page .ctxcurve { display: block; width: 100%; height: 72px; background: var(--ins-recess); border: 1px solid var(--line); border-radius: 6px; }
7202
+ .insights-page .ctxline { fill: none; stroke: var(--acc); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
7203
+ .insights-page .ctxarea { fill: var(--accent-soft); opacity: .4; stroke: none; }
7204
+ .insights-page .ctxhit { fill: transparent; cursor: crosshair; }
7205
+ .insights-page .ctxhit:hover { fill: var(--acc); opacity: .12; }
7206
+ .insights-page .ctxxaxis { display: flex; justify-content: space-between; margin-top: 3px; font-size: 10px; color: var(--mut); font-variant-numeric: tabular-nums; }
7207
+ /* shared hover tooltip for rail / gantt / context curve */
7208
+ .insights-page .ins-tip { position: fixed; z-index: 1200; pointer-events: none; max-width: 340px; padding: 5px 9px; font-size: 11px; line-height: 1.5; color: var(--fg); background: var(--panel); border: 1px solid var(--line); border-radius: 6px; box-shadow: 0 4px 16px rgba(0, 0, 0, .32); font-variant-numeric: tabular-nums; white-space: nowrap; }
7209
+ .insights-page .ins-tip[hidden] { display: none; }
7210
+ .insights-page .turnrow { background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--ph-discuss); border-radius: 8px; overflow: hidden; }
7211
+ .insights-page .turnrow.sev-bad { border-left-color: var(--bad); }
7212
+ .insights-page .turnrow.sev-warn { border-left-color: var(--warn); }
7213
+ .insights-page .turnrow.sev-info { border-left-color: var(--line); }
7214
+ .insights-page .turnrow.flagged { background: var(--ins-inner); }
7215
+ .insights-page .turnrow.hot { box-shadow: 0 0 0 1px var(--acc) inset; }
7216
+ .insights-page .turnline { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; padding: 8px 11px; }
7217
+ .insights-page .turnrow .turn-headline { font-size: 12px; }
7218
+ .insights-page .turnrow.sev-info .turn-headline { color: var(--mut); font-weight: 500; }
7219
+ .insights-page .turn-strip { flex: 1 1 120px; }
7220
+ .insights-page .turn-mini { font-size: 11px; color: var(--mut); font-family: var(--mono); flex: 0 0 auto; }
7221
+ .insights-page .turn-expand-btn {
7222
+ flex: 0 0 auto; cursor: pointer; font: inherit; font-size: 11px; color: var(--mut);
7223
+ background: var(--bg); border: 1px solid var(--line); border-radius: 999px; padding: 1px 10px;
7224
+ }
7225
+ .insights-page .turn-expand-btn:hover { color: var(--fg); border-color: var(--acc); }
7226
+ .insights-page .turnrow.open .turn-expand-btn { color: var(--acc); border-color: var(--acc); }
7227
+ .insights-page .turn-prompt { display: flex; gap: 8px; padding: 0 11px 8px; font-size: 12px; align-items: flex-start; }
7228
+ .insights-page .tp-label { flex: 0 0 auto; font-size: 10px; color: var(--mut); text-transform: uppercase; letter-spacing: .04em; border: 1px solid var(--line); border-radius: 999px; padding: 0 7px; margin-top: 2px; }
7229
+ /* prompt source attribution chip (人 / bot / a2a) — replaces the generic 用户 chip when known */
7230
+ .insights-page .tp-src { display: inline-flex; align-items: center; gap: 3px; max-width: 16em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-transform: none; letter-spacing: 0; }
7231
+ .insights-page .tp-src-bot { border-color: var(--ph-delegate); color: var(--ph-delegate); }
7232
+ .insights-page .tp-src-a2a { border-color: var(--acc); color: var(--acc); }
7233
+ .insights-page .tp-src-system { border-color: var(--line); color: var(--mut); opacity: .85; }
7234
+ .insights-page .tp-mentions { font-size: 10px; color: var(--mut); align-self: center; }
7235
+ /* 系统 sender filter chip is a muted opt-in (codex: system 默认弱化) */
7236
+ .insights-page .spanchip-sys { color: var(--mut); opacity: .8; }
7237
+ .insights-page .spanchip-sys.on { opacity: 1; }
7238
+
7239
+ /* full-text prompt modal (老滕: 弹窗看全文) — fixed overlay + centred reading panel */
7240
+ .insights-page .insight-modal { position: fixed; inset: 0; z-index: 1000; }
7241
+ .insights-page .insight-modal[hidden] { display: none; }
7242
+ .insights-page .modal-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .55); }
7243
+ .insights-page .modal-panel { position: relative; margin: 6vh auto 0; width: min(760px, calc(100% - 32px)); max-height: 84vh; display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 24px 64px rgba(0, 0, 0, .45); overflow: hidden; animation: insight-fade-up .18s ease both; }
7244
+ .insights-page .modal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 11px 14px; border-bottom: 1px solid var(--line); flex: 0 0 auto; }
7245
+ .insights-page .modal-who { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
7246
+ .insights-page .modal-turnno { font-family: var(--mono); font-size: 11px; color: var(--mut); }
7247
+ .insights-page .modal-acts { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
7248
+ .insights-page .modal-close { cursor: pointer; font-size: 20px; line-height: 1; color: var(--mut); background: none; border: none; padding: 0 2px; }
7249
+ .insights-page .modal-close:hover { color: var(--fg); }
7250
+ .insights-page .modal-body { padding: 14px 16px; overflow: auto; }
7251
+ .insights-page .modal-md { font-size: 13px; }
7252
+ .insights-page .modal-raw { font-size: 12px; max-height: none; }
7253
+ .insights-page .modal-trunc { margin: 10px 0 0; font-size: 11px; }
7254
+
7255
+ /* 对话回放 (conversation replay) — Feishu-style chat bubbles + load-more */
7256
+ .insights-page .convo { display: flex; flex-direction: column; gap: 10px; }
7257
+ .insights-page .convo-controls { display: flex; flex-direction: column; gap: 8px; }
7258
+ .insights-page .convo-search { width: 100%; padding: 7px 11px; background: var(--ins-inner); border: 1px solid var(--line); border-radius: 8px; color: var(--fg); font: inherit; font-size: 13px; }
7259
+ .insights-page .convo-search:focus { outline: none; border-color: var(--acc); }
7260
+ .insights-page .convo-filters { display: flex; flex-wrap: wrap; gap: 6px 16px; }
7261
+ .insights-page .convo-filters .spanfilter { margin-bottom: 0; align-items: center; }
7262
+ .insights-page .convo-flabel { font-size: 11px; color: var(--mut); margin-right: 2px; align-self: center; }
7263
+ .insights-page .convothread { display: flex; flex-direction: column; gap: 10px; max-height: 64vh; overflow: auto; padding: 4px 2px; }
7264
+ .insights-page .cbub { max-width: 82%; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); padding: 8px 11px; display: flex; flex-direction: column; gap: 5px; }
7265
+ .insights-page .cbub-left { align-self: flex-start; border-top-left-radius: 3px; }
7266
+ .insights-page .cbub-right { align-self: flex-end; border-top-right-radius: 3px; background: var(--accent-soft); border-color: var(--acc); }
7267
+ .insights-page .cbub.sev-bad { border-left: 3px solid var(--bad); }
7268
+ .insights-page .cbub.sev-warn { border-left: 3px solid var(--warn); }
7269
+ .insights-page .cbub-head { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
7270
+ .insights-page .cbub-turn { font-family: var(--mono); font-size: 10px; color: var(--mut); }
7271
+ .insights-page .cbub-opcount { font-size: 10px; color: var(--mut); }
7272
+ .insights-page .cbub-rec { font-size: 10px; color: var(--warn); border: 1px solid var(--warn); border-radius: 999px; padding: 0 6px; max-width: 14em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
7273
+ .insights-page .cbub-body { font-size: 13px; min-width: 0; }
7274
+ .insights-page .cbub-body .md-body { font-size: 13px; }
7275
+ .insights-page .cbub-foot { display: flex; justify-content: flex-end; }
7276
+ .insights-page .cbub-ops { background: var(--ins-recess); max-width: 88%; }
7277
+ .insights-page .cbub-ops-list { display: flex; flex-direction: column; gap: 3px; }
7278
+ .insights-page .cop-line { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; font-size: 12px; padding: 3px 5px; border-radius: 6px; }
7279
+ .insights-page .cop-line.clickable { cursor: pointer; }
7280
+ .insights-page .cop-line.clickable:hover { background: var(--ins-inner); }
7281
+ .insights-page .cop.open > .cop-line { background: var(--ins-inner); }
7282
+ .insights-page .cop.bad .span-what { color: var(--bad); }
7283
+ .insights-page .cop .spandetail { border: 1px solid var(--line); border-radius: 6px; margin-top: 3px; }
7284
+ .insights-page .convo-more { display: flex; justify-content: center; padding: 6px 0 2px; }
7285
+ .insights-page p.convo-more { font-size: 11px; }
7286
+ .insights-page .convo-loadmore { font-size: 12px; padding: 5px 16px; }
7287
+
7288
+ /* 文件改动 + 跑过的命令 — work-summary panels at the top of 动作 span */
7289
+ .insights-page .worksum { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 12px; }
7290
+ .insights-page .ws-panel { border: 1px solid var(--line); border-radius: 8px; background: var(--ins-recess); padding: 9px 11px; min-width: 0; }
7291
+ .insights-page .ws-panel h4 { margin: 0 0 7px; font-size: 12px; color: var(--mut); font-weight: 650; }
7292
+ .insights-page .ws-list { display: flex; flex-direction: column; gap: 2px; max-height: 240px; overflow: auto; }
7293
+ .insights-page .ws-row { display: flex; align-items: center; gap: 8px; padding: 2px 0; }
7294
+ .insights-page .ws-path, .insights-page .ws-cmd { font-family: var(--mono); font-size: 11px; color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1 1 auto; min-width: 0; }
7295
+ .insights-page .ws-path { direction: rtl; text-align: left; }
7296
+ .insights-page .ws-row.bad .ws-cmd { color: var(--bad); }
7297
+ .insights-page .ws-meta { flex: 0 0 auto; display: inline-flex; gap: 6px; align-items: center; color: var(--mut); font-size: 10.5px; font-family: var(--mono); }
7298
+ .insights-page .ws-stat { flex: 0 0 auto; display: inline-flex; gap: 7px; align-items: baseline; font-family: var(--mono); font-size: 11px; font-weight: 650; font-variant-numeric: tabular-nums; }
7299
+ .insights-page .ws-stat-edits { color: var(--mut); font-weight: 500; }
7300
+ .insights-page .ws-add { color: var(--success); }
7301
+ .insights-page .ws-del { color: var(--danger); }
7302
+ .insights-page .ws-x { color: var(--mut); }
7303
+ .insights-page .ws-fail { color: var(--bad); }
7304
+ @media (max-width: 760px) { .insights-page .worksum { grid-template-columns: 1fr; } }
7305
+ /* prompt 原文: markdown-rendered by default, clamped (展开 lifts the clamp, 原文 shows raw) */
7306
+ .insights-page .tp-body { flex: 1 1 auto; min-width: 0; display: grid; gap: 4px; }
7307
+ .insights-page .tp-md { max-height: 7.5em; overflow: auto; }
7308
+ .insights-page .tp-md.expanded { max-height: 60vh; }
7309
+ .insights-page .tp-actions { display: flex; gap: 6px; }
7310
+ .insights-page .tp-toggle { cursor: pointer; font: inherit; font-size: 10px; color: var(--mut); background: none; border: 1px solid var(--line); border-radius: 999px; padding: 0 8px; }
7311
+ .insights-page .tp-toggle:hover { color: var(--fg); border-color: var(--acc); }
7312
+ .insights-page .tp-raw { margin: 0; font-family: var(--mono); font-size: 11px; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--fg); }
7313
+ /* markdown body — compact, scoped to .insights-page, dashboard tokens only (no new palette) */
7314
+ .insights-page .md-body { color: var(--fg); line-height: 1.55; overflow-wrap: anywhere; }
7315
+ .insights-page .md-body > :first-child { margin-top: 0; }
7316
+ .insights-page .md-body > :last-child { margin-bottom: 0; }
7317
+ .insights-page .md-body p { margin: 4px 0; }
7318
+ .insights-page .md-body h1, .insights-page .md-body h2, .insights-page .md-body h3,
7319
+ .insights-page .md-body h4, .insights-page .md-body h5, .insights-page .md-body h6 { margin: 7px 0 3px; font-size: 12.5px; font-weight: 700; line-height: 1.3; }
7320
+ .insights-page .md-body ul, .insights-page .md-body ol { margin: 4px 0; padding-left: 18px; }
7321
+ .insights-page .md-body li { margin: 1px 0; }
7322
+ .insights-page .md-body blockquote { margin: 5px 0; padding: 2px 10px; border-left: 3px solid var(--line); color: var(--mut); }
7323
+ .insights-page .md-body a { color: var(--acc); text-decoration: underline; }
7324
+ .insights-page .md-body code { font-family: var(--mono); font-size: 11px; background: var(--ins-inner); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; }
7325
+ .insights-page .md-body pre { margin: 5px 0; background: var(--ins-inner); border: 1px solid var(--line); border-radius: 6px; padding: 7px 9px; overflow-x: auto; }
7326
+ .insights-page .md-body pre code { background: none; border: none; padding: 0; font-size: 11px; line-height: 1.5; white-space: pre; }
7327
+ .insights-page .md-body table { border-collapse: collapse; margin: 5px 0; font-size: 11px; display: block; overflow-x: auto; }
7328
+ .insights-page .md-body th, .insights-page .md-body td { border: 1px solid var(--line); padding: 3px 8px; text-align: left; }
7329
+ .insights-page .md-body th { background: var(--ins-inner); }
7330
+ .insights-page .md-body img { max-width: 100%; height: auto; }
7331
+ .insights-page .md-body hr { border: none; border-top: 1px solid var(--line); margin: 7px 0; }
7332
+ .insights-page .turn-advice { padding: 0 11px 8px; font-size: 12px; color: var(--warn); line-height: 1.45; }
7333
+ .insights-page .turnrow.sev-bad .turn-advice { color: var(--bad); }
7334
+ .insights-page .turn-detail { border-top: 1px dashed var(--line); background: var(--ins-recess); padding: 9px 11px; display: grid; gap: 8px; }
7335
+ .insights-page .turn-detail .turn-metrics { margin-top: 0; }
7336
+
7337
+ /* raw command/output preview inside a 详情 drawer (owner-only, run-class spans) */
7338
+ .insights-page .span-io { display: grid; gap: 3px; }
7339
+ .insights-page .span-io-label { font-size: 10px; color: var(--mut); text-transform: uppercase; letter-spacing: .04em; }
7340
+ .insights-page .span-io-text {
7341
+ margin: 0; font-family: var(--mono); font-size: 11.5px; line-height: 1.5; color: var(--fg);
7342
+ background: var(--ins-inner); border: 1px solid var(--line); border-radius: 6px; padding: 7px 9px;
7343
+ max-height: 220px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere;
7344
+ }
7345
+
7346
+ /* 逐轮对账 grouped-by-recommendation mode: section header + turns beneath it */
7347
+ .insights-page .ledgersort { margin-bottom: 10px; }
7348
+ .insights-page .turn-group { margin-bottom: 16px; }
7349
+ .insights-page .turn-group:last-child { margin-bottom: 0; }
7350
+ .insights-page .turn-group > .turnrow { margin-bottom: 8px; }
7351
+ .insights-page .turn-group > .turnrow:last-child { margin-bottom: 0; }
7352
+ .insights-page .turn-group-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 0 2px 7px; margin-bottom: 8px; border-bottom: 1px solid var(--line); }
7353
+ .insights-page .turn-group-head b { font-size: 12px; color: var(--fg); }
7354
+ .insights-page .turn-group-head span { font-size: 11px; color: var(--mut); font-family: var(--mono); flex: 0 0 auto; }
7355
+ .insights-page .turn-group-head.sev-bad b { color: var(--bad); }
7356
+ .insights-page .turn-group-head.sev-warn b { color: var(--warn); }
7357
+
7358
+ /* motion: staggered page-load reveal + grow failure bars */
7359
+ @keyframes insight-fade-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
7360
+ @keyframes insight-bar-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
7361
+ .insights-page .insights-metrics { animation: insight-fade-up .35s ease both; }
7362
+ .insights-page .insights-overview-grid { animation: insight-fade-up .35s ease both; animation-delay: .05s; }
7363
+ .insights-page .insight-workbench { animation: insight-fade-up .35s ease both; animation-delay: .1s; }
7364
+ @media (prefers-reduced-motion: reduce) {
7365
+ .insights-page .insights-metrics,
7366
+ .insights-page .insights-overview-grid,
7367
+ .insights-page .insight-workbench,
7368
+ .insights-page .hbfill { animation: none; }
7369
+ .insights-page .srow { transition: none; }
7370
+ .insights-page .srow:hover { transform: none; }
7371
+ }