@1agh/maude 0.28.1 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (372) hide show
  1. package/README.md +3 -3
  2. package/{plugins/design/dev-server → apps/studio}/ai-banner.tsx +1 -2
  3. package/apps/studio/annotations-align.ts +149 -0
  4. package/apps/studio/annotations-bindings.ts +197 -0
  5. package/{plugins/design/dev-server → apps/studio}/annotations-context-toolbar.tsx +681 -151
  6. package/apps/studio/annotations-groups.ts +270 -0
  7. package/apps/studio/annotations-layer.tsx +4537 -0
  8. package/apps/studio/annotations-model.ts +2077 -0
  9. package/apps/studio/annotations-snap.ts +125 -0
  10. package/{plugins/design/dev-server → apps/studio}/api.ts +616 -70
  11. package/{plugins/design/dev-server → apps/studio}/artboard-activity-overlay.tsx +1 -1
  12. package/{plugins/design/dev-server → apps/studio}/artboard-marquee.tsx +1 -1
  13. package/apps/studio/bin/_motion-sample-playwright.mjs +129 -0
  14. package/{plugins/design/dev-server → apps/studio}/bin/_png-playwright.mjs +1 -1
  15. package/apps/studio/bin/annotate.mjs +732 -0
  16. package/apps/studio/bin/annotate.sh +17 -0
  17. package/{plugins/design/dev-server → apps/studio}/bin/canvas-edit.sh +1 -1
  18. package/{plugins/design/dev-server → apps/studio}/bin/draw-proof.sh +37 -2
  19. package/{plugins/design/dev-server → apps/studio}/bin/preflight.sh +1 -1
  20. package/apps/studio/bin/read-annotations.mjs +573 -0
  21. package/apps/studio/bin/read-annotations.sh +11 -0
  22. package/{plugins/design/dev-server → apps/studio}/bin/runtime-health.sh +1 -1
  23. package/{plugins/design/dev-server → apps/studio}/bin/screenshot.sh +62 -2
  24. package/{plugins/design/dev-server → apps/studio}/bin/server-up.sh +9 -3
  25. package/apps/studio/bin/to-lottie-verify.html +68 -0
  26. package/apps/studio/bin/to-lottie.sh +128 -0
  27. package/{plugins/design/dev-server → apps/studio}/build.ts +6 -4
  28. package/{plugins/design/dev-server → apps/studio}/canvas-arrowheads.ts +79 -10
  29. package/{plugins/design/dev-server → apps/studio}/canvas-comment-mount.tsx +1 -1
  30. package/apps/studio/canvas-create.ts +104 -0
  31. package/{plugins/design/dev-server → apps/studio}/canvas-cursors.ts +48 -12
  32. package/{plugins/design/dev-server → apps/studio}/canvas-edit.ts +257 -7
  33. package/{plugins/design/dev-server → apps/studio}/canvas-icons.tsx +165 -1
  34. package/{plugins/design/dev-server → apps/studio}/canvas-lib-inline.ts +1 -1
  35. package/{plugins/design/dev-server → apps/studio}/canvas-lib-resolver.ts +1 -1
  36. package/{plugins/design/dev-server → apps/studio}/canvas-lib.tsx +31 -12
  37. package/{plugins/design/dev-server → apps/studio}/canvas-shell.tsx +360 -48
  38. package/apps/studio/client/app.jsx +6742 -0
  39. package/apps/studio/client/canvas-url.js +81 -0
  40. package/{plugins/design/dev-server → apps/studio}/client/comments-overlay.css +41 -27
  41. package/apps/studio/client/index.html +16 -0
  42. package/apps/studio/client/styles/1-tokens-maude.css +296 -0
  43. package/apps/studio/client/styles/3-shell-maude.css +1161 -0
  44. package/{plugins/design/dev-server → apps/studio}/client/styles/3-shell.css +129 -0
  45. package/apps/studio/client/styles/4-components-maude.css +74 -0
  46. package/{plugins/design/dev-server → apps/studio}/client/styles/4-components.css +396 -34
  47. package/apps/studio/client/styles/5-maude-overrides.css +137 -0
  48. package/{plugins/design/dev-server → apps/studio}/client/styles/_index.css +9 -0
  49. package/{plugins/design/dev-server → apps/studio}/client/styles.css +1 -1
  50. package/apps/studio/client/tour/overlay.jsx +279 -0
  51. package/apps/studio/client/tour/usage-tour.js +48 -0
  52. package/apps/studio/client/whats-new-seen.js +52 -0
  53. package/apps/studio/client/whats-new.jsx +250 -0
  54. package/{plugins/design/dev-server → apps/studio}/commands/annotation-strokes-command.ts +2 -2
  55. package/{plugins/design/dev-server → apps/studio}/commands/equal-spacing-command.ts +1 -1
  56. package/{plugins/design/dev-server → apps/studio}/commands/move-artboards-command.ts +2 -2
  57. package/{plugins/design/dev-server → apps/studio}/comments-overlay.tsx +32 -11
  58. package/{plugins/design/dev-server → apps/studio}/context-menu.tsx +5 -4
  59. package/{plugins/design/dev-server → apps/studio}/contextual-toolbar.tsx +18 -7
  60. package/{plugins/design/dev-server → apps/studio}/cursors-overlay.tsx +21 -21
  61. package/apps/studio/dist/client.bundle.js +25545 -0
  62. package/apps/studio/dist/comment-mount.js +2046 -0
  63. package/apps/studio/dist/styles.css +8018 -0
  64. package/apps/studio/dom-selection.ts +342 -0
  65. package/apps/studio/draw/animate.ts +333 -0
  66. package/{plugins/design/dev-server → apps/studio}/draw/brush.ts +1 -1
  67. package/{plugins/design/dev-server → apps/studio}/draw/composition.ts +1 -1
  68. package/{plugins/design/dev-server → apps/studio}/draw/geometry.ts +1 -1
  69. package/{plugins/design/dev-server → apps/studio}/draw/index.ts +4 -1
  70. package/{plugins/design/dev-server → apps/studio}/draw/layout.ts +1 -1
  71. package/apps/studio/draw/morph.ts +204 -0
  72. package/{plugins/design/dev-server → apps/studio}/draw/optimize.ts +1 -1
  73. package/{plugins/design/dev-server → apps/studio}/draw/palette.ts +1 -1
  74. package/{plugins/design/dev-server → apps/studio}/draw/primitives.ts +1 -1
  75. package/apps/studio/draw/serialize-animate.ts +324 -0
  76. package/{plugins/design/dev-server → apps/studio}/draw/serialize.ts +9 -3
  77. package/apps/studio/draw/test/animate.test.ts +172 -0
  78. package/apps/studio/draw/test/morph.test.ts +107 -0
  79. package/apps/studio/draw/test/serialize-animate.test.ts +142 -0
  80. package/{plugins/design/dev-server → apps/studio}/equal-spacing-detector.ts +1 -1
  81. package/{plugins/design/dev-server → apps/studio}/equal-spacing-handles.tsx +7 -29
  82. package/{plugins/design/dev-server → apps/studio}/export-dialog.tsx +16 -4
  83. package/{plugins/design/dev-server → apps/studio}/history.ts +20 -3
  84. package/{plugins/design/dev-server → apps/studio}/http.ts +226 -6
  85. package/{plugins/design/dev-server → apps/studio}/input-router.tsx +15 -1
  86. package/{plugins/design/dev-server → apps/studio}/inspect.ts +50 -4
  87. package/{plugins/design/dev-server → apps/studio}/marquee-overlay.tsx +5 -2
  88. package/{plugins/design/dev-server → apps/studio}/participants-chrome.tsx +2 -8
  89. package/{plugins/design/dev-server → apps/studio}/paths.ts +15 -11
  90. package/{plugins/design/dev-server → apps/studio}/server.ts +23 -2
  91. package/{plugins/design/dev-server → apps/studio}/sync/agent.ts +231 -57
  92. package/{plugins/design/dev-server → apps/studio}/sync/codec.ts +45 -0
  93. package/apps/studio/sync/cold-start.ts +158 -0
  94. package/{plugins/design/dev-server → apps/studio}/sync/connection-state.ts +58 -2
  95. package/{plugins/design/dev-server → apps/studio}/sync/index.ts +563 -221
  96. package/apps/studio/sync/journal.ts +190 -0
  97. package/apps/studio/sync/migrate-seed.ts +321 -0
  98. package/{plugins/design/dev-server → apps/studio}/sync/projection.ts +22 -3
  99. package/{plugins/design/dev-server → apps/studio}/sync/status.ts +15 -4
  100. package/{plugins/design/dev-server → apps/studio}/test/activity.test.ts +1 -7
  101. package/apps/studio/test/annotate-write.test.ts +184 -0
  102. package/apps/studio/test/annotations-align.test.ts +88 -0
  103. package/apps/studio/test/annotations-bindings.test.ts +124 -0
  104. package/apps/studio/test/annotations-groups.test.ts +231 -0
  105. package/{plugins/design/dev-server → apps/studio}/test/annotations-layer.test.ts +63 -0
  106. package/{plugins/design/dev-server → apps/studio}/test/annotations-roundtrip.test.ts +97 -0
  107. package/apps/studio/test/annotations-snap.test.ts +79 -0
  108. package/apps/studio/test/annotations-text-format.test.ts +396 -0
  109. package/apps/studio/test/asset-api.test.ts +149 -0
  110. package/apps/studio/test/canvas-create-api.test.ts +361 -0
  111. package/{plugins/design/dev-server → apps/studio}/test/canvas-cursors.test.ts +2 -0
  112. package/apps/studio/test/canvas-edit.test.ts +319 -0
  113. package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-resolver.test.ts +1 -1
  114. package/apps/studio/test/canvas-media-drop.test.ts +158 -0
  115. package/{plugins/design/dev-server → apps/studio}/test/canvas-origin-gate.test.ts +25 -1
  116. package/apps/studio/test/canvas-url.test.ts +99 -0
  117. package/{plugins/design/dev-server → apps/studio}/test/collab-bridge.test.ts +0 -2
  118. package/{plugins/design/dev-server → apps/studio}/test/collab-room.test.ts +2 -7
  119. package/{plugins/design/dev-server → apps/studio}/test/csp-canvas-shell.test.ts +5 -0
  120. package/apps/studio/test/csrf-write-guard.test.ts +52 -0
  121. package/apps/studio/test/figjam-v3-model.test.ts +342 -0
  122. package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +1 -0
  123. package/apps/studio/test/index-data-canvas-ds.test.ts +97 -0
  124. package/apps/studio/test/motion-sample.test.ts +35 -0
  125. package/{plugins/design/dev-server → apps/studio}/test/perf-harness.ts +1 -1
  126. package/{plugins/design/dev-server → apps/studio}/test/phase-3.6-smoke.test.ts +3 -1
  127. package/apps/studio/test/read-annotations.test.ts +409 -0
  128. package/{plugins/design/dev-server → apps/studio}/test/sanitize-annotation-svg.test.ts +108 -2
  129. package/{plugins/design/dev-server → apps/studio}/test/shared-doc-convergence.test.ts +1 -1
  130. package/apps/studio/test/shared-doc-migrate.test.ts +369 -0
  131. package/apps/studio/test/sync-agent.test.ts +575 -0
  132. package/{plugins/design/dev-server → apps/studio}/test/sync-codec.test.ts +65 -0
  133. package/apps/studio/test/sync-cold-start.test.ts +244 -0
  134. package/{plugins/design/dev-server → apps/studio}/test/sync-connection-state.test.ts +68 -0
  135. package/{plugins/design/dev-server → apps/studio}/test/sync-hardening.test.ts +0 -8
  136. package/{plugins/design/dev-server → apps/studio}/test/sync-hubs-config.test.ts +0 -1
  137. package/apps/studio/test/sync-incident-replay.test.ts +211 -0
  138. package/apps/studio/test/sync-journal.test.ts +176 -0
  139. package/{plugins/design/dev-server → apps/studio}/test/sync-runtime.test.ts +360 -5
  140. package/{plugins/design/dev-server → apps/studio}/test/sync-status.test.ts +66 -0
  141. package/apps/studio/test/tour-overlay.test.tsx +56 -0
  142. package/apps/studio/test/use-annotation-resize.test.ts +402 -0
  143. package/{plugins/design/dev-server → apps/studio}/test/use-artboard-drag.test.ts +0 -1
  144. package/{plugins/design/dev-server → apps/studio}/test/use-collab.test.ts +0 -0
  145. package/{plugins/design/dev-server → apps/studio}/test/use-tool-mode.test.tsx +8 -2
  146. package/apps/studio/test/whats-new.test.ts +101 -0
  147. package/apps/studio/text-imports.d.ts +9 -0
  148. package/{plugins/design/dev-server → apps/studio}/tool-palette.tsx +15 -70
  149. package/{plugins/design/dev-server → apps/studio}/undo-hud.tsx +1 -2
  150. package/{plugins/design/dev-server → apps/studio}/undo-stack.ts +1 -1
  151. package/{plugins/design/dev-server → apps/studio}/use-agent-presence.tsx +5 -3
  152. package/apps/studio/use-annotation-resize.tsx +912 -0
  153. package/{plugins/design/dev-server → apps/studio}/use-annotation-selection.tsx +17 -5
  154. package/{plugins/design/dev-server → apps/studio}/use-annotations-visibility.tsx +1 -1
  155. package/{plugins/design/dev-server → apps/studio}/use-artboard-drag.tsx +1 -1
  156. package/{plugins/design/dev-server → apps/studio}/use-canvas-activity.tsx +3 -3
  157. package/apps/studio/use-canvas-media-drop.tsx +343 -0
  158. package/{plugins/design/dev-server → apps/studio}/use-collab.tsx +21 -16
  159. package/{plugins/design/dev-server → apps/studio}/use-cursor-modifiers.tsx +1 -1
  160. package/{plugins/design/dev-server → apps/studio}/use-keyboard-discipline.tsx +5 -2
  161. package/{plugins/design/dev-server → apps/studio}/use-selection-set.tsx +18 -1
  162. package/{plugins/design/dev-server → apps/studio}/use-snap-guides.tsx +1 -1
  163. package/{plugins/design/dev-server → apps/studio}/use-tool-mode.tsx +8 -2
  164. package/{plugins/design/dev-server → apps/studio}/use-undo-stack.tsx +1 -1
  165. package/apps/studio/whats-new.json +264 -0
  166. package/apps/studio/whats-new.schema.json +86 -0
  167. package/apps/studio/whats-new.ts +87 -0
  168. package/cli/bin/maude.mjs +10 -0
  169. package/cli/commands/design-link.test.mjs +84 -0
  170. package/cli/commands/design.mjs +16 -7
  171. package/cli/commands/design.test.mjs +40 -0
  172. package/cli/commands/help.mjs +8 -2
  173. package/cli/commands/hub.mjs +3 -3
  174. package/cli/commands/hub.test.mjs +1 -1
  175. package/cli/commands/scenario-report.mjs +2 -9
  176. package/cli/lib/design-link.mjs +51 -1
  177. package/cli/lib/flow-design-integration.test.mjs +1 -1
  178. package/cli/lib/gitignore-block.mjs +1 -0
  179. package/cli/lib/plugin-cli-reachability.test.mjs +8 -7
  180. package/cli/lib/preflight.mjs +1 -1
  181. package/package.json +15 -15
  182. package/plugins/design/templates/_shell.html +28 -4
  183. package/plugins/design/templates/brief-board.tsx.template +61 -0
  184. package/plugins/design/templates/canvas.tsx.template +1 -1
  185. package/plugins/design/templates/design-system-inspiration/core/config.json.tpl +1 -1
  186. package/plugins/design/templates/design-system-inspiration/core/preview/_motion-readme.md.tpl +1 -1
  187. package/plugins/flow/.claude-plugin/config.schema.json +16 -0
  188. package/plugins/design/dev-server/annotations-layer.tsx +0 -3402
  189. package/plugins/design/dev-server/client/app.jsx +0 -2985
  190. package/plugins/design/dev-server/client/index.html +0 -15
  191. package/plugins/design/dev-server/dist/client.bundle.js +0 -20692
  192. package/plugins/design/dev-server/dist/comment-mount.js +0 -1924
  193. package/plugins/design/dev-server/dist/styles.css +0 -2710
  194. package/plugins/design/dev-server/dom-selection.ts +0 -156
  195. package/plugins/design/dev-server/sync/migrate-seed.ts +0 -163
  196. package/plugins/design/dev-server/test/canvas-edit.test.ts +0 -139
  197. package/plugins/design/dev-server/test/shared-doc-migrate.test.ts +0 -159
  198. package/plugins/design/dev-server/test/sync-agent.test.ts +0 -305
  199. package/plugins/design/dev-server/test/use-annotation-resize.test.ts +0 -200
  200. package/plugins/design/dev-server/use-annotation-resize.tsx +0 -449
  201. /package/{plugins/design/dev-server → apps/studio}/activity.ts +0 -0
  202. /package/{plugins/design/dev-server → apps/studio}/bin/_enumerate-artboards-playwright.mjs +0 -0
  203. /package/{plugins/design/dev-server → apps/studio}/bin/_html-playwright.mjs +0 -0
  204. /package/{plugins/design/dev-server → apps/studio}/bin/_pdf-playwright.mjs +0 -0
  205. /package/{plugins/design/dev-server → apps/studio}/bin/_pptx-playwright.mjs +0 -0
  206. /package/{plugins/design/dev-server → apps/studio}/bin/_pw-launch.mjs +0 -0
  207. /package/{plugins/design/dev-server → apps/studio}/bin/_screenshot-playwright.mjs +0 -0
  208. /package/{plugins/design/dev-server → apps/studio}/bin/_svg-optimize.mjs +0 -0
  209. /package/{plugins/design/dev-server → apps/studio}/bin/_svg-playwright.mjs +0 -0
  210. /package/{plugins/design/dev-server → apps/studio}/bin/asset-sweep.sh +0 -0
  211. /package/{plugins/design/dev-server → apps/studio}/bin/bootstrap-check.sh +0 -0
  212. /package/{plugins/design/dev-server → apps/studio}/bin/check-runtime-bundles.sh +0 -0
  213. /package/{plugins/design/dev-server → apps/studio}/bin/draw-build.sh +0 -0
  214. /package/{plugins/design/dev-server → apps/studio}/bin/handoff.sh +0 -0
  215. /package/{plugins/design/dev-server → apps/studio}/bin/prep.sh +0 -0
  216. /package/{plugins/design/dev-server → apps/studio}/bin/scenario-report.mjs +0 -0
  217. /package/{plugins/design/dev-server → apps/studio}/bin/slug.sh +0 -0
  218. /package/{plugins/design/dev-server → apps/studio}/bin/smoke.sh +0 -0
  219. /package/{plugins/design/dev-server → apps/studio}/bin/svg-optimize.sh +0 -0
  220. /package/{plugins/design/dev-server → apps/studio}/bin/visual-sanity.sh +0 -0
  221. /package/{plugins/design/dev-server → apps/studio}/boot-self-heal.ts +0 -0
  222. /package/{plugins/design/dev-server → apps/studio}/canvas-build.ts +0 -0
  223. /package/{plugins/design/dev-server → apps/studio}/canvas-header.ts +0 -0
  224. /package/{plugins/design/dev-server → apps/studio}/canvas-meta.schema.json +0 -0
  225. /package/{plugins/design/dev-server → apps/studio}/canvas-pipeline.ts +0 -0
  226. /package/{plugins/design/dev-server → apps/studio}/client/hmr.mjs +0 -0
  227. /package/{plugins/design/dev-server → apps/studio}/client/iframe-lazy.mjs +0 -0
  228. /package/{plugins/design/dev-server → apps/studio}/client/styles/0-reset.css +0 -0
  229. /package/{plugins/design/dev-server → apps/studio}/client/styles/1-tokens.css +0 -0
  230. /package/{plugins/design/dev-server → apps/studio}/client/styles/2-layout.css +0 -0
  231. /package/{plugins/design/dev-server → apps/studio}/client/styles/5-utilities.css +0 -0
  232. /package/{plugins/design/dev-server → apps/studio}/collab/ai-activity.ts +0 -0
  233. /package/{plugins/design/dev-server → apps/studio}/collab/awareness-bridge.ts +0 -0
  234. /package/{plugins/design/dev-server → apps/studio}/collab/git-lifecycle.ts +0 -0
  235. /package/{plugins/design/dev-server → apps/studio}/collab/index.ts +0 -0
  236. /package/{plugins/design/dev-server → apps/studio}/collab/persistence.ts +0 -0
  237. /package/{plugins/design/dev-server → apps/studio}/collab/protocol.ts +0 -0
  238. /package/{plugins/design/dev-server → apps/studio}/collab/registry.ts +0 -0
  239. /package/{plugins/design/dev-server → apps/studio}/collab/room.ts +0 -0
  240. /package/{plugins/design/dev-server → apps/studio}/config.schema.json +0 -0
  241. /package/{plugins/design/dev-server → apps/studio}/context.ts +0 -0
  242. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/.min-sizes.json +0 -0
  243. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/lib0_decoding.js +0 -0
  244. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/lib0_encoding.js +0 -0
  245. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/motion.js +0 -0
  246. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/motion_react.js +0 -0
  247. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/pixi-js.js +0 -0
  248. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react-dom.js +0 -0
  249. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react-dom_client.js +0 -0
  250. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react.js +0 -0
  251. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react_jsx-dev-runtime.js +0 -0
  252. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react_jsx-runtime.js +0 -0
  253. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/y-protocols_awareness.js +0 -0
  254. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/y-protocols_sync.js +0 -0
  255. /package/{plugins/design/dev-server → apps/studio}/dist/runtime/yjs.js +0 -0
  256. /package/{plugins/design/dev-server → apps/studio}/draw/test/brush.test.ts +0 -0
  257. /package/{plugins/design/dev-server → apps/studio}/draw/test/composition.test.ts +0 -0
  258. /package/{plugins/design/dev-server → apps/studio}/draw/test/geometry.test.ts +0 -0
  259. /package/{plugins/design/dev-server → apps/studio}/draw/test/gradient.test.ts +0 -0
  260. /package/{plugins/design/dev-server → apps/studio}/draw/test/layout.test.ts +0 -0
  261. /package/{plugins/design/dev-server → apps/studio}/draw/test/optimize.test.ts +0 -0
  262. /package/{plugins/design/dev-server → apps/studio}/draw/test/palette.test.ts +0 -0
  263. /package/{plugins/design/dev-server → apps/studio}/draw/test/primitives.test.ts +0 -0
  264. /package/{plugins/design/dev-server → apps/studio}/draw/test/serialize.test.ts +0 -0
  265. /package/{plugins/design/dev-server → apps/studio}/examples/README.md +0 -0
  266. /package/{plugins/design/dev-server → apps/studio}/examples/perf-100-artboards.tsx +0 -0
  267. /package/{plugins/design/dev-server → apps/studio}/exporters/_browser-bundles.ts +0 -0
  268. /package/{plugins/design/dev-server → apps/studio}/exporters/canva-handoff-prompt.ts +0 -0
  269. /package/{plugins/design/dev-server → apps/studio}/exporters/canva.ts +0 -0
  270. /package/{plugins/design/dev-server → apps/studio}/exporters/html.ts +0 -0
  271. /package/{plugins/design/dev-server → apps/studio}/exporters/index.ts +0 -0
  272. /package/{plugins/design/dev-server → apps/studio}/exporters/pdf.ts +0 -0
  273. /package/{plugins/design/dev-server → apps/studio}/exporters/png.ts +0 -0
  274. /package/{plugins/design/dev-server → apps/studio}/exporters/pptx.ts +0 -0
  275. /package/{plugins/design/dev-server → apps/studio}/exporters/scope.ts +0 -0
  276. /package/{plugins/design/dev-server → apps/studio}/exporters/svg.ts +0 -0
  277. /package/{plugins/design/dev-server → apps/studio}/exporters/zip.ts +0 -0
  278. /package/{plugins/design/dev-server → apps/studio}/fs-watch.ts +0 -0
  279. /package/{plugins/design/dev-server → apps/studio}/handoff.ts +0 -0
  280. /package/{plugins/design/dev-server → apps/studio}/hmr-broadcast.ts +0 -0
  281. /package/{plugins/design/dev-server → apps/studio}/locator.ts +0 -0
  282. /package/{plugins/design/dev-server → apps/studio}/mem.ts +0 -0
  283. /package/{plugins/design/dev-server → apps/studio}/runtime-bundle.ts +0 -0
  284. /package/{plugins/design/dev-server → apps/studio}/server.mjs +0 -0
  285. /package/{plugins/design/dev-server → apps/studio}/sync/atomic-write.ts +0 -0
  286. /package/{plugins/design/dev-server → apps/studio}/sync/echo-guard.ts +0 -0
  287. /package/{plugins/design/dev-server → apps/studio}/sync/fs-mirror.ts +0 -0
  288. /package/{plugins/design/dev-server → apps/studio}/sync/hubs-config.ts +0 -0
  289. /package/{plugins/design/dev-server → apps/studio}/sync/materialize.ts +0 -0
  290. /package/{plugins/design/dev-server → apps/studio}/sync/origins.ts +0 -0
  291. /package/{plugins/design/dev-server → apps/studio}/sync/untrusted.ts +0 -0
  292. /package/{plugins/design/dev-server → apps/studio}/test/_helpers.ts +0 -0
  293. /package/{plugins/design/dev-server → apps/studio}/test/active-state.test.ts +0 -0
  294. /package/{plugins/design/dev-server → apps/studio}/test/ai-activity.test.ts +0 -0
  295. /package/{plugins/design/dev-server → apps/studio}/test/annotation-strokes-command.test.ts +0 -0
  296. /package/{plugins/design/dev-server → apps/studio}/test/annotations-api.test.ts +0 -0
  297. /package/{plugins/design/dev-server → apps/studio}/test/annotations-draw-modifiers.test.ts +0 -0
  298. /package/{plugins/design/dev-server → apps/studio}/test/artboard-activity-overlay.test.tsx +0 -0
  299. /package/{plugins/design/dev-server → apps/studio}/test/binary-smoke.test.ts +0 -0
  300. /package/{plugins/design/dev-server → apps/studio}/test/boot-self-heal.test.ts +0 -0
  301. /package/{plugins/design/dev-server → apps/studio}/test/bundle-smoke.test.ts +0 -0
  302. /package/{plugins/design/dev-server → apps/studio}/test/canvas-build.test.ts +0 -0
  303. /package/{plugins/design/dev-server → apps/studio}/test/canvas-header.test.ts +0 -0
  304. /package/{plugins/design/dev-server → apps/studio}/test/canvas-hmr-runtime.test.tsx +0 -0
  305. /package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-inline.test.ts +0 -0
  306. /package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-motion.test.ts +0 -0
  307. /package/{plugins/design/dev-server → apps/studio}/test/canvas-meta-api.test.ts +0 -0
  308. /package/{plugins/design/dev-server → apps/studio}/test/canvas-pipeline.test.ts +0 -0
  309. /package/{plugins/design/dev-server → apps/studio}/test/canvas-route.test.ts +0 -0
  310. /package/{plugins/design/dev-server → apps/studio}/test/collab-annotations-bridge.test.ts +0 -0
  311. /package/{plugins/design/dev-server → apps/studio}/test/collab-awareness-bridge.test.ts +0 -0
  312. /package/{plugins/design/dev-server → apps/studio}/test/collab-loopback.test.ts +0 -0
  313. /package/{plugins/design/dev-server → apps/studio}/test/collab-protocol.test.ts +0 -0
  314. /package/{plugins/design/dev-server → apps/studio}/test/collab-reseed-guard.test.ts +0 -0
  315. /package/{plugins/design/dev-server → apps/studio}/test/collab-stress.test.ts +0 -0
  316. /package/{plugins/design/dev-server → apps/studio}/test/comment-mount.test.ts +0 -0
  317. /package/{plugins/design/dev-server → apps/studio}/test/comments-api.test.ts +0 -0
  318. /package/{plugins/design/dev-server → apps/studio}/test/compile-entry.test.ts +0 -0
  319. /package/{plugins/design/dev-server → apps/studio}/test/context-resolve-tokens.test.ts +0 -0
  320. /package/{plugins/design/dev-server → apps/studio}/test/equal-spacing-detector.test.ts +0 -0
  321. /package/{plugins/design/dev-server → apps/studio}/test/exporters/canva.test.ts +0 -0
  322. /package/{plugins/design/dev-server → apps/studio}/test/exporters/endpoint.test.ts +0 -0
  323. /package/{plugins/design/dev-server → apps/studio}/test/exporters/history.test.ts +0 -0
  324. /package/{plugins/design/dev-server → apps/studio}/test/exporters/html.test.ts +0 -0
  325. /package/{plugins/design/dev-server → apps/studio}/test/exporters/pdf.test.ts +0 -0
  326. /package/{plugins/design/dev-server → apps/studio}/test/exporters/png.test.ts +0 -0
  327. /package/{plugins/design/dev-server → apps/studio}/test/exporters/pptx-deck.test.ts +0 -0
  328. /package/{plugins/design/dev-server → apps/studio}/test/exporters/pptx.test.ts +0 -0
  329. /package/{plugins/design/dev-server → apps/studio}/test/exporters/pw-launch.test.ts +0 -0
  330. /package/{plugins/design/dev-server → apps/studio}/test/exporters/scope.test.ts +0 -0
  331. /package/{plugins/design/dev-server → apps/studio}/test/exporters/svg.test.ts +0 -0
  332. /package/{plugins/design/dev-server → apps/studio}/test/exporters/zip.test.ts +0 -0
  333. /package/{plugins/design/dev-server → apps/studio}/test/fixtures/phase-20-annotations.svg +0 -0
  334. /package/{plugins/design/dev-server → apps/studio}/test/fixtures/phase-21-annotations.svg +0 -0
  335. /package/{plugins/design/dev-server → apps/studio}/test/fs-watch.test.ts +0 -0
  336. /package/{plugins/design/dev-server → apps/studio}/test/git-lifecycle.test.ts +0 -0
  337. /package/{plugins/design/dev-server → apps/studio}/test/handoff-static-frames.test.ts +0 -0
  338. /package/{plugins/design/dev-server → apps/studio}/test/handoff.test.ts +0 -0
  339. /package/{plugins/design/dev-server → apps/studio}/test/history-rollback.test.ts +0 -0
  340. /package/{plugins/design/dev-server → apps/studio}/test/hmr-broadcast.test.ts +0 -0
  341. /package/{plugins/design/dev-server → apps/studio}/test/hmr-classify.test.ts +0 -0
  342. /package/{plugins/design/dev-server → apps/studio}/test/input-router.test.ts +0 -0
  343. /package/{plugins/design/dev-server → apps/studio}/test/locator.test.ts +0 -0
  344. /package/{plugins/design/dev-server → apps/studio}/test/marquee-overlay.test.ts +0 -0
  345. /package/{plugins/design/dev-server → apps/studio}/test/move-artboards-command.test.ts +0 -0
  346. /package/{plugins/design/dev-server → apps/studio}/test/participants-chrome.test.ts +0 -0
  347. /package/{plugins/design/dev-server → apps/studio}/test/paths.test.ts +0 -0
  348. /package/{plugins/design/dev-server → apps/studio}/test/runtime-bundle-error-mapping.test.ts +0 -0
  349. /package/{plugins/design/dev-server → apps/studio}/test/runtime-bundle.test.ts +0 -0
  350. /package/{plugins/design/dev-server → apps/studio}/test/server-lifecycle.test.ts +0 -0
  351. /package/{plugins/design/dev-server → apps/studio}/test/shared-doc-foundation.test.ts +0 -0
  352. /package/{plugins/design/dev-server → apps/studio}/test/shared-doc-projection.test.ts +0 -0
  353. /package/{plugins/design/dev-server → apps/studio}/test/snap-distance-pill.test.ts +0 -0
  354. /package/{plugins/design/dev-server → apps/studio}/test/sync-atomic-write.test.ts +0 -0
  355. /package/{plugins/design/dev-server → apps/studio}/test/sync-echo-guard.test.ts +0 -0
  356. /package/{plugins/design/dev-server → apps/studio}/test/sync-fs-mirror.test.ts +0 -0
  357. /package/{plugins/design/dev-server → apps/studio}/test/sync-meta-codec.test.ts +0 -0
  358. /package/{plugins/design/dev-server → apps/studio}/test/sync-untrusted.test.ts +0 -0
  359. /package/{plugins/design/dev-server → apps/studio}/test/system-endpoint.test.ts +0 -0
  360. /package/{plugins/design/dev-server → apps/studio}/test/tool-palette.test.tsx +0 -0
  361. /package/{plugins/design/dev-server → apps/studio}/test/undo-stack.test.ts +0 -0
  362. /package/{plugins/design/dev-server → apps/studio}/test/use-agent-presence.test.tsx +0 -0
  363. /package/{plugins/design/dev-server → apps/studio}/test/use-annotation-selection.test.tsx +0 -0
  364. /package/{plugins/design/dev-server → apps/studio}/test/use-canvas-activity.test.tsx +0 -0
  365. /package/{plugins/design/dev-server → apps/studio}/test/use-cursor-modifiers.test.ts +0 -0
  366. /package/{plugins/design/dev-server → apps/studio}/test/use-keyboard-discipline.test.ts +0 -0
  367. /package/{plugins/design/dev-server → apps/studio}/test/use-selection-set.test.tsx +0 -0
  368. /package/{plugins/design/dev-server → apps/studio}/test/use-snap-guides.test.ts +0 -0
  369. /package/{plugins/design/dev-server → apps/studio}/test/use-undo-stack.test.tsx +0 -0
  370. /package/{plugins/design/dev-server → apps/studio}/test/ws-handshake.test.ts +0 -0
  371. /package/{plugins/design/dev-server → apps/studio}/tsconfig.json +0 -0
  372. /package/{plugins/design/dev-server → apps/studio}/ws.ts +0 -0
@@ -0,0 +1,1161 @@
1
+ /* @layer shell — maude DS studio chrome (Plan B), ported from `.design/ui/Studio.css`.
2
+ *
3
+ * The `.st-*` classes are lifted near-verbatim from the approved Studio.css
4
+ * mockup (every value a maude `var(--*)` token). They live inside the
5
+ * `.maude[data-theme]` root the App renders, so the maude ladder
6
+ * (1-tokens-maude.css) drives them. Grown slice-by-slice:
7
+ * Task 3 — shell scaffold · menubar · dropdowns · status bar · atoms.
8
+ * Task 4 — sidebar · tree · rail. (appended later)
9
+ * Task 5 — stage · world chrome. (appended later)
10
+ * Task 6 — right panel · palette · toast. (appended later)
11
+ *
12
+ * Per CLAUDE.md "Lift, don't reinvent"; DDR-014 @layer order preserved.
13
+ */
14
+
15
+ @layer shell {
16
+
17
+ /* ─── Shell scaffold ───────────────────────────────────────────────────────
18
+ * The real app fills the viewport (NOT an artboard body), so this overrides the
19
+ * mockup's rounded-border `.st-shell` frame: full-bleed flex column, the
20
+ * existing `.app` grid flexes as the middle body row between the bars. */
21
+ .maude { position: relative; }
22
+ .st-shell {
23
+ width: 100vw; height: 100vh; overflow: hidden;
24
+ display: flex; flex-direction: column;
25
+ background: var(--bg-0); color: var(--fg-0);
26
+ font-family: var(--font-body); font-size: var(--type-base); line-height: var(--lh-base);
27
+ -webkit-font-smoothing: antialiased;
28
+ }
29
+ /* The legacy grid body (sidebar | main | rsidebar) now flexes between the
30
+ * full-width menubar + status bar instead of owning the whole viewport. */
31
+ .st-shell > .app { width: 100%; height: auto; flex: 1 1 auto; min-height: 0; }
32
+ .st-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
33
+
34
+ /* ─── Menubar (top) ───────────────────────────────────────────────────────── */
35
+ .st-menubar {
36
+ height: 40px; flex: 0 0 40px;
37
+ display: flex; align-items: center; gap: var(--space-3);
38
+ padding: 0 var(--space-3) 0 var(--space-4);
39
+ background: var(--bg-1); border-bottom: 1px solid var(--border-default);
40
+ position: relative; z-index: 40;
41
+ }
42
+ .st-brand { display: inline-flex; align-items: center; gap: var(--space-3); padding-right: var(--space-3); }
43
+ .st-brand-mark {
44
+ width: 18px; height: 18px;
45
+ /* message-bubble corner — bottom-right squared, the other three rounded */
46
+ border-radius: var(--radius-sm) var(--radius-sm) 0 var(--radius-sm);
47
+ background: var(--accent); display: grid; place-items: center; color: var(--accent-fg);
48
+ box-shadow: 0 0 0 3px var(--accent-tint);
49
+ }
50
+ /* the spark star fills the bubble (32-grid path, identical to the logo specimen) */
51
+ .st-brand-mark svg { width: 100%; height: 100%; display: block; }
52
+ .st-brand-name { font-family: var(--font-display); font-weight: 600; font-size: var(--type-md); letter-spacing: var(--tracking-tight); }
53
+ .st-menus { display: flex; align-items: center; gap: var(--space-1); }
54
+ .st-menu {
55
+ appearance: none; border: 0; background: transparent; cursor: pointer;
56
+ font-family: var(--font-body); font-size: var(--type-sm); color: var(--fg-1);
57
+ padding: var(--space-2) var(--space-3); border-radius: var(--radius-xs);
58
+ transition: background var(--dur-soft) var(--ease-out), color var(--dur-soft) var(--ease-out);
59
+ }
60
+ .st-menu:hover { background: var(--bg-3); color: var(--fg-0); }
61
+ .st-menu[aria-expanded="true"] { background: var(--bg-3); color: var(--fg-0); }
62
+ .st-menu[aria-disabled="true"] { color: var(--fg-3); cursor: default; }
63
+ /* keyboard ring: the shared `.maude :is(button…):focus-visible` recipe */
64
+
65
+ .st-mb-right { margin-left: auto; display: flex; align-items: center; gap: var(--space-3); }
66
+ .st-stamp {
67
+ font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide);
68
+ text-transform: uppercase; color: var(--accent);
69
+ padding: var(--space-1) var(--space-3); border: 1px solid var(--accent-muted);
70
+ border-radius: var(--radius-pill); background: var(--accent-tint);
71
+ }
72
+ .st-mb-file { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px; }
73
+ .st-mb-file b { color: var(--fg-0); font-weight: 600; }
74
+ .st-mb-sep { width: 1px; height: 16px; background: var(--border-default); }
75
+ .st-mb-count { display: inline-flex; align-items: center; gap: var(--space-2); font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-1); }
76
+ .st-mb-proj { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--status-success); }
77
+ .st-whatsnew {
78
+ position: relative; appearance: none; border: 0; background: transparent; cursor: pointer;
79
+ width: 26px; height: 26px; display: grid; place-items: center; border-radius: var(--radius-sm);
80
+ color: var(--fg-1);
81
+ }
82
+ .st-whatsnew:hover { background: var(--bg-3); color: var(--fg-0); }
83
+ .st-whatsnew[data-unseen="true"] { color: var(--accent); }
84
+ .st-whatsnew[data-unseen="true"]::after {
85
+ content: ""; position: absolute; top: 3px; right: 3px; width: 7px; height: 7px;
86
+ border-radius: var(--radius-pill); background: var(--accent); border: 1.5px solid var(--bg-1);
87
+ }
88
+
89
+ /* ─── Menubar dropdown ────────────────────────────────────────────────────── */
90
+ .st-dropdown {
91
+ position: absolute; top: 38px; min-width: 230px;
92
+ background: var(--bg-2); border: 1px solid var(--border-default);
93
+ border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
94
+ /* above the floating st-banner (9100) — an open menu must never sit under
95
+ a transient notice */
96
+ padding: var(--space-2); z-index: 9150;
97
+ animation: st-pop var(--dur-panel) var(--ease-out);
98
+ transform-origin: top left;
99
+ }
100
+ @keyframes st-pop { from { opacity: 0; transform: translateY(-4px) scale(0.985); } to { opacity: 1; transform: none; } }
101
+ .st-dd-hd {
102
+ font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide);
103
+ text-transform: uppercase; color: var(--fg-3); padding: var(--space-2) var(--space-3) var(--space-1);
104
+ }
105
+ .st-dd-item {
106
+ display: flex; align-items: center; gap: var(--space-3); justify-content: space-between;
107
+ padding: var(--space-2) var(--space-3); border-radius: var(--radius-xs);
108
+ font-size: var(--type-sm); color: var(--fg-1); cursor: pointer;
109
+ appearance: none; border: 0; background: transparent; width: 100%; text-align: left;
110
+ font-family: var(--font-body);
111
+ }
112
+ .st-dd-item:hover, .st-dd-item.is-hover { background: var(--bg-4); color: var(--fg-0); }
113
+ .st-dd-item[aria-disabled="true"] { color: var(--fg-3); cursor: default; }
114
+ .st-dd-item[aria-disabled="true"]:hover { background: transparent; color: var(--fg-3); }
115
+ .st-dd-item .st-dd-lead { display: inline-flex; align-items: center; gap: var(--space-3); }
116
+ .st-dd-check { width: 14px; color: var(--accent); display: inline-flex; }
117
+ .st-dd-sep { height: 1px; background: var(--border-subtle); margin: var(--space-2) var(--space-2); }
118
+ .st-dd-phase { font-family: var(--font-mono); font-size: 10px; color: var(--fg-3); letter-spacing: var(--tracking-wide); text-transform: uppercase; }
119
+
120
+ /* ─── Icon button (shared chrome control) ─────────────────────────────────── */
121
+ .st-iconbtn {
122
+ appearance: none; border: 0; background: transparent; cursor: pointer;
123
+ width: 26px; height: 26px; display: grid; place-items: center;
124
+ border-radius: var(--radius-sm); color: var(--fg-2);
125
+ transition: background var(--dur-soft) var(--ease-out), color var(--dur-soft) var(--ease-out);
126
+ }
127
+ .st-iconbtn:hover { background: var(--bg-3); color: var(--fg-0); }
128
+
129
+ /* ─── Presence avatars (menubar) ──────────────────────────────────────────── */
130
+ .st-presence { display: flex; align-items: center; }
131
+ /* DS avatar recipe (ui_kits showcase `.sc-avatar`): hue-TINTED surface + hue
132
+ * border + fg-0 text. A solid hue fill with white text broke the accent-fg
133
+ * contrast rule on dark and washed out entirely in light theme. */
134
+ .st-avatar {
135
+ --av-hue: var(--accent);
136
+ width: 22px; height: 22px; border-radius: var(--radius-pill);
137
+ display: grid; place-items: center;
138
+ font-family: var(--font-mono); font-size: 10px; line-height: 1;
139
+ letter-spacing: 0.02em; text-transform: uppercase; font-weight: 600;
140
+ background: color-mix(in oklab, var(--av-hue) 22%, var(--bg-3));
141
+ border: 1px solid var(--av-hue);
142
+ color: var(--fg-0);
143
+ }
144
+ .st-presence .st-avatar { margin-left: -6px; box-shadow: 0 0 0 1.5px var(--bg-1); }
145
+ .st-presence .st-avatar:first-child { margin-left: 0; }
146
+
147
+ /* ─── Status bar (bottom — context) ───────────────────────────────────────── */
148
+ .st-statusbar {
149
+ height: 30px; flex: 0 0 30px; display: flex; align-items: center; gap: var(--space-4);
150
+ padding: 0 var(--space-4); background: var(--bg-2);
151
+ border-top: 1px solid var(--border-strong);
152
+ box-shadow: inset 0 1px 0 color-mix(in oklab, var(--fg-0) 6%, transparent);
153
+ font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-1); z-index: 30;
154
+ }
155
+ .st-sb-slot { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; }
156
+ .st-sb-slot .lbl { color: var(--fg-3); text-transform: uppercase; letter-spacing: var(--tracking-wide); font-size: 10px; flex: none; }
157
+ .st-sb-slot .val { color: var(--fg-0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
158
+ .st-sb-slot + .st-sb-slot { padding-left: var(--space-4); border-left: 1px solid var(--border-subtle); }
159
+ .st-sb-active { font-weight: 500; }
160
+ .st-sb-active .lead { width: 6px; height: 6px; border-radius: var(--radius-pill); background: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); flex: none; }
161
+ .st-sb-sel .val { color: var(--accent); }
162
+ .st-sb-sel-clear { appearance: none; border: 0; background: transparent; color: var(--fg-3); cursor: pointer; font-size: 13px; line-height: 1; padding: 0 2px; }
163
+ .st-sb-sel-clear:hover { color: var(--fg-0); }
164
+ .st-sb-spacer { flex: 1; }
165
+ .st-sb-theme { display: inline-flex; align-items: center; gap: var(--space-2); cursor: pointer; appearance: none; color: var(--fg-0); font-family: var(--font-mono); font-size: var(--type-xs); padding: 3px var(--space-3); border-radius: var(--radius-sm); border: 1px solid var(--border-default); background: var(--bg-3); }
166
+ .st-sb-theme:hover { background: var(--bg-4); border-color: var(--border-strong); }
167
+ .st-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); display: inline-block; flex: none; }
168
+ .st-live-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--presence-offline); flex: none; }
169
+ .st-live-dot.is-connected { background: var(--presence-online); }
170
+ .st-sb-sync-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--status-warn); flex: none; }
171
+ .st-sb-sync-dot.is-online { background: var(--presence-online); }
172
+
173
+ /* ═══ Task 4 — body row · sidebar · tree · rail ═══════════════════════════════ */
174
+
175
+ /* The body flex row replaces the legacy `.app` grid: rail | sidebar | main | rpanel. */
176
+ .st-body { flex: 1; display: flex; min-height: 0; min-width: 0; }
177
+ .st-body > .main { flex: 1; min-width: 0; }
178
+ .st-body > .st-rpanel { flex: 0 0 304px; }
179
+
180
+ /* ─── Left sidebar — file tree ────────────────────────────────────────────── */
181
+ .st-sidebar {
182
+ width: 252px; flex: 0 0 252px;
183
+ background: var(--bg-1); border-right: 1px solid var(--border-default);
184
+ display: flex; flex-direction: column; min-height: 0;
185
+ transition: width var(--dur-panel) var(--ease-in-out), flex-basis var(--dur-panel) var(--ease-in-out);
186
+ overflow: hidden;
187
+ }
188
+ .st-sidebar.is-collapsed { width: 0; flex-basis: 0; border-right-color: transparent; }
189
+ .st-sb-hd {
190
+ display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
191
+ padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border-subtle);
192
+ }
193
+ .st-sb-title { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); }
194
+ .st-sb-hd-actions { display: flex; align-items: center; gap: var(--space-2); }
195
+ .st-live { display: inline-flex; align-items: center; gap: var(--space-2); font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); white-space: nowrap; }
196
+
197
+ .st-search { padding: var(--space-3) var(--space-3) var(--space-2); }
198
+ .st-search-box {
199
+ display: flex; align-items: center; gap: var(--space-2);
200
+ background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-sm);
201
+ padding: var(--space-2) var(--space-3); color: var(--fg-3);
202
+ }
203
+ .st-search-box svg { flex: none; }
204
+ .st-search-box input {
205
+ appearance: none; border: 0; background: transparent; color: var(--fg-0);
206
+ font-family: var(--font-body); font-size: var(--type-sm); width: 100%; min-width: 0;
207
+ }
208
+ .st-search-box input::placeholder { color: var(--fg-3); }
209
+ .st-search-box .kbd { margin-left: auto; }
210
+ .st-search-clear { appearance: none; border: 0; background: transparent; color: var(--fg-3); cursor: pointer; margin-left: auto; font-size: 14px; line-height: 1; padding: 0 2px; }
211
+ .st-search-clear:hover { color: var(--fg-0); }
212
+
213
+ /* New-board composer (Phase 22) — opens inline below the header on the + click. */
214
+ .st-newboard { display: flex; gap: var(--space-2); padding: var(--space-2) var(--space-3); }
215
+ .st-newboard input {
216
+ flex: 1; min-width: 0; appearance: none; background: var(--bg-3); border: 1px solid var(--accent-muted);
217
+ border-radius: var(--radius-sm); color: var(--fg-0); font-family: var(--font-body); font-size: var(--type-sm);
218
+ padding: var(--space-2) var(--space-3);
219
+ }
220
+ .st-newboard-go {
221
+ appearance: none; border: 1px solid var(--accent); background: var(--accent); color: var(--accent-fg);
222
+ border-radius: var(--radius-sm); cursor: pointer; padding: 0 var(--space-3); font-family: var(--font-mono); font-size: var(--type-sm);
223
+ }
224
+ .st-newboard-go:disabled { opacity: 0.5; cursor: not-allowed; }
225
+ .st-newboard-err { padding: var(--space-1) var(--space-4) var(--space-2); color: var(--status-error); font-size: var(--type-xs); }
226
+
227
+ .st-tree { flex: 1; overflow-y: auto; padding: var(--space-2) var(--space-2) var(--space-4); }
228
+ .st-tree-section { margin-bottom: var(--space-2); }
229
+ .st-tree-sec-hd {
230
+ display: flex; align-items: center; gap: var(--space-2); width: 100%;
231
+ padding: var(--space-2) var(--space-3); cursor: pointer; color: var(--fg-2);
232
+ appearance: none; border: 0; background: transparent; text-align: left;
233
+ }
234
+ .st-tree-sec-hd:hover { color: var(--fg-0); }
235
+ .st-tree-sec-hd .st-sec-name { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; }
236
+ .st-tree-sec-hd .st-pill {
237
+ margin-left: auto; font-family: var(--font-mono); font-size: 10px; color: var(--fg-3);
238
+ padding: 0 6px; border: 1px solid var(--border-subtle); border-radius: var(--radius-pill);
239
+ }
240
+ .st-tree-empty { padding: var(--space-2) var(--space-5); color: var(--fg-3); font-size: var(--type-xs); font-style: italic; }
241
+
242
+ .st-row {
243
+ display: flex; align-items: center; gap: var(--space-2); width: 100%;
244
+ padding: var(--space-2) var(--space-3); border-radius: var(--radius-xs);
245
+ font-size: var(--type-sm); color: var(--fg-1); cursor: default; position: relative;
246
+ appearance: none; border: 0; background: transparent; text-align: left; font-family: var(--font-body);
247
+ }
248
+ .st-row:hover { background: var(--bg-2); }
249
+ .st-row.is-sel { background: var(--accent-tint); color: var(--fg-0); box-shadow: inset 2px 0 0 var(--accent); }
250
+ .st-row.is-muted { color: var(--fg-3); }
251
+ .st-row[aria-disabled="true"] { cursor: default; }
252
+ .st-row-glyph { width: 14px; display: inline-flex; justify-content: center; color: var(--fg-3); flex: 0 0 14px; }
253
+ .st-row.is-sel .st-row-glyph { color: var(--accent); }
254
+ .st-row-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
255
+ .st-row-badge {
256
+ margin-left: auto; font-family: var(--font-mono); font-size: 10px; line-height: 1;
257
+ min-width: 16px; height: 16px; padding: 0 4px; display: inline-flex; align-items: center; justify-content: center;
258
+ border-radius: var(--radius-pill); background: var(--accent); color: var(--accent-fg); flex: none;
259
+ }
260
+ /* delete affordance — sibling of the row button (can't nest buttons). */
261
+ .st-row-wrap { position: relative; display: flex; align-items: center; }
262
+ .st-row-wrap .st-row { flex: 1; }
263
+ .st-row-del {
264
+ position: absolute; right: var(--space-2); top: 50%; transform: translateY(-50%);
265
+ appearance: none; border: 0; background: transparent; color: var(--fg-3); cursor: pointer;
266
+ width: 22px; height: 22px; display: grid; place-items: center; border-radius: var(--radius-xs);
267
+ opacity: 0; transition: opacity var(--dur-soft) var(--ease-out);
268
+ }
269
+ /* Kept in the a11y tree (opacity, not display:none) so keyboard users reach it. */
270
+ .st-row-wrap:hover .st-row-del, .st-row-del:focus-visible { opacity: 1; }
271
+ /* Shift the open-comments badge left of the delete button on hover so they
272
+ don't overlap (the delete is absolute at the row's right edge). */
273
+ .st-row-wrap:hover .st-row-badge,
274
+ .st-row-wrap:focus-within .st-row-badge { margin-right: 24px; }
275
+ .st-row-del:hover { color: var(--status-error); background: color-mix(in oklab, var(--status-error) 14%, transparent); }
276
+
277
+ /* DS-folder row — chevron toggles disclosure, name opens the system view. */
278
+ .st-ds-folder { display: flex; align-items: center; gap: 0; padding: 0; }
279
+ .st-ds-folder.is-sel { background: var(--accent-tint); border-radius: var(--radius-xs); box-shadow: inset 2px 0 0 var(--accent); }
280
+ .st-ds-chev { appearance: none; border: 0; background: transparent; cursor: pointer; color: var(--fg-3); display: inline-flex; padding: var(--space-2) 0 var(--space-2) var(--space-2); }
281
+ .st-ds-open { appearance: none; border: 0; background: transparent; cursor: pointer; color: var(--fg-1); flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--space-2); text-align: left; padding: var(--space-2) var(--space-3) var(--space-2) 0; font-family: var(--font-body); font-size: var(--type-sm); }
282
+ .st-ds-folder.is-sel .st-ds-open { color: var(--fg-0); }
283
+
284
+ /* collapsed rail — thin strip with a re-open affordance */
285
+ .st-rail {
286
+ width: 0; flex: 0 0 0; overflow: hidden; background: var(--bg-1);
287
+ border-right: 1px solid transparent;
288
+ transition: width var(--dur-panel) var(--ease-in-out), flex-basis var(--dur-panel) var(--ease-in-out), border-color var(--dur-panel) var(--ease-in-out);
289
+ }
290
+ .st-rail.is-shown { width: 44px; flex-basis: 44px; border-right-color: var(--border-default); }
291
+ .st-rail-inner { width: 44px; display: flex; flex-direction: column; align-items: center; gap: var(--space-3); padding: var(--space-3) 0; }
292
+
293
+ /* ═══ Task 5 — stage (iframe viewport frame) + empty state ════════════════════
294
+ * The canvas iframe (canvas-shell.tsx) renders its OWN dotted world + floating
295
+ * toolbar + minimap + zoom HUD (DDR-054, reskinned to maude in Task 7). The
296
+ * shell stage only frames it; the maude dot-grid shows in the empty/system
297
+ * state behind the iframe. NO shell-side floating chrome — that would duplicate
298
+ * the in-iframe controls. Keeps the legacy `.viewport > iframe` fill rules. */
299
+ .st-stage {
300
+ background: var(--canvas-bg);
301
+ background-image: radial-gradient(var(--canvas-dot) 1.1px, transparent 1.2px);
302
+ background-size: var(--canvas-grid) var(--canvas-grid);
303
+ }
304
+ .st-empty {
305
+ position: absolute; inset: 0; display: flex; flex-direction: column;
306
+ align-items: center; justify-content: center; gap: var(--space-4);
307
+ text-align: center; padding: var(--space-8); pointer-events: none;
308
+ }
309
+ .st-empty code, .st-empty .kbd, .st-empty strong { pointer-events: auto; }
310
+ .st-empty-brand { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-4); }
311
+ .st-empty-wm { font-family: var(--font-display); font-size: var(--type-2xl); font-weight: 600; letter-spacing: var(--tracking-tight); color: var(--fg-0); }
312
+ .st-empty-sub { font-size: var(--type-xs); color: var(--fg-3); letter-spacing: var(--tracking-wide); }
313
+ .st-empty-title { font-family: var(--font-display); font-size: var(--type-xl); font-weight: 600; color: var(--fg-1); }
314
+ .st-empty-body { max-width: 540px; font-size: var(--type-sm); line-height: 1.7; color: var(--fg-2); }
315
+ .st-empty-body code { font-family: var(--font-mono); font-size: var(--type-xs); background: var(--bg-2); color: var(--accent); padding: 1px 5px; border-radius: var(--radius-xs); }
316
+ .st-empty-body strong { color: var(--fg-0); font-weight: 600; }
317
+
318
+ /* ═══ Task 6 — right panel (Inspector / Comments) + palette + toast ═══════════ */
319
+ .st-rpanel {
320
+ background: var(--bg-1); border-left: 1px solid var(--border-default);
321
+ display: flex; flex-direction: column; min-height: 0;
322
+ }
323
+ .st-rp-tabs { display: flex; gap: var(--space-1); padding: var(--space-2) var(--space-3) 0; border-bottom: 1px solid var(--border-subtle); flex: none; }
324
+ .st-rp-tabs--filters { border-bottom: none; padding-bottom: var(--space-3); }
325
+ .st-rp-tab {
326
+ appearance: none; border: 0; background: transparent; cursor: pointer;
327
+ font-size: var(--type-sm); color: var(--fg-2); font-family: var(--font-body);
328
+ padding: var(--space-3) var(--space-3); border-bottom: 2px solid transparent;
329
+ display: inline-flex; align-items: center; gap: var(--space-2);
330
+ }
331
+ .st-rp-tab.is-active { color: var(--fg-0); border-bottom-color: var(--accent); }
332
+ .st-rp-tab .st-rp-tabct { font-family: var(--font-mono); font-size: 10px; color: var(--fg-3); }
333
+ .st-rp-body { flex: 1; overflow-y: auto; padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-4); }
334
+ .st-rp-hd { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); }
335
+ .st-rp-empty { color: var(--fg-2); font-size: var(--type-sm); line-height: 1.6; display: flex; flex-direction: column; gap: var(--space-4); }
336
+
337
+ /* comment pin (inline badge in the panel) */
338
+ .st-pin--inline {
339
+ position: static; width: 18px; height: 18px; border-radius: 4px;
340
+ background: var(--accent); color: var(--accent-fg); display: grid; place-items: center;
341
+ font-family: var(--font-mono); font-size: var(--type-xs); font-weight: 600; flex: none;
342
+ }
343
+
344
+ /* comments panel */
345
+ .st-cm-filters { display: flex; gap: var(--space-1); flex-wrap: wrap; }
346
+ .st-cm-filter { appearance: none; border: 1px solid var(--border-default); background: var(--bg-2); cursor: pointer; font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill); }
347
+ .st-cm-filter.is-active { background: var(--accent-tint); color: var(--accent); border-color: var(--accent-muted); }
348
+ .st-cm-group-hd { display: flex; align-items: center; justify-content: space-between; width: 100%; font-size: var(--type-xs); color: var(--fg-2); padding: var(--space-1) 0; appearance: none; border: 0; background: transparent; cursor: pointer; font-family: var(--font-body); }
349
+ .st-cm-group-hd:hover { color: var(--fg-0); }
350
+ .st-comment { border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: var(--space-3); background: var(--bg-2); display: flex; flex-direction: column; gap: var(--space-2); cursor: pointer; }
351
+ .st-comment:hover { border-color: var(--border-default); }
352
+ .st-comment.is-active { border-color: var(--accent-muted); box-shadow: 0 0 0 2px var(--accent-tint); }
353
+ .st-comment.is-resolved { opacity: 0.6; }
354
+ .st-comment-hd { display: flex; align-items: center; gap: var(--space-2); }
355
+ .st-comment-time { margin-left: auto; font-family: var(--font-mono); font-size: 10px; color: var(--fg-3); }
356
+ .st-comment-txt { font-size: var(--type-sm); color: var(--fg-1); line-height: 1.5; word-break: break-word; }
357
+ .st-comment-foot { display: flex; align-items: center; gap: var(--space-2); }
358
+ .st-comment-sel { font-family: var(--font-mono); font-size: 10px; color: var(--fg-3); background: var(--bg-3); padding: 1px 5px; border-radius: var(--radius-xs); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; }
359
+ .st-mini-act { margin-left: auto; display: flex; gap: var(--space-1); flex: none; }
360
+ .st-mini-act .st-iconbtn { width: 22px; height: 22px; }
361
+
362
+ /* inspector panel rows */
363
+ .st-rp-tabct { font-family: var(--font-mono); font-size: 10px; color: var(--fg-3); }
364
+ .st-insp-row { display: grid; grid-template-columns: 56px 1fr; align-items: center; gap: var(--space-3); }
365
+ .st-insp-label { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
366
+ .st-insp-val { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-0); word-break: break-word; }
367
+ .st-insp-empty { color: var(--fg-3); font-size: var(--type-sm); line-height: 1.6; }
368
+ .st-insp-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
369
+ .st-insp-chip { font-family: var(--font-mono); font-size: 10px; color: var(--fg-1); background: var(--bg-3); border: 1px solid var(--border-subtle); padding: 1px 5px; border-radius: var(--radius-xs); }
370
+
371
+ /* ─── Floating status banners (sync / git-lifecycle) ──────────────────────── */
372
+ .st-banner {
373
+ /* below the 40px menubar — at top:12px the banner covered the menus + file slot */
374
+ position: fixed; top: 48px; left: 50%; transform: translateX(-50%); z-index: 9100;
375
+ display: flex; align-items: center; gap: var(--space-3);
376
+ padding: var(--space-2) var(--space-4); border-radius: var(--radius-pill);
377
+ border: 1px solid var(--border-default); background: var(--bg-2); color: var(--fg-0);
378
+ box-shadow: var(--shadow-md); font-family: var(--font-body); font-size: var(--type-sm);
379
+ font-weight: 500; max-width: 80vw; line-height: 1.3;
380
+ animation: st-slide-down var(--dur-route) var(--ease-out);
381
+ }
382
+ @keyframes st-slide-down { from { opacity: 0; transform: translate(-50%, -6px); } to { opacity: 1; transform: translate(-50%, 0); } }
383
+ .st-banner--warn { border-color: var(--status-warn); background: color-mix(in oklab, var(--status-warn) 14%, var(--bg-1)); }
384
+ .st-banner--error { border-color: var(--status-error); background: color-mix(in oklab, var(--status-error) 14%, var(--bg-1)); }
385
+ .st-banner--success { border-color: var(--status-success); background: color-mix(in oklab, var(--status-success) 14%, var(--bg-1)); }
386
+ .st-banner--info { border-color: var(--status-info); background: color-mix(in oklab, var(--status-info) 14%, var(--bg-1)); }
387
+ .st-banner-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); flex: none; }
388
+ .st-banner--warn .st-banner-dot { background: var(--status-warn); }
389
+ .st-banner--error .st-banner-dot { background: var(--status-error); }
390
+ .st-banner--success .st-banner-dot { background: var(--status-success); }
391
+ .st-banner--info .st-banner-dot { background: var(--status-info); }
392
+ .st-banner .btn--sm { margin-left: var(--space-2); }
393
+ .st-banner-close { appearance: none; border: 0; background: transparent; color: var(--fg-2); cursor: pointer; font-size: 16px; line-height: 1; padding: 0 2px; margin-left: var(--space-1); border-radius: var(--radius-xs); flex: none; }
394
+ .st-banner-close:hover { background: color-mix(in oklab, var(--fg-0) 12%, transparent); color: var(--fg-0); }
395
+
396
+ /* ─── Command palette (⌘K) ───────────────────────────────────────────────── */
397
+ .st-scrim { position: fixed; inset: 0; background: color-mix(in oklab, var(--bg-0) 62%, transparent); z-index: 9000; display: grid; place-items: start center; padding-top: 12vh; }
398
+ .st-palette {
399
+ width: 560px; max-width: 92vw; background: var(--bg-2); border: 1px solid var(--border-default);
400
+ border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden;
401
+ animation: st-pop var(--dur-route) var(--ease-out);
402
+ }
403
+ .st-pal-search { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border-subtle); color: var(--fg-3); }
404
+ .st-pal-search input { flex: 1; min-width: 0; appearance: none; border: 0; background: transparent; color: var(--fg-0); font-size: var(--type-lg); font-family: var(--font-body); }
405
+ .st-pal-search input::placeholder { color: var(--fg-3); }
406
+ .st-pal-search .kbd { margin-left: auto; }
407
+ .st-pal-list { max-height: 340px; overflow-y: auto; padding: var(--space-2); }
408
+ .st-pal-group { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-3); padding: var(--space-3) var(--space-3) var(--space-1); }
409
+ .st-pal-empty { padding: var(--space-5); text-align: center; color: var(--fg-3); font-size: var(--type-sm); }
410
+ .st-pal-item { display: flex; align-items: center; gap: var(--space-3); width: 100%; padding: var(--space-3); border-radius: var(--radius-sm); color: var(--fg-1); appearance: none; border: 0; background: transparent; cursor: pointer; text-align: left; font-family: var(--font-body); font-size: var(--type-sm); }
411
+ .st-pal-item.is-active { background: var(--accent-tint); color: var(--fg-0); }
412
+ .st-pal-label { flex: 1; }
413
+ .st-pal-item .st-pal-kbd { margin-left: auto; flex: none; }
414
+ .st-pal-icon { width: 26px; height: 26px; border-radius: var(--radius-sm); background: var(--bg-4); display: grid; place-items: center; color: var(--fg-1); flex: none; }
415
+ .st-pal-item.is-active .st-pal-icon { background: var(--accent); color: var(--accent-fg); }
416
+
417
+ /* ─── What's-new toast (Plan C P6) ─────────────────────────────────────────
418
+ * Lifted from Studio.css `.st-toast*`; repositioned fixed bottom-left for the
419
+ * real shell (the mockup floated it inside the stage). Mirrors ai-banner. */
420
+ .st-toast {
421
+ /* bottom raised above the in-canvas zoom pill (`.dc-zoom-tb`, bottom-left). */
422
+ position: fixed; left: 16px; bottom: 84px; width: 320px; z-index: 8000;
423
+ background: var(--bg-2); border: 1px solid var(--border-default); border-left: 3px solid var(--accent);
424
+ border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: var(--space-4);
425
+ display: flex; flex-direction: column; gap: var(--space-2);
426
+ animation: st-toast-in var(--dur-route) var(--ease-out);
427
+ }
428
+ @keyframes st-toast-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
429
+ @media (prefers-reduced-motion: reduce) { .st-toast { animation-duration: 1ms; } }
430
+ .st-toast-hd { display: flex; align-items: center; gap: var(--space-2); color: var(--accent); font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; }
431
+ .st-toast-title { font-size: var(--type-md); font-weight: 600; color: var(--fg-0); }
432
+ .st-toast-txt { font-size: var(--type-sm); color: var(--fg-1); line-height: 1.5; }
433
+ .st-toast-actions { display: flex; gap: var(--space-2); margin-top: var(--space-1); }
434
+ .st-toast-close { position: absolute; top: var(--space-2); right: var(--space-2); appearance: none; border: 0; background: transparent; color: var(--fg-3); cursor: pointer; font-size: 16px; line-height: 1; padding: 2px 6px; border-radius: var(--radius-xs); }
435
+ .st-toast-close:hover { background: var(--bg-3); color: var(--fg-0); }
436
+
437
+ /* ─── Export & handoff dialog (Plan C P9/P10) ──────────────────────────────
438
+ * Lifted from Studio.css `.st-dialog*` / `.st-fmt*`. Rendered inside `.st-scrim`. */
439
+ .st-dialog { width: 540px; max-width: 92vw; background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden; animation: st-pop var(--dur-route) var(--ease-out); }
440
+ .st-dialog-hd { display: flex; align-items: center; justify-content: space-between; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border-subtle); }
441
+ .st-dialog-title { font-family: var(--font-display); font-size: var(--type-lg); font-weight: 600; color: var(--fg-0); }
442
+ .st-dialog-bd { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-4); }
443
+ .st-fmt-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); }
444
+ .st-fmt { display: flex; flex-direction: column; gap: var(--space-2); align-items: flex-start; padding: var(--space-3) var(--space-4); border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-2); cursor: pointer; color: var(--fg-1); appearance: none; text-align: left; }
445
+ .st-fmt:hover { border-color: var(--border-strong); }
446
+ .st-fmt.is-on { border-color: var(--accent); background: var(--accent-tint); color: var(--fg-0); box-shadow: 0 0 0 2px var(--accent-tint); }
447
+ .st-fmt-name { font-family: var(--font-mono); font-size: var(--type-sm); font-weight: 600; }
448
+ .st-fmt-sub { font-size: var(--type-xs); color: var(--fg-2); }
449
+ .st-dialog-row { display: flex; align-items: center; gap: var(--space-3); }
450
+ .st-dialog-lbl { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
451
+ .st-select { flex: 1; appearance: none; background: var(--bg-2); color: var(--fg-0); border: 1px solid var(--border-default); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); font-family: var(--font-body); font-size: var(--type-sm); cursor: pointer; }
452
+ .st-dialog-ft { display: flex; align-items: center; gap: var(--space-3); justify-content: flex-end; padding: var(--space-4) var(--space-5); border-top: 1px solid var(--border-subtle); }
453
+ .st-export-recent { display: flex; flex-direction: column; gap: 2px; max-height: 132px; overflow-y: auto; }
454
+ .st-export-recent-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); font-size: var(--type-xs); color: var(--fg-2); }
455
+ .st-export-recent-row:hover { background: var(--bg-2); }
456
+ .st-export-recent-row .st-mono { color: var(--fg-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 50%; }
457
+
458
+ /* ─── Inspector panel fields / layers / css (Plan C P11–P13) ───────────────
459
+ * Lifted from Studio.css; complements the already-present `.st-insp-row`,
460
+ * `.st-insp-label`, `.st-rp-*`. */
461
+ .st-insp-fields { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }
462
+ .st-field { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); color: var(--fg-0); background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: var(--space-1) var(--space-2); width: 58px; text-align: right; }
463
+ .st-field-lead { display: inline-flex; align-items: center; gap: var(--space-1); }
464
+ .st-field-lead .k { font-family: var(--font-mono); font-size: 9px; color: var(--fg-3); }
465
+ /* Phase 12.3 — maude DS coordinate cell (components-inputs `.fld-mini`): a mono
466
+ * axis tag glued to the tabular field, the tag a left segment of one bordered
467
+ * group. focus-within rings the whole cell (border-accent + 3px tint halo). */
468
+ .st-fmini { display: inline-flex; align-items: stretch; min-width: 0; flex: 1 1 0; border: 1px solid var(--border-default); border-radius: var(--radius-xs); overflow: hidden; background: var(--bg-3); transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out); }
469
+ .st-fmini .st-mtag { flex: none; display: flex; align-items: center; justify-content: center; width: 20px; font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); background: var(--bg-2); border-right: 1px solid var(--border-default); }
470
+ .st-fmini input, .st-fmini .st-fminival { flex: 1 1 auto; min-width: 0; width: 100%; box-sizing: border-box; appearance: none; border: 0; border-radius: 0; background: transparent; color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); text-align: right; padding: 3px var(--space-2); }
471
+ .st-fmini input:focus { outline: none; }
472
+ .st-fmini:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
473
+ .st-insp-unit { align-self: center; font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); letter-spacing: var(--tracking-wide); }
474
+ /* design-critic 1.2 — the Inspect FILL/TEXT chip was collapsing to a thin sliver
475
+ * (read as a text caret) because its container `.st-swatch-row` had no flex rule,
476
+ * so the inline swatch span ignored its width/height. Define the row + make the
477
+ * chip a block so the resolved colour reads as a real swatch. */
478
+ .st-swatch-row { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
479
+ .st-insp-swatch { display: block; width: 18px; height: 18px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); flex: none; }
480
+ .st-layer { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2); border-radius: var(--radius-xs); font-size: var(--type-sm); color: var(--fg-1); font-family: var(--font-mono); }
481
+ .st-layer:hover { background: var(--bg-2); }
482
+ /* maude signature — selection is an accent-tint wash + an inset 2px accent bar,
483
+ * never a solid fill (DS hard rule). */
484
+ .st-layer.is-sel { background: var(--accent-tint); color: var(--fg-0); box-shadow: inset 2px 0 0 var(--accent); }
485
+ /* Phase 12 Task 4 — browsable layers tree rows */
486
+ .st-layer--row { cursor: pointer; padding: 3px var(--space-2); gap: 4px; white-space: nowrap; }
487
+ .st-layer--row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
488
+ .st-layer-caret { flex: none; width: 14px; height: 14px; display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 0; color: var(--fg-3); font-size: 9px; line-height: 1; cursor: pointer; padding: 0; }
489
+ .st-layer-label { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; }
490
+ .st-layer-type { flex: none; font-size: 9px; color: var(--fg-3); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
491
+ /* Phase 12.3 (W3.1) — type icon tint + per-row visibility (eye) toggle. */
492
+ .st-layer-ticon { flex: none; color: var(--fg-3); }
493
+ .st-layer.is-sel .st-layer-ticon { color: var(--accent); }
494
+ .st-layer-eye { flex: none; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 0; color: var(--fg-3); cursor: pointer; padding: 0; border-radius: var(--radius-xs); opacity: 0; }
495
+ .st-layer--row:hover .st-layer-eye, .st-layer--row:focus-within .st-layer-eye { opacity: 1; }
496
+ .st-layer-eye:hover { color: var(--fg-0); background: var(--bg-3); }
497
+ .st-layer-eye:focus-visible { outline: none; color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
498
+ /* a hidden layer stays dim + keeps its eye visible (so it can be re-shown) */
499
+ .st-layer.is-hidden { opacity: 0.45; }
500
+ .st-layer.is-hidden .st-layer-eye { opacity: 1; color: var(--fg-2); }
501
+ .st-css { font-family: var(--font-mono); font-size: var(--type-xs); background: var(--bg-0); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: var(--space-3); line-height: 1.7; color: var(--fg-1); }
502
+ .st-css .comment { color: var(--fg-3); }
503
+
504
+ /* Phase 12.2 — in-canvas CSS editor knobs. Full-width value fields (NOT the 58px
505
+ read-only inspect fields), grouped sections, color swatch, per-field feedback. */
506
+ .st-css-panel { display: flex; flex-direction: column; gap: var(--space-2); }
507
+ .st-css-title { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-1); word-break: break-word; }
508
+ .st-css-group { font-family: var(--font-mono); font-size: 10px; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-3); margin-top: var(--space-3); }
509
+ .st-css-row { display: grid; grid-template-columns: 72px 1fr; align-items: center; gap: var(--space-2); }
510
+ .st-css-label { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); }
511
+ .st-css-control { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
512
+ .st-css-input { flex: 1 1 auto; min-width: 0; width: 100%; box-sizing: border-box; font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); color: var(--fg-0); background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: var(--space-1) var(--space-2); text-align: left; }
513
+ .st-css-input::placeholder { color: var(--fg-3); }
514
+ .st-css-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
515
+ .st-css-swatch { position: relative; flex: none; width: 22px; height: 22px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); padding: 0; cursor: pointer; overflow: hidden; background-image: linear-gradient(45deg, var(--bg-2) 25%, transparent 25%), linear-gradient(-45deg, var(--bg-2) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--bg-2) 75%), linear-gradient(-45deg, transparent 75%, var(--bg-2) 75%); background-size: 8px 8px; background-position: 0 0, 0 4px, 4px -4px, -4px 0; }
516
+ .st-css-swatch > span { position: absolute; inset: 0; }
517
+ .st-css-swatch input[type="color"] { position: absolute; inset: -4px; width: calc(100% + 8px); height: calc(100% + 8px); opacity: 0; cursor: pointer; border: 0; padding: 0; }
518
+ .st-css-status { font-family: var(--font-mono); font-size: 10px; min-height: 12px; }
519
+ .st-css-status.is-error { color: oklch(0.62 0.2 25); }
520
+ .st-css-status.is-saved { color: var(--fg-3); }
521
+ .st-css-help { font-size: var(--type-xs); color: var(--fg-3); line-height: 1.5; margin-top: var(--space-2); }
522
+ .st-css-help code { font-family: var(--font-mono); color: var(--fg-2); background: var(--bg-3); padding: 0 3px; border-radius: 3px; }
523
+ .st-css-disabled { color: var(--fg-2); font-size: var(--type-sm); line-height: 1.6; }
524
+ .st-css-disabled code { font-family: var(--font-mono); color: var(--accent); background: var(--bg-2); padding: 1px 5px; border-radius: var(--radius-xs); }
525
+
526
+
527
+ /* Phase 12.2 port — interactive CSS panel knobs (DDR-104). Ported from the
528
+ critic-approved + user-iterated Studio.css spec. Tokens resolve from the
529
+ shell .maude[data-theme] root (1-tokens-maude.css). */
530
+ /* ─── CSS panel · Phase 12.2 spec (DDR-104) ──────────────────────────────────
531
+ * Hybrid vocabulary (friendly section headers + CSS-named rows), per-field
532
+ * token dropdowns, nested box-model widget, per-row provenance, two-hatch
533
+ * Advanced section. Scoped `.st-cp-*` (never reuses the cramped `.st-field`).
534
+ * Critic iter-1 fixes: live text off the disabled --fg-3 token → --fg-2 (WCAG
535
+ * AA ≥4.5:1); SHAPE-coded provenance (circle/square/ring, not colour alone);
536
+ * colour swatch lives INSIDE the token field so every control shares one left
537
+ * rail; 24px+ targets (bind / seg / box-model inputs); legible box-model. */
538
+ .st-cp { display: flex; flex-direction: column; gap: var(--space-4); }
539
+
540
+ /* element identity — Phase 12.3 (W2.3) hairline under the header for structure (Figma-ish) */
541
+ .st-cp-id { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); padding-bottom: var(--space-3); border-bottom: 1px solid var(--border-subtle); }
542
+ .st-cp-idtag { font-family: var(--font-mono); font-size: var(--type-sm); color: var(--fg-0); }
543
+ .st-cp-idcls { color: var(--accent); }
544
+ .st-cp-idmeta { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
545
+
546
+ /* sections */
547
+ .st-cp-sec { display: flex; flex-direction: column; gap: var(--space-2); }
548
+ /* section header — collapsible disclosure button */
549
+ .st-cp-sechd { width: 100%; appearance: none; cursor: pointer; display: flex; align-items: center; gap: var(--space-2); background: transparent; border: 0; border-bottom: 1px solid var(--border-subtle); text-align: left; font-family: var(--font-mono); font-size: var(--type-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-2); padding: 0 0 var(--space-1); }
550
+ .st-cp-sechd svg { color: var(--fg-2); }
551
+ .st-cp-sechd:hover, .st-cp-sechd:hover svg { color: var(--fg-0); }
552
+ /* Phase 12.3 — section header row carries the shared underline so the toggle
553
+ * button + the per-section reset sit on one baseline. */
554
+ .st-cp-sechd-row { display: flex; align-items: stretch; gap: var(--space-1); border-bottom: 1px solid var(--border-subtle); }
555
+ .st-cp-sechd-row .st-cp-sechd { border-bottom: 0; flex: 1 1 auto; }
556
+ /* reset affordances — a subtle revert glyph (⟲). Muted by default, brightens on
557
+ * hover/focus. The per-row variant lives in .st-cp-ctl / .st-cp-kv; the
558
+ * per-section variant sits at the end of the header row. */
559
+ .st-cp-reset, .st-cp-secreset { flex: none; appearance: none; cursor: pointer; background: transparent; border: 0; color: var(--fg-3); font-size: 12px; line-height: 1; padding: 2px; border-radius: var(--radius-xs); }
560
+ .st-cp-reset { width: 16px; height: 16px; }
561
+ .st-cp-reset:hover, .st-cp-secreset:hover { color: var(--accent); background: var(--accent-tint); }
562
+ .st-cp-reset:focus-visible, .st-cp-secreset:focus-visible { outline: none; color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
563
+ .st-cp-secreset { align-self: center; }
564
+ /* read-only name field for an existing custom CSS prop / HTML attr row */
565
+ .st-cp-fin--ro { flex: 0 0 38%; background: var(--bg-2); color: var(--fg-2); cursor: default; }
566
+ .st-cp-fin--ro:focus { outline: none; border-color: var(--border-strong); box-shadow: none; }
567
+
568
+ /* a labelled row: [provenance] [css property] [control] */
569
+ .st-cp-row { display: grid; grid-template-columns: 10px 92px 1fr; align-items: center; gap: var(--space-2); min-height: 28px; }
570
+ /* #1 bigger-bet — unset rows recede so the overridden ones pop; full opacity on
571
+ * hover/focus so they're still editable. The panel reads as a diff of overrides. */
572
+ .st-cp-row.is-unset { opacity: 0.5; transition: opacity var(--dur-soft) var(--ease-out); }
573
+ .st-cp-row.is-unset:hover, .st-cp-row.is-unset:focus-within { opacity: 1; }
574
+ /* one-line labels keep the row rhythm uniform; the full property name is in the
575
+ * row's title tooltip (design-critic 4.1 — uneven wrap was the top craft nit). */
576
+ .st-cp-label { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-1); line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
577
+ .st-cp-ctl { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
578
+
579
+ /* provenance — SHAPE-coded so token/override/inherited survive small size +
580
+ * colour-blindness: token = filled accent circle · override = filled neutral
581
+ * square · inherited = hollow ring. Each carries role=img + aria-label. */
582
+ .st-cp-prov { width: 8px; height: 8px; display: inline-block; flex: none; padding: 0; }
583
+ /* Phase 12.3 (#4) — the row's leading dot is a button: provenance + save status
584
+ * (glow) + double-click reset. No appearance chrome; the variant fills it. */
585
+ /* reset native button chrome; the variants own the FILL (a transparent bg here
586
+ * would out-specify them and hollow the dot — that was the bug). */
587
+ button.st-cp-prov { appearance: none; border: 0; cursor: default; }
588
+ .st-cp-prov.is-resettable { cursor: pointer; }
589
+ .st-cp-prov.is-resettable:hover { box-shadow: 0 0 0 3px var(--bg-4); }
590
+ .st-cp-prov:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--accent-tint); }
591
+ /* save-status glows (replaces the trailing ✓/! markers) */
592
+ .st-cp-prov.is-saved { box-shadow: 0 0 0 3px color-mix(in oklab, var(--status-success) 45%, transparent); }
593
+ .st-cp-prov.is-saving { box-shadow: 0 0 0 3px color-mix(in oklab, var(--fg-2) 35%, transparent); }
594
+ .st-cp-prov.is-err { background: var(--status-error); border-color: var(--status-error); box-shadow: 0 0 0 3px color-mix(in oklab, var(--status-error) 40%, transparent); }
595
+ /* Phase 12.3 — provenance is SHAPE-coded (token=circle · override=square ·
596
+ * inherited=ring) on NEUTRAL fills. Indigo is reserved for its one job on this
597
+ * surface (the bound-token ◇ button + the focus ring), so the token dot must NOT
598
+ * reuse the accent (design-critic 1.4/1.5). */
599
+ .st-cp-prov--bound { background: var(--fg-0); border-radius: 50%; }
600
+ .st-cp-prov--raw { background: var(--fg-2); border-radius: 1px; }
601
+ .st-cp-prov--inherit { background: transparent; box-shadow: inset 0 0 0 1.5px var(--fg-3); border-radius: 50%; }
602
+
603
+ /* colour swatch — standalone (border cluster) + inline (inside the token field) */
604
+ .st-cp-swatch { flex: none; width: 22px; height: 22px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); }
605
+ .st-cp-swatch--mini { width: 18px; height: 18px; }
606
+ .st-cp-tokswatch { flex: none; width: 14px; height: 14px; border-radius: 3px; border: 1px solid var(--border-default); }
607
+
608
+ /* token field (per-field DS-token dropdown) */
609
+ .st-cp-token { flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center; gap: var(--space-2); appearance: none; cursor: pointer; font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-0); background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 4px var(--space-2); }
610
+ .st-cp-token:hover { border-color: var(--accent); }
611
+ .st-cp-tokdot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
612
+ .st-cp-tokname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
613
+ .st-cp-token svg { flex: none; color: var(--fg-2); }
614
+
615
+ /* number field: input + steppers + unit-select + bind-to-token */
616
+ .st-cp-num { flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: stretch; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); overflow: hidden; min-height: 26px; }
617
+ /* #2 — Figma-style property prefix segment inside the numeric field. */
618
+ .st-cp-numlead { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 20px; color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); border-right: 1px solid var(--border-subtle); background: var(--bg-2); }
619
+ .st-cp-num:focus-within .st-cp-numlead { color: var(--fg-1); }
620
+ .st-cp-num:hover { border-color: var(--border-strong); }
621
+ .st-cp-num:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
622
+ .st-cp-numin { flex: 1 1 auto; min-width: 0; width: 100%; appearance: none; border: 0; background: transparent; color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); padding: 3px var(--space-2); }
623
+ .st-cp-numin::placeholder { color: var(--fg-2); }
624
+ .st-cp-numin:focus { outline: none; }
625
+ /* Phase 12.3 (W2.2) — scrub affordance: a number field signals it's draggable
626
+ * (ew-resize), reverts to a text caret when focused for typing. While a scrub is
627
+ * active the whole document holds the resize cursor + suppresses selection. */
628
+ .st-cp-scrub { cursor: ew-resize; }
629
+ .st-cp-scrub:focus { cursor: text; }
630
+ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-select: none !important; }
631
+ .st-cp-step { flex: none; display: flex; flex-direction: column; border-left: 1px solid var(--border-subtle); }
632
+ .st-cp-stepb { flex: 1; appearance: none; cursor: pointer; border: 0; background: var(--bg-2); color: var(--fg-2); font-size: 7px; line-height: 1; padding: 0 5px; }
633
+ .st-cp-stepb:first-child { border-bottom: 1px solid var(--border-subtle); }
634
+ .st-cp-stepb:hover { color: var(--accent); }
635
+ .st-cp-unit { flex: none; appearance: none; cursor: pointer; display: inline-flex; align-items: center; gap: 2px; border: 0; border-left: 1px solid var(--border-subtle); background: var(--bg-2); color: var(--fg-2); font-family: var(--font-mono); font-size: 10px; padding: 0 var(--space-2); }
636
+ .st-cp-unit svg { color: var(--fg-2); }
637
+ .st-cp-bind { flex: none; width: 24px; appearance: none; cursor: pointer; border: 0; border-left: 1px solid var(--border-subtle); background: var(--bg-2); position: relative; }
638
+ .st-cp-bind::before { content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid var(--fg-2); }
639
+ .st-cp-bind:hover::before { border-color: var(--accent); }
640
+ .st-cp-numin--mini { flex: none; width: 38px; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); }
641
+
642
+ /* select (font-weight, border-style) */
643
+ .st-cp-select { flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center; justify-content: space-between; gap: var(--space-2); appearance: none; cursor: pointer; font-family: var(--font-body); font-size: var(--type-xs); color: var(--fg-0); background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 4px var(--space-2); min-height: 26px; }
644
+ .st-cp-select span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
645
+ .st-cp-select svg { flex: none; color: var(--fg-2); }
646
+ .st-cp-select--mini { flex: 0 1 auto; }
647
+
648
+ /* segmented control (text-align) with drawn align glyphs — 26px tall targets */
649
+ .st-cp-seg { display: inline-flex; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); overflow: hidden; }
650
+ .st-cp-segbtn { appearance: none; cursor: pointer; border: 0; background: transparent; min-width: 26px; min-height: 26px; padding: 0 7px; display: inline-flex; align-items: center; justify-content: center; border-right: 1px solid var(--border-subtle); }
651
+ .st-cp-segbtn:last-child { border-right: 0; }
652
+ .st-cp-segbtn.is-active { background: var(--accent-tint); }
653
+ .st-cp-segbtn:hover:not(.is-active) { background: var(--bg-4); }
654
+ .st-cp-bars { display: flex; flex-direction: column; gap: 2px; width: 13px; color: var(--fg-1); }
655
+ .st-cp-segbtn.is-active .st-cp-bars { color: var(--accent); }
656
+ .st-cp-bars i { height: 2px; border-radius: 1px; background: currentColor; }
657
+ .st-cp-bars--left i:nth-child(1) { width: 100%; }
658
+ .st-cp-bars--left i:nth-child(2) { width: 60%; }
659
+ .st-cp-bars--left i:nth-child(3) { width: 80%; }
660
+ .st-cp-bars--center i { margin: 0 auto; }
661
+ .st-cp-bars--center i:nth-child(1) { width: 100%; }
662
+ .st-cp-bars--center i:nth-child(2) { width: 55%; }
663
+ .st-cp-bars--center i:nth-child(3) { width: 75%; }
664
+ .st-cp-bars--right i { margin-left: auto; }
665
+ .st-cp-bars--right i:nth-child(1) { width: 100%; }
666
+ .st-cp-bars--right i:nth-child(2) { width: 60%; }
667
+ .st-cp-bars--right i:nth-child(3) { width: 80%; }
668
+ .st-cp-bars--just i { width: 100%; }
669
+
670
+ /* nested box-model widget (Webflow-style): margin outer · padding inner */
671
+ .st-cp-box { position: relative; margin-top: var(--space-1); padding: 26px; border: 1px dashed var(--border-default); border-radius: var(--radius-sm); background: var(--bg-2); display: grid; place-items: center; }
672
+ .st-cp-boxpad { position: relative; width: 100%; padding: 26px; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); display: grid; place-items: center; }
673
+ .st-cp-boxcore { min-width: 72px; padding: 7px 12px; border-radius: var(--radius-xs); background: var(--bg-4); border: 1px solid var(--accent); color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 11px; text-align: center; }
674
+ .st-cp-boxtag { position: absolute; top: 4px; left: 6px; display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-mono); font-size: 10px; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); pointer-events: none; }
675
+ .st-cp-boxtag .st-cp-prov { width: 6px; height: 6px; }
676
+ .st-cp-boxv { position: absolute; width: 36px; height: 24px; border: 1px solid transparent; border-radius: var(--radius-xs); background: transparent; color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 11px; text-align: center; padding: 0; }
677
+ .st-cp-boxv.is-zero { color: var(--fg-2); }
678
+ .st-cp-boxv:hover, .st-cp-boxv:focus { border-color: var(--border-strong); background: var(--bg-1); outline: none; color: var(--fg-0); }
679
+ .st-cp-boxv--mt, .st-cp-boxv--pt { top: 1px; left: 50%; transform: translateX(-50%); }
680
+ .st-cp-boxv--mb, .st-cp-boxv--pb { bottom: 1px; left: 50%; transform: translateX(-50%); }
681
+ .st-cp-boxv--ml, .st-cp-boxv--pl { left: 0; top: 50%; transform: translateY(-50%); }
682
+ .st-cp-boxv--mr, .st-cp-boxv--pr { right: 0; top: 50%; transform: translateY(-50%); }
683
+ .st-cp-boxhint { display: flex; flex-wrap: wrap; gap: var(--space-1); }
684
+ .st-cp-boxhint + .st-cp-row { margin-top: var(--space-1); }
685
+ .st-cp-chip { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); background: var(--bg-2); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 1px 6px; }
686
+
687
+ /* opacity slider — role=slider, focusable */
688
+ .st-cp-slider { flex: 1 1 auto; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
689
+ .st-cp-track { position: relative; flex: 1 1 auto; height: 6px; border-radius: 3px; background: var(--bg-4); border: 1px solid var(--border-default); cursor: pointer; }
690
+ .st-cp-track:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
691
+ .st-cp-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; background: var(--accent); }
692
+ .st-cp-thumb { position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%; background: var(--fg-0); border: 2px solid var(--accent); transform: translate(-50%, -50%); }
693
+ .st-cp-slval { flex: none; font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); color: var(--fg-1); width: 34px; text-align: right; }
694
+
695
+ /* border cluster — fills to the right control rail */
696
+ .st-cp-border { flex: 1 1 auto; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
697
+ .st-cp-border .st-cp-swatch--mini { margin-left: 0; }
698
+ /* design-critic 1.1 — the border row was cramming width+style+swatch; the
699
+ * width field was eating the flex and clipping the style select to "styl▾".
700
+ * Fix the width field, let the style select take the rest. */
701
+ .st-cp-border .st-cp-num { flex: 0 0 58px; }
702
+ .st-cp-border .st-cp-nsel { flex: 1 1 auto; max-width: none; }
703
+
704
+ /* per-field save state */
705
+ /* #5 — error-only now (idle/saved status moved into each row's leading dot). */
706
+ .st-cp-save { display: inline-flex; align-items: center; gap: var(--space-2); align-self: flex-start; font-size: var(--type-xs); font-family: var(--font-mono); padding: 4px var(--space-2); border-radius: var(--radius-xs); background: color-mix(in oklab, var(--status-error) 14%, var(--bg-2)); border: 1px solid var(--status-error); color: var(--status-error); }
707
+ .st-cp-save.is-saved { color: var(--status-success); }
708
+ .st-cp-save.is-saved svg { color: var(--status-success); }
709
+
710
+ /* Advanced — the two-hatch escape (custom CSS property + custom HTML attribute) */
711
+ .st-cp-adv { border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-0); overflow: hidden; }
712
+ .st-cp-advhd { width: 100%; appearance: none; cursor: pointer; display: flex; align-items: center; gap: var(--space-2); border: 0; background: transparent; color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); padding: var(--space-2) var(--space-3); }
713
+ .st-cp-advhd svg { color: var(--fg-2); }
714
+ .st-cp-advbody { display: flex; flex-direction: column; gap: var(--space-2); padding: 0 var(--space-3) var(--space-3); }
715
+ .st-cp-advgrp { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-2); margin-top: var(--space-1); }
716
+ /* #3 — custom prop/attr rows are ONE line: [name] [value] [×]. The reset glyph
717
+ * used to wrap to a second line; a trailing × close button keeps it on one row. */
718
+ .st-cp-kv { display: grid; grid-template-columns: 1fr 1fr auto; gap: var(--space-2); align-items: center; }
719
+ .st-cp-kvx { flex: none; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; appearance: none; cursor: pointer; background: transparent; border: 0; color: var(--fg-3); padding: 0; border-radius: var(--radius-xs); }
720
+ .st-cp-kvx:hover { color: var(--status-error); background: var(--bg-3); }
721
+ .st-cp-kvx:focus-visible { outline: none; color: var(--status-error); box-shadow: 0 0 0 2px var(--accent-tint); }
722
+ .st-cp-kv .st-cp-numin { background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); }
723
+ .st-cp-kv.has-warn .st-cp-numin { border-color: var(--status-warn); }
724
+ .st-cp-warn { font-size: 10px; color: var(--status-warn); font-family: var(--font-mono); }
725
+ .st-cp-add { align-self: flex-start; appearance: none; cursor: pointer; border: 1px dashed var(--border-default); background: transparent; color: var(--fg-1); font-family: var(--font-mono); font-size: var(--type-xs); border-radius: var(--radius-xs); padding: 4px var(--space-2); }
726
+ .st-cp-add:hover { border-color: var(--accent); color: var(--fg-0); }
727
+ .st-cp-note { font-size: 10px; color: var(--fg-2); font-style: italic; }
728
+
729
+ /* provenance legend */
730
+ .st-cp-legend { display: flex; flex-wrap: wrap; gap: var(--space-3); padding-top: var(--space-1); border-top: 1px solid var(--border-subtle); }
731
+ .st-cp-legend span { display: inline-flex; align-items: center; gap: var(--space-1); font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); }
732
+
733
+ /* box-model link-all-sides toggle (replaces the cryptic modifier-key chips) */
734
+ .st-cp-boxlink { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
735
+ .st-cp-linkbtn { appearance: none; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; min-height: 24px; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); color: var(--fg-1); font-family: var(--font-mono); font-size: 10px; padding: 0 8px; }
736
+ .st-cp-linkbtn.is-on { border-color: var(--accent); color: var(--fg-0); background: var(--accent-tint); }
737
+ .st-cp-linkglyph { width: 13px; height: 9px; border: 1.5px solid currentColor; border-radius: 4px; }
738
+ .st-cp-linkhint { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); }
739
+
740
+ /* per-corner border-radius: split toggle + 4-corner inputs (TL/TR/BL/BR) */
741
+ .st-cp-split { flex: none; width: 24px; height: 24px; appearance: none; cursor: pointer; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); position: relative; }
742
+ .st-cp-split.is-on { border-color: var(--accent); background: var(--accent-tint); }
743
+ .st-cp-split::before { content: ""; position: absolute; inset: 6px; border: 1.5px solid var(--fg-1); border-radius: 3px; }
744
+ .st-cp-split.is-on::before { border-color: var(--accent); border-style: dashed; }
745
+ .st-cp-corners { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-1); margin: 0 0 var(--space-1) 18px; }
746
+ .st-cp-cornerf { display: flex; align-items: center; gap: 6px; min-height: 24px; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 0 8px; }
747
+ .st-cp-cornerf span { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); }
748
+ .st-cp-cornerf input { flex: 1; min-width: 0; width: 100%; appearance: none; border: 0; background: transparent; color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 11px; padding: 0; }
749
+ .st-cp-cornerf input:focus { outline: none; }
750
+
751
+ /* Phase 12.2 PORT-only controls — the live panel uses native <select>/<input>
752
+ for real interactivity + a11y where the Studio.tsx spec used styled buttons. */
753
+ /* The port mounts an absolute `inset:0` fill span + a hidden color <input>
754
+ INSIDE the swatch (the spec's swatch was decorative-only, so the ported rule
755
+ has no `position`). Without `relative` the fill anchored to `.maude` and
756
+ painted the element's computed colour across the ENTIRE window (dark element
757
+ → black screen, light → white), and the invisible input swallowed every
758
+ click. The old `.st-css-swatch` had `position:relative` for exactly this. */
759
+ .st-cp-swatch { position: relative; overflow: hidden; }
760
+ .st-cp-caret { flex: none; color: var(--fg-2); font-size: 9px; width: 9px; text-align: center; }
761
+ .st-cp-fin { flex: 1 1 auto; min-width: 0; width: 100%; box-sizing: border-box; appearance: none; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); padding: 4px var(--space-2); min-height: 26px; transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out); }
762
+ .st-cp-fin::placeholder { color: var(--fg-2); }
763
+ .st-cp-fin:hover { border-color: var(--border-strong); }
764
+ /* maude signature focus — border goes accent + a 3px tint halo (DS focus spec). */
765
+ .st-cp-fin:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
766
+ .st-cp-nsel { flex: 1 1 auto; min-width: 0; box-sizing: border-box; cursor: pointer; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); color: var(--fg-0); font-family: var(--font-body); font-size: var(--type-xs); padding: 3px var(--space-2); min-height: 26px; transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out); }
767
+ .st-cp-nsel:hover { border-color: var(--border-strong); }
768
+ .st-cp-nsel:focus, .st-cp-nsel:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
769
+ .st-cp-nsel--tok { flex: 0 1 auto; max-width: 108px; font-family: var(--font-mono); color: var(--fg-2); background: var(--bg-2); }
770
+ .st-cp-nsel--mini { flex: 0 1 auto; max-width: 92px; }
771
+ .st-cp-unitsel { flex: none; cursor: pointer; appearance: none; border: 0; border-left: 1px solid var(--border-subtle); background: var(--bg-2); color: var(--fg-2); font-family: var(--font-mono); font-size: 10px; padding: 0 4px; }
772
+ /* Phase 12.3 (W2.1) — token picker as a popover. The trigger is a compact
773
+ * variables button (◇ glyph); bound state tints it accent. */
774
+ .st-cp-tokbtn { flex: none; width: 24px; height: 26px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; appearance: none; background: var(--bg-2); border: 1px solid var(--border-default); border-radius: var(--radius-xs); color: var(--fg-2); padding: 0; }
775
+ .st-cp-tokbtn:hover { color: var(--fg-0); border-color: var(--border-strong); }
776
+ .st-cp-tokbtn:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
777
+ .st-cp-tokbtn.is-bound { color: var(--accent); border-color: var(--accent-muted); background: var(--accent-tint); }
778
+ /* the glyph — a small rotated square (variable diamond, Figma-ish) */
779
+ .st-cp-tokbtn-glyph { width: 8px; height: 8px; border: 1.5px solid currentColor; border-radius: 1px; transform: rotate(45deg); }
780
+ .st-cp-tokbtn.is-bound .st-cp-tokbtn-glyph { background: currentColor; }
781
+ /* the floating popover (portalled to body, fixed-positioned) */
782
+ .st-cp-pop { position: fixed; z-index: 1000; overflow-y: auto; background: var(--bg-2); border: 1px solid var(--border-default); border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: var(--space-2); }
783
+ .st-cp-pop-empty { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); padding: var(--space-2); }
784
+ /* sticky search over the token list */
785
+ .st-cp-pop-search { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: var(--space-2); padding: 0 0 var(--space-2); margin: calc(-1 * var(--space-2)) 0 0; background: var(--bg-2); color: var(--fg-2); }
786
+ .st-cp-pop-search svg { flex: none; margin-left: var(--space-1); }
787
+ .st-cp-pop-search input { flex: 1 1 auto; min-width: 0; appearance: none; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); color: var(--fg-0); font-family: var(--font-body); font-size: var(--type-xs); padding: 4px var(--space-2); }
788
+ .st-cp-pop-search input::placeholder { color: var(--fg-3); }
789
+ .st-cp-pop-search input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
790
+ /* #4 — colour popover tabs (Custom picker · Variables list) */
791
+ .st-cp-poptabs { display: flex; border-bottom: 1px solid var(--border-subtle); margin: calc(-1 * var(--space-2)) calc(-1 * var(--space-2)) var(--space-2); }
792
+ .st-cp-poptab { flex: 1; appearance: none; border: 0; background: transparent; cursor: pointer; font-family: var(--font-body); font-size: var(--type-xs); color: var(--fg-2); padding: var(--space-3); border-bottom: 2px solid transparent; }
793
+ .st-cp-poptab.is-active { color: var(--fg-0); border-bottom-color: var(--accent); }
794
+ .st-cp-poptab:hover:not(.is-active) { color: var(--fg-1); }
795
+ /* #6 — the unified HSV colour picker (Custom tab): saturation/value square +
796
+ * hue slider + eyedropper + hex field. The swatch on the colour row is the only
797
+ * trigger (no separate native picker). */
798
+ .st-cp-cpick { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-1); }
799
+ .st-cp-swatch--trigger { position: relative; overflow: hidden; cursor: pointer; appearance: none; padding: 0; }
800
+ .st-cp-swatch--trigger.is-bound { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
801
+ .st-cp-cpick-sv { position: relative; display: block; width: 100%; height: 120px; border-radius: var(--radius-sm); border: 1px solid var(--border-default); overflow: hidden; cursor: crosshair; padding: 0; touch-action: none; }
802
+ .st-cp-cpick-svwhite { position: absolute; inset: 0; background: linear-gradient(to right, #fff, transparent); }
803
+ .st-cp-cpick-svblack { position: absolute; inset: 0; background: linear-gradient(to top, #000, transparent); }
804
+ .st-cp-cpick-knob { position: absolute; width: 12px; height: 12px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.5); transform: translate(-50%, -50%); pointer-events: none; }
805
+ .st-cp-cpick-controls { display: flex; align-items: center; gap: var(--space-2); }
806
+ .st-cp-cpick-eye { flex: none; width: 26px; height: 16px; display: inline-flex; align-items: center; justify-content: center; appearance: none; cursor: pointer; background: transparent; border: 0; color: var(--fg-2); padding: 0; border-radius: var(--radius-xs); }
807
+ .st-cp-cpick-eye:hover { color: var(--fg-0); }
808
+ .st-cp-cpick-hue { position: relative; flex: 1 1 auto; height: 12px; border-radius: var(--radius-pill); border: 1px solid var(--border-default); cursor: pointer; padding: 0; touch-action: none; background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%); }
809
+ .st-cp-cpick-huethumb { position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%; background: #fff; border: 1px solid rgba(0,0,0,0.4); box-shadow: 0 1px 3px rgba(0,0,0,0.4); transform: translate(-50%, -50%); pointer-events: none; }
810
+ /* W3 — per-design-system grouping. The DS name labels each group when >1 DS. */
811
+ .st-cp-pop-group + .st-cp-pop-group { margin-top: var(--space-2); }
812
+ .st-cp-pop-ds { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-2); padding: 2px var(--space-1) 4px; position: sticky; top: 30px; background: var(--bg-2); z-index: 1; }
813
+ /* color: swatch grid */
814
+ .st-cp-pop-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; }
815
+ .st-cp-pop-sw { aspect-ratio: 1; min-height: 26px; cursor: pointer; appearance: none; border: 1px solid var(--border-subtle); border-radius: var(--radius-xs); padding: 0; }
816
+ .st-cp-pop-sw:hover { border-color: var(--fg-2); transform: scale(1.06); }
817
+ .st-cp-pop-sw.is-on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
818
+ .st-cp-pop-sw:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
819
+ /* value: variable list (name + resolved value) */
820
+ .st-cp-pop-list { display: flex; flex-direction: column; gap: 1px; }
821
+ .st-cp-pop-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); cursor: pointer; appearance: none; background: transparent; border: 0; border-radius: var(--radius-xs); padding: 5px var(--space-2); text-align: left; }
822
+ .st-cp-pop-row:hover { background: var(--bg-3); }
823
+ .st-cp-pop-row.is-on { background: var(--accent-tint); }
824
+ .st-cp-pop-row:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--accent-tint); }
825
+ .st-cp-pop-name { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
826
+ /* #2 — colour Variables as a list row: [swatch] [name] [value] */
827
+ .st-cp-pop-crow { justify-content: flex-start; }
828
+ .st-cp-pop-crow .st-cp-pop-name { flex: 1 1 auto; min-width: 0; }
829
+ .st-cp-pop-cswatch { flex: none; width: 16px; height: 16px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); }
830
+ .st-cp-pop-val { flex: none; font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 10px; color: var(--fg-2); }
831
+ .st-cp-pop-row.is-on .st-cp-pop-name { color: var(--accent); }
832
+ .st-cp-fs { flex: none; width: 14px; text-align: center; font-family: var(--font-mono); font-size: 11px; }
833
+ .st-cp-fs.is-saving { color: var(--fg-3); }
834
+ .st-cp-fs.is-saved { color: var(--status-success); }
835
+ .st-cp-fs.is-err { color: var(--status-warn); cursor: help; }
836
+
837
+ /* shared focus ring for the panel's interactive controls (incl. native selects) */
838
+ .st-cp button:focus-visible, .st-cp input:focus-visible, .st-cp select:focus-visible, .st-cp-token:focus-visible, .st-cp-track:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
839
+ /* ═══ DS-parity polish (specimen sweep) ═══════════════════════════════════════
840
+ * Gaps found auditing the shell against `.design/system/maude/preview/*`:
841
+ * focus-visible coverage, the DS input focus ring, select chevron, unified
842
+ * thin scrollbars, tooltip bubbles. */
843
+
844
+ /* Catch-all keyboard focus — the DS focus specimen's ONE ring: 2px accent
845
+ * outline at 2px offset wrapped in a 5px --accent-tint halo (`focus.css`
846
+ * .fo-chip). :focus-visible only — mouse clicks never paint it. Inputs are
847
+ * NOT here — they take the DS input recipe (accent border + 3px tint ring). */
848
+ .maude :is(button, [role="tab"], select, summary, a):focus-visible {
849
+ outline: 2px solid var(--accent);
850
+ outline-offset: 2px;
851
+ box-shadow: 0 0 0 5px var(--accent-tint);
852
+ }
853
+ /* tight rows inside scrollers — the inset variant so the ring never clips
854
+ * (focus.css .fo-tree .tree-row recipe). */
855
+ .maude :is(.st-row, .st-dd-item, .st-pal-item, .st-layer, .st-tree-sec-hd, .st-cm-group-hd):focus-visible {
856
+ outline-offset: -2px;
857
+ box-shadow: inset 0 0 0 5px var(--accent-tint);
858
+ }
859
+
860
+ /* DS input recipe (`_components.css` .input:focus) — accent hairline + 3px tint
861
+ * ring, never the default UA outline. */
862
+ .st-search-box:focus-within {
863
+ border-color: var(--accent);
864
+ box-shadow: 0 0 0 3px var(--accent-tint);
865
+ color: var(--fg-2);
866
+ }
867
+ .st-search-box input:focus { outline: none; }
868
+ .st-newboard input:focus,
869
+ .st-newboard input:focus-visible {
870
+ outline: none;
871
+ border-color: var(--accent);
872
+ box-shadow: 0 0 0 3px var(--accent-tint);
873
+ }
874
+ .st-field:focus {
875
+ outline: none;
876
+ border-color: var(--accent);
877
+ box-shadow: 0 0 0 3px var(--accent-tint);
878
+ }
879
+ .st-select:hover { border-color: var(--border-strong); background-color: var(--bg-3); }
880
+ .st-select:focus-visible {
881
+ outline: none;
882
+ border-color: var(--accent);
883
+ box-shadow: 0 0 0 3px var(--accent-tint);
884
+ }
885
+ /* palette search — the container is the field; the inner input stays naked */
886
+ .st-pal-search input:focus { outline: none; }
887
+ .st-pal-search:focus-within { border-bottom-color: var(--accent-muted); }
888
+
889
+ /* select chevron — `appearance:none` dropped the UA arrow and left the control
890
+ * affordance-less. Data-URIs can't read tokens, so the stroke is the resolved
891
+ * --fg-1 per theme (dark ≈ #c0c4cf, light ≈ #4f5563). */
892
+ .st-select {
893
+ padding-right: 30px;
894
+ background-repeat: no-repeat;
895
+ background-position: right 10px center;
896
+ background-size: 12px;
897
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23c0c4cf' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3.5 6 8 10.5 12.5 6'/%3E%3C/svg%3E");
898
+ }
899
+ .maude[data-theme="light"] .st-select {
900
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%234f5563' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3.5 6 8 10.5 12.5 6'/%3E%3C/svg%3E");
901
+ }
902
+
903
+ /* unified thin scrollbars — one material everywhere (tree, panels, palette,
904
+ * system view, modals). Hairline thumb, transparent track. */
905
+ .maude * {
906
+ scrollbar-width: thin;
907
+ scrollbar-color: var(--border-default) transparent;
908
+ }
909
+ .maude ::-webkit-scrollbar { width: 8px; height: 8px; }
910
+ .maude ::-webkit-scrollbar-track { background: transparent; }
911
+ .maude ::-webkit-scrollbar-thumb {
912
+ background: var(--border-default);
913
+ border-radius: var(--radius-pill);
914
+ border: 2px solid transparent;
915
+ background-clip: padding-box;
916
+ }
917
+ .maude ::-webkit-scrollbar-thumb:hover { background-color: var(--border-strong); }
918
+
919
+ /* tooltip bubble — DS `components-tooltips` recipe (bg-2 hairline bubble), CSS
920
+ * attr-driven so chrome controls opt in via `data-tip` without a JS layer.
921
+ * 500ms reveal delay ≈ native tooltip timing; reduced-motion shows instantly. */
922
+ .maude [data-tip] { position: relative; }
923
+ .maude [data-tip]::after {
924
+ content: attr(data-tip);
925
+ position: absolute;
926
+ top: calc(100% + 7px);
927
+ left: 50%;
928
+ transform: translateX(-50%);
929
+ z-index: 9200;
930
+ white-space: nowrap;
931
+ padding: var(--space-2) var(--space-3);
932
+ background: var(--bg-2);
933
+ color: var(--fg-0);
934
+ font-family: var(--font-body);
935
+ font-size: var(--type-xs);
936
+ font-weight: 400;
937
+ letter-spacing: normal;
938
+ text-transform: none;
939
+ line-height: 1;
940
+ border: 1px solid var(--border-default);
941
+ border-radius: var(--radius-sm);
942
+ box-shadow: var(--shadow-md);
943
+ pointer-events: none;
944
+ opacity: 0;
945
+ transition: opacity var(--dur-soft) var(--ease-out);
946
+ }
947
+ .maude [data-tip]:hover::after,
948
+ .maude [data-tip]:focus-visible::after {
949
+ opacity: 1;
950
+ transition-delay: 500ms;
951
+ }
952
+ /* bottom-bar + right-edge hosts flip/clamp so the bubble stays on screen */
953
+ .maude [data-tip][data-tip-pos="top"]::after { top: auto; bottom: calc(100% + 7px); }
954
+ .maude [data-tip][data-tip-pos="left"]::after { top: 50%; left: auto; right: calc(100% + 7px); transform: translateY(-50%); }
955
+
956
+ /* ═══ Behavioral polish (specimen sweep, round 2) ═════════════════════════════ */
957
+
958
+ /* ─── Panel grip — DS components-resize-panels recipe ──────────────────────
959
+ * 8px hit area; the panel's own border is the at-rest hairline, the grip seam
960
+ * surfaces accent + grip dots on hover/focus/drag. col-resize everywhere
961
+ * while dragging; iframes drop pointer events so they can't eat the stream. */
962
+ .st-grip {
963
+ flex: 0 0 8px;
964
+ width: 8px;
965
+ position: relative;
966
+ cursor: col-resize;
967
+ display: grid;
968
+ place-items: center;
969
+ background: transparent;
970
+ /* sit over the adjacent panel borders so the accent seam reads centered */
971
+ margin: 0 -4px;
972
+ z-index: 25;
973
+ }
974
+ .st-grip::before {
975
+ content: "";
976
+ position: absolute;
977
+ top: 0; bottom: 0; left: 50%;
978
+ width: 1px;
979
+ transform: translateX(-50%);
980
+ background: transparent;
981
+ transition: background var(--dur-flip) var(--ease-out), width var(--dur-flip) var(--ease-out);
982
+ }
983
+ .st-grip:hover::before,
984
+ .st-grip:focus-visible::before,
985
+ .st-grip.is-active::before { background: var(--accent); width: 2px; }
986
+ .st-grip-dots {
987
+ width: 6px; height: 18px;
988
+ color: var(--accent);
989
+ opacity: 0;
990
+ position: relative;
991
+ transition: opacity var(--dur-flip) var(--ease-out);
992
+ }
993
+ .st-grip:hover .st-grip-dots,
994
+ .st-grip:focus-visible .st-grip-dots,
995
+ .st-grip.is-active .st-grip-dots { opacity: 1; }
996
+ /* specimen recipe — inset ring on the narrow hit area (the seam + dots already
997
+ * surface accent, this keeps a proper outline for WCAG focus visibility) */
998
+ .st-grip:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
999
+ .st-body.is-resizing { cursor: col-resize; user-select: none; }
1000
+ .st-body.is-resizing iframe { pointer-events: none; }
1001
+ .st-sidebar.is-resizing, .st-rpanel.is-resizing { transition: none; }
1002
+
1003
+ /* ─── Canvas-compile skeleton — DS skeletons recipe (.skel pulse) ──────────── */
1004
+ .st-canvas-loading {
1005
+ position: absolute; inset: 0;
1006
+ display: grid; place-items: center;
1007
+ pointer-events: none;
1008
+ z-index: 5;
1009
+ /* 180ms appearance delay — warm canvases mount in <150ms and never flash it */
1010
+ opacity: 0;
1011
+ animation: st-loading-in var(--dur-soft) var(--ease-out) 180ms forwards;
1012
+ }
1013
+ @keyframes st-loading-in { to { opacity: 1; } }
1014
+ .st-skel-card {
1015
+ width: 300px;
1016
+ display: flex; flex-direction: column; gap: var(--space-3);
1017
+ padding: var(--space-5);
1018
+ background: var(--bg-1);
1019
+ border: 1px solid var(--border-default);
1020
+ border-radius: var(--radius-md);
1021
+ box-shadow: var(--shadow-md);
1022
+ animation: st-pop var(--dur-panel) var(--ease-out);
1023
+ }
1024
+ .st-skel-cap {
1025
+ font-size: var(--type-xs); letter-spacing: var(--tracking-wide);
1026
+ text-transform: uppercase; color: var(--fg-3);
1027
+ }
1028
+ .skel {
1029
+ display: block;
1030
+ background: var(--bg-3);
1031
+ border-radius: var(--radius-xs);
1032
+ animation: sk-pulse calc(var(--dur-route) * 3) var(--ease-in-out) infinite alternate;
1033
+ }
1034
+ @keyframes sk-pulse { from { opacity: 0.45; } to { opacity: 0.95; } }
1035
+ @media (prefers-reduced-motion: reduce) { .skel { animation: none; opacity: 0.7; } }
1036
+ .st-skel-thumb { height: 96px; border-radius: var(--radius-sm); }
1037
+ .st-skel-line { height: 10px; }
1038
+
1039
+ /* ─── Micro-motion — hover/disclosure transitions on the dense surfaces ───── */
1040
+ .st-row,
1041
+ .st-comment,
1042
+ .st-fmt,
1043
+ .st-cm-filter,
1044
+ .st-rp-tab,
1045
+ .st-dd-item,
1046
+ .st-pal-item,
1047
+ .st-layer,
1048
+ .st-export-recent-row {
1049
+ transition: background var(--dur-soft) var(--ease-out),
1050
+ border-color var(--dur-soft) var(--ease-out),
1051
+ color var(--dur-soft) var(--ease-out);
1052
+ }
1053
+ /* tree disclosure chevron — one glyph, rotated (animatable) */
1054
+ .st-chev { transition: transform var(--dur-flip) var(--ease-out); }
1055
+ .st-chev.is-open { transform: rotate(90deg); }
1056
+ /* right dock slides in as a panel (DS motion role: panel) */
1057
+ .st-rpanel { animation: st-panel-in var(--dur-panel) var(--ease-out); }
1058
+ @keyframes st-panel-in { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; transform: none; } }
1059
+
1060
+ /* ─── Keyboard-shortcuts overlay — DS components-shortcuts-overlay recipe ──── */
1061
+ .so-overlay {
1062
+ position: relative;
1063
+ width: 100%;
1064
+ max-width: 720px;
1065
+ background: var(--bg-1);
1066
+ border: 1px solid var(--border-default);
1067
+ border-radius: var(--radius-lg);
1068
+ box-shadow: var(--shadow-lg);
1069
+ padding: var(--space-6);
1070
+ margin-top: -4vh;
1071
+ animation: so-enter var(--dur-panel) var(--ease-out) both;
1072
+ }
1073
+ @keyframes so-enter {
1074
+ 0% { opacity: 0; transform: translateY(-6px) scale(0.99); }
1075
+ 100% { opacity: 1; transform: none; }
1076
+ }
1077
+ .so-overlay-hd {
1078
+ display: flex;
1079
+ align-items: baseline;
1080
+ justify-content: space-between;
1081
+ gap: var(--space-4);
1082
+ margin: 0 0 var(--space-5);
1083
+ padding-bottom: var(--space-4);
1084
+ border-bottom: 1px solid var(--border-subtle);
1085
+ }
1086
+ .so-title {
1087
+ font-family: var(--font-display);
1088
+ font-size: var(--type-lg);
1089
+ line-height: var(--lh-lg);
1090
+ font-weight: 600;
1091
+ letter-spacing: var(--tracking-tight);
1092
+ color: var(--fg-0);
1093
+ }
1094
+ .so-trigger { font-size: var(--type-xs); color: var(--fg-2); }
1095
+ .so-columns {
1096
+ display: grid;
1097
+ grid-template-columns: repeat(2, 1fr);
1098
+ gap: var(--space-6) var(--space-7);
1099
+ }
1100
+ .so-section-hd {
1101
+ margin: 0 0 var(--space-3);
1102
+ font-family: var(--font-mono);
1103
+ font-size: var(--type-xs);
1104
+ font-weight: 500;
1105
+ letter-spacing: var(--tracking-wide);
1106
+ text-transform: uppercase;
1107
+ color: var(--fg-2);
1108
+ padding-bottom: var(--space-2);
1109
+ border-bottom: 1px solid var(--border-subtle);
1110
+ }
1111
+ /* the canvas-tools column reads as the in-canvas scope — accent-muted header */
1112
+ .so-section--tools .so-section-hd {
1113
+ color: var(--accent);
1114
+ border-bottom-color: color-mix(in oklab, var(--accent) 40%, var(--border-subtle));
1115
+ }
1116
+ .so-list { display: flex; flex-direction: column; gap: var(--space-1); margin: 0; }
1117
+ .so-pair {
1118
+ display: grid;
1119
+ grid-template-columns: 1fr auto;
1120
+ align-items: center;
1121
+ gap: var(--space-4);
1122
+ padding: var(--space-1) var(--space-1);
1123
+ border-radius: var(--radius-xs);
1124
+ }
1125
+ .so-pair:hover { background: var(--bg-2); }
1126
+ .so-pair dt { font-size: var(--type-sm); color: var(--fg-1); }
1127
+ .so-pair dd { margin: 0; justify-self: end; }
1128
+ .so-combos { display: inline-flex; align-items: center; gap: var(--space-2); }
1129
+ .so-combo { display: inline-flex; align-items: center; gap: var(--space-1); }
1130
+ .so-or { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-3); padding: 0 1px; }
1131
+ .so-overlay-ft {
1132
+ display: flex;
1133
+ align-items: center;
1134
+ justify-content: space-between;
1135
+ gap: var(--space-4);
1136
+ margin-top: var(--space-5);
1137
+ padding-top: var(--space-4);
1138
+ border-top: 1px solid var(--border-subtle);
1139
+ font-size: var(--type-xs);
1140
+ color: var(--fg-2);
1141
+ }
1142
+ @media (max-width: 640px) { .so-columns { grid-template-columns: 1fr; } }
1143
+
1144
+ /* ─── Agent presence pulse — DS motion-presence role (scale+opacity ring) ──── */
1145
+ .st-avatar.is-pulsing::after {
1146
+ content: "";
1147
+ position: absolute;
1148
+ inset: -1px;
1149
+ border-radius: var(--radius-pill);
1150
+ border: 1px solid var(--av-hue);
1151
+ animation: st-presence-ring 1600ms var(--ease-out) infinite;
1152
+ pointer-events: none;
1153
+ }
1154
+ .st-avatar { position: relative; }
1155
+ @keyframes st-presence-ring {
1156
+ 0% { opacity: 0.9; transform: scale(1); }
1157
+ 70%, 100% { opacity: 0; transform: scale(1.45); }
1158
+ }
1159
+ @media (prefers-reduced-motion: reduce) { .st-avatar.is-pulsing::after { animation: none; opacity: 0; } }
1160
+
1161
+ }