@worca/app 1.3.0 → 1.4.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +85 -6
  2. package/agents/clarify.meta.json +1 -0
  3. package/agents/memoryDefragmenter.meta.json +2 -1
  4. package/agents/reviewer.meta.json +60 -0
  5. package/agents/worca-cc-code-reviewer.md +33 -0
  6. package/agents/worca-cc-memory-defragmenter.md +5 -3
  7. package/agents/workspaceScanner.meta.json +1 -0
  8. package/package.json +14 -10
  9. package/scripts/git-diff.mjs +25 -0
  10. package/scripts/gitDiff.meta.json +18 -0
  11. package/scripts/js-inline.mjs +11 -0
  12. package/scripts/js.meta.json +22 -0
  13. package/scripts/py-inline.py +27 -0
  14. package/scripts/py.meta.json +22 -0
  15. package/scripts/shell.meta.json +24 -0
  16. package/skills/worca/SKILL.md +3 -2
  17. package/src/cli/models.mjs +247 -0
  18. package/src/cli/render.mjs +72 -4
  19. package/src/cli/schedule.mjs +494 -0
  20. package/src/cli/worca-cc.mjs +1001 -22
  21. package/src/core/agent-registry.mjs +75 -23
  22. package/src/core/agent-store.mjs +51 -2
  23. package/src/core/artifacts.mjs +73 -10
  24. package/src/core/ask/events.mjs +119 -1
  25. package/src/core/ask/limits.mjs +32 -4
  26. package/src/core/ask/mcp-stdio.mjs +12 -0
  27. package/src/core/ask/model-deps.mjs +126 -0
  28. package/src/core/ask/model-proposal.mjs +370 -0
  29. package/src/core/ask/models.mjs +12 -0
  30. package/src/core/ask/policy-deps.mjs +124 -0
  31. package/src/core/ask/policy-proposal.mjs +363 -0
  32. package/src/core/ask/prompt.mjs +74 -9
  33. package/src/core/ask/proposal.mjs +54 -5
  34. package/src/core/ask/schedule-deps.mjs +83 -0
  35. package/src/core/ask/schedule-spec.mjs +310 -0
  36. package/src/core/ask/script-deps.mjs +357 -0
  37. package/src/core/ask/source-deps.mjs +52 -0
  38. package/src/core/ask/source-spec.mjs +157 -0
  39. package/src/core/ask/spawn.mjs +1 -0
  40. package/src/core/ask/store.mjs +6 -3
  41. package/src/core/ask/tool-deps.mjs +4 -0
  42. package/src/core/ask/tools.mjs +657 -37
  43. package/src/core/ask/turn.mjs +109 -2
  44. package/src/core/ask-files.mjs +406 -0
  45. package/src/core/ask-forms.mjs +195 -0
  46. package/src/core/ask-projection.mjs +72 -0
  47. package/src/core/bridge/errors.mjs +84 -0
  48. package/src/core/bridge/provider-ops.mjs +281 -0
  49. package/src/core/bridge/providers/copilot.mjs +269 -0
  50. package/src/core/bridge/providers/endpoint.mjs +257 -0
  51. package/src/core/bridge/registry.mjs +88 -0
  52. package/src/core/bridge/semaphore.mjs +73 -0
  53. package/src/core/bridge/server.mjs +184 -0
  54. package/src/core/bridge/telemetry.mjs +53 -0
  55. package/src/core/bridge/translate/request.mjs +252 -0
  56. package/src/core/bridge/translate/response.mjs +82 -0
  57. package/src/core/bridge/translate/stream.mjs +242 -0
  58. package/src/core/bridge/upstream.mjs +209 -0
  59. package/src/core/chat/command-router.mjs +58 -4
  60. package/src/core/chat/notifier.mjs +14 -1
  61. package/src/core/chat/renderers.mjs +35 -0
  62. package/src/core/claude-runner.mjs +126 -19
  63. package/src/core/config.mjs +212 -31
  64. package/src/core/cost-budget.mjs +3 -2
  65. package/src/core/db.mjs +169 -15
  66. package/src/core/failure-policy.mjs +10 -0
  67. package/src/core/fs-browse.mjs +16 -4
  68. package/src/core/git-info.mjs +22 -0
  69. package/src/core/graph/builtin-workflows.mjs +3 -1
  70. package/src/core/graph/exec-io.mjs +71 -0
  71. package/src/core/graph/executor.mjs +139 -70
  72. package/src/core/graph/human-evidence.mjs +131 -0
  73. package/src/core/graph/python-probe.mjs +172 -0
  74. package/src/core/graph/registry-ports.mjs +10 -6
  75. package/src/core/graph/scheduler.mjs +39 -24
  76. package/src/core/graph/script-child.mjs +81 -0
  77. package/src/core/graph/script-runner.mjs +597 -0
  78. package/src/core/graph/worca_script.py +207 -0
  79. package/src/core/guardrail-store.mjs +16 -0
  80. package/src/core/human-backfill.mjs +108 -0
  81. package/src/core/human-rate.mjs +17 -0
  82. package/src/core/index-html.mjs +6 -2
  83. package/src/core/memory-defrag-model.mjs +112 -0
  84. package/src/core/memory-store.mjs +70 -18
  85. package/src/core/memory-sync.mjs +22 -11
  86. package/src/core/metrics/read.mjs +4 -1
  87. package/src/core/metrics/record.mjs +50 -2
  88. package/src/core/metrics/sync.mjs +6 -4
  89. package/src/core/model-env.mjs +149 -0
  90. package/src/core/model-test.mjs +14 -1
  91. package/src/core/notifications.mjs +128 -0
  92. package/src/core/onboarding.mjs +8 -2
  93. package/src/core/orchestrator.mjs +357 -26
  94. package/src/core/phases.mjs +95 -6
  95. package/src/core/plugin-api.mjs +24 -7
  96. package/src/core/plugin-manifest.mjs +184 -18
  97. package/src/core/plugin-models.mjs +1 -0
  98. package/src/core/plugin-script-cases.mjs +118 -0
  99. package/src/core/plugin-store.mjs +163 -17
  100. package/src/core/plugin-workflows.mjs +71 -17
  101. package/src/core/policy/cache.mjs +116 -0
  102. package/src/core/policy/effective.mjs +175 -0
  103. package/src/core/policy/gate.mjs +91 -0
  104. package/src/core/policy/local.mjs +145 -0
  105. package/src/core/policy/registry.mjs +330 -0
  106. package/src/core/policy/scope.mjs +61 -0
  107. package/src/core/policy/state.mjs +79 -0
  108. package/src/core/policy/sync.mjs +513 -0
  109. package/src/core/protocol.mjs +43 -0
  110. package/src/core/run-harness.mjs +421 -72
  111. package/src/core/scheduler.mjs +980 -0
  112. package/src/core/script-bench.mjs +628 -0
  113. package/src/core/script-registry.mjs +116 -0
  114. package/src/core/script-store.mjs +563 -0
  115. package/src/core/settings.mjs +489 -14
  116. package/src/core/stats.mjs +33 -2
  117. package/src/core/workflow-export.mjs +94 -3
  118. package/src/core/workflow-share.mjs +67 -18
  119. package/src/core/workflows.mjs +47 -11
  120. package/src/core/workspaces.mjs +18 -12
  121. package/src/shared/forms/answer.mjs +164 -0
  122. package/src/shared/forms/catalog.mjs +91 -0
  123. package/src/shared/forms/form-def.mjs +290 -0
  124. package/src/shared/forms/layout.mjs +67 -0
  125. package/src/shared/forms/paths.mjs +47 -0
  126. package/src/shared/forms/project.mjs +309 -0
  127. package/src/shared/forms/schema.mjs +205 -0
  128. package/src/shared/graph/agent-meta.mjs +55 -5
  129. package/src/shared/graph/constants.mjs +14 -2
  130. package/src/shared/graph/flow-layout.mjs +2 -1
  131. package/src/shared/graph/isomorphic.mjs +5 -3
  132. package/src/shared/graph/manifest.mjs +22 -13
  133. package/src/shared/graph/ports.mjs +45 -19
  134. package/src/shared/graph/script-cases.mjs +257 -0
  135. package/src/shared/graph/script-icons.mjs +46 -0
  136. package/src/shared/graph/script-infer.mjs +259 -0
  137. package/src/shared/graph/script-meta.mjs +408 -0
  138. package/src/shared/graph/script-templates.mjs +201 -0
  139. package/src/shared/graph/template.mjs +4 -4
  140. package/src/shared/graph/validate.mjs +89 -16
  141. package/src/shared/human-estimate.mjs +100 -0
  142. package/src/shared/schedule/recurrence.mjs +353 -0
  143. package/src/shared/team-metrics/aggregate.mjs +51 -11
  144. package/{scripts → tools}/install.mjs +3 -3
  145. package/ui/public/app.js +4390 -683
  146. package/ui/public/artifact-picker.mjs +189 -0
  147. package/ui/public/ask/dom.mjs +121 -0
  148. package/ui/public/ask/form-preview.mjs +55 -0
  149. package/ui/public/ask/form-renderer.mjs +250 -0
  150. package/ui/public/ask/registry.mjs +53 -0
  151. package/ui/public/ask/widgets-display.mjs +370 -0
  152. package/ui/public/ask/widgets-input.mjs +624 -0
  153. package/ui/public/ask/widgets-layout.mjs +90 -0
  154. package/ui/public/ask-panel.mjs +401 -27
  155. package/ui/public/ask-run-card.mjs +1 -1
  156. package/ui/public/bridge-view.mjs +694 -0
  157. package/ui/public/chat-settings-view.mjs +24 -0
  158. package/ui/public/code-editor.mjs +181 -0
  159. package/ui/public/getting-started.mjs +34 -7
  160. package/ui/public/graph/composer.mjs +138 -10
  161. package/ui/public/graph/inspector.mjs +61 -58
  162. package/ui/public/graph/palette.mjs +27 -9
  163. package/ui/public/graph/run-decor.mjs +34 -17
  164. package/ui/public/graph/run-hosts.mjs +7 -1
  165. package/ui/public/graph/save-dialog.mjs +3 -0
  166. package/ui/public/graph/view.mjs +23 -7
  167. package/ui/public/guardrails-view.mjs +15 -3
  168. package/ui/public/guide-spot.mjs +87 -9
  169. package/ui/public/index.html +480 -141
  170. package/ui/public/memory-view.mjs +22 -4
  171. package/ui/public/models-view.mjs +162 -17
  172. package/ui/public/node-tunables.mjs +33 -4
  173. package/ui/public/plugins-view.mjs +23 -1
  174. package/ui/public/results-view.mjs +4 -2
  175. package/ui/public/schedule-sheet.mjs +430 -0
  176. package/ui/public/schedules-view.mjs +432 -0
  177. package/ui/public/script-bench-view.mjs +1154 -0
  178. package/ui/public/script-forms.mjs +282 -0
  179. package/ui/public/script-wizard.mjs +529 -0
  180. package/ui/public/scripts-view.mjs +868 -0
  181. package/ui/public/stats-view.mjs +159 -52
  182. package/ui/public/style.css +1461 -44
  183. package/ui/public/team-metrics-surfaces.mjs +77 -16
  184. package/ui/public/team-metrics-view.mjs +68 -5
  185. package/ui/public/team-policy-view.mjs +1402 -0
  186. package/ui/public/ui-level.mjs +237 -0
  187. package/ui/server.mjs +1827 -73
@@ -31,12 +31,20 @@
31
31
  --line-2:light-dark(#E3E3E0,#494944);
32
32
 
33
33
  --green-bg:light-dark(#E2F3DF,#1C2F1D); --green:#5BAE5B; --green-ink:light-dark(#2F7A38,#8FD48F);
34
+ --green-ink-strong:light-dark(#2C7535,#8FD48F); /* sidebar Saved figure: 4.79:1 on --line (the spend card's hover fill); --green-ink is 4.48:1 */
34
35
  --peach-bg:light-dark(#FCEEDA,#33261A); --peach:#EFA63C; --peach-ink:light-dark(#B5751A,#F2B96A);
35
36
  --red-bg:light-dark(#FBE3E0,#34201D); --red:#E76A5A; --red-ink:light-dark(#C5483A,#F08C7E);
36
37
  --blue-bg:light-dark(#DEEFF7,#1A2A33); --blue:#5BA6CC; --blue-ink:light-dark(#3782A8,#86C4E3);
37
38
  --blue-ink-strong:light-dark(#2B6A8C,#86C4E3); /* inline link text at small sizes: 5.9:1 on white (--blue-ink is 3.8:1) */
38
39
  --violet-bg:light-dark(#EAE6F8,#262336); --violet:#8C7FD6; --violet-ink:light-dark(#6353B8,#B3A8EE);
39
40
  --amber-bg:light-dark(#FCE8C8,#332715); --amber:#E6962A; --amber-ink:light-dark(#A66510,#F0B45A);
41
+ /* Script-only families (script-wizard plan S10): the same lightness as the six above, both themes. */
42
+ --teal-bg:light-dark(#DDF2EF,#1A2E2B); --teal:#4FB3A9; --teal-ink:light-dark(#2A8A80,#86D3CA);
43
+ --pink-bg:light-dark(#FBE4EE,#33202A); --pink:#E27BA8; --pink-ink:light-dark(#B84A7C,#F0A2C3);
44
+ --indigo-bg:light-dark(#E3E7F9,#232739); --indigo:#6A7FD8; --indigo-ink:light-dark(#4457B5,#A3B0EE);
45
+ --lime-bg:light-dark(#EEF4D5,#262E15); --lime:#A3BF3A; --lime-ink:light-dark(#6E8A14,#C7DB6E);
46
+ --cocoa-bg:light-dark(#F1E7DB,#2F2620); --cocoa:#B08A5E; --cocoa-ink:light-dark(#7E5D33,#D2B08A);
47
+ --slate-bg:light-dark(#E8ECF0,#262A2E); --slate:#8A96A3; --slate-ink:light-dark(#58646F,#B3BEC8);
40
48
  --seq:light-dark(#B7B7BC,#8E8E92); /* text role too (.ask-thinking-meter): 4.85:1 on panel */
41
49
 
42
50
  /* Question/ask amber wash (design §9, C3). --amber-bg is the SOLID amber; this
@@ -164,12 +172,14 @@ body{
164
172
  .nav button.active .nav-count{background:var(--on-ink-wash);color:var(--on-ink);}
165
173
  /* Running split-badges: green = work in flight, amber = paused count. Green is
166
174
  applied by app.js ONLY while the count is >0 — at zero the badge falls back to
167
- n-grey, the inert-inventory treatment History/Projects/Workspaces use, so a
175
+ n-grey, the inert-inventory treatment the Schedules count uses, so a
168
176
  permanently green pill cannot dilute the green that should catch the eye.
169
177
  Both keep their colour on the dark active fill (the generic active rule above
170
178
  would wash them into translucent white). */
171
179
  .nav-count.n-run{background:var(--green);color:var(--on-status);}
172
180
  .nav-count.n-paused{background:var(--amber);color:var(--on-status);position:relative;margin-left:6px;}
181
+ /* Schedules' unread-problems badge sits beside its grey count exactly as Running's paused badge does */
182
+ #nav-schedules-unread{margin-left:6px;}
173
183
  .nav-count[hidden]{display:none;} /* author display:grid beats the UA [hidden] rule */
174
184
  .nav button.active .nav-count.n-run{background:var(--green);color:var(--on-status);}
175
185
  .nav button.active .nav-count.n-paused{background:var(--amber);color:var(--on-status);}
@@ -236,6 +246,19 @@ body{
236
246
  -webkit-line-clamp: 3; line-clamp: 3; overflow-wrap: anywhere; }
237
247
  .nav-child.active .child-proj { color: var(--ink-3); }
238
248
 
249
+ /* Static group (Nodes › Agents, Scripts). The parent is a disclosure: it never
250
+ takes the dark current-page fill (`.active` belongs to the child page) and
251
+ reads as --ink via .has-active while a child is open. The children reuse the
252
+ Running-row elbow above, but carry an icon where a run row carries a dot;
253
+ `.nav .nav-child > svg` (0,2,1) out-ranks `.nav button svg` (0,1,2). */
254
+ .nav .nav-group.has-active { color: var(--ink); font-weight: 600; }
255
+ .nav .nav-group-chev { width: 14px; height: 14px; margin-left: auto; color: var(--ink-3); transition: transform .2s; }
256
+ .nav-group[aria-expanded="false"] .nav-group-chev { transform: rotate(-90deg); }
257
+ .nav .nav-child > svg { width: 17px; height: 17px; }
258
+ /* `.nav button.active svg` (0,2,2) paints the stroke --on-ink for the dark fill;
259
+ a child's fill is the soft --field tint, so its icon stays --ink. */
260
+ .nav .nav-child.active svg { stroke: var(--ink); }
261
+
239
262
  /* Status dot (left). Color matches the current running agent/phase
240
263
  (violet=plan, peach=refine/review/running, blue=implement, red=clarify),
241
264
  grey-pulse=starting/pausing, green=done, red=error/stopped. */
@@ -293,11 +316,13 @@ body{
293
316
  plain height:100% here would push the track past the viewport and
294
317
  overflow:hidden would clip both screens' bottoms off-screen. */
295
318
  body.view-history .main,body.view-projects .main{display:flex;flex-direction:column;overflow:hidden;padding:0;}
319
+ body.view-workspaces .main{display:flex;flex-direction:column;overflow:hidden;padding:0;} /* the Workspaces track: the same bounded column */
296
320
  /* .main's 32px gutter goes with padding:0, so the compact top-nav (<1080px, a
297
321
  SIBLING of the views inside .main) must re-apply it or it lands 20px left of
298
322
  the list content, which keeps its own 32px on .hist-screen. flex:0 0 auto
299
323
  stops the wrapped 9-button nav from being squeezed once .main is a column. */
300
324
  body.view-history .topnav,body.view-projects .topnav{margin:12px 32px 0;flex:0 0 auto;}
325
+ body.view-workspaces .topnav{margin:12px 32px 0;flex:0 0 auto;}
301
326
  .topbar{display:flex;align-items:flex-start;justify-content:space-between;
302
327
  gap:24px;margin-bottom:22px;}
303
328
  .topbar h1{font-size:26px;font-weight:700;letter-spacing:-.025em;margin:0 0 4px;}
@@ -356,6 +381,8 @@ body.view-history .topnav,body.view-projects .topnav{margin:12px 32px 0;flex:0 0
356
381
  .hint{display:block;color:var(--ink-3);font-size:12px;margin-top:7px;line-height:1.45;}
357
382
  .hint.err{color:var(--red-ink);}
358
383
  .hint.warn{color:var(--amber-ink);}
384
+ .stat-tile .stat-value.is-neg{color:var(--red-ink);}
385
+ .stat-tile .stat-value.is-pos{color:var(--green-ink);}
359
386
 
360
387
  .input,.select,.textarea,.ta-hl-back,
361
388
  input[type="text"],input[type="number"],textarea,select{
@@ -547,7 +574,8 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
547
574
  .actions{display:flex;align-items:center;justify-content:space-between;gap:14px;margin-top:22px;}
548
575
  .btn-ghost{background:var(--surface);border:1.5px solid var(--line-2);color:var(--ink);font-family:inherit;
549
576
  font-weight:600;font-size:13.5px;padding:13px 20px;border-radius:999px;cursor:pointer;transition:.15s;}
550
- .btn-ghost:hover{background:var(--field);}
577
+ .btn-ghost:hover:not(:disabled){background:var(--field);}
578
+ .btn-ghost:disabled{opacity:.45;cursor:not-allowed;} /* a waiting step must not look clickable */
551
579
  .btn-go{display:inline-flex;align-items:center;gap:9px;background:var(--ink);color:var(--on-ink);border:none;
552
580
  font-family:inherit;font-weight:600;font-size:14px;padding:14px 28px;border-radius:999px;cursor:pointer;
553
581
  transition:transform .15s,filter .15s;}
@@ -920,6 +948,231 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
920
948
  .qopen[hidden]{display:none;}
921
949
  .rd-questions .qanswered{font-size:12.5px;}
922
950
 
951
+ /* ---------- Ask forms (agent-ask-forms design §6.1) ---------- */
952
+ /* The declarative widget catalog, inside the same amber .qpanel wash. Every
953
+ colour is a token — the stylesheet's own rule, and several tests count hex
954
+ occurrences. Both themes ride the light-dark() tokens: no media query here.
955
+ Anything the renderer can hide carries an [hidden] guard, because an author
956
+ `display` beats the hidden attribute and `when` relies on it. */
957
+ .af-form{display:flex;flex-direction:column;gap:14px;margin-top:12px;}
958
+ .af-form>*{min-width:0;}
959
+ /* `when` hides an EXISTING node (el.hidden = …) so focus and half-typed text survive.
960
+ The UA [hidden] rule loses to any author display, and almost every rule below sets
961
+ one, so this blanket guard carries the whole family. Specificity (0,1,1) beats a
962
+ single-class display rule without !important — keep every display rule at ONE class
963
+ (the stylesheet test pins that). */
964
+ .af-form [hidden],.af-form[hidden]{display:none;}
965
+ .af-fld{display:flex;flex-direction:column;gap:7px;}
966
+ .af-fld[hidden]{display:none;}
967
+ .af-display{gap:8px;}
968
+ .af-label{font-weight:600;font-size:12.5px;color:var(--ink);display:flex;align-items:center;gap:5px;}
969
+ .af-req{color:var(--red-ink);font-weight:700;}
970
+ .af-help{margin:0;font-size:12px;line-height:1.45;color:var(--ink-2);}
971
+ .af-err{font-size:12px;font-weight:500;color:var(--red-ink);}
972
+ .af-err[hidden]{display:none;}
973
+ .af-fld.af-bad .af-inp,.af-fld.af-bad .af-choices{border-color:var(--red);}
974
+
975
+ /* text-ish controls */
976
+ .af-inp{width:100%;font-family:inherit;font-size:12.5px;color:var(--ink);background:var(--field);
977
+ border:1.5px solid var(--line);border-radius:11px;padding:10px 14px;transition:.14s;}
978
+ .af-inp::placeholder{color:var(--ink-3);}
979
+ .af-inp:focus{outline:none;background:var(--field-focus);border-color:var(--green);}
980
+ .af-inp:disabled{opacity:.72;cursor:default;}
981
+ .af-area{min-height:64px;resize:vertical;line-height:1.5;}
982
+ .af-date{max-width:220px;}
983
+ .af-num-row{display:flex;align-items:center;gap:9px;}
984
+ .af-num-row .af-inp{max-width:160px;}
985
+ .af-unit{font:500 12px var(--mono);color:var(--ink-3);}
986
+ .af-slider-row{display:flex;align-items:center;gap:12px;}
987
+ .af-slider-row input[type="range"]{flex:1;min-width:0;}
988
+ .af-slider-val{font:600 12.5px var(--mono);color:var(--ink);min-width:54px;text-align:right;}
989
+ .af-slider-ends{display:flex;justify-content:space-between;font-size:11.5px;color:var(--ink-3);}
990
+ .af-switch-row{display:flex;align-items:center;gap:10px;cursor:pointer;}
991
+ .af-switch-txt{font-weight:500;font-size:12.5px;color:var(--ink);}
992
+ .af-select{width:100%;}
993
+
994
+ /* choices — the .qopt idea, generalised to label + description */
995
+ .af-choices{display:flex;flex-direction:column;align-items:stretch;gap:7px;}
996
+ .af-choices.af-chips{flex-direction:row;flex-wrap:wrap;}
997
+ .af-choice{display:flex;align-items:flex-start;gap:9px;font-family:inherit;font-weight:500;font-size:12.5px;
998
+ color:var(--ink);background:var(--panel);border:1.5px solid var(--line);border-radius:11px;
999
+ padding:10px 14px;cursor:pointer;transition:.14s;text-align:left;width:100%;}
1000
+ .af-chips .af-choice{width:auto;border-radius:999px;}
1001
+ .af-choice:hover{border-color:var(--ink-3);}
1002
+ .af-choice:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
1003
+ .af-choice:disabled{cursor:default;}
1004
+ .af-choice.on{background:var(--green-bg);border-color:var(--green);}
1005
+ .af-mark{flex:0 0 auto;width:15px;height:15px;margin-top:1px;border-radius:50%;
1006
+ border:1.5px solid var(--radio-ring);background:var(--panel);display:grid;place-items:center;color:var(--panel);}
1007
+ .af-choice[role="checkbox"] .af-mark{border-radius:5px;}
1008
+ .af-choice.on .af-mark{background:var(--green);border-color:var(--green);color:var(--on-ink);}
1009
+ .af-choice-txt{display:flex;flex-direction:column;gap:3px;min-width:0;}
1010
+ .af-choice-desc{font-weight:400;font-size:11.5px;color:var(--ink-2);}
1011
+ .af-seg-sm button{font-size:12px;padding:5px 11px;}
1012
+ .af-free{margin-top:2px;}
1013
+
1014
+ /* rank */
1015
+ .af-rank{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px;}
1016
+ .af-rank li{display:flex;align-items:center;gap:11px;background:var(--panel);border:1.5px solid var(--line);
1017
+ border-radius:11px;padding:9px 12px;}
1018
+ .af-rank li.af-drag{opacity:.55;}
1019
+ .af-rank li.af-over{border-color:var(--green);}
1020
+ .af-rank-n{flex:0 0 auto;width:20px;height:20px;border-radius:50%;background:var(--ink);color:var(--on-ink);
1021
+ font:600 10.5px var(--mono);display:grid;place-items:center;}
1022
+ .af-rank-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;font-size:12.5px;color:var(--ink);}
1023
+ .af-rank-txt span{font-size:11.5px;color:var(--ink-3);}
1024
+ .af-rank-btns{display:flex;gap:4px;}
1025
+ .af-icon-btn{display:grid;place-items:center;width:28px;height:28px;border-radius:9px;cursor:pointer;
1026
+ border:1.5px solid var(--line);background:var(--panel);color:var(--ink-2);}
1027
+ .af-icon-btn:hover{border-color:var(--ink-3);color:var(--ink);}
1028
+ .af-icon-btn:disabled{opacity:.4;cursor:default;}
1029
+ .af-icon-btn:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
1030
+
1031
+ /* tables */
1032
+ .af-tbl-wrap{overflow-x:auto;border:1.5px solid var(--line);border-radius:12px;background:var(--panel);}
1033
+ .af-tbl{width:100%;border-collapse:collapse;font-size:12.5px;}
1034
+ .af-tbl th{text-align:left;font:400 10.5px var(--mono);letter-spacing:.08em;text-transform:uppercase;
1035
+ color:var(--ink-3);height:32px;padding:0 12px;border-bottom:1px solid var(--line);white-space:nowrap;}
1036
+ .af-tbl td{height:38px;padding:0 12px;border-bottom:1px solid var(--line);color:var(--ink);vertical-align:middle;}
1037
+ .af-tbl tr:last-child td{border-bottom:none;}
1038
+ .af-tbl th.af-r,.af-tbl td.af-r{text-align:right;}
1039
+ .af-tbl td.af-up{color:var(--green-ink);}
1040
+ .af-tbl td.af-down{color:var(--red-ink);}
1041
+ .af-pill{display:inline-block;padding:3px 9px;border-radius:999px;font-weight:600;font-size:11px;background:var(--field);color:var(--ink-2);}
1042
+ /* the closed tone vocabulary (dom.mjs TONES): the four status families, tokens only */
1043
+ .af-pill[data-tone="ok"]{background:var(--green-bg);color:var(--green-ink);}
1044
+ .af-pill[data-tone="warn"]{background:var(--amber-bg);color:var(--amber-ink);}
1045
+ .af-pill[data-tone="bad"]{background:var(--red-bg);color:var(--red-ink);}
1046
+ .af-pill[data-tone="info"]{background:var(--blue-bg);color:var(--blue-ink);}
1047
+ .af-tbl tr.af-pick{cursor:pointer;}
1048
+ .af-tbl tr.af-pick:hover td{background:var(--field);}
1049
+ .af-tbl tr.af-pick[aria-selected="true"] td{background:var(--green-bg);}
1050
+
1051
+ /* review list */
1052
+ .af-rv{display:flex;flex-direction:column;gap:9px;}
1053
+ .af-rv-item{background:var(--panel);border:1.5px solid var(--line);border-radius:12px;padding:11px 13px;
1054
+ display:flex;flex-direction:column;gap:9px;}
1055
+ .af-rv-top{display:flex;align-items:flex-start;gap:12px;}
1056
+ .af-rv-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;}
1057
+ .af-rv-title{font-weight:600;font-size:12.5px;color:var(--ink);}
1058
+ .af-rv-body{font-size:12px;line-height:1.45;color:var(--ink-2);}
1059
+ .af-rv-meta{font:500 11px var(--mono);color:var(--ink-3);}
1060
+ .af-rv-note[hidden]{display:none;}
1061
+ .af-rv-item[data-tone="ok"]{border-color:var(--green);}
1062
+ .af-rv-item[data-tone="warn"]{border-color:var(--amber-line);}
1063
+ .af-rv-item[data-tone="bad"]{border-color:var(--red);}
1064
+ .af-rv-item[data-tone="info"]{border-color:var(--blue-ink);}
1065
+ .af-form .seg button[data-tone="ok"].on{color:var(--green-ink);}
1066
+ .af-form .seg button[data-tone="warn"].on{color:var(--amber-ink);}
1067
+ .af-form .seg button[data-tone="bad"].on{color:var(--red-ink);}
1068
+ .af-form .seg button[data-tone="info"].on{color:var(--blue-ink);}
1069
+
1070
+ /* gallery, image, compare, media */
1071
+ .af-gal{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:11px;}
1072
+ .af-gal-card{display:flex;flex-direction:column;gap:6px;padding:9px;border:1.5px solid var(--line);
1073
+ border-radius:12px;background:var(--panel);text-align:left;font-family:inherit;}
1074
+ button.af-gal-card{cursor:pointer;}
1075
+ button.af-gal-card:hover{border-color:var(--ink-3);}
1076
+ button.af-gal-card:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
1077
+ .af-gal-card[aria-pressed="true"]{border-color:var(--green);background:var(--green-bg);}
1078
+ .af-gal-card img{width:100%;height:112px;object-fit:cover;border-radius:8px;background:var(--field);}
1079
+ .af-gal-cap{font-weight:600;font-size:12px;color:var(--ink);}
1080
+ .af-gal-sub{font:400 11px var(--mono);color:var(--ink-3);}
1081
+ .af-img{margin:0;display:flex;flex-direction:column;gap:6px;}
1082
+ .af-img img{width:100%;border-radius:12px;border:1px solid var(--line);background:var(--field);}
1083
+ .af-img figcaption{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--ink-3);}
1084
+ .af-cmp{display:flex;flex-direction:column;gap:9px;}
1085
+ .af-cmp-view{position:relative;border-radius:12px;overflow:hidden;border:1px solid var(--line);background:var(--field);}
1086
+ .af-cmp-view img{display:block;width:100%;}
1087
+ .af-cmp-top{position:absolute;inset:0;}
1088
+ .af-cmp-line{position:absolute;top:0;bottom:0;width:2px;background:var(--panel);}
1089
+ .af-cmp-tag{position:absolute;top:9px;padding:3px 9px;border-radius:999px;font:600 11px var(--mono);
1090
+ background:var(--surface);color:var(--ink-2);}
1091
+ .af-cmp-tag.af-l{left:9px;}
1092
+ .af-cmp-tag.af-r{right:9px;}
1093
+ .af-media{width:100%;border-radius:12px;background:var(--field);}
1094
+
1095
+ /* files, pdf, code, json, markdown, callout */
1096
+ .af-files{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px;}
1097
+ .af-files li{display:flex;align-items:center;gap:9px;padding:8px 11px;border:1px solid var(--line);
1098
+ border-radius:10px;background:var(--panel);font-size:12px;color:var(--ink);}
1099
+ .af-file-badge{font:700 10px var(--mono);letter-spacing:.06em;padding:3px 7px;border-radius:6px;
1100
+ background:var(--blue-bg);color:var(--blue-ink);}
1101
+ .af-file-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);font-size:11.5px;}
1102
+ .af-file-note{font-size:11.5px;color:var(--ink-2);}
1103
+ .af-file-size{font:400 11px var(--mono);color:var(--ink-3);}
1104
+ .af-file-bar{display:flex;align-items:center;gap:9px;}
1105
+ /* X14 — the ONE placeholder for a file with no snapshot (P5's `example` preview) or a
1106
+ rel the manifest lacks. Never a broken <img>, never an empty frame. P5 reuses it. */
1107
+ .af-nofile{display:flex;align-items:center;gap:9px;padding:10px 12px;border:1px dashed var(--line-2);
1108
+ border-radius:10px;background:var(--field);color:var(--ink-3);font-size:12px;}
1109
+ .af-gal-nofile{width:100%;height:112px;justify-content:center;flex-direction:column;gap:5px;text-align:center;}
1110
+ .af-open{font-weight:600;font-size:11.5px;color:var(--blue-ink);text-decoration:none;}
1111
+ .af-open:hover{text-decoration:underline;}
1112
+ .af-open[hidden]{display:none;}
1113
+ .af-pdf{display:flex;flex-direction:column;gap:8px;}
1114
+ .af-pdf-bar{display:flex;align-items:center;gap:9px;}
1115
+ .af-pdf-frame{width:100%;height:520px;border:1px solid var(--line);border-radius:12px;background:var(--field);}
1116
+ .af-code{border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--panel);}
1117
+ .af-code-bar{display:flex;align-items:center;gap:10px;padding:7px 12px;background:var(--field);
1118
+ border-bottom:1px solid var(--line);font:600 11px var(--mono);color:var(--ink-2);}
1119
+ .af-code-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
1120
+ .af-code-lang{color:var(--ink-3);}
1121
+ .af-code pre{margin:0;padding:10px 0;overflow-x:auto;font:400 12px/1.6 var(--mono);color:var(--ink);}
1122
+ .af-code code{display:block;}
1123
+ .af-ln{display:block;padding:0 12px;white-space:pre;}
1124
+ .af-ln.af-add{background:var(--green-bg);}
1125
+ .af-ln.af-del{background:var(--red-bg);}
1126
+ .af-ln.af-hunk{color:var(--ink-3);}
1127
+ .af-code-bar .af-add{color:var(--green-ink);}
1128
+ .af-code-bar .af-del{color:var(--red-ink);}
1129
+ .af-json{font:400 12px/1.65 var(--mono);color:var(--ink);background:var(--panel);border:1px solid var(--line);
1130
+ border-radius:12px;padding:10px 12px;overflow-x:auto;}
1131
+ .af-json details{margin-left:11px;}
1132
+ .af-json summary{cursor:pointer;}
1133
+ .af-json .af-j-k{color:var(--ink-2);}
1134
+ .af-json .af-j-c{color:var(--ink-3);}
1135
+ .af-json .af-j-s{color:var(--green-ink);}
1136
+ .af-json .af-j-n{color:var(--blue-ink);}
1137
+ .af-json .af-j-leaf{margin-left:11px;}
1138
+ .af-md{font-size:13px;line-height:1.55;color:var(--ink);}
1139
+ .af-md-host{display:flex;flex-direction:column;gap:8px;}
1140
+ .af-callout{display:flex;align-items:flex-start;gap:9px;padding:10px 13px;border-radius:11px;
1141
+ font-size:12.5px;line-height:1.5;border:1px solid var(--line);background:var(--surface);color:var(--ink-2);}
1142
+ .af-callout b{color:var(--ink);}
1143
+ .af-callout.af-info{background:var(--blue-bg);border-color:var(--blue-bg);color:var(--blue-ink);}
1144
+ .af-callout.af-ok{background:var(--green-bg);border-color:var(--green-bg);color:var(--green-ink);}
1145
+ .af-callout.af-warn{background:var(--amber-bg);border-color:var(--amber-bg);color:var(--amber-ink);}
1146
+ .af-callout.af-bad{background:var(--red-bg);border-color:var(--red-bg);color:var(--red-ink);}
1147
+
1148
+ /* layout containers */
1149
+ .af-grp{display:flex;flex-direction:column;gap:12px;padding:13px 15px;border:1px solid var(--amber-line);
1150
+ border-radius:12px;background:var(--amber-wash-2);}
1151
+ .af-grp-title{margin:0;font-weight:600;font-size:12.5px;color:var(--ink);}
1152
+ .af-cols{display:grid;grid-template-columns:repeat(var(--af-cols,2),minmax(0,1fr));gap:14px;}
1153
+ .af-col{display:flex;flex-direction:column;gap:14px;min-width:0;}
1154
+ .af-tabs{display:flex;flex-direction:column;gap:12px;}
1155
+ .af-tabs-bar{display:flex;gap:6px;border-bottom:1px solid var(--line);}
1156
+ .af-tab{font-family:inherit;font-weight:600;font-size:12.5px;color:var(--ink-3);background:none;border:none;
1157
+ border-bottom:2px solid transparent;padding:7px 11px;cursor:pointer;}
1158
+ .af-tab.on{color:var(--ink);border-bottom-color:var(--ink);}
1159
+ .af-tab:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
1160
+ .af-pane{display:flex;flex-direction:column;gap:14px;}
1161
+ .af-pane[hidden]{display:none;}
1162
+
1163
+ /* the detail screen scales the family up, like `.rd-questions .qopt` does */
1164
+ .rd-questions .af-form{gap:18px;margin-top:16px;}
1165
+ .rd-questions .af-label{font-size:13.5px;}
1166
+ .rd-questions .af-choice{gap:11px;padding:13px 16px;border-radius:13px;font-size:13.5px;}
1167
+ .rd-questions .af-inp{padding:13px 16px;border-radius:13px;font-size:13.5px;}
1168
+ .rd-questions .af-gal-card img{height:148px;}
1169
+ .rd-questions .af-pdf-frame{height:640px;}
1170
+
1171
+ /* readonly (History): the controls stay, greyed, and nothing hints why */
1172
+ .af-readonly .af-choice,.af-readonly .af-inp,.af-readonly .af-icon-btn{opacity:.78;}
1173
+ .af-readonly .af-choice{cursor:default;}
1174
+ .hd-cl-form{display:flex;flex-direction:column;gap:9px;padding:13px 15px;border:1px solid var(--line);
1175
+ border-radius:var(--r-card);background:var(--panel);}
923
1176
  /* ---------- Gate (cycle gate) ---------- */
924
1177
  .gate-intro{font-size:13px;color:var(--ink-2);margin:0 0 14px;line-height:1.5;}
925
1178
  .issues{list-style:none;margin:0 0 16px;padding:0;display:flex;flex-direction:column;gap:9px;}
@@ -1221,24 +1474,45 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
1221
1474
  .ws-src-name{font-weight:600;font-size:12.5px;color:var(--ink-2);}
1222
1475
  .ws-src-row .select-wrap{width:100%;}
1223
1476
  .ws-src-row select[disabled]{opacity:.55;}
1224
-
1225
- /* Workspace management cards. */
1226
- .ws-card{padding:0;overflow:hidden;}
1227
- .ws-head{display:flex;align-items:center;gap:14px;padding:16px 20px;cursor:pointer;}
1228
- .ws-head:focus-visible{outline:2px solid var(--ink);outline-offset:-2px;}
1229
- .ws-h-meta{flex:1;min-width:0;display:flex;flex-wrap:wrap;align-items:center;gap:8px;}
1230
- .ws-h-meta .ws-name{font-weight:600;font-size:15px;letter-spacing:-.01em;color:var(--ink);}
1231
- .ws-h-meta .ws-projects{display:block;width:100%;font-size:12.5px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
1477
+ .ws-src-prev { margin-top: 6px; }
1478
+
1479
+ /* Workspaces list: the Projects list's shape (one card headed "Workspaces · N", a row per
1480
+ workspace that IS the control), on its own ids. The page rides the pd- classes below. */
1481
+ #ws-list .saved-card{padding:0;overflow:hidden;}
1482
+ #ws-list .ws-item{border-bottom:1px solid var(--line);}
1483
+ #ws-list .ws-item:last-child{border-bottom:none;}
1484
+ #ws-list .ws-row{display:flex;align-items:center;gap:15px;padding:16px 20px;cursor:pointer;transition:background .12s;}
1485
+ #ws-list .ws-row:hover{background:var(--field);}
1486
+ #ws-list .ws-row:focus-visible{outline:2px solid var(--ink);outline-offset:-2px;}
1487
+ #ws-list .ws-main{flex:1 1 auto;min-width:0;}
1488
+ #ws-list .ws-name{font-weight:600;font-size:14px;letter-spacing:-.01em;color:var(--ink);}
1489
+ #ws-list .ws-name .ws-stale{margin-left:8px;vertical-align:middle;}
1490
+ .ws-projects{display:block;margin-top:4px;font-size:12.5px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
1232
1491
  .ws-projects .mono{font-size:12px;color:var(--ink-2);}
1233
1492
  .ws-projects .tm-home-mark{margin-right:5px;}
1234
1493
  .ws-sum-warn{color:var(--amber-ink);} .ws-sum-bad{color:var(--red-ink);}
1235
1494
  .tm-icon{width:14px;height:14px;color:var(--ink-2);flex:0 0 auto;}
1236
1495
  .ws-stale[hidden]{display:none;}
1237
- .ws-actions{display:flex;align-items:center;gap:8px;flex:0 0 auto;}
1238
- .ws-actions .btn-ghost{padding:7px 12px;font-size:12px;}
1239
- .ws-detail{padding:0 20px 18px;border-top:1px dashed var(--line-2);}
1240
- .ws-detail[hidden]{display:none;}
1241
- .ws-desc{margin-top:14px;padding-top:12px;border-top:1px solid var(--line);}
1496
+ /* Workspace page: the summary line under the title, the members list, the description panel. */
1497
+ .wd .pd-meta .ws-projects{margin-top:0;white-space:normal;font-size:12.5px;color:var(--ink-2);}
1498
+ /* The workspace header is two rows, not three: summary and actions share the second. */
1499
+ .wd-row2{display:flex;align-items:center;flex-wrap:wrap;gap:8px 16px;margin-top:8px;}
1500
+ .wd-row2 .pd-meta{margin-top:0;flex:1 1 320px;}
1501
+ .wd-row2 .pd-actions{margin-top:0;margin-left:auto;flex:0 0 auto;}
1502
+ .wd-row2 .pd-spacer{display:none;}
1503
+ .wd .pd-row1 .ws-stale{flex:0 0 auto;}
1504
+ .wd-member-list{display:flex;flex-direction:column;}
1505
+ .wd-member{display:flex;align-items:center;flex-wrap:wrap;gap:4px 14px;padding:11px 0;border-bottom:1px solid var(--line);
1506
+ background:none;border-left:0;border-right:0;border-top:0;text-align:left;font:inherit;color:inherit;width:100%;}
1507
+ .wd-member:last-child{border-bottom:0;}
1508
+ .wd-member-name{font-weight:600;font-size:13.5px;color:var(--ink);}
1509
+ .wd-member .proj-path{margin-top:0;flex:1 1 auto;min-width:0;}
1510
+ .wd-member-chev{display:flex;align-items:center;color:var(--ink-3);margin-left:auto;}
1511
+ button.wd-member{cursor:pointer;}
1512
+ button.wd-member:hover .wd-member-name{text-decoration:underline;}
1513
+ button.wd-member:focus-visible{outline:2px solid var(--ink);outline-offset:-2px;}
1514
+ .wd-desc .card-head .ws-edit{margin-left:auto;}
1515
+ .ws-desc .ws-desc-view{margin-top:0;}
1242
1516
  /* The wizard's project rows show each path as a sub-line (new on this branch): --ink-2 clears
1243
1517
  4.5:1 on white, the generic .opt-sub --ink-3 does not. */
1244
1518
  .wiz-proj.opt-row .opt-sub{color:var(--ink-2);} /* three classes: outranks the generic .opt-row .opt-sub declared later */
@@ -1426,10 +1700,284 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
1426
1700
  .pf-hint[hidden],.pf-note[hidden]{display:none;}
1427
1701
  .agent-caps,.agent-workspace{display:flex;flex-direction:column;gap:2px;}
1428
1702
 
1703
+ /* ===== Agent ask forms (ask-forms spec §11) ===== */
1704
+ .agent-forms{display:flex;flex-direction:column;gap:8px;}
1705
+ .agent-forms-list{display:flex;flex-direction:column;gap:14px;}
1706
+ .agent-form-row{border:1px solid var(--line);border-radius:10px;padding:12px;display:flex;flex-direction:column;gap:8px;}
1707
+ .afm-head{display:flex;align-items:flex-end;gap:12px;}
1708
+ .afm-head .field{margin:0;} /* .field{margin-bottom:18px} would lift the id input off the Remove button's baseline */
1709
+ .afm-head .afm-f-id{flex:1 1 auto;}
1710
+ .afm-remove{flex:0 0 auto;}
1711
+ .afm-editor .code-editor{width:100%;}
1712
+ .afm-add{align-self:flex-start;}
1713
+ .afm-panes{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px;}
1714
+ .afm-preview{min-width:0;border:1px solid var(--line);border-radius:8px;padding:10px;}
1715
+ .afm-projection{min-width:0;margin:0;white-space:pre-wrap;font-size:12px;}
1716
+ .afm-projection[hidden]{display:none;}
1717
+ .agent-forms-view{display:flex;flex-direction:column;gap:12px;margin-top:12px;}
1718
+ .agent-forms-view[hidden]{display:none;}
1719
+ .afv-row{border:1px solid var(--line);border-radius:10px;padding:12px;}
1720
+ .afv-head{display:flex;align-items:baseline;gap:10px;margin-bottom:8px;}
1721
+ @media (max-width:900px){.afm-panes{grid-template-columns:minmax(0,1fr);}}
1722
+
1429
1723
  /* (2) space between the header pills and the expanded markdown body */
1430
1724
  .agent-detail { margin-top:14px; }
1431
1725
  .agent-origin.origin-user { background:var(--violet-bg); }
1432
1726
  .agents-group-label { font-size:12px; font-weight:700; opacity:.65; margin:18px 0 8px; text-transform:uppercase; letter-spacing:.06em; }
1727
+
1728
+ /* ===== Scripts view (scripts-workbench §5.1) ===== */
1729
+ .scripts-host{display:block;}
1730
+ .scripts-tools{display:flex;align-items:center;gap:10px;}
1731
+ .scripts-tools .script-filter{width:220px;padding:9px 13px;font-size:13px;}
1732
+ .script-card{display:flex;align-items:center;gap:14px;}
1733
+ .script-card .script-card-main{flex:1;min-width:0;}
1734
+ .script-card .script-card-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
1735
+ .script-card .script-name{font-size:14px;}
1736
+ .script-card .script-origin.badge{background:var(--field);color:var(--ink-2);}
1737
+ .script-card .script-runtime{font-family:var(--mono);font-size:11px;padding:2px 9px;}
1738
+ .script-card .script-warn{background:var(--amber-bg);color:var(--amber-ink);font-size:11px;padding:2px 9px;}
1739
+ .script-card .script-desc{display:block;margin-top:5px;color:var(--ink-2);}
1740
+ .script-card .script-meta{display:flex;align-items:center;gap:8px;margin-top:7px;min-width:0;}
1741
+ .script-card .script-ports{font-size:11.5px;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
1742
+ .script-card .script-cases{font-size:11px;padding:2px 9px;}
1743
+ /* The list card's case dot AND the bench's case rows (spec §5.3) — one rule for both. */
1744
+ .script-dot{width:8px;height:8px;border-radius:999px;border:1.5px solid var(--line-2);background:transparent;flex:0 0 auto;}
1745
+ .script-dot[data-state="pass"]{background:var(--green);border-color:var(--green);}
1746
+ .script-dot[data-state="fail"]{background:var(--red);border-color:var(--red);}
1747
+ .script-dot[data-state="ran"]{background:var(--seq);border-color:var(--seq);}
1748
+ .script-card .script-actions{display:flex;gap:8px;flex:0 0 auto;}
1749
+ .script-card .script-actions .btn-mini{font-size:11.5px;padding:5px 10px;}
1750
+ .scripts-empty{font-size:12px;color:var(--ink-3);padding:6px 0 4px;}
1751
+ /* ---------- Scripts detail (scripts-workbench §5.2) ---------- */
1752
+ .script-detail .script-dirty{background:var(--amber-bg);color:var(--amber-ink);font-size:11px;padding:2px 9px;}
1753
+ .script-form{max-width:760px;}
1754
+ .script-form .ins-f{margin-bottom:14px;}
1755
+ .script-form .ins-label{display:block;font-weight:600;font-size:12px;margin-bottom:6px;color:var(--ink-2);}
1756
+ .script-form .ins-number,.script-form .ins-select{width:100%;padding:9px 12px;font-size:13px;border:1px solid var(--line-2);
1757
+ border-radius:10px;background:var(--field);color:var(--ink);}
1758
+ .script-form .ins-number:focus,.script-form .ins-select:focus{background:var(--field-focus);border-color:var(--ink);outline:none;}
1759
+ .script-zone{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);margin:20px 0 8px;}
1760
+ .script-path-row{display:flex;align-items:center;gap:10px;margin-top:16px;}
1761
+ .script-path{font-family:var(--mono);font-size:11.5px;color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;}
1762
+ .script-source{display:flex;flex-direction:column;gap:10px;align-items:flex-start;}
1763
+ .script-source .script-editor-mount{width:100%;}
1764
+ .script-source [hidden]{display:none;}
1765
+ /* ---------- Test bench (scripts-workbench §5.3) ---------- */
1766
+ /* The bench is stacked under the editor now (script-wizard plan S12): the bar, the setup, the cases strip, the result. */
1767
+ .bench{display:flex;flex-direction:column;gap:14px;}
1768
+ .bench-col{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);padding:16px;min-width:0;}
1769
+ .bench-col-head{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);margin-bottom:10px;}
1770
+ .bench-case-list{display:flex;flex-direction:column;gap:4px;margin-bottom:10px;}
1771
+ .bench-case-row{display:flex;align-items:center;gap:4px;min-width:0;}
1772
+ .bench-case{display:flex;align-items:center;gap:7px;flex:1;min-width:0;text-align:left;font-family:inherit;font-size:12.5px;
1773
+ color:var(--ink);background:transparent;border:1px solid transparent;border-radius:10px;padding:6px 8px;cursor:pointer;}
1774
+ .bench-case:hover{background:var(--field);}
1775
+ .bench-case.on{background:var(--field);border-color:var(--line-2);}
1776
+ .bench-case .bench-case-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
1777
+ .bench-case-row .bench-lock{font-size:10px;padding:1px 7px;flex:0 0 auto;}
1778
+ /* The per-row actions stay small and only appear on hover or while the row is
1779
+ selected, so a list of eight cases still reads as a list. */
1780
+ /* visibility, NOT opacity: an invisible control must not still be clickable. */
1781
+ .bench-case-row .bench-case-rename,.bench-case-row .bench-case-delete{flex:0 0 auto;padding:3px 7px;font-size:10.5px;visibility:hidden;}
1782
+ .bench-case-row:hover .bench-case-rename,.bench-case-row:hover .bench-case-delete,
1783
+ .bench-case-row:focus-within .bench-case-rename,.bench-case-row:focus-within .bench-case-delete{visibility:visible;}
1784
+ /* Setup edited since the case was selected: Run sends what is on screen, not the stored case. */
1785
+ .bench-case-row[data-edited="true"] .bench-case-name{font-style:italic;}
1786
+ .bench-case-rename-input{flex:1;min-width:0;padding:4px 7px;font-size:12px;}
1787
+ input.bench-case-name{width:100%;padding:9px 12px;font-size:13px;}
1788
+ .bench-case-actions{display:flex;flex-direction:column;gap:4px;margin-top:8px;}
1789
+ .bench-cases > .btn-mini,.bench-case-actions .btn-mini{width:100%;margin-top:4px;}
1790
+ .bench-zone{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);margin:16px 0 8px;}
1791
+ /* The shared params form's one caption is styled for .ins-panel only; the bench hosts it too. */
1792
+ .bench-setup .ins-caption{display:block;margin:-7px 0 12px;color:var(--ink-3);font-size:11px;}
1793
+ .bench-setup .ins-f{margin-bottom:14px;}
1794
+ .bench-setup .ins-label{display:block;font-weight:600;font-size:12px;margin-bottom:6px;color:var(--ink-2);}
1795
+ .bench-setup .ins-select,.bench-setup .ins-number,.bench-setup .ins-textarea{width:100%;padding:9px 12px;font-size:13px;
1796
+ border:1px solid var(--line-2);border-radius:10px;background:var(--field);color:var(--ink);}
1797
+ .bench-port{border:1px solid var(--line);border-radius:12px;padding:10px 12px;margin-bottom:8px;}
1798
+ .bench-bind{display:flex;align-items:center;gap:7px;font-size:12.5px;cursor:pointer;}
1799
+ .bench-port-id{font-family:var(--mono);}
1800
+ .bench-port-type{font-size:10px;padding:1px 7px;}
1801
+ .bench-void-fired{margin-left:24px;font-size:11.5px;color:var(--ink-3);}
1802
+ .bench-src{margin:8px 0 6px;}
1803
+ .bench-text{width:100%;min-height:0;font-family:var(--mono);font-size:12px;padding:8px 10px;border:1px solid var(--line-2);
1804
+ border-radius:10px;background:var(--field);color:var(--ink);resize:vertical;}
1805
+ .bench-actions{display:flex;gap:8px;margin-top:10px;flex-wrap:wrap;}
1806
+ .bench-expect-row{margin-top:4px;}
1807
+ .bench-expect-head{display:flex;align-items:center;gap:8px;}
1808
+ .bench-expect-head .ins-select{flex:1;min-width:0;}
1809
+ .bench-expect-head .bench-expect-from-result{flex:0 0 auto;}
1810
+ .bench-expect-detail{margin-top:8px;}
1811
+ .bench-expect-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px;}
1812
+ .bench-expect-chip{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;border:1px solid var(--line);
1813
+ border-radius:999px;padding:3px 10px;cursor:pointer;}
1814
+ .bench-expect-chip:has(input:checked){background:var(--green-bg);border-color:transparent;color:var(--green-ink);}
1815
+ .bench-status{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
1816
+ .bench-status-text{font-weight:600;font-size:13px;}
1817
+ .bench-dot{width:9px;height:9px;border-radius:999px;background:var(--seq);}
1818
+ .bench-dot[data-status="clean"]{background:var(--green);}
1819
+ .bench-dot[data-status="blocking"]{background:var(--amber);}
1820
+ .bench-dot[data-status="error"],.bench-dot[data-status="timeout"]{background:var(--red);}
1821
+ .bench-dot[data-status="running"]{background:var(--peach);}
1822
+ .bench-status .chip{font-size:11px;padding:2px 9px;}
1823
+ .bench-draft{background:var(--violet-bg);color:var(--violet-ink);}
1824
+ .bench-status [hidden]{display:none;}
1825
+ .bench-summary{margin-top:8px;font-size:12.5px;color:var(--ink-2);}
1826
+ .bench-fired{display:flex;flex-wrap:wrap;gap:6px;}
1827
+ .bench-fired-chip{font-size:11px;padding:2px 9px;}
1828
+ .bench-expect{margin-top:8px;font-size:12px;}
1829
+ .bench-expect-state.pass{color:var(--green-ink);}
1830
+ .bench-expect-state.fail{color:var(--red-ink);}
1831
+ .bench-expect-diff{color:var(--ink-2);margin-top:3px;}
1832
+ .bench-error{margin-top:8px;color:var(--red-ink);font-size:12.5px;}
1833
+ .bench-error-tail,.bench-warn{margin-top:4px;font-family:var(--mono);font-size:11.5px;color:var(--ink-3);white-space:pre-wrap;}
1834
+ .bench-tabs{margin:12px 0 10px;flex-wrap:wrap;}
1835
+ .bench-pane[hidden]{display:none;}
1836
+ .bench-pane .bench-log,.bench-pane .bench-json,.bench-pane .bench-rawtext{margin:0;max-height:360px;overflow:auto;
1837
+ font-family:var(--mono);font-size:11.5px;line-height:1.5;white-space:pre-wrap;color:var(--ink);}
1838
+ .bench-pane .bench-raw{margin-bottom:8px;}
1839
+ .bench-open-full{display:inline-block;margin-top:8px;font-size:12px;color:var(--blue-ink-strong);}
1840
+ .bench-msg{min-height:0;}
1841
+ /* ===== Script wizard (script-wizard plan): step 1 and the workspace ===== */
1842
+ .wz{display:flex;flex-direction:column;gap:18px;}
1843
+ .wz-bar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
1844
+ .wz .sp{flex:1 1 auto;}
1845
+ .wz-track{display:flex;align-items:center;gap:6px;}
1846
+ .wz-step-pill{display:inline-flex;align-items:center;gap:8px;height:30px;padding:0 12px 0 8px;border-radius:999px;border:0;background:transparent;font:600 12.5px var(--sans);color:var(--ink-3);cursor:pointer;}
1847
+ .wz-step-pill:disabled{cursor:default;}
1848
+ .wz-step-pill.on{background:var(--ink);color:var(--on-ink);}
1849
+ .wz-step-pill.done{color:var(--green-ink);background:var(--green-bg);}
1850
+ .wz-step-n{width:20px;height:20px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:11px;background:color-mix(in srgb, currentColor 12%, transparent);}
1851
+ .wz-step-pill.on .wz-step-n{background:color-mix(in srgb, var(--on-ink) 22%, transparent);}
1852
+ .wz-step-pill.done .wz-step-n{background:var(--green);color:var(--on-status);}
1853
+ .wz-step-pill .chip-rt{margin-left:2px;}
1854
+ .wz-step-sep{color:var(--seq);font-size:14px;}
1855
+ .wz-pick{display:flex;flex-direction:column;align-items:center;gap:28px;padding:40px 0 20px;}
1856
+ .wz-pick-title{display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;}
1857
+ .wz-pick-title h1{margin:0;font-size:32px;letter-spacing:-.01em;}
1858
+ .wz-pick-line{font-size:14px;color:var(--ink-2);}
1859
+ .wz-rt-cards{display:flex;gap:20px;width:100%;max-width:1080px;}
1860
+ @media (max-width:900px){.wz-rt-cards{flex-direction:column;}}
1861
+ .wz .rt{display:flex;flex-direction:column;gap:12px;flex:1 1 0;min-width:0;min-height:250px;padding:22px;border-radius:20px;background:var(--panel);border:2px solid transparent;box-shadow:var(--shadow);cursor:pointer;text-align:left;font-family:inherit;color:var(--ink);}
1862
+ .wz .rt:hover:not(:disabled){transform:translateY(-1px);}
1863
+ .wz .rt.sel{border-color:var(--ink);}
1864
+ .wz .rt:disabled{opacity:.45;cursor:not-allowed;}
1865
+ .wz .rt-head{display:flex;align-items:flex-start;justify-content:space-between;}
1866
+ .wz .rt-check{width:24px;height:24px;border-radius:999px;background:var(--ink);color:var(--on-ink);display:inline-flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;}
1867
+ .wz .rt-name{font-size:19px;font-weight:600;}
1868
+ .wz .rt-line{font-size:13px;color:var(--ink-2);line-height:1.55;}
1869
+ .wz .rt-sig{margin-top:auto;font-size:11.5px;color:var(--ink-2);background:var(--field);border-radius:8px;padding:8px 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
1870
+ .wz-pick-foot{display:flex;justify-content:flex-end;width:100%;max-width:1080px;}
1871
+ .wz-body{display:grid;grid-template-columns:460px minmax(0,1fr);gap:24px;align-items:start;}
1872
+ @media (max-width:1100px){.wz-body{grid-template-columns:minmax(0,1fr);}}
1873
+ .wz-left,.wz-right{display:flex;flex-direction:column;gap:14px;min-width:0;}
1874
+ .wz .panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);}
1875
+ .wz-panel-title{font-size:13.5px;font-weight:600;}
1876
+ .wz-tile{display:flex;align-items:center;gap:14px;padding:14px 16px;}
1877
+ .wz .tile{width:48px;height:48px;border-radius:14px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;}
1878
+ .wz .tile-green{background:var(--green-bg);color:var(--green-ink);}.wz .tile-peach{background:var(--peach-bg);color:var(--peach-ink);}
1879
+ .wz .tile-red{background:var(--red-bg);color:var(--red-ink);}.wz .tile-blue{background:var(--blue-bg);color:var(--blue-ink);}
1880
+ .wz .tile-violet{background:var(--violet-bg);color:var(--violet-ink);}.wz .tile-amber{background:var(--amber-bg);color:var(--amber-ink);}
1881
+ .wz .tile-teal{background:var(--teal-bg);color:var(--teal-ink);}.wz .tile-pink{background:var(--pink-bg);color:var(--pink-ink);}
1882
+ .wz .tile-indigo{background:var(--indigo-bg);color:var(--indigo-ink);}.wz .tile-lime{background:var(--lime-bg);color:var(--lime-ink);}
1883
+ .wz .tile-cocoa{background:var(--cocoa-bg);color:var(--cocoa-ink);}.wz .tile-slate{background:var(--slate-bg);color:var(--slate-ink);}
1884
+ .wz-tile-text{display:flex;flex-direction:column;gap:4px;min-width:0;}
1885
+ .wz .pv-name{font-size:15px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
1886
+ .wz .pv-name.muted{color:var(--seq);font-weight:500;}
1887
+ .wz-tile-line{display:flex;align-items:center;gap:8px;}
1888
+ .wz .pv-key{font-size:12px;color:var(--ink-2);}
1889
+ .wz .chip-rt{font-family:var(--mono);font-size:11px;padding:2px 9px;}
1890
+ .wz .chip-node{background:var(--violet-bg);color:var(--violet-ink);}.wz .chip-python{background:var(--blue-bg);color:var(--blue-ink);}.wz .chip-shell{background:var(--amber-bg);color:var(--amber-ink);}
1891
+ .wz .chip-ok{background:var(--green-bg);color:var(--green-ink);}.wz .chip-warn{background:var(--amber-bg);color:var(--amber-ink);}.wz .chip-muted{background:var(--field);color:var(--ink-2);}
1892
+ .wz .chip-tiny{font-size:10px;padding:1px 7px;}
1893
+ .wz-identity,.wz-iface{padding:16px;display:flex;flex-direction:column;gap:12px;}
1894
+ .wz-row{display:grid;grid-template-columns:minmax(0,1fr) 180px;gap:12px;}
1895
+ .wz .ins-f{margin:0;}
1896
+ .wz .ins-label{display:block;font-weight:600;font-size:12px;margin-bottom:6px;color:var(--ink-2);}
1897
+ .wz .ins-number,.wz .ins-textarea{width:100%;padding:9px 12px;font-size:13px;border:1px solid var(--line-2);border-radius:var(--r-ctrl);background:var(--field);color:var(--ink);font-family:inherit;}
1898
+ .wz .ins-number:focus,.wz .ins-textarea:focus{background:var(--field-focus);border-color:var(--ink);outline:none;}
1899
+ .wz .ins-textarea{resize:none;line-height:1.5;}
1900
+ .wz-swatches{display:flex;gap:8px;flex-wrap:wrap;}
1901
+ .wz .sw{width:28px;height:28px;border-radius:999px;border:3px solid var(--panel);box-shadow:0 0 0 1.5px var(--line-2);cursor:pointer;padding:0;}
1902
+ .wz .sw:hover:not(:disabled){box-shadow:0 0 0 1.5px var(--ink-3);}
1903
+ .wz .sw.sel{box-shadow:0 0 0 2px var(--ink);}
1904
+ .wz .sw:disabled{cursor:default;}
1905
+ .wz .sw-green{background:var(--green);}.wz .sw-peach{background:var(--peach);}.wz .sw-red{background:var(--red);}.wz .sw-blue{background:var(--blue);}
1906
+ .wz .sw-violet{background:var(--violet);}.wz .sw-amber{background:var(--amber);}.wz .sw-teal{background:var(--teal);}.wz .sw-pink{background:var(--pink);}
1907
+ .wz .sw-indigo{background:var(--indigo);}.wz .sw-lime{background:var(--lime);}.wz .sw-cocoa{background:var(--cocoa);}.wz .sw-slate{background:var(--slate);}
1908
+ .wz-icons{display:grid;grid-template-columns:repeat(10,36px);gap:6px;}
1909
+ .wz .ico{width:36px;height:36px;border-radius:10px;border:1.5px solid var(--line-2);background:var(--panel);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;color:var(--ink-2);padding:0;}
1910
+ .wz .ico:hover:not(:disabled){border-color:var(--ink-3);}
1911
+ .wz .ico.sel{border-color:var(--ink);color:var(--ink);background:var(--field);}
1912
+ .wz .ico:disabled{cursor:default;}
1913
+ .wz-iface-head,.wz-zone-head{display:flex;align-items:center;gap:8px;}
1914
+ .wz-iface .zone{font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3);font-weight:700;}
1915
+ .wz-prow{display:flex;align-items:center;gap:10px;min-height:32px;padding:0 10px 0 12px;border-radius:10px;background:var(--field);}
1916
+ .wz-prow.stale{background:transparent;border:1.5px dashed var(--line-2);}
1917
+ .wz-prow .pid{font-size:12.5px;font-weight:600;}
1918
+ .wz .tchip{font-family:var(--mono);font-size:11px;font-weight:600;height:22px;padding:0 8px;border-radius:999px;border:1.5px solid var(--line-2);background:var(--panel);color:var(--ink-2);cursor:pointer;}
1919
+ .wz .tchip:hover:not(:disabled){border-color:var(--ink);color:var(--ink);}
1920
+ .wz .tchip:disabled{cursor:default;}
1921
+ .wz .tchip.void{color:var(--ink-3);}
1922
+ .wz .tchip.when{border-style:dashed;color:var(--violet-ink);border-color:var(--violet);}
1923
+ .wz .tchip.mode{color:var(--ink-3);}
1924
+ .wz-pdflt{flex:1 1 auto;min-width:60px;width:auto;margin:0;height:24px;padding:0 8px;font-size:12px;font-family:var(--mono);color:var(--ink);background:var(--panel);border:1px solid var(--line-2);border-radius:var(--r-ctrl);}
1925
+ .wz-pdflt:focus{background:var(--field-focus);border-color:var(--ink);outline:none;}
1926
+ .wz-prm{background:none;border:0;padding:0 4px;color:var(--ink-3);cursor:pointer;font-size:14px;line-height:1;}
1927
+ .wz-prm:hover{color:var(--red-ink);}
1928
+ .wz-iface .empty{font-size:12px;color:var(--ink-3);min-height:32px;display:flex;align-items:center;padding:0 12px;border:1.5px dashed var(--line-2);border-radius:10px;}
1929
+ .wz-routing{display:flex;align-items:center;gap:10px;min-height:28px;padding-left:2px;font-size:12.5px;color:var(--ink-2);}
1930
+ .wz .tog{width:34px;height:20px;border-radius:999px;background:var(--seq);position:relative;cursor:pointer;border:0;padding:0;flex:0 0 auto;}
1931
+ .wz .tog.on{background:var(--ink);}
1932
+ .wz .tog::after{content:'';position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:999px;background:var(--panel);transition:left .15s;}
1933
+ .wz .tog.on::after{left:16px;}
1934
+ .wz .tog:disabled{cursor:default;opacity:.6;}
1935
+ .wz-adv{padding:0 16px;}
1936
+ .wz-adv-toggle{height:44px;width:100%;display:flex;align-items:center;gap:10px;background:none;border:0;padding:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:left;}
1937
+ .wz-adv-sum{font-size:12px;color:var(--ink-3);}
1938
+ .wz .chev{display:inline-block;transition:transform .15s;color:var(--ink-3);font-size:16px;line-height:1;}
1939
+ .wz .chev.open{transform:rotate(90deg);}
1940
+ .wz-adv-body{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:0 0 16px;}
1941
+ .wz-adv-body[hidden]{display:none;}
1942
+ .wz-verdict-file{font-size:12px;color:var(--ink-2);display:flex;align-items:center;min-height:34px;}
1943
+ .wz-editor{display:flex;flex-direction:column;overflow:hidden;}
1944
+ .wz-ed-head{display:flex;align-items:center;gap:10px;min-height:46px;padding:0 12px 0 18px;border-bottom:1px solid var(--line);flex-wrap:wrap;}
1945
+ .wz-file{font-size:13px;font-weight:600;}
1946
+ .wz-editor .script-editor-mount{width:100%;}
1947
+ .wz-editor .code-editor{border:0;border-radius:0;}
1948
+ .wz-editor [hidden]{display:none;}
1949
+ .wz .script-path-row{display:inline-flex;align-items:center;gap:8px;margin:0;max-width:420px;}
1950
+ .bench-bar{display:flex;align-items:center;gap:10px;padding:10px 16px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);flex-wrap:wrap;}
1951
+ .bench-bar .ins-f{margin:0;display:flex;align-items:center;gap:8px;}
1952
+ .bench-bar .ins-label{margin:0;}
1953
+ .bench-bar .ins-select{width:auto;min-width:180px;}
1954
+ .wz .bench-col{padding:14px 16px;}
1955
+ .wz .bench-cases{display:flex;flex-wrap:wrap;align-items:center;gap:8px;}
1956
+ .wz .bench-cases .bench-col-head{width:100%;margin-bottom:2px;}
1957
+ .wz .bench-cases .bench-case-list{display:flex;flex-wrap:wrap;gap:6px;margin:0;width:100%;}
1958
+ .wz .bench-cases .bench-case-row{width:auto;}
1959
+ .wz .bench-cases input.bench-case-name{width:220px;}
1960
+ .wz .bench-cases > .btn-mini,.wz .bench-case-actions .btn-mini{width:auto;margin:0;}
1961
+ .wz .bench-case-actions{flex-direction:row;margin:0;gap:6px;}
1962
+ /* ---------- past-run artifact picker (W2) ---------- */
1963
+ .apick{display:flex;flex-direction:column;gap:6px;max-height:420px;overflow:auto;}
1964
+ .apick-project-name{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);margin:10px 0 4px;}
1965
+ .apick-run,.apick-art{display:flex;align-items:center;gap:10px;width:100%;text-align:left;font-family:inherit;font-size:12.5px;
1966
+ color:var(--ink);background:transparent;border:1px solid var(--line);border-radius:12px;padding:8px 11px;cursor:pointer;}
1967
+ .apick-run:hover,.apick-art:hover{background:var(--field);}
1968
+ .apick-run-title,.apick-art-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
1969
+ .apick-run-meta,.apick-art-bytes{font-family:var(--mono);font-size:11px;color:var(--ink-3);flex:0 0 auto;}
1970
+ .apick-art-kind{font-size:10px;padding:1px 7px;}
1971
+ .apick-back{align-self:flex-start;}
1972
+ .apick-empty{font-size:12px;color:var(--ink-3);padding:6px 0;}
1973
+ .apick-err{font-size:12.5px;color:var(--red-ink);padding:6px 0;}
1974
+ .bench-src-label{display:block;margin:4px 0 2px;font-family:var(--mono);font-size:11px;color:var(--ink-3);
1975
+ overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
1976
+ .bench-port .bench-file[hidden]{display:none;}
1977
+ @media (max-width:760px){
1978
+ .script-card{flex-direction:column;align-items:stretch;}
1979
+ .scripts-tools .script-filter{width:100%;}
1980
+ }
1433
1981
  .agent-actions { display:flex; gap:8px; }
1434
1982
  .chip-select { display:flex; flex-wrap:wrap; gap:8px; }
1435
1983
  .chip-select label { display:inline-flex; gap:6px; align-items:center; font-size:12.5px; border:1px solid var(--line); border-radius:999px; padding:4px 10px; cursor:pointer; }
@@ -1461,12 +2009,28 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
1461
2009
  /* NO top padding on the scroller: the detail's sticky .pd-tabs must pin flush, as .hd-tabs does. */
1462
2010
  .proj-screen{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;padding:0 32px 40px;
1463
2011
  transition:transform .46s cubic-bezier(.65,.02,.28,1);}
2012
+ /* The SHOWN screen rests on transform:none (not translateX(0)): a transform makes a stacking
2013
+ context, and a Getting started guide elevates a control inside it (a project row, the Team
2014
+ tab, Add project) above the scrim by z-index — which cannot escape a transformed ancestor.
2015
+ none ↔ translateX() still animates (none is the identity). */
1464
2016
  .proj-screen-list .topbar{padding-top:26px;}
1465
- .proj-screen-list{transform:translateX(0);}
2017
+ .proj-screen-list{transform:none;}
1466
2018
  .proj-screen-detail{transform:translateX(100%);padding:0;background:var(--bg);}
1467
2019
  .proj-shell.detail-open .proj-screen-list{transform:translateX(-100%);}
1468
- .proj-shell.detail-open .proj-screen-detail{transform:translateX(0);}
2020
+ .proj-shell.detail-open .proj-screen-detail{transform:none;}
1469
2021
  .proj-shell.no-anim .proj-screen{transition:none;}
2022
+ /* ---------- Workspaces two-screen shell: the Projects track's twin, rule for rule (the Projects
2023
+ rules above are pinned verbatim by tests, so this block repeats them on its own names). ---------- */
2024
+ .view[data-view="workspaces"]{flex:1 1 auto;min-height:0;padding:0;position:relative;}
2025
+ .ws-shell{position:relative;height:100%;overflow:hidden;}
2026
+ .ws-screen{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;padding:0 32px 40px;
2027
+ transition:transform .46s cubic-bezier(.65,.02,.28,1);}
2028
+ .ws-screen-list .topbar{padding-top:26px;}
2029
+ .ws-screen-list{transform:none;}
2030
+ .ws-screen-detail{transform:translateX(100%);padding:0;background:var(--bg);}
2031
+ .ws-shell.detail-open .ws-screen-list{transform:translateX(-100%);}
2032
+ .ws-shell.detail-open .ws-screen-detail{transform:none;}
2033
+ .ws-shell.no-anim .ws-screen{transition:none;}
1470
2034
  /* A keyed row IS the control (role=button): pointer + hover tint, the .hist-head idiom. The
1471
2035
  keyless row keeps #projects-list .pl-row's default cursor. */
1472
2036
  #projects-list .pl-row[role="button"]{cursor:pointer;transition:background .12s;}
@@ -1486,7 +2050,7 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
1486
2050
  card is a real <button> — reset the UA look so it reads like its siblings. */
1487
2051
  .pd-ov-value.pd-ov-wrap{font-size:13px;overflow-wrap:anywhere;}
1488
2052
  .pd-ov-missing{color:var(--red-ink);}
1489
- button.pd-ov-card{text-align:left;font:inherit;color:inherit;cursor:pointer;width:100%;}
2053
+ button.pd-ov-card{display:flex;flex-direction:column;align-items:stretch;text-align:left;font:inherit;color:inherit;cursor:pointer;width:100%;} /* a button centres its content vertically: the label must sit where its siblings' do */
1490
2054
  button.pd-ov-card:hover{border-color:var(--ink-3);}
1491
2055
  /* Memory tab: the same grid Settings → Memory paints (.mem-host); its message line sits above. */
1492
2056
  .pd-sec-memory .form-msg{margin:0 0 10px;}
@@ -1504,6 +2068,9 @@ button.pd-ov-card:hover{border-color:var(--ink-3);}
1504
2068
  .confirm-modal .card{width:min(440px,100%);}
1505
2069
  .confirm-message{margin:4px 0 18px;color:var(--ink-2);font-size:14px;line-height:1.5;white-space:pre-line;}
1506
2070
  .confirm-actions{display:flex;gap:9px;justify-content:flex-end;margin-top:14px;}
2071
+ .gv-import-scripts p{margin:0 0 12px;color:var(--ink-2);font-size:13.5px;}
2072
+ .gv-import-script-h{font-size:12px;font-weight:700;margin:10px 0 4px;}
2073
+ .gv-import-script-v{margin:0;padding:8px 10px;border:1px solid var(--line-2);border-radius:10px;background:var(--field);color:var(--ink);font-size:12px;white-space:pre-wrap;word-break:break-all;max-height:180px;overflow:auto;}
1507
2074
 
1508
2075
  /* ── domain tag: palette sections + filter chips, workflow badge + filter ── */
1509
2076
  .pal-chips{display:flex;flex-wrap:wrap;gap:6px;width:100%;margin-bottom:8px;}
@@ -1663,8 +2230,11 @@ button.pd-ov-card:hover{border-color:var(--ink-3);}
1663
2230
  .stat-tile{padding:18px 20px;}
1664
2231
  .stat-label{display:flex;align-items:center;gap:8px;color:var(--ink-2);font-size:12.5px;font-weight:600;}
1665
2232
  .stat-ico{width:16px;height:16px;color:var(--ink-3);flex:0 0 auto;}
1666
- .stat-delta{margin-left:auto;background:var(--field);color:var(--ink-2);font-size:11px;font-weight:600;
1667
- padding:2px 8px;border-radius:999px;}
2233
+ .stat-delta,.stat-mult{margin-left:auto;background:var(--field);color:var(--ink-2);font-size:11px;font-weight:600;
2234
+ padding:2px 8px;border-radius:999px;white-space:nowrap;}
2235
+ /* Saved's "9.0× spend" pill sits far right; when a delta pill precedes it, that one takes the
2236
+ auto margin and the two share the label row's 8px gap. */
2237
+ .stat-delta+.stat-mult{margin-left:0;}
1668
2238
  .stat-value{font-family:var(--mono);font-size:26px;font-weight:600;color:var(--ink);margin-top:8px;line-height:1.2;}
1669
2239
  .stat-frac{font-size:16px;color:var(--ink-3);}
1670
2240
  .stat-sub{display:block;color:var(--ink-3);font-size:11.5px;margin-top:6px;}
@@ -1743,11 +2313,14 @@ section[data-view="team-metrics"] .topbar{align-items:flex-start;}
1743
2313
  .tm-tbl td{padding:9px 10px;border-bottom:1px solid var(--line);}
1744
2314
  .tm-tbl tbody tr[data-filter-dim]{cursor:pointer;} .tm-tbl tbody tr[data-filter-dim]:hover,.tm-tbl tbody tr.on{background:var(--field);}
1745
2315
  .tm-tbl tr.dim td{color:var(--ink-3);}
2316
+ .tm-tbl td.tm-saved.pos{color:var(--green-ink);} .tm-tbl td.tm-saved.neg{color:var(--red-ink);}
1746
2317
  .tm-runs-foot{display:flex;align-items:center;gap:12px;margin-top:8px;}
1747
2318
  .tm-share{display:inline-block;width:90px;height:6px;border-radius:3px;background:var(--field);vertical-align:middle;}
1748
2319
  .tm-share-fill{display:block;height:100%;border-radius:3px;background:var(--blue);}
1749
2320
  .tm-runs{margin-top:18px;} .tm-runs-head{display:flex;align-items:center;justify-content:space-between;}
1750
2321
  .tm-run-tbl .tm-title{max-width:340px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
2322
+ /* Actor and Started never wrap: with the Saved column in, Title (ellipsis) and Workflow give way first. */
2323
+ .tm-run-tbl td:nth-last-child(-n+2){white-space:nowrap;}
1751
2324
  .badge.grey{background:var(--field);color:var(--ink-2);}
1752
2325
  .tm-empty{display:grid;grid-template-columns:1fr 1fr;gap:14px;} .tm-empty .card{padding:22px;}
1753
2326
  .tm-step{font-size:11px;letter-spacing:.08em;font-weight:700;color:var(--ink-2);}
@@ -1761,7 +2334,7 @@ section[data-view="team-metrics"] .topbar{align-items:flex-start;}
1761
2334
  .hd-tm.st-ok{color:var(--green-ink)} .hd-tm.st-warn{color:var(--amber-ink)} .hd-tm.st-err{color:var(--red-ink)} .hd-tm.st-muted{color:var(--ink-2)}
1762
2335
 
1763
2336
  /* Team metrics — Projects cell (board 4) */
1764
- #projects-list .tm-slot{flex:0 1 420px;min-width:0;}
2337
+
1765
2338
  /* border-left + padding-left are board 4's divider between the project row and the cell
1766
2339
  (mockup `.tm-cell{border-left:1px solid var(--line);padding-left:18px;min-width:420px}`);
1767
2340
  the 420px sizing lives on .tm-slot above so the cell itself can still wrap. */
@@ -1869,6 +2442,12 @@ section[data-view="team-metrics"] .topbar{align-items:flex-start;}
1869
2442
  .spend-ind.over .spend-ind-meter{background:var(--red-bg);}
1870
2443
  .spend-ind.over .spend-ind-meter-fill{background:var(--red-ink);}
1871
2444
  .spend-ind.over .spend-ind-sub{color:var(--red-ink);}
2445
+ /* No total limit: the Saved row takes the place the "no total limit" note held. A gain
2446
+ is green — --green-ink-strong, since --green-ink measures 4.48:1 on this card's hover
2447
+ fill (--line), under verify:theme's 4.5:1. A loss keeps neutral ink (--red-ink is
2448
+ 4.07:1 there); its "−" carries it. */
2449
+ .spend-ind-saved{margin-top:6px;}
2450
+ .spend-ind-saved.pos .spend-ind-label,.spend-ind-saved.pos .spend-ind-amt{color:var(--green-ink-strong);}
1872
2451
  .topnav-amt{margin-left:7px;font-family:var(--mono);font-weight:600;}
1873
2452
  .topnav-amt.warn{color:var(--amber-ink);}
1874
2453
  .topnav-amt.over{color:var(--red-ink);}
@@ -1938,6 +2517,11 @@ section[data-view="team-metrics"] .topbar{align-items:flex-start;}
1938
2517
  /* ---- Models view (configurable-models-design.md §4.10) ---- */
1939
2518
  .mv-list{display:grid;gap:18px;}
1940
2519
  .mv-section{display:grid;gap:10px;}
2520
+ /* Stacked cards keep the house 18px; the built-ins are compact rows, not panels, so they stay tight.
2521
+ (The rows moved into .mv-sec-body when groups became foldable — the section's own gap no longer
2522
+ reaches them.) */
2523
+ .mv-sec-body{display:grid;gap:18px;}
2524
+ .mv-section[data-section="builtin"] .mv-sec-body{gap:10px;}
1941
2525
  .mv-hide-builtin-row{display:grid;gap:6px;padding:10px 12px;border:1px solid var(--line-2);border-radius:10px;}
1942
2526
  .mv-hide-builtin-row .hint{margin:0;}
1943
2527
  .mv-section-title{margin:4px 0 0;font-size:13px;text-transform:uppercase;letter-spacing:.04em;opacity:.75;}
@@ -1981,6 +2565,129 @@ section[data-view="team-metrics"] .topbar{align-items:flex-start;}
1981
2565
  .mv-cost-rate .mv-cost-rate-in{min-width:0;font-family:var(--mono);font-size:12.5px;}
1982
2566
  .mv-cost-rate-unit{color:var(--ink-3);font-size:11.5px;white-space:nowrap;}
1983
2567
 
2568
+ /* ---- Model bridge (model-bridge-design.md §8): Providers card, Connection,
2569
+ import sheet, sign-in block. Same 18px rhythm and card chrome as the rest
2570
+ of the Models view; every revealed block gets an explicit [hidden] rule
2571
+ because the grid/flex rules here otherwise beat the UA hidden rule. ---- */
2572
+ .mv-providers{padding:18px 22px;display:grid;gap:14px;}
2573
+ /* The Providers TAB: one card per account, so three unrelated sign-ins stop reading as one form. */
2574
+ .mv-providers-split{padding:0;background:transparent;box-shadow:none;gap:18px;}
2575
+ .mv-providers-split .mv-providers-hint{margin:0 2px 0;}
2576
+ .mv-pv-card{padding:18px 22px;display:grid;gap:12px;}
2577
+ .mv-pv-card .mv-pv-row{border:0;padding:0;margin:0;}
2578
+ /* New surface, new contrast: the house `.hint` / placeholder grey (--ink-3) sits at
2579
+ 2.8:1 on a white card and is only tolerated where the light baseline predates the
2580
+ dark theme (test/fixtures/contrast-baseline-light.json — shrink, never grow). The
2581
+ bridge's copy uses --ink-2 (6.5:1) so the theme proof passes without a new entry. */
2582
+ .mv-providers .hint,.mv-conn .hint,.mv-degradation,.mvi .hint,.mv-cp-signin-box .hint{color:var(--ink-2);}
2583
+ .mv-pv-row .input::placeholder,.mv-conn .input::placeholder,.mv-conn .textarea::placeholder{color:var(--ink-2);}
2584
+ .mv-providers .mv-providers-hint{margin:-6px 0 0;}
2585
+ .mv-pv-row{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:12px 18px;padding:14px 0 0;border-top:1px solid var(--line-2);}
2586
+ .mv-pv-main{display:grid;gap:6px;align-content:start;min-width:0;}
2587
+ .mv-pv-main .hint{margin:0;}
2588
+ .mv-pv-ctl{display:grid;gap:10px;align-content:start;}
2589
+ .mv-pv-btns{grid-column:1 / -1;display:flex;gap:10px;flex-wrap:wrap;justify-content:flex-end;align-items:center;}
2590
+ /* Test connection's verdict, beside the button (bridge-view.mjs renderProvidersCard). Empty until
2591
+ a test runs, so the row keeps its rhythm. */
2592
+ .mv-pv-result{margin-right:auto;display:none;align-items:center;gap:6px;min-width:0;padding:5px 10px;border-radius:999px;
2593
+ font:600 12px var(--sans);background:var(--field);color:var(--ink-2);overflow-wrap:anywhere;}
2594
+ .mv-pv-result.is-on{display:inline-flex;}
2595
+ .mv-pv-result.is-ok{background:var(--green-bg);color:var(--green-ink);}
2596
+ .mv-pv-result.is-err{background:var(--red-bg);color:var(--red-ink);}
2597
+ .mv-pv-result.is-busy{color:var(--ink-3);}
2598
+
2599
+ /* Import dialog (app.js openImportDialog; model-bridge-design.md §8.4). The sheet it hosts is the
2600
+ same node the page used to show, so its card chrome is dropped here rather than in two renderers. */
2601
+ /* ONE scroll area: .viewer-modal .card scrolls by default, and with the body scrolling too the
2602
+ dialog showed two scrollbars side by side. The card is a column that clips; the list scrolls. */
2603
+ .mimp{width:min(980px,100%);max-height:86vh;display:flex;flex-direction:column;gap:14px;overflow:hidden;}
2604
+ .mimp-src{display:grid;grid-template-columns:minmax(190px,250px) minmax(0,1fr);align-items:start;gap:12px 16px;}
2605
+ .mimp-src .mv-field{min-width:0;}
2606
+ .mimp-src .mimp-base-field.hidden{display:none;}
2607
+ /* One source: the picker takes the row rather than leaving a gap where a URL would be. */
2608
+ .mimp-src:has(.mimp-base-field.hidden) .mimp-source-field{grid-column:1 / -1;}
2609
+ .mimp-base-row{display:flex;gap:8px;min-width:0;}
2610
+ .mimp-base-row .input{flex:1 1 auto;min-width:0;}
2611
+ .mimp-base-row .btn-ghost{flex:0 0 auto;white-space:nowrap;}
2612
+ /* The note and the warnings sit clear of the scroll edge: flush against it, Chrome clipped their
2613
+ first glyph. The table is what may scroll sideways, and it starts below them. */
2614
+ #mimp-body .mvi>.hint,#mimp-body .mvi-warn{padding-right:2px;}
2615
+ .mimp-msg{margin:0;}
2616
+ #mimp-body{flex:1 1 auto;min-height:0;overflow:auto;padding:0 4px;}
2617
+ .mimp-filter{flex:0 0 auto;}
2618
+ .mimp-filter.hidden{display:none;}
2619
+ #mimp-body tr.is-filtered{display:none;}
2620
+ /* The sheet carries .card, and `.viewer-modal .card` gives every card its own max-height + scroll:
2621
+ inside the dialog that made a SECOND scrollbar beside the body's. The body is the one scroller. */
2622
+ #mimp-body .mvi{box-shadow:none;border:0;background:transparent;padding:0;margin:0;max-height:none;overflow:visible;}
2623
+ #mimp-body .mv-editor-title{display:none;}
2624
+ .mimp-btns{margin-top:0;}
2625
+
2626
+ /* Model editor dialog (app.js openModelEditorDialog; configurable-models-design.md §4.10). The
2627
+ editor renders its own .card, so the host only sizes and scrolls it. */
2628
+ .mv-editor-host{width:min(880px,100%);max-height:86vh;overflow:auto;}
2629
+ .mv-editor-host .mv-editor{margin:0;}
2630
+
2631
+ /* Catalog toolbar and folding groups (models-view.mjs renderModelsList). */
2632
+ .mv-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:14px;}
2633
+ .mv-toolbar .mv-search{flex:1 1 280px;min-width:0;}
2634
+ .mv-filters{display:flex;flex-wrap:wrap;gap:6px;}
2635
+ .mv-filter{padding:6px 12px;border:1.5px solid var(--line-2);border-radius:999px;background:transparent;
2636
+ color:var(--ink-2);font:600 12px var(--sans);cursor:pointer;white-space:nowrap;}
2637
+ .mv-filter:hover{border-color:var(--ink-3);}
2638
+ .mv-filter.on{background:var(--ink);border-color:var(--ink);color:var(--on-ink);}
2639
+ .mv-section-head{display:flex;align-items:center;gap:8px;}
2640
+ .mv-sec-toggle{display:flex;align-items:center;gap:8px;padding:2px 0;border:0;background:transparent;cursor:pointer;color:inherit;font:inherit;}
2641
+ .mv-sec-toggle .mv-section-title{margin:0;}
2642
+ .mv-sec-caret{color:var(--ink-2);font-size:11px;line-height:1;transition:transform .12s ease;}
2643
+ .mv-sec-count{padding:1px 8px;border-radius:999px;background:var(--field);color:var(--ink-2);font:600 11px var(--mono);}
2644
+ .mv-section.is-folded .mv-sec-caret{transform:rotate(-90deg);}
2645
+ .mv-section.is-folded .mv-sec-body,.mv-section.is-folded .mv-sec-hint{display:none;}
2646
+ .mv-no-hits{margin-top:6px;}
2647
+ @media (prefers-reduced-motion: reduce){.mv-sec-caret{transition:none;}}
2648
+ .mv-pv-btns .btn-ghost,.mv-pv-btns .btn-go{padding:7px 12px;font-size:12px;}
2649
+ .mv-pv-row .input,.mv-pv-row .select{font-family:var(--mono);font-size:12.5px;padding:9px 12px;}
2650
+ .mv-pv-row .mv-pv-conc{max-width:120px;}
2651
+ .mv-cp-signin-box{display:grid;gap:8px;padding:12px 14px;border:1px solid var(--line-2);border-radius:10px;background:var(--field);}
2652
+ .mv-cp-code-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
2653
+ .mv-cp-code{font-family:var(--mono);font-size:26px;font-weight:700;letter-spacing:.12em;padding:4px 10px;border-radius:8px;background:var(--panel);border:1px solid var(--line);}
2654
+ .mv-cp-code-row .btn-ghost{padding:7px 12px;font-size:12px;text-decoration:none;}
2655
+ .mv-cp-status.err{color:var(--red);}
2656
+ .mv-cp-signin-box .mv-cp-cancel{justify-self:start;padding:7px 12px;font-size:12px;}
2657
+ .mv-needs-signin{display:inline-flex;align-items:center;gap:6px;}
2658
+ .mv-needs-signin .mv-signin{padding:4px 10px;font-size:11.5px;}
2659
+ .mv-degradation{display:block;margin:4px 0 0;}
2660
+ .mv-conn{display:grid;gap:12px;}
2661
+ .mv-conn-modes{display:grid;gap:8px;}
2662
+ .mv-conn-mode{display:flex;align-items:flex-start;gap:8px;font-size:13px;cursor:pointer;}
2663
+ .mv-conn-mode input{margin-top:3px;}
2664
+ .mv-conn-mode-text{display:grid;gap:2px;}
2665
+ .mv-conn-mode-text .hint{margin:0;}
2666
+ .mv-conn-body{display:grid;gap:12px;padding:12px 14px;border:1px solid var(--line-2);border-radius:10px;}
2667
+ .mv-conn-body[hidden]{display:none;}
2668
+ .mv-conn-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px 14px;}
2669
+ /* A field without a hint sits beside one with a hint: start-align so the
2670
+ select keeps its own height instead of stretching to the row's. */
2671
+ .mv-conn-grid .mv-field{align-content:start;}
2672
+ .mv-conn-grid .input,.mv-conn-grid .select{font-family:var(--mono);font-size:12.5px;}
2673
+ .mv-conn-provider-hint.warn{color:var(--amber-ink);}
2674
+ .mv-conn-adv{margin-top:0;}
2675
+ .mv-conn-adv[hidden]{display:none;}
2676
+ .mv-conn-adv-body{display:grid;gap:10px;}
2677
+ .mv-conn-adv-body .input,.mv-conn-adv-body .textarea{font-family:var(--mono);font-size:12.5px;}
2678
+ .mv-conn-caps{display:grid;gap:6px;}
2679
+ .mv-conn-caps-row{display:flex;gap:14px;flex-wrap:wrap;align-items:center;}
2680
+ .mv-conn-cap{display:flex;align-items:center;gap:6px;font-size:13px;cursor:pointer;}
2681
+ .mv-conn-limit{display:flex;align-items:center;gap:6px;font-size:12.5px;}
2682
+ .mv-conn-limit .mv-conn-limit-in{max-width:120px;font-family:var(--mono);font-size:12.5px;padding:7px 10px;}
2683
+ .mv-conn-note{margin:0;}
2684
+ .mvi-tbl{margin-top:8px;}
2685
+ .mvi-tbl td{vertical-align:top;}
2686
+ .mvi-tbl .mvi-id{display:block;margin:2px 0 0;font-family:var(--mono);}
2687
+ .mvi-tbl tr.mvi-disabled{opacity:.55;}
2688
+ .mvi-status{color:var(--ink-3);font-size:12px;}
2689
+ @media (max-width:720px){.mv-pv-row{grid-template-columns:1fr;}}
2690
+
1984
2691
  /* ---- Model plugins (design §9.6): plugin cards + export wizard ---- */
1985
2692
  .mv-secret{display:block;margin:4px 0 0;}
1986
2693
  .mv-secret.err{color:var(--red);}
@@ -2101,7 +2808,7 @@ section[data-view="team-metrics"] .topbar{align-items:flex-start;}
2101
2808
  .hd-report has no icon, but it stands in the SAME row as .hd-archive and needs the
2102
2809
  same padding for the same reason: on .btn-ghost's own 13px it measured 48px beside
2103
2810
  a 38px Archive (headless Chrome, both themes). */
2104
- .hd-back,.hd-resume,.hd-report,.pd-back,.pd-new,.pd-history{display:inline-flex;align-items:center;gap:8px;padding:8px 15px;}
2811
+ .hd-back,.hd-resume,.hd-report,.pd-back,.pd-new,.pd-history,.ws-rescan{display:inline-flex;align-items:center;gap:8px;padding:8px 15px;} /* one height for every header action */
2105
2812
  .hd-resume[hidden]{display:none;}
2106
2813
  /* Same trap as the fallback issue link in the report modal: the author `display`
2107
2814
  above beats the UA's `[hidden]{display:none}`, and this button ships hidden. */
@@ -2136,7 +2843,7 @@ section[data-view="team-metrics"] .topbar{align-items:flex-start;}
2136
2843
  13.5px, so equal padding renders it 36px tall in a row of 38px buttons
2137
2844
  (measured in headless Chrome). The extra pixel per side matches .hd-pr, which
2138
2845
  is the same type size and already pays it. */
2139
- .hd-archive,.pd-remove{display:flex;align-items:center;gap:8px;padding:9px 15px;border:1.5px solid var(--red-bg);
2846
+ .hd-archive,.pd-remove{display:flex;align-items:center;gap:8px;padding:8.5px 15px;border:1.5px solid var(--red-bg); /* 12.5px type + 8.5px = the 13.5px buttons' height */
2140
2847
  border-radius:999px;background:var(--panel);font:600 12.5px var(--sans);color:var(--red-ink);cursor:pointer;}
2141
2848
  .hd-archive[hidden]{display:none;}
2142
2849
  .hd-archive:hover:not([disabled]),.pd-remove:hover:not([disabled]){background:var(--red-bg);border-color:var(--red);}
@@ -2180,6 +2887,33 @@ section[data-view="team-metrics"] .topbar{align-items:flex-start;}
2180
2887
  .hd-sec-* body) a display value, the inactive panels would all render at once. */
2181
2888
  .hd-sec[hidden],.pd-sec[hidden]{display:none;}
2182
2889
 
2890
+ /* ---------- shared code editor (scripts workbench §W16) ---------- */
2891
+ /* Two layers, one box: the <pre> paints the colours, the textarea above it is
2892
+ transparent ink with a visible caret. Both must share EVERY metric that moves
2893
+ a glyph — font, size, line-height, padding, white-space, tab-size — or the two
2894
+ layers drift apart as the text grows. */
2895
+ .code-editor{position:relative;border:1px solid var(--line-2);border-radius:var(--r-ctrl);background:var(--field);overflow:hidden;}
2896
+ .code-editor:focus-within{background:var(--field-focus);border-color:var(--ink);}
2897
+ .code-editor .code-editor-hl,.code-editor .code-editor-ta{
2898
+ margin:0;padding:12px 14px;font-family:var(--mono);font-size:12.5px;line-height:1.55;
2899
+ white-space:pre;tab-size:2;border:0;letter-spacing:normal;}
2900
+ .code-editor .code-editor-hl{position:absolute;inset:0;overflow:auto;pointer-events:none;color:var(--ink);background:transparent;}
2901
+ .code-editor .code-editor-hl code{font:inherit;color:inherit;background:none;padding:0;}
2902
+ .code-editor .code-editor-ta{position:relative;display:block;width:100%;min-height:0;resize:vertical;
2903
+ overflow:auto;background:transparent;color:transparent;caret-color:var(--ink);outline:none;}
2904
+ .code-editor .code-editor-ta::selection{background:var(--selection);}
2905
+ .code-editor.ro{background:var(--field);}
2906
+ .code-editor.ro .code-editor-ta{cursor:default;caret-color:transparent;}
2907
+ .code-editor :is(.hljs-comment,.hljs-quote,.hljs-punctuation){color:var(--hd-syntax-comment);}
2908
+ .code-editor :is(.hljs-keyword,.hljs-operator,.hljs-meta,.hljs-deletion){color:var(--hd-syntax-keyword);}
2909
+ .code-editor :is(.hljs-type,.hljs-built_in,.hljs-attr,.hljs-attribute,
2910
+ .hljs-selector-class,.hljs-selector-id,.hljs-selector-tag){color:var(--hd-syntax-type);}
2911
+ .code-editor :is(.hljs-string,.hljs-regexp,.hljs-addition){color:var(--hd-syntax-string);}
2912
+ .code-editor :is(.hljs-number,.hljs-literal,.hljs-symbol,.hljs-bullet,
2913
+ .hljs-variable,.hljs-template-variable){color:var(--hd-syntax-literal);}
2914
+ .code-editor :is(.hljs-title,.hljs-section,.hljs-name){color:var(--hd-syntax-title);}
2915
+ .code-editor :is(.hljs-comment,.hljs-quote){font-style:italic;}
2916
+
2183
2917
  /* ---------- History detail: Diff tab ---------- */
2184
2918
  .hd-diff{display:grid;grid-template-columns:minmax(280px,340px) 1fr;gap:18px;align-items:start;}
2185
2919
  .hd-diff{
@@ -2190,7 +2924,7 @@ section[data-view="team-metrics"] .topbar{align-items:flex-start;}
2190
2924
  .hd-diff .diff-del{color:var(--hd-count-del);}
2191
2925
  @media (max-width:900px){.hd-diff{grid-template-columns:1fr;}}
2192
2926
  .hd-diff-list,.hd-diff-pane{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;}
2193
- .hd-diff-pane,.ask-md{
2927
+ .hd-diff-pane,.ask-md,.code-editor{
2194
2928
  --hd-syntax-comment:light-dark(#5B6167,#8B949E);
2195
2929
  --hd-syntax-keyword:light-dark(#B31D28,#FF7B72);
2196
2930
  --hd-syntax-type:light-dark(#9A3E00,#FFA657);
@@ -2498,6 +3232,11 @@ button.hd-mem-chip:focus-visible{outline:2px solid var(--ink);outline-offset:2px
2498
3232
  .mem-reasons li{margin:4px 0;}
2499
3233
  .mem-actions{margin-top:12px;align-items:center;gap:10px;}
2500
3234
  .mem-health-head .mem-defrag{margin-left:auto;}
3235
+ /* Settings → Memory: the Defragment model card above the scope (app.js paintMemDefragModelSettings). */
3236
+ .mem-model-card{margin-bottom:16px;}
3237
+ .mem-model-text{margin:0 0 12px;color:var(--ink-2);font-size:13px;line-height:1.5;}
3238
+ .mem-model-row{display:flex;flex-wrap:wrap;gap:12px;}
3239
+ .mem-model-row .field{flex:1 1 220px;margin-bottom:0;}
2501
3240
  .mem-defrag svg{display:block;flex:none;}
2502
3241
  .mem-host-hint{display:block;margin-top:8px;}
2503
3242
  .mem-list,.mem-history{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);padding:14px 16px;}
@@ -2572,6 +3311,8 @@ button.hd-mem-chip:focus-visible{outline:2px solid var(--ink);outline-offset:2px
2572
3311
  .hd-pr:hover{opacity:.88;}
2573
3312
  .hd-pr-link{flex:0 0 auto;font:600 12.5px var(--sans);}
2574
3313
  .hd-pr-link[hidden]{display:none;}
3314
+ .hd-after{display:inline-flex;align-items:center;gap:8px;padding:8px 15px;flex:0 0 auto;}
3315
+ .hd-after[hidden]{display:none;}
2575
3316
 
2576
3317
  /* WIDTH GOES ON `#shipit-modal .card`, NOT `.shipit-card`. The markup is
2577
3318
  `<div class="card shipit-card">` inside `.viewer-modal`, and
@@ -2604,6 +3345,15 @@ button.hd-mem-chip:focus-visible{outline:2px solid var(--ink);outline-offset:2px
2604
3345
  .shipit-files:empty + .shipit-dot{display:none;}
2605
3346
  .shipit-break{flex-basis:100%;height:0;}
2606
3347
  .shipit-branch{color:var(--ink);word-break:break-all;}
3348
+ /* The base-branch pick stands where the plain base name was, inline in the
3349
+ summary line: a compact house select (cf. `.step-config select`) on the
3350
+ --field pill, not the full-width form field. */
3351
+ .shipit-summary .select-wrap{max-width:100%;}
3352
+ .shipit-summary .select{width:auto;max-width:100%;padding:6px 30px 6px 10px;font:inherit;color:var(--ink);
3353
+ background:var(--surface);border-color:var(--line-2);border-radius:10px;}
3354
+ .shipit-summary .select:focus{border-color:var(--ink);}
3355
+ .shipit-summary .select-wrap::after{right:11px;}
3356
+ .shipit-summary select:disabled{opacity:.55;cursor:not-allowed;}
2607
3357
  .shipit-actions{display:flex;align-items:center;justify-content:center;gap:10px;margin-top:22px;}
2608
3358
  .shipit-ok{padding:11px 22px;border:1.5px solid var(--ink);border-radius:999px;background:var(--ink);
2609
3359
  font:600 13.5px var(--sans);color:var(--on-ink);cursor:pointer;}
@@ -2686,7 +3436,7 @@ button.hd-mem-chip:focus-visible{outline:2px solid var(--ink);outline-offset:2px
2686
3436
  `.hd-diff-file` already has its own (inset) ring and is not repeated here. */
2687
3437
  .hd-tab:focus-visible,.hd-back:focus-visible,.hd-resume:focus-visible,.pd-tab:focus-visible,.pd-back:focus-visible,.pd-new:focus-visible,.pd-history:focus-visible,.pd-remove:focus-visible,.pd-sec:focus-visible,.proj-open:focus-visible,.pd-ov-link:focus-visible,
2688
3438
  .hd-more:focus-visible,.hd-report:focus-visible,
2689
- .hd-archive:focus-visible,.hd-pr:focus-visible,.hd-pr-link:focus-visible,
3439
+ .hd-archive:focus-visible,.hd-pr:focus-visible,.hd-pr-link:focus-visible,.hd-after:focus-visible,
2690
3440
  .hd-branch-copy:focus-visible,.hd-sec:focus-visible,.hist-open:focus-visible,
2691
3441
  .hist-branch-copy:focus-visible,.shipit-ok:focus-visible,.shipit-cancel:focus-visible{
2692
3442
  outline:2px solid var(--ink);outline-offset:2px;}
@@ -2748,8 +3498,8 @@ button.hd-mem-chip:focus-visible{outline:2px solid var(--ink);outline-offset:2px
2748
3498
  .rc-qpill{display:inline-flex;align-items:center;padding:5px 11px;border-radius:999px;
2749
3499
  background:var(--amber-bg);color:var(--amber-ink);font:700 11.5px var(--sans);white-space:nowrap;}
2750
3500
  .rc-qpill[hidden]{display:none;}
2751
- /* the four 30px icon buttons; .rc-open mirrors .hist-open exactly */
2752
- .rc-acts .btn-pause,.rc-acts .btn-resume,.rc-acts .btn-stop,.rc-open{
3501
+ /* the five 30px icon buttons; .rc-open mirrors .hist-open exactly */
3502
+ .rc-acts .btn-pause,.rc-acts .btn-resume,.rc-acts .btn-stop,.rc-after,.rc-open{
2753
3503
  display:inline-flex;align-items:center;justify-content:center;gap:0;
2754
3504
  width:30px;height:30px;padding:0;border-radius:9px;background:var(--panel);cursor:pointer;}
2755
3505
  .rc-acts .btn-pause,.rc-acts .btn-resume{border:1px solid var(--amber);color:var(--amber-ink);}
@@ -2760,9 +3510,15 @@ button.hd-mem-chip:focus-visible{outline:2px solid var(--ink);outline-offset:2px
2760
3510
  with `.rc-acts .btn-pause` above and would LOSE on source order — a paused card
2761
3511
  would show both buttons. Re-state it at the cluster's specificity. */
2762
3512
  .rc-acts .btn-pause[hidden],.rc-acts .btn-resume[hidden]{display:none;}
3513
+ /* Same footgun for the run-chain button: the shared `display:inline-flex` above is an
3514
+ AUTHOR rule and outranks the UA `[hidden]{display:none}`, so paintRunCard's
3515
+ `afterBtn.hidden = true` would not hide it. Re-state it here. */
3516
+ .rc-acts .rc-after[hidden]{display:none;}
2763
3517
  .rc-open{border:1px solid var(--line);color:var(--ink-2);}
2764
3518
  .rc-open:hover{background:var(--ink);color:var(--on-ink);border-color:var(--ink);}
2765
- .rc-open:focus-visible,.rc-branch-copy:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
3519
+ .rc-after{border:1px solid var(--line);color:var(--ink-2);}
3520
+ .rc-after:hover{background:var(--ink);color:var(--on-ink);border-color:var(--ink);}
3521
+ .rc-after:focus-visible,.rc-open:focus-visible,.rc-branch-copy:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
2766
3522
  /* ---------- Running redesign: shared keyframes (C2 — declared ONCE, here) ----------
2767
3523
  @keyframes are name-resolved, not cascaded, so their position relative to the
2768
3524
  rules that use them is irrelevant; what matters is that there is exactly one of
@@ -3106,9 +3862,9 @@ body.view-running .topnav{margin:12px 32px 0;flex:0 0 auto;}
3106
3862
 
3107
3863
  /* ---------- Collapsible sidebar: the 76px icon rail ---------- */
3108
3864
  /* No rule here restyles anything the expanded 298px column already had: 21 of
3109
- the 39 are scoped under `.sidebar.collapsed`, and the other 18
3110
- (`.brand .logo-mark`, `.side-toggle*`, `.nav .rail-tile*`, `.spend-ring*`)
3111
- style nodes that exist only because of this feature. The <1080px breakpoint
3865
+ them are scoped under `.sidebar.collapsed`, and the rest (`.brand .logo-mark`,
3866
+ `.side-toggle*`, `.nav .rail-tile*`, `.spend-ring*`, `.spend-stack*`) style
3867
+ nodes that exist only because of this feature. The <1080px breakpoint
3112
3868
  (:920-922) still hides the sidebar outright and hands over to .topnav —
3113
3869
  collapse is a preference that only exists above it, and the two never overlap.
3114
3870
  HOUSE RULE for this whole block: no comment inside a rule body, and no
@@ -3244,6 +4000,19 @@ body.view-running .topnav{margin:12px 32px 0;flex:0 0 auto;}
3244
4000
  `padding:11px 13px` and hold its initials in an 8px content box.
3245
4001
  `flex:0 0 auto` keeps the fixed 36px box out of the column flex shrink. */
3246
4002
  .sidebar.collapsed .nav-children{align-items:center;gap:5px;margin-top:5px;}
4003
+ /* Nodes on the rail: no room for a parent row, so it goes and its two children
4004
+ stand as ordinary 40px squares — the rail reads exactly as it did before the
4005
+ group existed. The children must show even while the group is folded, so the
4006
+ (0,3,0) rule out-ranks `.nav-children.collapsed` (0,2,0). The elbow has
4007
+ nothing to hang from here, and an open child takes the same dark fill as
4008
+ every other current-page square (beats `.nav .nav-child.active` on class
4009
+ count). */
4010
+ .sidebar.collapsed .nav-group{display:none;}
4011
+ .sidebar.collapsed .nav-group-children.collapsed{display:flex;}
4012
+ .sidebar.collapsed .nav-child::before,.sidebar.collapsed .nav-child::after{content:none;}
4013
+ .sidebar.collapsed .nav .nav-child > svg{width:19px;height:19px;}
4014
+ .sidebar.collapsed .nav .nav-child.active{background:var(--ink);color:var(--on-ink);box-shadow:none;}
4015
+ .sidebar.collapsed .nav .nav-child.active svg{stroke:var(--on-ink);}
3247
4016
  .nav .rail-tile{position:relative;display:flex;align-items:center;justify-content:center;
3248
4017
  width:36px;height:36px;flex:0 0 auto;padding:0;gap:0;
3249
4018
  border:1.5px solid var(--line-2);border-radius:11px;
@@ -3311,15 +4080,33 @@ body.view-running .topnav{margin:12px 32px 0;flex:0 0 auto;}
3311
4080
  filter:brightness(.96);}
3312
4081
  .spend-ring.warn{--ring-fill:var(--amber-ink);--ring-track:var(--amber-bg);}
3313
4082
  .spend-ring.over{--ring-fill:var(--red-ink);--ring-track:var(--red-bg);}
3314
- /* No total limit means no denominator: a flat neutral ring, and the centre shows
3315
- the amount instead of a percentage nothing backs. var(--ink-3), not
3316
- var(--line) — var(--line) on var(--panel) is ~1.1:1 across a 4.5px annulus, i.e.
3317
- an absent ring, which is not the same thing as a neutral one. */
3318
- .spend-ring.no-limit{--ring-fill:var(--ink-3);--ring-track:var(--ink-3);}
3319
4083
  .spend-ring-val{display:flex;align-items:center;justify-content:center;
3320
4084
  width:29px;height:29px;border-radius:50%;background:var(--panel);
3321
4085
  font-family:var(--mono);font-size:9.5px;color:var(--ink-2);}
3322
4086
 
4087
+ /* ---- rail spend stack (no total limit) ---- */
4088
+ /* No total limit means no denominator, so the rail drops the ring for two stacked
4089
+ figures: a caps label over a compact mono amount, Spent then Saved.
4090
+ `.spend-stack` ties `.spend-ind` at (0,1,0) and wins the tie on source order, which
4091
+ is what lets it override display / width / padding / border-radius and keep the
4092
+ card's border, --field fill and pointer. 40px is the width of every rail square
4093
+ (nav buttons, the toggle), so it overhangs the 39px content box by the same half
4094
+ pixel they do and nothing clips; border-box leaves 38px inside, and the widest
4095
+ amount railUsd() emits ("−$8.8k", six glyphs at 10px mono) is 36px.
4096
+ `.spend-ind:hover` recolours the background only, which is the hover this wants.
4097
+ A non-negative Saved pair is --green-ink-strong, as in the expanded card; Spent and a
4098
+ loss stay --ink (--red-ink is 4.07:1 on that hover fill, under verify:theme's 4.5:1). */
4099
+ .spend-stack{display:flex;flex-direction:column;align-items:center;
4100
+ width:40px;padding:7px 0;border-radius:12px;text-align:center;}
4101
+ .spend-stack-pair{display:flex;flex-direction:column;align-items:center;gap:1px;}
4102
+ .spend-stack-pair + .spend-stack-pair::before{content:"";width:22px;height:1px;
4103
+ margin:5px 0;background:var(--line-2);}
4104
+ .spend-stack-lbl{font-family:var(--sans);font-size:9px;font-weight:600;line-height:1.1;
4105
+ letter-spacing:.04em;text-transform:uppercase;color:var(--ink-2);}
4106
+ .spend-stack-val{font-family:var(--mono);font-size:10px;font-weight:600;line-height:1.2;
4107
+ white-space:nowrap;color:var(--ink);}
4108
+ .spend-stack-pair.pos .spend-stack-lbl,.spend-stack-pair.pos .spend-stack-val{color:var(--green-ink-strong);}
4109
+
3323
4110
  /* ---------- Ask Worca (spec §10.3-§10.6; tokens only, no hex) ---------- */
3324
4111
  /* Fixed full-height dock over the content column; children restore pointer
3325
4112
  events. z-40 sits above sticky tab lists (5) and below .viewer-modal (50)
@@ -3624,6 +4411,7 @@ body.rail-collapsed .ask-dock{left:76px;}
3624
4411
  .ask-rp-lane-msg{padding:12px 14px;font-size:12px;color:var(--ink-3);}
3625
4412
  .ask-card.ask-rp textarea.ask-rp-brief{width:100%;min-height:150px;max-height:420px;padding:12px 14px;border:1px solid var(--line-2);border-radius:12px;background:var(--field);font-size:13px;line-height:1.6;resize:vertical;}
3626
4413
  .ask-rp-brief-foot{display:flex;align-items:center;gap:12px;margin-top:8px;font-size:11.5px;color:var(--ink-3);flex-wrap:wrap;}
4414
+ .ask-rp-brief-foot[hidden],.ask-rp-brief[hidden]{display:none;} /* a tracker-task card shows the task instead */
3627
4415
  .ask-rp-brief-foot kbd{font-family:var(--mono);font-size:10px;padding:1px 5px;border:1px solid var(--line-2);border-radius:5px;background:var(--panel);color:var(--ink-2);}
3628
4416
  .ask-rp-count{margin-left:auto;}
3629
4417
  .ask-rp-pills{display:flex;gap:6px;flex-wrap:wrap;}
@@ -3695,6 +4483,27 @@ body.rail-collapsed .ask-dock{left:76px;}
3695
4483
  .ask-mcard-results li.is-skipped{color:var(--ink-3);}
3696
4484
  .ask-mcard-actions{display:flex;align-items:center;gap:8px;margin-top:14px;}
3697
4485
  .ask-mcard.is-applied .ask-mcard-head{opacity:.9;}
4486
+ /* Team policy card (docs/team-policy.md "Ask Worca"): an edit's before → after list. */
4487
+ .ask-mcard-changes{list-style:none;margin:4px 0 0;padding:8px 10px;border-radius:8px;background:var(--field);display:flex;flex-direction:column;gap:4px;font-size:12.5px;}
4488
+ .ask-mcard-changes li{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:4px 12px;min-width:0;}
4489
+ .ask-mcard-change-label{color:var(--ink-2);}
4490
+ .ask-mcard-change-val{display:inline-flex;flex-wrap:wrap;align-items:baseline;gap:6px;font-family:var(--mono);font-size:11.5px;min-width:0;}
4491
+ .ask-mcard-before{color:var(--ink-3);text-decoration:line-through;}
4492
+ .ask-mcard-before.is-unset,.ask-mcard-after.is-unset{text-decoration:none;font-style:italic;color:var(--ink-3);}
4493
+ .ask-mcard-arrow{color:var(--ink-3);}
4494
+ .ask-mcard-after{color:var(--ink);font-weight:600;}
4495
+ /* schedule card (buildScheduleCard; docs/scheduled-runs.md "Ask Worca"): the metrics card's chrome + a before/after grid */
4496
+ .ask-scard-kv{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:4px 14px;margin-top:4px;font-size:12.5px;}
4497
+ .ask-scard-k{color:var(--ink-3);}
4498
+ .ask-scard-v{color:var(--ink);font-variant-numeric:tabular-nums;overflow-wrap:anywhere;}
4499
+ .ask-scard .ask-card-sched-link{align-self:flex-start;margin-top:2px;}
4500
+ .ask-card-start.is-danger{background:var(--red-ink);color:var(--on-status);}
4501
+ /* endpoint import sheet (bridge-view.mjs renderEndpointSheet): the server's own warnings, and a window it would not name */
4502
+ .mvi-warn{display:block;color:var(--amber-ink);}
4503
+ .mvi-ctx-unknown{color:var(--ink-3);font-size:11.5px;}
4504
+ /* model card (buildModelCard; docs/models.md "Ask Worca"): the policy card's change list + what will still block the model */
4505
+ .ask-modcard-warn{color:var(--amber-ink);}
4506
+ .ask-modcard .ask-card-sched-link{align-self:flex-start;margin-top:2px;}
3698
4507
 
3699
4508
  /* ---------- Auto proposal body (ui/public/auto-proposal.mjs) — one body, two hosts (mockup §D/§F) ----------
3700
4509
  Rhythm top→bottom: name → 8 → reasoning → 16 → chips → 8 → fingerprint → 16 → graph → 12 → loops → 16 → match → 8 → meta.
@@ -4018,6 +4827,7 @@ body.rail-collapsed .ask-dock{left:76px;}
4018
4827
  their sticky tab bars and take clearance via .rd-body/.hd-body/.pd-body instead;
4019
4828
  body.view-history/.view-running/.view-projects .main keep padding:0 by specificity. */
4020
4829
  .main,.run-screen-list,.hist-screen-list,.proj-screen-list,.rd-body,.hd-body,.pd-body{padding-bottom:var(--ask-dock-clearance);}
4830
+ .ws-screen-list{padding-bottom:var(--ask-dock-clearance);} /* the Workspaces track's list gutter, the same clearance */
4021
4831
 
4022
4832
  /* ---------- native control skins (checkbox / radio / switch / rows) -------- */
4023
4833
  /* Everything the browser used to draw for itself. The mark is the one .qopt
@@ -4188,10 +4998,10 @@ html{scrollbar-color:var(--line-2) transparent;scrollbar-width:thin;}
4188
4998
  .gs-hide{background:none;border:0;padding:0;font:inherit;font-size:12.5px;color:var(--ink-2);cursor:pointer;
4189
4999
  text-decoration:underline;text-underline-offset:3px;}
4190
5000
  .gs-hide:hover{color:var(--ink);}
4191
- /* Equal tiles that fill the row and wrap 4 -> 2 -> 1: symmetric, never a 3+1 orphan. */
4192
- .gs-tiles{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;}
4193
- @media (max-width:760px){.gs-tiles{grid-template-columns:repeat(2,minmax(0,1fr));}}
4194
- @media (max-width:440px){.gs-tiles{grid-template-columns:1fr;}}
5001
+ /* Nine equal tiles that fill the row and wrap 3 -> 1: a 3×3 square, then one column — two
5002
+ columns would leave the ninth an orphan. */
5003
+ .gs-tiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;}
5004
+ @media (max-width:640px){.gs-tiles{grid-template-columns:1fr;}}
4195
5005
  .gs-tile{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:6px;
4196
5006
  border:1.5px solid var(--line);border-radius:var(--r-ctrl);background:var(--surface);
4197
5007
  padding:12px 14px 13px;font:inherit;font-size:13px;line-height:1.35;color:var(--ink);text-align:left;cursor:pointer;
@@ -4300,8 +5110,12 @@ html{scrollbar-color:var(--line-2) transparent;scrollbar-width:thin;}
4300
5110
  modal layer instead. */
4301
5111
  .guide-scrim{position:fixed;inset:0;z-index:44;background:var(--scrim);}
4302
5112
  /* !important: a control may carry its own id-level position/z-index (#prompt has z-index:1) that
4303
- would otherwise beat this transient class and leave the ringed control UNDER the scrim. */
4304
- .guide-target{position:relative !important;z-index:45 !important;}
5113
+ would otherwise beat this transient class and leave the ringed control UNDER the scrim.
5114
+ The position is forced only on a STATIC control (guide-spot adds -static after reading
5115
+ the computed style): an absolutely positioned target — the Composer's floating rail —
5116
+ must keep its own position or it drops out of place. */
5117
+ .guide-target{z-index:45 !important;}
5118
+ .guide-target-static{position:relative !important;}
4305
5119
  .guide-lift{z-index:45 !important;}
4306
5120
  .guide-lift-static{position:relative;}
4307
5121
  /* A lifted select wrapper keeps its chevron ON TOP of the elevated select (the
@@ -4321,22 +5135,316 @@ html{scrollbar-color:var(--line-2) transparent;scrollbar-width:thin;}
4321
5135
  .guide-balloon::before{content:'';position:absolute;top:-6px;left:calc(var(--arrow-x,20px) - 5px);width:10px;height:10px;
4322
5136
  background:var(--panel);border-left:1px solid var(--line-2);border-top:1px solid var(--line-2);transform:rotate(45deg);}
4323
5137
  .guide-balloon.above::before{top:auto;bottom:-6px;transform:rotate(225deg);}
5138
+ /* Pinned inside the viewport over a target taller than it: no edge to point at. */
5139
+ .guide-balloon.pinned::before{display:none;}
4324
5140
  .guide-skip{background:none;border:0;padding:0;font:inherit;font-size:12px;color:var(--ink-2);cursor:pointer;
4325
5141
  text-decoration:underline;text-underline-offset:3px;}
4326
5142
  .guide-skip:hover{color:var(--ink);}
5143
+ /* Next (an explanation hop, or a control whose state is already right) sits beside Skip. */
5144
+ .guide-actions{display:flex;align-items:center;gap:14px;}
5145
+ .guide-next{padding:6px 14px;border:0;border-radius:999px;background:var(--ink);color:var(--on-ink);
5146
+ font:600 12px var(--sans);font-family:inherit;cursor:pointer;transition:filter .12s;}
5147
+ .guide-next:hover{filter:brightness(1.15);}
5148
+ .guide-next:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
4327
5149
  .guide-ring[hidden],.guide-balloon[hidden]{display:none;}
5150
+ /* A click on the scrim: the ring flashes a wider halo and the balloon bobs once — "here". */
5151
+ .guide-ring.nudge{animation:guide-nudge-ring .45s ease-out;}
5152
+ .guide-balloon.nudge{animation:guide-nudge-balloon .45s ease-out;}
5153
+ @keyframes guide-nudge-ring{
5154
+ 0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--violet) 70%,transparent);transform:scale(1);}
5155
+ 40%{transform:scale(1.04);}
5156
+ 100%{box-shadow:0 0 0 22px color-mix(in srgb,var(--violet) 0%,transparent);transform:scale(1);}
5157
+ }
5158
+ @keyframes guide-nudge-balloon{
5159
+ 0%,100%{transform:translateY(0);}
5160
+ 35%{transform:translateY(-6px);}
5161
+ 70%{transform:translateY(2px);}
5162
+ }
4328
5163
  .guide-layer.pointer .guide-ring{z-index:72;}
4329
5164
  .guide-layer.pointer .guide-balloon{z-index:73;}
4330
5165
 
4331
5166
 
5167
+
5168
+ /* ---------- Scheduled runs: the Schedules view, the schedule sheet, the split Start button ----------
5169
+ Tokens only (no hex): a waiting run is NEUTRAL — grey with a clock — so it never competes
5170
+ with the amber items that need a decision. Missed is amber; a schedule that paused itself too. */
5171
+ .rc-sic.st-grey{background:var(--field);color:var(--ink-2);}
5172
+ .rc-status-word.st-grey{color:var(--ink-2);}
5173
+ .badge.blue{background:var(--blue-bg);color:var(--blue-ink);}
5174
+
5175
+ /* split Start button: the primary action keeps its pill; the caret is its right half */
5176
+ .btn-split{display:inline-flex;align-items:stretch;position:relative;}
5177
+ .btn-split > .btn-go:first-child{border-radius:999px 0 0 999px;padding-right:22px;}
5178
+ .btn-split > .btn-split-more{display:inline-flex;align-items:center;justify-content:center;background:var(--ink);color:var(--on-ink);
5179
+ border:none;border-left:1px solid var(--on-ink-wash-2);border-radius:0 999px 999px 0;padding:0 16px 0 13px;cursor:pointer;
5180
+ transition:transform .15s,filter .15s;}
5181
+ .btn-split > .btn-split-more:hover{filter:brightness(1.08);}
5182
+ .btn-split > .btn-split-more:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
5183
+ .btn-split > .btn-go:disabled,.btn-split > .btn-split-more:disabled{opacity:.45;cursor:not-allowed;transform:none;filter:none;}
5184
+ .btn-split-menu{position:absolute;right:0;bottom:calc(100% + 8px);z-index:20;min-width:230px;padding:6px;
5185
+ background:var(--panel);border:1px solid var(--line);border-radius:16px;box-shadow:var(--shadow-menu);}
5186
+ .btn-split-menu[hidden]{display:none;}
5187
+ .btn-split-menu button{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;text-align:left;
5188
+ background:transparent;border:none;border-radius:11px;padding:10px 12px;font-family:inherit;cursor:pointer;color:var(--ink);}
5189
+ .btn-split-menu button:hover,.btn-split-menu button:focus-visible{background:var(--field);outline:none;}
5190
+ .btn-split-menu b{font-weight:600;font-size:13.5px;}
5191
+ .btn-split-menu small{font-size:12px;color:var(--ink-3);}
5192
+ .btn-split.mini > .btn-go:first-child{padding:9px 14px 9px 16px;font-size:12.5px;}
5193
+ .btn-split.mini > .btn-split-more{padding:0 12px 0 9px;}
5194
+ .btn-split.mini .btn-split-menu{bottom:auto;top:calc(100% + 8px);}
5195
+ /* Simple mode hides the caret (Schedule… is Advanced): the Start pill closes up again. */
5196
+ :root[data-level="simple"] .btn-split > .btn-go:first-child:not(:has(~ [data-level-keep])){border-radius:999px;padding-right:28px;}
5197
+ :root[data-level="simple"] .btn-split.mini > .btn-go:first-child:not(:has(~ [data-level-keep])){padding-right:14px;}
5198
+
5199
+ /* the schedule sheet */
5200
+ .sched-modal .card.sched-card{width:min(600px,100%);animation:wr-rise .28s cubic-bezier(.2,.7,.3,1) both;}
5201
+ .sched-run-title{margin:-10px 0 16px;color:var(--ink-2);font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
5202
+ .sched-presets{display:flex;flex-wrap:wrap;margin-bottom:16px;}
5203
+ .sched-presets button{flex:1 1 auto;padding:9px 8px;font-size:12.5px;white-space:nowrap;}
5204
+ .sched-quick{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px;}
5205
+ .sched-quick[hidden]{display:none;}
5206
+ .sched-kind{display:flex;margin-bottom:14px;}
5207
+ .sched-kind button{flex:1 1 0;padding:11px 12px;font-size:13px;}
5208
+ .sched-after{display:grid;gap:10px;}
5209
+ /* paint() hides the presets seg and the After block by the `hidden` PROPERTY. `.sched-presets`
5210
+ (display:flex) and `.sched-after` (display:grid) are AUTHOR display rules and outrank the UA
5211
+ [hidden]{display:none} — the .sched-quick[hidden] footgun above. Restate both. */
5212
+ .sched-presets[hidden],.sched-after[hidden]{display:none;}
5213
+ .sched-chip{border:1.5px solid transparent;cursor:pointer;font-family:inherit;transition:background .14s,border-color .14s;}
5214
+ .sched-chip:hover{border-color:var(--line-2);}
5215
+ .sched-chip.on{background:var(--surface);border-color:var(--ink);color:var(--ink);}
5216
+ .sched-chip:focus-visible,.sched-day:focus-visible,.sched-tz-change:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
5217
+ .sched-days{display:flex;flex-wrap:wrap;gap:6px;}
5218
+ .sched-day{width:42px;height:38px;border-radius:12px;border:1.5px solid transparent;background:var(--field);color:var(--ink-2);
5219
+ font:600 12.5px var(--sans);cursor:pointer;transition:background .14s,color .14s;}
5220
+ .sched-day:hover{border-color:var(--line-2);}
5221
+ .sched-day.on{background:var(--ink);color:var(--on-ink);}
5222
+ .sched-inline{display:flex;gap:9px;align-items:center;}
5223
+ .sched-inline > *{flex:1 1 0;min-width:0;}
5224
+ .sched-inline > input[type="number"]{flex:0 0 92px;}
5225
+ .sched-inline > [hidden]{display:none;}
5226
+ .sched-card .field-grid-2[hidden],.sched-card .field[hidden]{display:none;}
5227
+ .sched-sentence{margin:4px 0 8px;padding:13px 15px;border-radius:var(--r-ctrl);background:var(--violet-wash);
5228
+ border:1px solid var(--violet-bg);font-size:14px;line-height:1.45;}
5229
+ .sched-sentence b{font-weight:600;}
5230
+ .sched-sentence.bad{background:var(--field);border-color:var(--line);}
5231
+ .sched-next{margin-top:3px;color:var(--ink-2);font-size:12.5px;font-variant-numeric:tabular-nums;min-height:18px;}
5232
+ .sched-tz{margin:0 0 16px;color:var(--ink-3);font-size:12px;}
5233
+ .sched-tz-change{background:none;border:none;padding:0;font:600 12px var(--sans);color:var(--blue-ink-strong);cursor:pointer;text-decoration:underline;}
5234
+ #sched-tz{margin:-8px 0 16px;}
5235
+ #sched-tz[hidden]{display:none;}
5236
+ .sched-note{margin-top:2px;}
5237
+ .sched-warn{margin-top:10px;padding:10px 13px;border-radius:12px;background:var(--amber-wash);border:1px solid var(--amber-line);}
5238
+ .sched-err{margin-top:10px;}
5239
+ .sched-err[hidden]{display:none;}
5240
+
5241
+ /* the Schedules view: a tab strip (the Statistics .seg) over one pane at a time */
5242
+ .sched-tabs{display:flex;margin-bottom:18px;}
5243
+ .sched-pane[hidden]{display:none;}
5244
+ .sched-list{display:flex;flex-direction:column;gap:14px;}
5245
+ .sched-group-title{font:700 11.5px var(--sans);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);margin:6px 4px -2px;}
5246
+ .sched-item{padding:18px 20px;}
5247
+ .sched-item.attention{border:1.5px solid var(--amber);box-shadow:0 0 0 4px var(--amber-bg),var(--shadow);}
5248
+ .sched-head{display:flex;align-items:flex-start;gap:13px;}
5249
+ .sched-head .rc-sic{align-self:flex-start;}
5250
+ .sched-head .rc-title{white-space:normal;}
5251
+ .sched-head > .switch{flex:0 0 auto;margin-top:5px;}
5252
+ .sched-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px;
5253
+ margin-top:14px;padding-top:12px;border-top:1px solid var(--line);}
5254
+ .sched-acts{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:7px;margin-left:auto;}
5255
+ .sched-acts [hidden]{display:none;}
5256
+ .sched-sub{display:flex;flex-wrap:wrap;align-items:center;gap:9px;margin-top:9px;font-size:12.5px;color:var(--ink-2);}
5257
+ .sched-when{font-variant-numeric:tabular-nums;}
5258
+ .sched-sub .sched-when{font-weight:600;color:var(--ink);}
5259
+ .sched-target{margin-top:4px;font-size:12.5px;color:var(--ink-3);overflow-wrap:anywhere;}
5260
+ .sched-rule{color:var(--ink-2);font-weight:500;}
5261
+ .sched-reason{margin-top:7px;font-size:12.5px;color:var(--amber-ink);}
5262
+ .sched-more{display:inline-flex;align-items:center;gap:7px;background:none;border:none;padding:6px 2px;cursor:pointer;
5263
+ font:600 12px var(--sans);color:var(--ink-3);}
5264
+ .sched-more:hover{color:var(--ink);}
5265
+ .sched-more::before{content:"";width:6px;height:6px;border-right:1.8px solid currentColor;border-bottom:1.8px solid currentColor;
5266
+ transform:rotate(-45deg);transition:transform .15s;}
5267
+ .sched-more[aria-expanded="true"]::before{transform:rotate(45deg);}
5268
+ .sched-more:focus-visible{outline:2px solid var(--ink);outline-offset:3px;border-radius:6px;}
5269
+ .sched-details-body{display:grid;gap:7px;margin-top:12px;}
5270
+ .sched-details-body[hidden]{display:none;}
5271
+ .sched-kv{display:grid;grid-template-columns:210px minmax(0,1fr);gap:12px;font-size:12.5px;}
5272
+ .sched-k{color:var(--ink-3);}
5273
+ .sched-v{color:var(--ink);white-space:pre-wrap;overflow-wrap:anywhere;}
5274
+ @media (max-width:720px){.sched-kv{grid-template-columns:minmax(0,1fr);gap:1px;}.sched-acts{justify-content:flex-start;margin-left:0;}}
5275
+
5276
+ .sched-feed{padding:20px 22px;}
5277
+ .sched-feed-head{flex-wrap:wrap;gap:12px;margin-bottom:8px;}
5278
+ .sched-feed-tools{display:flex;flex-wrap:wrap;align-items:center;gap:10px;}
5279
+ .sched-feed-item{display:grid;grid-template-columns:92px minmax(0,1fr) auto;gap:4px 12px;align-items:start;padding:13px 0 13px 12px;
5280
+ border-top:1px solid var(--line);border-left:3px solid transparent;margin-left:-12px;}
5281
+ .sched-feed-item:first-child{border-top:none;}
5282
+ .sched-feed-item.unread{border-left-color:var(--amber);}
5283
+ .sched-feed-item .badge{justify-self:start;margin-top:1px;}
5284
+ .sched-feed-text{font-size:13px;line-height:1.5;color:var(--ink-2);overflow-wrap:anywhere;}
5285
+ .sched-feed-text b{font-weight:600;color:var(--ink);}
5286
+ .sched-feed-time{margin-top:2px;font-size:11.5px;color:var(--ink-3);}
5287
+ .sched-feed-acts{grid-column:3;grid-row:1;align-self:center;justify-self:end;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:7px;}
5288
+ .sched-feed-acts:empty{display:none;}
5289
+ @media (max-width:720px){.sched-feed-item{grid-template-columns:92px minmax(0,1fr);}.sched-feed-acts{grid-column:2;grid-row:auto;align-self:start;justify-self:start;justify-content:flex-start;margin-top:7px;}}
5290
+ .sched-feed-read{background:none;border:none;padding:4px 2px;font:600 12px var(--sans);color:var(--ink-3);cursor:pointer;text-decoration:underline;}
5291
+ .sched-feed-read:hover{color:var(--ink);}
5292
+ .sched-feed-read:focus-visible{outline:2px solid var(--ink);outline-offset:2px;border-radius:6px;}
5293
+
5294
+ /* the Running view's Scheduled group (runs due within 24 h) */
5295
+ .run-scheduled{margin-top:22px;display:flex;flex-direction:column;gap:14px;}
5296
+ .run-scheduled[hidden]{display:none;}
5297
+ .run-scheduled-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin:0 4px -2px;}
5298
+ .run-scheduled-head a{font:600 12px var(--sans);color:var(--blue-ink-strong);}
5299
+
5300
+ /* Ask run card: the scheduled state line */
5301
+ .ask-card-sched{display:flex;flex-wrap:wrap;align-items:center;gap:9px;font-size:12.5px;color:var(--ink-2);}
5302
+ .ask-card-sched .badge{letter-spacing:.04em;}
5303
+ .ask-card-sched-text{color:var(--ink);font-weight:500;}
5304
+ .ask-card-sched-link{font:600 12px var(--sans);color:var(--blue-ink-strong);}
5305
+ .ask-card-sched .ask-card-err{flex-basis:100%;}
5306
+ /* New pipeline: the time picked before the task, left of the Start / Schedule button */
5307
+ .new-sched{margin-right:auto;padding:9px 12px;border-radius:12px;background:var(--canvas-2);border:1px solid var(--line);}
5308
+ .new-sched[hidden]{display:none;}
5309
+ .new-sched .link-btn{font-size:12px;}
5310
+ #start-btn-clock[hidden],#start-btn-play[hidden]{display:none;}
5311
+ /* a proposal Ask Worca scheduled (propose_run when / every): the line above the footer */
5312
+ .ask-card-sched-proposed{margin:0 18px 12px;padding:10px 12px;border-radius:12px;background:var(--canvas-2);border:1px solid var(--line);}
5313
+ .ask-card-sched-proposed .link-btn{font-size:12px;}
5314
+ /* a run card whose task is a tracker task (propose_run source): the reference instead of the brief */
5315
+ .ask-card-task{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;padding:11px 13px;border:1px solid var(--line);border-radius:var(--r-ctrl);background:var(--canvas-2);font-size:13px;}
5316
+ .ask-card-task .badge{letter-spacing:0;text-transform:none;font-family:var(--mono);font-size:11.5px;font-weight:600;color:var(--ink-2);}
5317
+ .ask-card-task-title{flex:1 1 200px;min-width:0;color:var(--ink);font-weight:600;overflow-wrap:anywhere;}
5318
+ a.ask-card-task-title{text-decoration:underline;text-decoration-color:var(--line-2);text-underline-offset:3px;}
5319
+ a.ask-card-task-title:hover{text-decoration-color:currentColor;}
5320
+ .ask-card-task-meta{font-size:12px;color:var(--ink-3);}
5321
+ .ask-card-task-warn{margin-top:8px;padding:9px 12px;border-radius:12px;background:var(--amber-wash);border:1px solid var(--amber-line);font-size:12.5px;color:var(--ink-2);}
5322
+
5323
+ /* History detail: the scheduled-run provenance link in the header meta */
5324
+ .hd-sched{color:var(--ink-2);text-decoration:underline;text-decoration-color:var(--line-2);text-underline-offset:3px;}
5325
+ .hd-sched:hover{color:var(--ink);}
5326
+ /* ======================================================================
5327
+ Interface mode — simple | advanced | expert (docs/ui-levels.md)
5328
+ ======================================================================
5329
+ <html data-level> is server-rendered (src/core/index-html.mjs) and kept live by
5330
+ ui-level.mjs. An element opts in with data-min-level; these three selectors are
5331
+ the WHOLE gate. No data-level attribute (tests, an old shell) gates nothing.
5332
+ [data-level-keep] is the escape hatch: a gated control holding a non-default
5333
+ value, or the nav item of the page you are on, stays visible.
5334
+ !important because a dozen author `display:flex/grid` rules in this file outrank
5335
+ a plain display:none — the same footgun the [hidden] notes above describe. */
5336
+ :root[data-level="simple"] [data-min-level="advanced"]:not([data-level-keep]),
5337
+ :root[data-level="simple"] [data-min-level="expert"]:not([data-level-keep]),
5338
+ :root[data-level="advanced"] [data-min-level="expert"]:not([data-level-keep]){display:none !important;}
5339
+ /* The rare inverse — copy that stands in for a control a higher mode shows (data-max-level). */
5340
+ :root[data-level="advanced"] [data-max-level="simple"],
5341
+ :root[data-level="expert"] [data-max-level="simple"],
5342
+ :root[data-level="expert"] [data-max-level="advanced"]{display:none !important;}
5343
+
5344
+ /* Simple shows General only: a one-button segmented control is noise, so the bar goes — unless a
5345
+ deep link parked us on a higher tab, whose button is then kept (paintLevelBanner). */
5346
+ :root[data-level="simple"] #settings-tabs:not(:has([data-level-keep])){display:none !important;}
5347
+
5348
+ /* The icon: a stack of layers, unlit ones ghosted. currentColor, so hover, the
5349
+ dark active fill and both themes come for free. */
5350
+ /* An <i>, not a <span>: the collapsed rail visually hides every direct span child of a nav button
5351
+ (the labels), and this icon is the one thing that must survive there. */
5352
+ .lv-icon-slot{display:inline-grid;place-items:center;flex:0 0 auto;font-style:normal;}
5353
+ .nav button.nav-mode .lv-icon{width:19px;height:19px;}
5354
+ .lv-icon .lv-off{opacity:.26;}
5355
+ .lv-icon path{transition:opacity .2s;}
5356
+
5357
+ /* Sidebar item: a plain `.nav button`. It is an action, never the current view. */
5358
+ .nav button.nav-mode .lv-icon-slot{width:19px;height:19px;}
5359
+ /* Top-nav twin (<1080px, where the sidebar is hidden): icon + the mode's name. */
5360
+ .topnav button.topnav-mode{display:inline-flex;align-items:center;justify-content:center;gap:7px;}
5361
+ .topnav button.topnav-mode .lv-icon{width:16px;height:16px;}
5362
+
5363
+ /* Level pill (banner, hidden-settings note). Colour is semantic to the level. */
5364
+ .lv-pill{display:inline-flex;align-items:center;padding:2px 10px;border-radius:999px;
5365
+ font-size:11.5px;font-weight:600;white-space:nowrap;background:var(--field);color:var(--ink-2);}
5366
+ .lv-pill[data-lv="simple"]{background:var(--green-bg);color:var(--green-ink);}
5367
+ .lv-pill[data-lv="advanced"]{background:var(--blue-bg);color:var(--blue-ink-strong);}
5368
+ .lv-pill[data-lv="expert"]{background:var(--violet-bg);color:var(--violet-ink);}
5369
+
5370
+ /* Page-above-the-mode banner. */
5371
+ .level-banner{display:flex;flex-wrap:wrap;align-items:center;gap:10px 12px;margin:0 0 18px;
5372
+ padding:10px 14px;border-radius:var(--r-ctrl);background:var(--canvas-2);border:1px solid var(--line-2);
5373
+ font-size:13px;color:var(--ink-2);}
5374
+ .level-banner[hidden]{display:none;}
5375
+ .level-banner-text{flex:1 1 220px;min-width:0;}
5376
+ .level-banner .btn{margin-left:auto;}
5377
+ body.view-history .level-banner,body.view-projects .level-banner,body.view-running .level-banner{margin:12px 32px 0;flex:0 0 auto;}
5378
+ body.view-workspaces .level-banner{margin:12px 32px 0;flex:0 0 auto;}
5379
+
5380
+ /* Simple hides the Target switch, which leaves .split-row's picker alone in the row: auto-placement
5381
+ would drop it into the narrow first track, so the row becomes one full-width column. */
5382
+ :root[data-level="simple"] .split-row:not(:has(#target-field[data-level-keep])){grid-template-columns:minmax(0,1fr);}
5383
+
5384
+ /* New pipeline: mock mode outside Advanced, and the hidden-but-active note. */
5385
+ .mock-row{margin-top:18px;padding-top:16px;border-top:1px solid var(--line);}
5386
+ :root:not([data-level="simple"]) .advanced + .mock-row{margin-top:14px;}
5387
+ .level-hidden-note{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;margin-top:14px;
5388
+ padding:10px 14px;border-radius:var(--r-ctrl);background:var(--amber-wash);border:1px solid var(--amber-line);
5389
+ font-size:12.5px;line-height:1.5;color:var(--ink-2);}
5390
+ .level-hidden-note[hidden]{display:none;}
5391
+ .level-hidden-note b{color:var(--ink);font-weight:600;}
5392
+ .link-btn{background:none;border:0;padding:0;font:inherit;font-weight:600;color:var(--blue-ink-strong);cursor:pointer;text-decoration:underline;text-underline-offset:2px;}
5393
+ .link-btn:hover{color:var(--ink);}
5394
+ .link-btn:focus-visible{outline:2px solid var(--ink);outline-offset:2px;border-radius:4px;}
5395
+
5396
+ /* Settings › General › Interface mode. */
5397
+ .mode-current{display:flex;align-items:center;gap:14px;}
5398
+ .mode-current-icon{display:grid;place-items:center;flex:0 0 auto;width:42px;height:42px;border-radius:13px;background:var(--field);color:var(--ink);}
5399
+ .mode-current-icon .lv-icon{width:22px;height:22px;}
5400
+ .mode-current-text{display:flex;flex-direction:column;gap:2px;flex:1 1 auto;min-width:0;font-size:12.5px;line-height:1.5;color:var(--ink-2);}
5401
+ .mode-current-text strong{font-size:14px;font-weight:600;color:var(--ink);}
5402
+ @media (max-width:560px){.mode-current{flex-wrap:wrap;}.mode-current .btn{margin-left:56px;}}
5403
+
5404
+ /* The dialog. Follows .ob-welcome's door cards: one bordered row per choice. */
5405
+ .mode-modal .card{width:min(580px,100%);padding:26px 28px 22px;animation:wr-rise .24s cubic-bezier(.2,.7,.3,1) both;}
5406
+ .mode-modal .card-head{margin-bottom:4px;}
5407
+ .mode-sub{margin:0 0 16px;font-size:13px;line-height:1.55;color:var(--ink-2);}
5408
+ .lv-cards{display:flex;flex-direction:column;gap:8px;}
5409
+ .lv-card{display:grid;grid-template-columns:40px minmax(0,1fr) 20px;align-items:center;gap:14px;width:100%;
5410
+ padding:13px 15px;border:1.5px solid var(--line-2);border-radius:16px;background:var(--panel);color:var(--ink);
5411
+ font:inherit;text-align:left;cursor:pointer;transition:border-color .15s,background .15s;}
5412
+ .lv-card:hover{background:var(--field);}
5413
+ .lv-card:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
5414
+ .lv-card[aria-checked="true"]{border-color:var(--ink);background:var(--canvas-2);}
5415
+ .lv-card-icon{display:grid;place-items:center;width:40px;height:40px;border-radius:12px;background:var(--field);color:var(--ink-2);}
5416
+ .lv-card-icon .lv-icon{width:23px;height:23px;}
5417
+ .lv-card[data-level-choice="simple"][aria-checked="true"] .lv-card-icon{background:var(--green-bg);color:var(--green-ink);}
5418
+ .lv-card[data-level-choice="advanced"][aria-checked="true"] .lv-card-icon{background:var(--blue-bg);color:var(--blue-ink-strong);}
5419
+ .lv-card[data-level-choice="expert"][aria-checked="true"] .lv-card-icon{background:var(--violet-bg);color:var(--violet-ink);}
5420
+ .lv-card-text{display:flex;flex-direction:column;gap:3px;min-width:0;}
5421
+ .lv-card-title{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 9px;font-size:14.5px;font-weight:600;}
5422
+ .lv-card-who{font-size:12px;font-weight:500;color:var(--ink-3);}
5423
+ .lv-card-desc{font-size:12.5px;line-height:1.5;color:var(--ink-2);}
5424
+ .lv-card-adds{font-size:12px;line-height:1.45;color:var(--ink-3);}
5425
+ .lv-card-radio{width:18px;height:18px;border-radius:50%;border:1.5px solid var(--radio-ring);background:var(--panel);transition:border .15s;}
5426
+ .lv-card[aria-checked="true"] .lv-card-radio{border:5.5px solid var(--ink);}
5427
+ #mode-msg{display:block;min-height:0;margin-top:10px;}
5428
+ #mode-msg:empty{display:none;}
5429
+ .mode-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 14px;margin-top:16px;}
5430
+ .mode-foot .hint{margin:0;}
5431
+ @media (max-width:520px){
5432
+ .mode-modal .card{padding:20px 18px 18px;}
5433
+ .lv-card{grid-template-columns:34px minmax(0,1fr) 18px;gap:11px;padding:12px;}
5434
+ .lv-card-icon{width:34px;height:34px;}
5435
+ }
5436
+ @media (prefers-reduced-motion: reduce){.mode-modal .card{animation:none;}.lv-icon path,.lv-card,.lv-card-radio{transition:none;}}
5437
+
4332
5438
  @media (prefers-reduced-motion: reduce){
4333
5439
  /* Getting started: tiles land drawn, vignettes paint finished, the guide ring holds a still halo. */
4334
- .gs-tile.reveal,.play .gs-pop,.play .gs-draw,.ob-welcome,.guide-ring,.nav button.gs-pill{animation:none;}
5440
+ .gs-tile.reveal,.play .gs-pop,.play .gs-draw,.ob-welcome,.guide-ring,.guide-ring.nudge,.guide-balloon.nudge,.nav button.gs-pill{animation:none;}
4335
5441
  .nav button.gs-pill{box-shadow:0 0 0 3px color-mix(in srgb,var(--violet) 25%,transparent);}
4336
5442
  .play .gs-draw{stroke-dashoffset:0;}
4337
5443
  .guide-ring{box-shadow:0 0 0 6px color-mix(in srgb,var(--violet) 30%,transparent);}
4338
5444
  /* #stop-modal is a top-level overlay, outside the shell — named explicitly. */
4339
5445
  #stop-modal .card{animation:none;}
5446
+ /* The schedule sheet is a body-level overlay too. */
5447
+ #schedule-modal .card{animation:none;}
4340
5448
  /* PSEUDO-ELEMENTS DO NOT INHERIT `animation`, so the `*` blanket below cannot
4341
5449
  reach the live-log caret — it has to be named. (Task 7's own reduced-motion
4342
5450
  block already carries this rule; the duplicate here is deliberate belt-and-
@@ -4393,6 +5501,8 @@ html{scrollbar-color:var(--line-2) transparent;scrollbar-width:thin;}
4393
5501
  border-radius:calc(14.5px * var(--gv-scale)) calc(14.5px * var(--gv-scale)) 0 0;font-size:max(9px,calc(13px * var(--gv-scale)));font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
4394
5502
  .gv-world .nhead svg{width:calc(15px * var(--gv-scale));height:calc(15px * var(--gv-scale));flex:0 0 auto;stroke-width:1.85;}
4395
5503
  .gv-world .nhead .tt{overflow:hidden;text-overflow:ellipsis;}
5504
+ .gv-world .nhead .chip.rt{margin-left:auto;flex:0 0 auto;font:700 max(8px,calc(10px * var(--gv-scale)))/1.6 var(--mono);text-transform:none;white-space:nowrap;
5505
+ padding:0 calc(6px * var(--gv-scale));border-radius:999px;background:color-mix(in srgb, currentColor 14%, transparent);color:inherit;}
4396
5506
  .gv-world .h-flow{background:var(--ink);color:var(--on-ink);}
4397
5507
  .gv-world .h-violet{background:var(--violet-bg);color:var(--violet-ink);}
4398
5508
  .gv-world .h-blue{background:var(--blue-bg);color:var(--h-blue-ink);}
@@ -4400,6 +5510,12 @@ html{scrollbar-color:var(--line-2) transparent;scrollbar-width:thin;}
4400
5510
  .gv-world .h-red{background:var(--red-bg);color:var(--red-ink);}
4401
5511
  .gv-world .h-peach{background:var(--peach-bg);color:var(--h-peach-ink);}
4402
5512
  .gv-world .h-amber{background:var(--amber-bg);color:var(--amber-ink);}
5513
+ .gv-world .h-teal{background:var(--teal-bg);color:var(--teal-ink);}
5514
+ .gv-world .h-pink{background:var(--pink-bg);color:var(--pink-ink);}
5515
+ .gv-world .h-indigo{background:var(--indigo-bg);color:var(--indigo-ink);}
5516
+ .gv-world .h-lime{background:var(--lime-bg);color:var(--lime-ink);}
5517
+ .gv-world .h-cocoa{background:var(--cocoa-bg);color:var(--cocoa-ink);}
5518
+ .gv-world .h-slate{background:var(--slate-bg);color:var(--slate-ink);}
4403
5519
  .gv-world .nbody{padding:var(--gv-pad-t) 0 var(--gv-pad-b);}
4404
5520
  /* the chip band (A2/A26): model · effort · flags, ONE line between the head and the body, on the panel (never on a
4405
5521
  tinted head). Chips are the mockup's one unfloored font — 10px mono, 13px tall at .65 — so the band's inner 137px
@@ -4478,11 +5594,12 @@ html{scrollbar-color:var(--line-2) transparent;scrollbar-width:thin;}
4478
5594
  set injectGeometry writes — dropping them fails that assertion. */
4479
5595
  .gv-world .xfoot{position:absolute;left:0;right:0;bottom:0;border-top:1px solid var(--line);
4480
5596
  border-radius:0 0 14.5px 14.5px;overflow:hidden;background:var(--panel);}
4481
- .gv-world .xfoot>.fan,.gv-world .xfoot>.xtoggle,.gv-world .xfoot>.xresult{height:var(--gv-exec-row-h);
5597
+ .gv-world .xfoot>.fan,.gv-world .xfoot>.xtoggle,.gv-world .xfoot>.xresult,.gv-world .xfoot>.xlive{height:var(--gv-exec-row-h);
4482
5598
  display:flex;align-items:center;gap:7px;padding:0 11px;width:100%;box-sizing:border-box;}
4483
5599
  .gv-world .xfoot>:first-child{height:var(--gv-foot-h);} /* the first line is the tall one nodeSize bills */
4484
5600
  .gv-world .xfoot>.fan.f2{height:calc(var(--gv-foot-h) + var(--gv-exec-row-h));} /* two wrapped square lines */
4485
5601
  .gv-world .xfoot>.xtoggle{border:none;background:none;font:inherit;color:inherit;cursor:pointer;text-align:left;}
5602
+ .gv-world .xfoot>.xlive{display:block;line-height:var(--gv-exec-row-h);font-size:max(8px,calc(10.5px * var(--gv-scale)));color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
4486
5603
  .gv-world .xfoot>.xrow{height:var(--gv-exec-row-h);display:flex;align-items:center;gap:7px;padding:0 11px;}
4487
5604
  /* stacked exec rows: dur · cost on its own right-aligned line (.stack), the
4488
5605
  label on up to two clamped lines above it (.l2) — run-decor execBandLayout
@@ -4634,6 +5751,25 @@ input.gv-name:focus-visible{outline:none;}
4634
5751
  .ins-label{font-weight:600;font-size:11.5px;color:var(--ink-2);}
4635
5752
  /* Compact restatement of the global field skin — the page metrics (13px/15px of
4636
5753
  padding, 14px text) are far too heavy for a 308px rail. */
5754
+ /* Script inspector (P1b): the params textarea wears the SAME field skin as .ins-select/.ins-number. */
5755
+ .ins-panel .ins-textarea{width:100%;box-sizing:border-box;padding:8px 11px;font-size:12px;line-height:1.45;border-radius:10px;
5756
+ background:var(--field);border:1.5px solid transparent;color:var(--ink);resize:vertical;}
5757
+ .ins-panel .ins-textarea:focus{background:var(--field-focus);border-color:var(--ink);outline:none;}
5758
+ .ins-panel .ins-caption{display:block;margin-top:-7px;color:var(--ink-3);font-size:11px;}
5759
+ .ins-panel .ins-f.ins-missing .ins-label::after{content:" · required";color:var(--amber-ink);}
5760
+ .ins-panel .ins-chiprow{display:flex;gap:6px;align-items:center;}
5761
+ .ins-panel .ins-chiprow .chip.rt{font-family:var(--mono);text-transform:none;font-size:10.5px;padding:2px 8px;}
5762
+ .ins-port-editor .ins-prow{display:grid;grid-template-columns:minmax(0,1fr) 72px auto auto 22px;gap:6px;align-items:center;margin-bottom:6px;}
5763
+ .ins-port-editor .ins-prow input[type="text"]{min-width:0;padding:5px 8px;font-size:12px;border-radius:8px;background:var(--field);border:1.5px solid transparent;color:var(--ink);}
5764
+ .ins-port-editor .ins-prow .ins-select{padding:5px 22px 5px 8px;font-size:12px;}
5765
+ .ins-port-editor .ins-prow[data-dir="outputs"] .ins-pf:nth-of-type(2){grid-column:3 / 5;}
5766
+ .ins-port-editor .ins-pfile{grid-column:1 / 5;grid-row:2;}
5767
+ .ins-port-editor .ins-prm{grid-column:5;grid-row:1;}
5768
+ .ins-port-editor .ins-pcheck{display:inline-flex;gap:4px;align-items:center;font-size:11px;color:var(--ink-2);}
5769
+ .ins-port-editor .ins-prm,.ins-port-editor .ins-padd{border:1px solid var(--line-2);background:var(--panel);color:var(--ink-2);border-radius:8px;cursor:pointer;font-size:12px;}
5770
+ .ins-port-editor .ins-padd{margin:2px 0 10px;padding:4px 10px;}
5771
+ .ins-port-editor .ins-perr{color:var(--red-ink);font-size:11px;margin-top:6px;}
5772
+
4637
5773
  .ins-panel .ins-select,.ins-panel .ins-number{width:100%;padding:8px 11px;font-size:12.5px;border-radius:10px;
4638
5774
  background:var(--field);border:1.5px solid transparent;color:var(--ink);font-family:inherit;}
4639
5775
  .ins-panel .ins-select:focus,.ins-panel .ins-number:focus{background:var(--field-focus);border-color:var(--ink);outline:none;}
@@ -4732,6 +5868,9 @@ input.gv-name:focus-visible{outline:none;}
4732
5868
  .ap .p{display:block;margin-top:2px;font:10.5px/1.4 var(--mono);color:var(--ink-3);
4733
5869
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
4734
5870
  .ap .chip{flex:0 0 auto;background:var(--field);color:var(--ink-3);font-weight:700;font-size:10px;padding:1px 7px;}
5871
+ .ap .nrow{display:flex;align-items:center;gap:6px;min-width:0;}
5872
+ .ap .nrow .n{min-width:0;}
5873
+ .ap .chip.rt{font-family:var(--mono);text-transform:none;color:var(--ink-2);} /* --ink-3 on --field is 2.6:1; the runtime is read, not decoration */
4735
5874
  .gv-drag-ghost{position:fixed;z-index:99;pointer-events:none;border:1.5px dashed var(--ink-3);border-radius:12px;
4736
5875
  background:var(--panel);padding:6px 10px;font:600 12px var(--sans);opacity:.9;box-shadow:var(--shadow);}
4737
5876
 
@@ -5040,3 +6179,281 @@ input.gv-name:focus-visible{outline:none;}
5040
6179
  /* No href => the preview is still building. Make that legible rather than letting a
5041
6180
  dead-looking button sit there (D24). */
5042
6181
  .report-modal .confirm-actions a.btn:not([href]){opacity:.5;pointer-events:none;}
6182
+
6183
+ /* History › Overview › Files changed: the plain-words stand-in for the (advanced) Diff tab. */
6184
+ .hd-ov-files{padding:16px 20px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);display:flex;flex-direction:column;gap:10px;}
6185
+ .hd-ov-files-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;}
6186
+ .hd-ov-files-head .link-btn{font-size:12.5px;}
6187
+ .hd-ov-files-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px;}
6188
+ .hd-ov-files-list li{display:flex;align-items:baseline;gap:10px;min-width:0;font-size:12.5px;}
6189
+ .hd-ov-file-kind{flex:0 0 58px;font-size:10.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3);}
6190
+ .hd-ov-file-kind.k-new{color:var(--green-ink);}
6191
+ .hd-ov-file-kind.k-deleted{color:var(--red-ink);}
6192
+ .hd-ov-file-path{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);color:var(--ink-2);}
6193
+
6194
+ /* Composer palette › Create agent…: a quiet footer action under the scrolling list. */
6195
+ .pal-create{display:flex;align-items:center;gap:8px;flex:0 0 auto;margin:10px 13px 13px;padding:9px 12px;
6196
+ border:1.5px dashed var(--line-2);border-radius:12px;background:transparent;color:var(--ink-2);
6197
+ font:inherit;font-size:12.5px;font-weight:600;cursor:pointer;transition:border-color .15s,color .15s,background .15s;}
6198
+ .pal-create:hover{border-color:var(--ink);color:var(--ink);background:var(--field);}
6199
+ .pal-create:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
6200
+
6201
+ /* ---------- Team policy (team-policy design §11, boards 1–11) ---------- */
6202
+ /* A project / workspace / home NAME inside prose (team-policy-view.mjs ref()): bold and mono, so
6203
+ "Follows gateway" reads as a name and a word, never two words. In a hint it keeps the hint's ink. */
6204
+ .ref{font-weight:600;color:var(--ink);font-size:.96em;}
6205
+ .hint .ref,small .ref{color:var(--ink-2);}
6206
+ /* Policy origin colour: blue. Amber is built-in, violet is plugin, green is user. */
6207
+ .badge.blue{background:var(--blue-bg);color:var(--blue-ink);}
6208
+ /* Projects row: the policy cell sits UNDER the team-metrics cell in the same 420px column (board 2,
6209
+ reworked): two cells side by side squeezed both to a truncated status at every laptop width, and
6210
+ the row's name column must not move. A grid, so the name spans both rows and the chevron stays
6211
+ centred; the cells keep their own left divider (.tm-cell) and are separated by a hairline. */
6212
+ /* The team column on a Projects row: two one-line chips, right-aligned, status only. The
6213
+ controls and the sentences behind a status are on the project page's Team tab. */
6214
+ .pl-team{flex:0 0 auto;max-width:42%;min-width:0;display:flex;flex-direction:column;align-items:flex-end;gap:5px;font-size:12px;line-height:1.3;} /* the chips keep their words; the path wraps */
6215
+ .pl-team-item{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;color:var(--ink-2);}
6216
+ .pl-team-item:empty{display:none;}
6217
+ .pl-team-item .tm-dot{flex:0 0 auto;}
6218
+ .pl-team-name{color:var(--ink-3);}
6219
+ .pl-team-state{white-space:nowrap;} /* never clipped: the column is flex:0 0 auto and the path wraps instead */
6220
+ .pl-team-state.muted{color:var(--ink-3);}
6221
+ @media (max-width:760px){.pl-team{display:none;}}
6222
+ /* The project / workspace page's Team tab: one panel per feature, the block inside wraps
6223
+ (the list cell it came from had to keep to one line). */
6224
+ /* Every section that stacks panels keeps the grid gap between them: cards touching read as one. */
6225
+ .pd-sec-team,.wd-sec-overview{display:flex;flex-direction:column;gap:18px;}
6226
+ .pd-team-card .card-head{display:flex;align-items:baseline;flex-wrap:wrap;gap:6px 12px;margin-bottom:12px;}
6227
+ .pd-team-card .card-head b{font-size:14px;}
6228
+ .pd-team-body .tm-cell{grid-template-rows:auto;}
6229
+ .pd-team-body .tm-cell .tm-line{grid-row:1;}
6230
+ .pd-team-body .tm-cell .tm-actions{grid-row:1;}
6231
+ .pd-team-body .tm-cell .tm-hint{grid-row:2;white-space:normal;line-height:1.45;}
6232
+ .pd-team-body .tm-cell .tm-status{white-space:normal;}
6233
+ .pd-team-body .ws-home-inner{padding-top:0;}
6234
+ .pd-team-body .ws-policy{margin-top:0;}
6235
+ .pd-team-body .ws-policy > .ws-policy-inner > .tm-label{display:none;} /* the panel head names it */
6236
+ .pd-ov-sub.pd-ov-attn{color:var(--amber-ink);}
6237
+ .pd-ov-card[data-kind="rejected"] .pd-ov-sub,.pd-ov-card[data-kind="delegate-invalid"] .pd-ov-sub,.pd-ov-card[data-kind="unsupported"] .pd-ov-sub{color:var(--red-ink);}
6238
+ @media (max-width:1080px){
6239
+ #projects-list .pl-row{grid-template-columns:minmax(0,1fr) auto;}
6240
+ #projects-list .pl-main{grid-column:1 / span 2;grid-row:1;}
6241
+ #projects-list .tm-slot{grid-column:1;grid-row:2;}
6242
+ #projects-list .tp-slot{grid-column:1;grid-row:3;}
6243
+ #projects-list .proj-open{grid-column:2;grid-row:1;}
6244
+ #projects-list .tm-slot .tm-cell,#projects-list .tp-slot .tm-cell{padding-left:0;border-left:0;padding-top:10px;border-top:1px solid var(--line);}
6245
+ }
6246
+ .tm-cell .tp-warn{color:var(--amber-ink);white-space:normal;line-height:1.4;}
6247
+ /* hidden-toggled flex/grid containers (style.css has no global [hidden] rule, see :324) */
6248
+ #policyLine[hidden],#tp-sync[hidden],.ws-policy[hidden],.tp-json[hidden],.tp-onbreach[hidden],.tp-require[hidden]{display:none;}
6249
+ /* Team policy page: the published document (panel) above what this machine makes of it (cards). */
6250
+ .tp-head{display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:18px;}
6251
+ .tp-head-main{min-width:0;flex:1 1 420px;}
6252
+ .tp-head-kicker{font:600 10.5px var(--sans);letter-spacing:.14em;color:var(--ink-3);}
6253
+ .tp-head-title{margin:6px 0 0;font-size:19px;font-weight:700;letter-spacing:-.015em;}
6254
+ .tp-facts{display:grid;grid-template-columns:96px minmax(0,1fr);gap:8px 16px;margin:16px 0 0;font-size:12.5px;}
6255
+ .tp-facts dt{font:600 10.5px var(--sans);letter-spacing:.14em;color:var(--ink-3);padding-top:2px;}
6256
+ .tp-facts dd{margin:0;color:var(--ink-2);min-width:0;overflow-wrap:anywhere;}
6257
+ .tp-facts dd code{font-size:11.5px;}
6258
+ .tp-head-notes{white-space:pre-wrap;}
6259
+ .tp-head-actions{display:flex;flex-direction:column;align-items:flex-end;gap:6px;text-align:right;}
6260
+ .tp-head-actions .hint{max-width:230px;}
6261
+ .tp-sec-label{margin:22px 0 12px;font:600 10.5px var(--sans);letter-spacing:.14em;color:var(--ink-3);}
6262
+ .tp-ov-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px;}
6263
+ .tp-ov-card{padding:20px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);}
6264
+ .tp-ov-label{font:600 10.5px var(--sans);letter-spacing:.14em;color:var(--ink-3);}
6265
+ .tp-ov-value{margin-top:10px;font-size:22px;font-weight:700;letter-spacing:-.02em;color:var(--ink);overflow-wrap:anywhere;}
6266
+ .tp-ov-sub{margin-top:6px;font-size:11.5px;color:var(--ink-3);overflow-wrap:anywhere;}
6267
+ .tp-ov-sub.is-warn{color:var(--amber-ink);}
6268
+ /* Tabs: the History / Project detail pills, one row per page section. */
6269
+ .tp-tabs{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:26px 0 16px;}
6270
+ .tp-tab{display:flex;align-items:center;gap:9px;padding:10px 17px;border:1.5px solid var(--line);
6271
+ border-radius:999px;background:var(--panel);font:600 13.5px var(--sans);color:var(--ink-2);cursor:pointer;}
6272
+ .tp-tab:hover{border-color:var(--ink-3);color:var(--ink);}
6273
+ .tp-tab.active{background:var(--ink);color:var(--on-ink);border-color:var(--ink);}
6274
+ .tp-tab-badge{padding:2px 8px;border-radius:999px;background:var(--field);color:var(--ink-3);font:600 10.5px var(--mono);}
6275
+ .tp-tab.active .tp-tab-badge{background:var(--blue-bg);color:var(--blue-ink);}
6276
+ .tp-sec[hidden]{display:none;}
6277
+ .tp-sec-body{display:flex;flex-direction:column;gap:18px;}
6278
+ /* Plugins tab */
6279
+ .tp-plugins-hint{display:block;margin:-8px 0 12px;}
6280
+ .tp-plugins .form-msg:empty{display:none;}
6281
+ .tp-plugins-tbl td.tp-plugin-act{text-align:right;white-space:nowrap;}
6282
+ .tp-plugins-tbl td.tp-key small{display:block;font-weight:400;color:var(--ink-3);font-size:11.5px;}
6283
+ .tp-blocked-list{display:flex;flex-direction:column;gap:10px;}
6284
+ .tp-blocked-row{display:flex;align-items:center;flex-wrap:wrap;gap:10px;font-size:12.5px;}
6285
+ /* Catalog tab */
6286
+ /* The catalog cards' heads: the title stays one word wide, the (long) hint takes the rest. */
6287
+ .tp-cat-card .card-head{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 14px;margin-bottom:12px;}
6288
+ .tp-cat-card .card-head h2{margin:0;white-space:nowrap;}
6289
+ .tp-cat-card .card-head .hint{flex:1 1 320px;min-width:0;margin:0;}
6290
+ .tp-catalogs{display:flex;flex-direction:column;gap:18px;} /* the two catalog cards: the panel gap */
6291
+ .tp-cat-list{display:flex;flex-direction:column;gap:12px;}
6292
+ .tp-cat-row{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:12px 0;border-bottom:1px solid var(--line);}
6293
+ .tp-cat-row:last-child{border-bottom:0;}
6294
+ .tp-cat-main{min-width:0;font-size:13px;}
6295
+ .tp-cat-main small{display:block;margin-top:4px;}
6296
+ @media (max-width:760px){
6297
+ .tp-facts{grid-template-columns:minmax(0,1fr);gap:2px 0;}
6298
+ .tp-facts dd{margin-bottom:10px;}
6299
+ .tp-head-actions{align-items:flex-start;text-align:left;}
6300
+ .tp-cat-row{flex-direction:column;}
6301
+ }
6302
+ .tp-tbl th:first-child,.tp-tbl td:first-child{padding-left:0;}
6303
+ .tp-tbl tr.tp-group td{padding:16px 0 6px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);font-weight:700;border-bottom:0;}
6304
+ .tp-tbl td.tp-key{font-weight:600;color:var(--ink);}
6305
+ .tp-tbl td.tp-key small{display:block;font-weight:400;color:var(--ink-3);font-size:11.5px;}
6306
+ .tp-tbl td.tp-team small{display:block;color:var(--ink-3);font-size:11px;margin-top:2px;}
6307
+ .tp-tbl .muted{color:var(--ink-3);}
6308
+ .tp-kind{display:inline-flex;font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:3px 8px;border-radius:6px;}
6309
+ .tp-kind.default{background:var(--field);color:var(--ink-2);}
6310
+ .tp-kind.soft{background:var(--blue-bg);color:var(--blue-ink);}
6311
+ .tp-kind.hard{background:var(--red-bg);color:var(--red-ink);}
6312
+ .tp-eff{font-family:var(--mono);font-size:12px;}
6313
+ .tp-eff.tight{color:var(--blue-ink-strong);font-weight:600;}
6314
+ .tp-eff.loose{color:var(--ink-3);text-decoration:line-through;}
6315
+ .tp-src{font-family:var(--sans);font-size:11px;color:var(--ink-3);font-weight:400;}
6316
+ .tp-foot{margin-top:14px;}
6317
+ /* editor (board 5) */
6318
+ .tp-editor{display:flex;flex-direction:column;gap:18px;}
6319
+ .tp-head + .tp-editor{margin-top:18px;} /* the same gap the editor keeps between its own cards */
6320
+ /* The editor's tabs: the read view's pills, then one section each (the read view's gap between cards). */
6321
+ .tp-editor > .tp-edit-tabs{padding:0 0 4px;}
6322
+ .tp-edit-sections{display:flex;flex-direction:column;}
6323
+ .tp-edit-sec{display:flex;flex-direction:column;gap:18px;}
6324
+ .tp-edit-sec[hidden]{display:none;}
6325
+ /* The catalog editor: one bordered item per set / model, its fields on a grid. */
6326
+ .tp-cat-list{display:flex;flex-direction:column;gap:12px;}
6327
+ .tp-cat-list:empty::before{content:'None yet.';color:var(--ink-3);font-size:12.5px;}
6328
+ .tp-cat-item{display:flex;flex-direction:column;gap:12px;padding:14px 16px;border:1px solid var(--line);border-radius:14px;background:var(--surface);}
6329
+ .tp-cat-item-head{display:flex;align-items:center;gap:10px;font-size:13.5px;}
6330
+ .tp-cat-item-head .tp-cat-rm{margin-left:auto;padding:5px 11px;font-size:12px;}
6331
+ .tp-cat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px 14px;}
6332
+ .tp-cat-field{display:flex;flex-direction:column;gap:6px;min-width:0;}
6333
+ .tp-cat-field > label{font:600 10.5px var(--sans);letter-spacing:.14em;color:var(--ink-3);text-transform:uppercase;}
6334
+ .tp-cat-field .input{padding:8px 12px;font-size:13px;border-radius:10px;}
6335
+ .tp-cat-flags{flex-direction:row;flex-wrap:wrap;align-items:center;gap:6px 18px;}
6336
+ .tp-cat-flags > label:first-child{flex-basis:100%;}
6337
+ .tp-cat-effort-row{display:flex;flex-wrap:wrap;gap:6px 16px;font-size:12.5px;}
6338
+ .tp-env-rows{display:flex;flex-direction:column;gap:6px;}
6339
+ .tp-env-row{display:flex;align-items:center;gap:6px;}
6340
+ .tp-env-row .tp-env-key{flex:0 1 240px;}
6341
+ .tp-env-row .tp-env-val{flex:1 1 200px;min-width:0;}
6342
+ .tp-cat-env .tp-env-add,.tp-cat-card > .tp-cat-add{align-self:flex-start;margin-top:4px;}
6343
+ .tp-editor > .tp-msg:empty,.tp-editor > .tp-json[hidden]{display:none;}
6344
+ .tp-editor > .tp-msg{margin:0;}
6345
+ /* Editing: Publish sits beside Cancel editing on the header; the count and links under them. */
6346
+ .tp-head-btns{display:flex;align-items:center;gap:8px;}
6347
+ .tp-head-status{font-size:12px;color:var(--ink-3);text-align:right;}
6348
+ .tp-head-status .linkish{font-size:12px;}
6349
+ .tp-editor .card.tp-group-card,.tp-editor details.card{padding:20px 22px;}
6350
+ .tp-editor details.card > summary{cursor:pointer;font-size:14px;list-style:none;}
6351
+ .tp-editor details.card > summary::-webkit-details-marker{display:none;}
6352
+ .tp-editor details.card > summary::before{content:"▸";display:inline-block;width:14px;color:var(--ink-3);}
6353
+ .tp-editor details.card[open] > summary::before{content:"▾";}
6354
+ .tp-editor details.card > summary .hint{display:inline;margin:0 0 0 6px;}
6355
+ .tp-edit-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr) auto auto;gap:8px 14px;align-items:center;padding:12px 0;border-bottom:1px solid var(--line);}
6356
+ .tp-edit-row > .tp-key{align-self:start;}
6357
+ .tp-row-unset{display:flex;align-items:center;}
6358
+ /* The second line: under the value and the kind, never beside them, so the first line keeps its
6359
+ shape when Soft is picked. */
6360
+ .tp-edit-row > .tp-extra{grid-column:2 / -1;display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px;font-size:11.5px;color:var(--ink-2);}
6361
+ .tp-edit-row > .tp-extra[hidden]{display:none;}
6362
+ .tp-edit-row:last-child{border-bottom:0;}
6363
+ .tp-edit-row .tp-key{font-weight:600;font-size:13px;line-height:1.45;}
6364
+ .tp-edit-row .tp-key small{display:block;font-weight:400;color:var(--ink-3);font-size:11.5px;}
6365
+ .tp-edit-row .input,.tp-edit-row .select{padding:9px 13px;font-size:13px;border-radius:11px;background:var(--surface);border-color:var(--line-2);}
6366
+ .tp-edit-row .select{padding-right:36px;}
6367
+ .tp-edit-row .seg button{padding:6px 11px;font-size:11.5px;}
6368
+ .tp-edit-row .seg button:disabled{opacity:.4;cursor:not-allowed;}
6369
+ .tp-control{display:flex;flex-direction:column;gap:8px;min-width:0;}
6370
+ .tp-control .check-row{margin-top:2px;}
6371
+ .tp-list{display:flex;flex-wrap:wrap;gap:6px;}
6372
+ .tp-chip{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:11.5px;}
6373
+ .tp-chip-rm{background:none;border:0;padding:0;color:var(--ink-3);font:inherit;cursor:pointer;}
6374
+ .tp-chip-rm:hover{color:var(--red-ink);}
6375
+ .tp-list-empty{color:var(--ink-3);font-size:12px;}
6376
+ .tp-add-row{display:flex;gap:6px;flex-wrap:wrap;}
6377
+ .tp-add-row .input{flex:1 1 120px;min-width:0;}
6378
+ /* An input with a datalist behind it: pick from what the machine knows, or type. */
6379
+ .tp-editor .tp-pick{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");background-repeat:no-repeat;background-position:right 10px center;background-size:14px;padding-right:30px;}
6380
+ .tp-editor .tp-pick::-webkit-calendar-picker-indicator{opacity:0;}
6381
+ .tp-add-row .select-wrap{flex:0 0 120px;}
6382
+ .tp-extra .tp-src{flex-basis:100%;}
6383
+ .tp-onbreach{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--ink-2);}
6384
+ .tp-onbreach .select-wrap{display:inline-block;width:96px;}
6385
+ .tp-onbreach .select{padding:6px 30px 6px 10px;font-size:12px;border-radius:9px;}
6386
+ .tp-unset{color:var(--ink-3);font-size:12px;background:none;border:none;font:inherit;cursor:pointer;text-decoration:underline;padding:0;}
6387
+ /* The pure editor's bar (team-policy-view.mjs): the page dismantles it into the header. */
6388
+ .tp-publish-bar{display:flex;align-items:center;gap:12px;}
6389
+ .tp-publish-bar .grow{flex:1;font-size:12.5px;color:var(--ink-2);}
6390
+ .tp-json{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px;font-size:12px;line-height:1.5;overflow-x:auto;margin:0;}
6391
+ .tp-msg{white-space:pre-wrap;}
6392
+ @media (max-width:900px){ .tp-edit-row{grid-template-columns:1fr;} }
6393
+ /* workspace card line (board 6) */
6394
+ /* Workspace page › Team › Team policy: the actions row (the metrics table head's twin), then a
6395
+ facts list with the label column the Team policy page uses. */
6396
+ .ws-policy{font-size:12.5px;margin-top:12px;}
6397
+ .ws-policy-inner{display:flex;flex-direction:column;gap:4px;}
6398
+ .ws-policy .tm-label{display:none;}
6399
+ .ws-policy .ws-tbl-actions{margin-left:auto;display:flex;align-items:center;flex-wrap:wrap;gap:8px;}
6400
+ .ws-policy .tp-facts{margin-top:8px;grid-template-columns:118px minmax(0,1fr);} /* WORKSPACE RUNS fits on one line */
6401
+ .ws-policy .tp-facts dd .tm-dot{display:inline-block;vertical-align:middle;margin-right:2px;}
6402
+ .ws-policy .tp-facts dd .muted{color:var(--ink-3);}
6403
+ .ws-policy .ws-home-hint,.ws-policy .ws-policy-results{margin-top:6px;}
6404
+ /* Settings readout + chip (board 7) */
6405
+ .team-readout{display:flex;flex-direction:column;gap:6px;margin:0 0 16px;padding:12px 14px;border-radius:12px;background:var(--field);font-size:12.5px;color:var(--ink-2);}
6406
+ .team-readout b{color:var(--ink);font-weight:600;}
6407
+ .team-readout-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
6408
+ /* A repository slug is a name, not a label: keep its case (the badge uppercases everything else). */
6409
+ .team-readout-row .badge.blue{text-transform:none;letter-spacing:0;font-family:var(--mono);font-weight:600;}
6410
+ .team-chip{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--blue-ink);background:var(--blue-bg);padding:3px 9px;border-radius:999px;margin-left:auto;}
6411
+ .team-chip .kind{font-weight:700;letter-spacing:.05em;text-transform:uppercase;font-size:9.5px;opacity:.85;}
6412
+ /* New pipeline notes line (board 8) */
6413
+ .policy-line{display:flex;flex-direction:column;gap:8px;margin:14px 0 0;padding:12px 14px;border-radius:12px;background:var(--field);font-size:12.5px;color:var(--ink-2);}
6414
+ .policy-line .pl-head-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
6415
+ .policy-line .pl-head-row .muted{color:var(--ink-3);}
6416
+ .policy-line .pl-note{display:flex;gap:8px;align-items:flex-start;line-height:1.45;}
6417
+ .policy-line .pl-note .tm-dot{margin-top:6px;}
6418
+ .policy-line .pl-note.warn{color:var(--amber-ink);}
6419
+ /* team-cap pause banner (board 9) */
6420
+ /* Team metrics KPI row: the policy tiles (Off-policy, Pooled budget) make 7–8 tiles, which leave a
6421
+ hole in the 3-column row; four columns fill two rows for eight. Back to one column when narrow. */
6422
+ .stat-row.tm-kpis:has(> .stat-tile:nth-child(7)){grid-template-columns:repeat(4,minmax(0,1fr));}
6423
+ @media (max-width:1080px){ .stat-row.tm-kpis:has(> .stat-tile:nth-child(7)){grid-template-columns:repeat(2,minmax(0,1fr));} }
6424
+ .cost-banner.cb-policy{background:var(--blue-bg);color:var(--blue-ink);}
6425
+ /* The policy home inside the sentence: bold like the figures, but inline (`.cost-banner b` is the block heading). */
6426
+ .cost-banner .cb-home{font-weight:600;color:var(--ink);}
6427
+ /* History meta segment (board 10) */
6428
+ .hd-policy.st-info{color:var(--blue-ink);}
6429
+ /* Plugins page strip + checklist (boards 10, 11) */
6430
+ /* Settings › Plugins: what the team policy asks for, as one panel of compact rows (it scales to
6431
+ however many plugins a policy names) with the mass action in the head. */
6432
+ .pl-required-card{margin:18px 0 14px;}
6433
+ .pl-required-card .card-head{display:flex;align-items:center;flex-wrap:wrap;gap:8px 10px;margin-bottom:6px;}
6434
+ .pl-required-card .card-head b{font-size:14px;}
6435
+ .pl-required-actions{display:flex;align-items:center;gap:8px;margin-left:auto;}
6436
+ .tp-plugins-actions{display:flex;align-items:center;gap:8px;margin-left:auto;}
6437
+ .pl-required-list{display:flex;flex-direction:column;}
6438
+ .pl-required{display:flex;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid var(--line);font-size:12.5px;color:var(--ink-2);}
6439
+ .pl-required:last-child{border-bottom:0;}
6440
+ .pl-required .tm-dot{flex:0 0 auto;}
6441
+ .pl-required-text{flex:1 1 auto;min-width:0;display:flex;align-items:baseline;flex-wrap:wrap;gap:2px 8px;}
6442
+ .pl-required-text b{font-weight:600;color:var(--ink);}
6443
+ .pl-required-text .hint{margin-top:0;}
6444
+ .pl-required-state{flex:0 0 auto;white-space:nowrap;}
6445
+ .pl-required-act{flex:0 0 auto;min-width:0;display:flex;justify-content:flex-end;}
6446
+ .pl-required-act:empty{display:none;}
6447
+ @media (max-width:760px){.pl-required{flex-wrap:wrap;} .pl-required-act{width:100%;}}
6448
+ .tp-setup-list{display:flex;flex-direction:column;margin-top:12px;}
6449
+ .tp-setup-row{display:flex;align-items:center;gap:12px;padding:11px 0;border-bottom:1px solid var(--line);font-size:13px;}
6450
+ .tp-setup-row:last-child{border-bottom:0;}
6451
+ .tp-setup-row .tm-dot{flex:0 0 auto;}
6452
+ .tp-setup-text{flex:1;min-width:0;}
6453
+ .tp-setup-text .hint{margin-top:2px;}
6454
+ .tp-trust-row{margin-top:16px;align-items:flex-start;}
6455
+ .tp-trust-row .switch{margin-top:2px;}
6456
+ .tp-trust-row .txt .hint{margin-top:2px;}
6457
+ /* pooled-budget tile meter (board 10): warn from 80 %, over from 100 % */
6458
+ .stat-meter .stat-meter-fill.warn{background:var(--amber-ink);}
6459
+ .stat-meter .stat-meter-fill.over{background:var(--red-ink);}