@1agh/maude 0.42.0 → 0.44.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 (332) hide show
  1. package/apps/studio/.ai/cache/_stats.json +7 -0
  2. package/apps/studio/acp/bootstrap-brief.ts +12 -2
  3. package/apps/studio/acp/bridge.ts +44 -10
  4. package/apps/studio/acp/env.ts +23 -0
  5. package/apps/studio/acp/login-state.ts +263 -0
  6. package/apps/studio/acp/plugin-bootstrap.ts +31 -25
  7. package/apps/studio/acp/probe.ts +152 -1
  8. package/apps/studio/annotations-layer.tsx +1451 -324
  9. package/apps/studio/annotations-model.ts +58 -0
  10. package/apps/studio/api.ts +568 -24
  11. package/apps/studio/bin/_audio-search.mjs +140 -0
  12. package/apps/studio/bin/_import-asset-pdf-worker.mjs +34 -0
  13. package/apps/studio/bin/_import-asset.mjs +815 -0
  14. package/apps/studio/bin/_import-brand.mjs +635 -0
  15. package/apps/studio/bin/_import-tokens-alias-resolver.mjs +95 -0
  16. package/apps/studio/bin/_import-tokens.mjs +1201 -0
  17. package/apps/studio/bin/_ingest-footage.mjs +386 -0
  18. package/apps/studio/bin/_probe-footage-playwright.mjs +269 -0
  19. package/apps/studio/bin/_transcribe.mjs +419 -0
  20. package/apps/studio/bin/_transcribe.test.mjs +80 -0
  21. package/apps/studio/bin/_video-playwright.mjs +141 -71
  22. package/apps/studio/bin/audio-search.sh +28 -0
  23. package/apps/studio/bin/generate.sh +154 -0
  24. package/apps/studio/bin/import-asset.sh +34 -0
  25. package/apps/studio/bin/import-brand.sh +29 -0
  26. package/apps/studio/bin/import-tokens.sh +33 -0
  27. package/apps/studio/bin/ingest-footage.sh +27 -0
  28. package/apps/studio/bin/photo-adjust.sh +163 -0
  29. package/apps/studio/bin/photo-bg-remove.sh +258 -0
  30. package/apps/studio/bin/probe-footage.sh +28 -0
  31. package/apps/studio/bin/read-annotations.mjs +125 -2
  32. package/apps/studio/bin/transcribe.sh +39 -0
  33. package/apps/studio/canvas-edit.ts +656 -12
  34. package/apps/studio/canvas-lib.tsx +637 -10
  35. package/apps/studio/canvas-pipeline.ts +65 -7
  36. package/apps/studio/canvas-shell.tsx +156 -16
  37. package/apps/studio/client/app.jsx +2385 -699
  38. package/apps/studio/client/export-center.jsx +35 -1
  39. package/apps/studio/client/generate-dialog.jsx +352 -0
  40. package/apps/studio/client/github.js +18 -0
  41. package/apps/studio/client/inspector-controls.jsx +781 -0
  42. package/apps/studio/client/panels/BrandUploadPanel.jsx +233 -0
  43. package/apps/studio/client/panels/ChatPanel.jsx +15 -33
  44. package/apps/studio/client/panels/GitPanel.jsx +8 -0
  45. package/apps/studio/client/panels/IntroVideoDialog.jsx +44 -0
  46. package/apps/studio/client/panels/OnboardingWizard.jsx +12 -0
  47. package/apps/studio/client/panels/ReadinessList.jsx +227 -7
  48. package/apps/studio/client/panels/RepoBranchSwitcher.jsx +133 -21
  49. package/apps/studio/client/panels/SettingsPanel.jsx +828 -0
  50. package/apps/studio/client/panels/SetupChecklist.jsx +223 -0
  51. package/apps/studio/client/panels/StickerPicker.jsx +160 -0
  52. package/apps/studio/client/panels/TimelinePanel.jsx +15 -2
  53. package/apps/studio/client/photo-knobs.jsx +432 -0
  54. package/apps/studio/client/styles/3-shell-maude.css +376 -28
  55. package/apps/studio/client/styles/4-components.css +223 -0
  56. package/apps/studio/client/styles/6-acp-chat.css +86 -0
  57. package/apps/studio/client/tour/quick-setup-tour.js +39 -0
  58. package/apps/studio/commands/annotation-strokes-command.ts +13 -3
  59. package/apps/studio/commands/edit-source-command.ts +31 -4
  60. package/apps/studio/config.schema.json +70 -0
  61. package/apps/studio/context-menu.tsx +42 -8
  62. package/apps/studio/context.ts +16 -0
  63. package/apps/studio/design-setup-readiness.ts +115 -0
  64. package/apps/studio/dist/client.bundle.js +5572 -21
  65. package/apps/studio/dist/comment-mount.js +2 -2
  66. package/apps/studio/dist/runtime/.min-sizes.json +1 -0
  67. package/apps/studio/dist/runtime/@imgly_background-removal.js +5543 -0
  68. package/apps/studio/dist/runtime/pixi-js.js +519 -519
  69. package/apps/studio/dist/styles.css +1 -1
  70. package/apps/studio/dom-selection.ts +25 -0
  71. package/apps/studio/draw/palette.ts +34 -0
  72. package/apps/studio/exporters/jobs.ts +47 -5
  73. package/apps/studio/exporters/video.ts +24 -4
  74. package/apps/studio/footage/schema.test.ts +287 -0
  75. package/apps/studio/footage/schema.ts +662 -0
  76. package/apps/studio/footage-store.ts +235 -0
  77. package/apps/studio/fs-watch.ts +10 -0
  78. package/apps/studio/generation/adapters/elevenlabs.ts +370 -0
  79. package/apps/studio/generation/adapters/gemini.ts +542 -0
  80. package/apps/studio/generation/adapters/groq.test.ts +80 -0
  81. package/apps/studio/generation/adapters/groq.ts +247 -0
  82. package/apps/studio/generation/audio-library.test.ts +95 -0
  83. package/apps/studio/generation/audio-library.ts +156 -0
  84. package/apps/studio/generation/captions.test.ts +78 -0
  85. package/apps/studio/generation/captions.ts +132 -0
  86. package/apps/studio/generation/download.ts +76 -0
  87. package/apps/studio/generation/elevenlabs.test.ts +223 -0
  88. package/apps/studio/generation/gemini.test.ts +350 -0
  89. package/apps/studio/generation/jobs.test.ts +128 -0
  90. package/apps/studio/generation/jobs.ts +243 -0
  91. package/apps/studio/generation/keys.test.ts +75 -0
  92. package/apps/studio/generation/keys.ts +162 -0
  93. package/apps/studio/generation/prefs.test.ts +95 -0
  94. package/apps/studio/generation/prefs.ts +82 -0
  95. package/apps/studio/generation/registry.ts +88 -0
  96. package/apps/studio/generation/types.test.ts +123 -0
  97. package/apps/studio/generation/types.ts +266 -0
  98. package/apps/studio/generation/whisper-models.test.ts +152 -0
  99. package/apps/studio/generation/whisper-models.ts +257 -0
  100. package/apps/studio/generation/whisper-spike-results.md +61 -0
  101. package/apps/studio/git/endpoints.ts +68 -7
  102. package/apps/studio/git/service.ts +199 -21
  103. package/apps/studio/github/service.ts +67 -0
  104. package/apps/studio/handoff.ts +3 -2
  105. package/apps/studio/http.ts +1039 -22
  106. package/apps/studio/input-router.tsx +10 -0
  107. package/apps/studio/inspect.ts +53 -1
  108. package/apps/studio/media/intro.mp4 +0 -0
  109. package/apps/studio/media-commit-chain.ts +119 -0
  110. package/apps/studio/paths.ts +20 -0
  111. package/apps/studio/photo/filters.ts +285 -0
  112. package/apps/studio/photo/pipeline.ts +607 -0
  113. package/apps/studio/photo/schema.ts +367 -0
  114. package/apps/studio/photo-store.ts +154 -0
  115. package/apps/studio/readiness.ts +108 -20
  116. package/apps/studio/runtime-bundle.ts +29 -6
  117. package/apps/studio/scaffold-design.ts +1145 -0
  118. package/apps/studio/server.ts +18 -2
  119. package/apps/studio/stickers/figjam-doodle/manifest.json +104 -0
  120. package/apps/studio/stickers/figjam-doodle/slice1.png +0 -0
  121. package/apps/studio/stickers/figjam-doodle/slice10.png +0 -0
  122. package/apps/studio/stickers/figjam-doodle/slice11.png +0 -0
  123. package/apps/studio/stickers/figjam-doodle/slice12.png +0 -0
  124. package/apps/studio/stickers/figjam-doodle/slice13.png +0 -0
  125. package/apps/studio/stickers/figjam-doodle/slice14.png +0 -0
  126. package/apps/studio/stickers/figjam-doodle/slice15.png +0 -0
  127. package/apps/studio/stickers/figjam-doodle/slice16.png +0 -0
  128. package/apps/studio/stickers/figjam-doodle/slice17.png +0 -0
  129. package/apps/studio/stickers/figjam-doodle/slice18.png +0 -0
  130. package/apps/studio/stickers/figjam-doodle/slice19.png +0 -0
  131. package/apps/studio/stickers/figjam-doodle/slice2.png +0 -0
  132. package/apps/studio/stickers/figjam-doodle/slice20.png +0 -0
  133. package/apps/studio/stickers/figjam-doodle/slice21.png +0 -0
  134. package/apps/studio/stickers/figjam-doodle/slice22.png +0 -0
  135. package/apps/studio/stickers/figjam-doodle/slice23.png +0 -0
  136. package/apps/studio/stickers/figjam-doodle/slice24.png +0 -0
  137. package/apps/studio/stickers/figjam-doodle/slice3.png +0 -0
  138. package/apps/studio/stickers/figjam-doodle/slice4.png +0 -0
  139. package/apps/studio/stickers/figjam-doodle/slice5.png +0 -0
  140. package/apps/studio/stickers/figjam-doodle/slice6.png +0 -0
  141. package/apps/studio/stickers/figjam-doodle/slice7.png +0 -0
  142. package/apps/studio/stickers/figjam-doodle/slice8.png +0 -0
  143. package/apps/studio/stickers/figjam-doodle/slice9.png +0 -0
  144. package/apps/studio/stickers/life-style/best.png +0 -0
  145. package/apps/studio/stickers/life-style/come-on.png +0 -0
  146. package/apps/studio/stickers/life-style/cut.png +0 -0
  147. package/apps/studio/stickers/life-style/detox.png +0 -0
  148. package/apps/studio/stickers/life-style/just.png +0 -0
  149. package/apps/studio/stickers/life-style/manifest.json +68 -0
  150. package/apps/studio/stickers/life-style/mirror.png +0 -0
  151. package/apps/studio/stickers/life-style/nice.png +0 -0
  152. package/apps/studio/stickers/life-style/objects.png +0 -0
  153. package/apps/studio/stickers/life-style/ok.png +0 -0
  154. package/apps/studio/stickers/life-style/queen.png +0 -0
  155. package/apps/studio/stickers/life-style/star.png +0 -0
  156. package/apps/studio/stickers/life-style/sun.png +0 -0
  157. package/apps/studio/stickers/life-style/water.png +0 -0
  158. package/apps/studio/stickers/life-style/yeah.png +0 -0
  159. package/apps/studio/stickers/life-style/you-can.png +0 -0
  160. package/apps/studio/stickers/opposing-thoughts/check-the-deets.png +0 -0
  161. package/apps/studio/stickers/opposing-thoughts/cut-it.png +0 -0
  162. package/apps/studio/stickers/opposing-thoughts/dope.png +0 -0
  163. package/apps/studio/stickers/opposing-thoughts/fresh.png +0 -0
  164. package/apps/studio/stickers/opposing-thoughts/hot.png +0 -0
  165. package/apps/studio/stickers/opposing-thoughts/idea.png +0 -0
  166. package/apps/studio/stickers/opposing-thoughts/keep-exploring.png +0 -0
  167. package/apps/studio/stickers/opposing-thoughts/killed-it.png +0 -0
  168. package/apps/studio/stickers/opposing-thoughts/love-it.png +0 -0
  169. package/apps/studio/stickers/opposing-thoughts/manifest.json +88 -0
  170. package/apps/studio/stickers/opposing-thoughts/not-sure.png +0 -0
  171. package/apps/studio/stickers/opposing-thoughts/ok.png +0 -0
  172. package/apps/studio/stickers/opposing-thoughts/pure-gold.png +0 -0
  173. package/apps/studio/stickers/opposing-thoughts/save-for-later.png +0 -0
  174. package/apps/studio/stickers/opposing-thoughts/steal-this.png +0 -0
  175. package/apps/studio/stickers/opposing-thoughts/take-a-peek.png +0 -0
  176. package/apps/studio/stickers/opposing-thoughts/this-or-that.png +0 -0
  177. package/apps/studio/stickers/opposing-thoughts/thoughts.png +0 -0
  178. package/apps/studio/stickers/opposing-thoughts/vibes.png +0 -0
  179. package/apps/studio/stickers/opposing-thoughts/winner.png +0 -0
  180. package/apps/studio/stickers/opposing-thoughts/wip.png +0 -0
  181. package/apps/studio/stickers/project-status/group-100.png +0 -0
  182. package/apps/studio/stickers/project-status/group-101.png +0 -0
  183. package/apps/studio/stickers/project-status/group-102.png +0 -0
  184. package/apps/studio/stickers/project-status/group-103.png +0 -0
  185. package/apps/studio/stickers/project-status/group-104.png +0 -0
  186. package/apps/studio/stickers/project-status/group-105.png +0 -0
  187. package/apps/studio/stickers/project-status/group-106.png +0 -0
  188. package/apps/studio/stickers/project-status/group-107.png +0 -0
  189. package/apps/studio/stickers/project-status/group-108.png +0 -0
  190. package/apps/studio/stickers/project-status/group-109.png +0 -0
  191. package/apps/studio/stickers/project-status/group-110.png +0 -0
  192. package/apps/studio/stickers/project-status/group-111.png +0 -0
  193. package/apps/studio/stickers/project-status/group-112.png +0 -0
  194. package/apps/studio/stickers/project-status/group-113.png +0 -0
  195. package/apps/studio/stickers/project-status/group-114.png +0 -0
  196. package/apps/studio/stickers/project-status/group-115.png +0 -0
  197. package/apps/studio/stickers/project-status/group-117.png +0 -0
  198. package/apps/studio/stickers/project-status/group-118.png +0 -0
  199. package/apps/studio/stickers/project-status/group-119.png +0 -0
  200. package/apps/studio/stickers/project-status/group-120.png +0 -0
  201. package/apps/studio/stickers/project-status/group-121.png +0 -0
  202. package/apps/studio/stickers/project-status/group-122.png +0 -0
  203. package/apps/studio/stickers/project-status/group-41.png +0 -0
  204. package/apps/studio/stickers/project-status/group-42.png +0 -0
  205. package/apps/studio/stickers/project-status/group-43.png +0 -0
  206. package/apps/studio/stickers/project-status/group-44.png +0 -0
  207. package/apps/studio/stickers/project-status/group-45.png +0 -0
  208. package/apps/studio/stickers/project-status/group-46.png +0 -0
  209. package/apps/studio/stickers/project-status/group-47.png +0 -0
  210. package/apps/studio/stickers/project-status/group-48.png +0 -0
  211. package/apps/studio/stickers/project-status/group-49.png +0 -0
  212. package/apps/studio/stickers/project-status/group-50.png +0 -0
  213. package/apps/studio/stickers/project-status/group-51.png +0 -0
  214. package/apps/studio/stickers/project-status/group-52.png +0 -0
  215. package/apps/studio/stickers/project-status/group-53.png +0 -0
  216. package/apps/studio/stickers/project-status/group-54.png +0 -0
  217. package/apps/studio/stickers/project-status/group-55.png +0 -0
  218. package/apps/studio/stickers/project-status/group-56.png +0 -0
  219. package/apps/studio/stickers/project-status/group-57.png +0 -0
  220. package/apps/studio/stickers/project-status/group-58.png +0 -0
  221. package/apps/studio/stickers/project-status/group-59.png +0 -0
  222. package/apps/studio/stickers/project-status/group-60.png +0 -0
  223. package/apps/studio/stickers/project-status/group-61.png +0 -0
  224. package/apps/studio/stickers/project-status/group-62.png +0 -0
  225. package/apps/studio/stickers/project-status/group-63.png +0 -0
  226. package/apps/studio/stickers/project-status/group-64.png +0 -0
  227. package/apps/studio/stickers/project-status/group-65.png +0 -0
  228. package/apps/studio/stickers/project-status/group-66.png +0 -0
  229. package/apps/studio/stickers/project-status/group-67.png +0 -0
  230. package/apps/studio/stickers/project-status/group-68.png +0 -0
  231. package/apps/studio/stickers/project-status/group-69.png +0 -0
  232. package/apps/studio/stickers/project-status/group-70.png +0 -0
  233. package/apps/studio/stickers/project-status/group-71.png +0 -0
  234. package/apps/studio/stickers/project-status/group-72.png +0 -0
  235. package/apps/studio/stickers/project-status/group-73.png +0 -0
  236. package/apps/studio/stickers/project-status/group-74.png +0 -0
  237. package/apps/studio/stickers/project-status/group-75.png +0 -0
  238. package/apps/studio/stickers/project-status/group-76.png +0 -0
  239. package/apps/studio/stickers/project-status/group-77.png +0 -0
  240. package/apps/studio/stickers/project-status/group-78.png +0 -0
  241. package/apps/studio/stickers/project-status/group-79.png +0 -0
  242. package/apps/studio/stickers/project-status/group-80.png +0 -0
  243. package/apps/studio/stickers/project-status/group-81.png +0 -0
  244. package/apps/studio/stickers/project-status/group-82.png +0 -0
  245. package/apps/studio/stickers/project-status/group-83.png +0 -0
  246. package/apps/studio/stickers/project-status/group-84.png +0 -0
  247. package/apps/studio/stickers/project-status/group-85.png +0 -0
  248. package/apps/studio/stickers/project-status/group-86.png +0 -0
  249. package/apps/studio/stickers/project-status/group-87.png +0 -0
  250. package/apps/studio/stickers/project-status/group-88.png +0 -0
  251. package/apps/studio/stickers/project-status/group-89.png +0 -0
  252. package/apps/studio/stickers/project-status/group-90.png +0 -0
  253. package/apps/studio/stickers/project-status/group-91.png +0 -0
  254. package/apps/studio/stickers/project-status/group-92.png +0 -0
  255. package/apps/studio/stickers/project-status/group-93.png +0 -0
  256. package/apps/studio/stickers/project-status/group-94.png +0 -0
  257. package/apps/studio/stickers/project-status/group-96.png +0 -0
  258. package/apps/studio/stickers/project-status/group-97.png +0 -0
  259. package/apps/studio/stickers/project-status/group-98.png +0 -0
  260. package/apps/studio/stickers/project-status/group-99.png +0 -0
  261. package/apps/studio/stickers/project-status/manifest.json +328 -0
  262. package/apps/studio/test/_helpers.ts +15 -2
  263. package/apps/studio/test/acp-bootstrap-brief.test.ts +11 -0
  264. package/apps/studio/test/acp-bridge.test.ts +34 -1
  265. package/apps/studio/test/acp-commands.test.ts +2 -1
  266. package/apps/studio/test/acp-env.test.ts +30 -0
  267. package/apps/studio/test/acp-plugin-bootstrap.test.ts +23 -57
  268. package/apps/studio/test/acp-session-plugins.test.ts +72 -1
  269. package/apps/studio/test/annotation-strokes-command.test.ts +17 -0
  270. package/apps/studio/test/annotations-layer.test.ts +174 -0
  271. package/apps/studio/test/asset-api.test.ts +3 -3
  272. package/apps/studio/test/canvas-edit.test.ts +17 -6
  273. package/apps/studio/test/canvas-origin-gate.test.ts +50 -0
  274. package/apps/studio/test/csp-canvas-shell.test.ts +11 -0
  275. package/apps/studio/test/csrf-write-guard.test.ts +23 -1
  276. package/apps/studio/test/design-setup-readiness.test.ts +155 -0
  277. package/apps/studio/test/dynamic-text-edit.test.ts +162 -0
  278. package/apps/studio/test/edit-source-command.test.ts +23 -0
  279. package/apps/studio/test/element-structural-edit.test.ts +154 -0
  280. package/apps/studio/test/fixtures/fake-claude-auth.mjs +13 -0
  281. package/apps/studio/test/footage-store.test.ts +100 -0
  282. package/apps/studio/test/generate-route.test.ts +106 -0
  283. package/apps/studio/test/git-branches.test.ts +97 -0
  284. package/apps/studio/test/github-api.test.ts +56 -1
  285. package/apps/studio/test/import-asset-browser.test.ts +64 -0
  286. package/apps/studio/test/import-asset-route.test.ts +71 -0
  287. package/apps/studio/test/import-asset.test.ts +399 -0
  288. package/apps/studio/test/import-brand-browser.test.ts +88 -0
  289. package/apps/studio/test/import-brand-route.test.ts +120 -0
  290. package/apps/studio/test/import-brand.test.ts +206 -0
  291. package/apps/studio/test/import-tokens.test.ts +722 -0
  292. package/apps/studio/test/input-router.test.ts +33 -0
  293. package/apps/studio/test/inspect-script-syntax.test.ts +53 -0
  294. package/apps/studio/test/media-commit-chain.test.ts +210 -0
  295. package/apps/studio/test/photo-bg-remove-validation.test.ts +71 -0
  296. package/apps/studio/test/photo-canvas-bundle.test.ts +61 -0
  297. package/apps/studio/test/photo-edit-api.test.ts +201 -0
  298. package/apps/studio/test/photo-filters.test.ts +149 -0
  299. package/apps/studio/test/photo-pipeline.test.ts +106 -0
  300. package/apps/studio/test/photo-taxonomy.test.ts +96 -0
  301. package/apps/studio/test/read-annotations.test.ts +164 -0
  302. package/apps/studio/test/readiness.test.ts +13 -11
  303. package/apps/studio/test/scaffold-design.test.ts +122 -0
  304. package/apps/studio/test/shell-importmap.test.ts +49 -0
  305. package/apps/studio/test/text-editability-stamp.test.ts +131 -0
  306. package/apps/studio/test/timeline-parse.test.ts +57 -0
  307. package/apps/studio/test/tool-palette-insert-anchor.test.ts +5 -3
  308. package/apps/studio/test/tour-overlay.test.tsx +16 -0
  309. package/apps/studio/test/undo-stack.test.ts +33 -0
  310. package/apps/studio/test/video-asset.test.ts +5 -5
  311. package/apps/studio/test/video-render-bridge.test.ts +23 -1
  312. package/apps/studio/text-caret.ts +239 -0
  313. package/apps/studio/tool-palette.tsx +49 -21
  314. package/apps/studio/ui-prefs.ts +130 -0
  315. package/apps/studio/undo-stack.ts +94 -2
  316. package/apps/studio/use-annotation-resize.tsx +4 -4
  317. package/apps/studio/use-canvas-media-drop.tsx +40 -1
  318. package/apps/studio/use-chrome-visibility.tsx +8 -2
  319. package/apps/studio/use-selection-set.tsx +21 -0
  320. package/apps/studio/video-comp.tsx +48 -7
  321. package/apps/studio/whats-new.json +149 -0
  322. package/apps/studio/ws.ts +5 -0
  323. package/cli/bin/maude.mjs +6 -6
  324. package/cli/commands/design.mjs +67 -3
  325. package/cli/lib/gitignore-block.mjs +2 -0
  326. package/cli/lib/pkg-root.mjs +107 -0
  327. package/cli/lib/pkg-root.test.mjs +79 -0
  328. package/cli/lib/reconstruct-toolset.test.mjs +194 -0
  329. package/cli/lib/update-check.mjs +8 -0
  330. package/package.json +13 -11
  331. package/plugins/design/dependencies.json +18 -0
  332. package/plugins/design/templates/_shell.html +1 -0
@@ -212,6 +212,20 @@
212
212
  .st-body > .main { flex: 1; min-width: 0; }
213
213
  .st-body > .st-rpanel { flex: 0 0 304px; }
214
214
 
215
+ /* ─── Dock slot (feature-configurable-panel-docking) ──────────────────────────
216
+ * A left/right slot: an optional tab strip over the active panel, which fills the
217
+ * remaining height. The wrapper owns the resizable width; the inner panel fills
218
+ * it (width:100% wins over the panel's own inline width, which we no longer set). */
219
+ .st-dockslot { display: flex; flex-direction: column; min-height: 0; min-width: 0; overflow: hidden; flex: none; }
220
+ .st-dockslot.is-collapsed { width: 0 !important; flex-basis: 0 !important; }
221
+ .st-dockslot > .st-rpanel,
222
+ .st-dockslot > .st-sidebar { flex: 1 1 auto; width: 100%; min-height: 0; }
223
+ .st-docktabs { display: flex; gap: 2px; padding: var(--space-2) var(--space-2) 0; border-bottom: 1px solid var(--border-subtle); background: var(--bg-1); flex: none; }
224
+ .st-docktab { appearance: none; border: 0; background: transparent; cursor: pointer; padding: var(--space-1) var(--space-3); border-radius: var(--radius-sm) var(--radius-sm) 0 0; color: var(--fg-3); font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); transition: color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out); }
225
+ .st-docktab:hover { color: var(--fg-1); background: var(--bg-2); }
226
+ .st-docktab.is-active { color: var(--fg-0); background: var(--bg-2); box-shadow: inset 0 -2px 0 var(--accent); }
227
+ .st-docktab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
228
+
215
229
  /* ─── Left sidebar — file tree ────────────────────────────────────────────── */
216
230
  .st-sidebar {
217
231
  width: 252px; flex: 0 0 252px;
@@ -292,6 +306,20 @@
292
306
  min-width: 16px; height: 16px; padding: 0 4px; display: inline-flex; align-items: center; justify-content: center;
293
307
  border-radius: var(--radius-pill); background: var(--accent); color: var(--accent-fg); flex: none;
294
308
  }
309
+ /* DDR-174 (T15) — "reconstructed from an image, experimental" marker. Sits left
310
+ of the git/open-count badges (which already claim margin-left:auto), so this
311
+ one gets an explicit left margin instead of fighting for the auto slot.
312
+ `--status-warn` stays on the border only (a UI-component outline needs just
313
+ 3:1, which it clears) — a11y-auditor caught it also being used as 9px TEXT
314
+ color failing WCAG AA in light theme (~3.46:1 vs the required 4.5:1); the
315
+ sibling `.st-git-badge[data-kind="M"]` avoids this by using the warn token
316
+ as a fill with a fixed dark foreground instead. Text uses `--fg-2` (the
317
+ DS's own documented AA-clearing muted-text token) so both themes pass. */
318
+ .st-row-exp-badge {
319
+ margin-left: 6px; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: 0.02em;
320
+ line-height: 1; padding: 2px 4px; display: inline-flex; align-items: center; justify-content: center;
321
+ border-radius: var(--radius-xs); border: 1px dashed var(--status-warn); color: var(--fg-2); flex: none;
322
+ }
295
323
  /* delete affordance — sibling of the row button (can't nest buttons). */
296
324
  .st-row-wrap { position: relative; display: flex; align-items: center; }
297
325
  .st-row-wrap .st-row { flex: 1; }
@@ -352,6 +380,10 @@
352
380
  .st-empty-body { max-width: 540px; font-size: var(--type-sm); line-height: 1.7; color: var(--fg-2); }
353
381
  .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); }
354
382
  .st-empty-body strong { color: var(--fg-0); font-weight: 600; }
383
+ /* DDR-166 plan, Phase 2 (T7) — persistent "Setup" affordance, shown only while
384
+ the project's own setup (design system / first canvas / brand assets) is
385
+ incomplete; auto-hides once probeSetupReadiness() reports ready. */
386
+ .st-empty-quick-setup { pointer-events: auto; margin-top: var(--space-2); }
355
387
 
356
388
  /* ═══ Task 6 — right panel (Inspector / Comments) + palette + toast ═══════════ */
357
389
  .st-rpanel {
@@ -495,6 +527,44 @@
495
527
  .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); }
496
528
  .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; }
497
529
  .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); }
530
+
531
+ /* ── Unified Settings modal (feature-unified-settings-modal) ────────────────
532
+ * One modal for every Maude preference: a vertical tab rail + an internally
533
+ * scrolling pane, so no category can push the dialog off-screen. Extends the
534
+ * shared .st-dialog shell (which already clips + pops). */
535
+ .st-dialog.is-settings { width: 760px; }
536
+ .st-settings-tabs { display: grid; grid-template-columns: 184px 1fr; min-height: 0; }
537
+ .st-settings-rail { display: flex; flex-direction: column; gap: 2px; padding: var(--space-4); border-right: 1px solid var(--border-subtle); background: var(--bg-0); }
538
+ .st-settings-tab { appearance: none; border: 0; background: transparent; text-align: left; cursor: pointer; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); color: var(--fg-2); font-family: var(--font-body); font-size: var(--type-sm); transition: background var(--dur-soft) var(--ease-out), color var(--dur-soft) var(--ease-out); }
539
+ .st-settings-tab:hover { background: var(--bg-3); color: var(--fg-0); }
540
+ .st-settings-tab.is-active { background: var(--accent-tint); color: var(--fg-0); font-weight: 600; }
541
+ .st-settings-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
542
+ /* The scrolling pane — this is the fix for the AI-generation section overflowing
543
+ * the viewport; the pane scrolls, the page never does. */
544
+ .st-settings-pane { max-height: min(72vh, 620px); overflow-y: auto; padding: var(--space-5); }
545
+ .st-settings-pane .st-rp-hd { margin-bottom: var(--space-3); }
546
+ .st-pref-row { display: flex; align-items: flex-start; gap: var(--space-4); justify-content: space-between; padding: var(--space-3) 0; border-bottom: 1px solid var(--border-subtle); cursor: pointer; }
547
+ .st-pref-row:last-child { border-bottom: 0; }
548
+ .st-pref-row.is-disabled { cursor: default; opacity: 0.6; }
549
+ .st-pref-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
550
+ .st-pref-label { font-size: var(--type-sm); color: var(--fg-0); font-weight: 500; }
551
+ .st-pref-note { font-size: var(--type-xs); color: var(--fg-3); line-height: 1.45; }
552
+ /* Switch — styled checkbox; compositor-only transition (transform/background). */
553
+ .st-switch { appearance: none; flex: none; position: relative; width: 34px; height: 20px; border-radius: 999px; background: var(--bg-4); border: 1px solid var(--border-default); cursor: pointer; transition: background var(--dur-soft) var(--ease-out); margin-top: 2px; }
554
+ .st-switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: var(--fg-2); transition: transform var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out); }
555
+ .st-switch:checked { background: var(--accent); border-color: var(--accent); }
556
+ .st-switch:checked::after { transform: translateX(14px); background: var(--accent-fg); }
557
+ .st-switch:disabled { cursor: default; }
558
+ .st-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
559
+ @media (prefers-reduced-motion: reduce) { .st-switch, .st-switch::after, .st-settings-tab { transition-duration: 1ms; } }
560
+ /* Layout tab — left/right segmented control per panel. */
561
+ .st-sidetoggle { display: inline-flex; flex: none; border: 1px solid var(--border-default); border-radius: var(--radius-sm); overflow: hidden; }
562
+ .st-sidebtn { appearance: none; border: 0; background: var(--bg-2); color: var(--fg-2); cursor: pointer; font-family: var(--font-mono); font-size: var(--type-xs); padding: var(--space-1) var(--space-3); min-width: 46px; transition: background var(--dur-soft) var(--ease-out), color var(--dur-soft) var(--ease-out); }
563
+ .st-sidebtn + .st-sidebtn { border-left: 1px solid var(--border-default); }
564
+ .st-sidebtn:hover:not(:disabled) { background: var(--bg-3); color: var(--fg-0); }
565
+ .st-sidebtn.is-active { background: var(--accent); color: var(--accent-fg); }
566
+ .st-sidebtn:disabled { opacity: 0.5; cursor: default; }
567
+ .st-sidebtn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
498
568
  .st-export-recent { display: flex; flex-direction: column; gap: 2px; max-height: 132px; overflow-y: auto; }
499
569
  .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); }
500
570
  .st-export-recent-row:hover { background: var(--bg-2); }
@@ -509,10 +579,46 @@
509
579
  .st-ap-err { color: var(--danger, #e5484d); font-family: var(--font-mono); font-size: var(--type-xs); }
510
580
  .st-ap-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: var(--space-3); max-height: 52vh; overflow-y: auto; padding: 2px; }
511
581
  .st-ap-empty { grid-column: 1 / -1; color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); padding: var(--space-6) 0; text-align: center; }
512
- .st-ap-cell { appearance: none; cursor: pointer; display: flex; flex-direction: column; gap: 4px; padding: 6px; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--bg-2); text-align: left; transition: border-color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out); }
582
+ .st-ap-cell { position: relative; appearance: none; cursor: pointer; display: flex; flex-direction: column; gap: 4px; padding: 6px; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--bg-2); text-align: left; transition: border-color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out); }
513
583
  .st-ap-cell:hover { border-color: var(--accent, var(--border-strong, var(--border-default))); background: var(--bg-3); }
514
584
  .st-ap-thumb { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--radius-xs); background: var(--bg-4, var(--bg-3)); display: block; }
515
585
  .st-ap-name { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
586
+
587
+ /* feature-bulk-media-insert — multi-select grid state + destination toggle + confirm bar */
588
+ .st-ap-cell[data-selected="true"] { border-color: var(--accent); background: var(--bg-3); }
589
+ .st-ap-check { position: absolute; top: 6px; right: 6px; width: 18px; height: 18px; border-radius: var(--radius-pill); border: 1px solid var(--border-default); background: var(--bg-1); color: var(--accent-fg, #fff); display: grid; place-items: center; }
590
+ .st-ap-cell[data-selected="true"] .st-ap-check { background: var(--accent); border-color: var(--accent); }
591
+ .st-ap-confirm { flex-wrap: wrap; }
592
+ .st-ap-count { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); }
593
+ .st-ap-seg { display: inline-flex; border: 1px solid var(--border-default); border-radius: var(--radius-sm); overflow: hidden; background: var(--bg-2); }
594
+ .st-ap-seg-btn { appearance: none; border: 0; background: transparent; color: var(--fg-2); font-size: var(--type-xs); font-family: var(--font-mono); padding: var(--space-2) var(--space-3); cursor: pointer; }
595
+ .st-ap-seg-btn[aria-pressed="true"] { background: var(--bg-4); color: var(--fg-0); }
596
+ .st-ap-seg-btn:disabled { opacity: 0.45; cursor: default; }
597
+ .st-ap-seg-btn + .st-ap-seg-btn { border-left: 1px solid var(--border-subtle); }
598
+ .st-ap-dest-note { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); }
599
+ .st-ap-confirm-spacer { flex: 1; }
600
+
601
+ /* ─── StickerPicker (feature-whiteboard-annotation-improvements Phase 4) ──── */
602
+ .st-sticker-picker { width: 640px; }
603
+ .st-sticker-picker .input {
604
+ font-family: var(--font-body); font-size: var(--type-sm); color: var(--fg-0);
605
+ background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-sm);
606
+ padding: var(--space-3) var(--space-4); width: 100%;
607
+ transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out);
608
+ }
609
+ .st-sticker-picker .input::placeholder { color: var(--fg-3); }
610
+ .st-sticker-picker .input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
611
+ .st-sp-body { max-height: 56vh; overflow-y: auto; padding: 2px; display: flex; flex-direction: column; gap: var(--space-5); }
612
+ .st-sp-pack-hd { display: flex; align-items: baseline; gap: var(--space-2); padding: 0 2px; }
613
+ .st-sp-pack-name { font-family: var(--font-mono); font-size: var(--type-xs); font-weight: 600; color: var(--fg-1); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
614
+ .st-sp-pack-author { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-3); }
615
+ .st-sp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); gap: var(--space-2); }
616
+ .st-sp-cell { appearance: none; cursor: pointer; display: flex; flex-direction: column; align-items: center; padding: 6px; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--bg-2); transition: border-color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out); }
617
+ .st-sp-cell:hover { border-color: var(--accent, var(--border-strong, var(--border-default))); background: var(--bg-3); }
618
+ .st-sp-thumb { width: 100%; aspect-ratio: 1; object-fit: contain; display: block; }
619
+ .st-sp-empty { color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); padding: var(--space-6) 0; text-align: center; }
620
+ .st-sp-ft { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); padding: var(--space-3) var(--space-5); border-top: 1px solid var(--border-subtle); font-family: var(--font-mono); font-size: 10px; color: var(--fg-3); }
621
+ .st-sp-ft a { color: var(--fg-2); }
516
622
  .st-cp-replace { width: 100%; justify-content: center; }
517
623
  /* Media "Replace…" — a full-width button, NOT inside the 3-col .st-cp-row grid
518
624
  (which would drop it into the 10px provenance-dot column and clip it). */
@@ -615,11 +721,68 @@
615
721
  * rail; 24px+ targets (bind / seg / box-model inputs); legible box-model. */
616
722
  .st-cp { display: flex; flex-direction: column; gap: var(--space-4); }
617
723
 
618
- /* element identity — Phase 12.3 (W2.3) hairline under the header for structure (Figma-ish) */
619
- .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); }
724
+ /* element identity — Phase 12.3 (W2.3) hairline under the header for structure
725
+ * (Figma-ish). DDR-171 critic pass this is the panel's own top-level
726
+ * boundary (vs. a section's internal divider below), so it gets the stronger
727
+ * of the two border tokens; otherwise the id-row rule and the first section's
728
+ * `.st-cp-sechd` rule read as identical weight stacked ~40px apart. */
729
+ .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-strong); }
620
730
  .st-cp-idtag { font-family: var(--font-mono); font-size: var(--type-sm); color: var(--fg-0); }
621
731
  .st-cp-idcls { color: var(--accent); }
622
- .st-cp-idmeta { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
732
+ /* DDR-171 the Advanced/Designer vocabulary toggle lives in the `.st-cp-id`
733
+ * row's corner slot as a plain `IconButtonGroup` (`.st-cp-iconseg`, styled
734
+ * below) — no extra wrapper class needed, `.st-cp-id`'s own flex/space-between
735
+ * places it. Deliberately NOT a full-width `Segmented` row (too heavy for a
736
+ * mode switch this minor — every other toggle in this panel is icon-sized).
737
+ * The active glyph gets the stronger accent-tint treatment (normally reserved
738
+ * for `aria-pressed` toggles) rather than the neutral `.is-active` fill every
739
+ * OTHER icon-seg in this panel uses — this one is a mode switch, not a value
740
+ * picker, so "which mode am I in" needs to read at a glance, not just on
741
+ * close inspection. Scoped to `.st-cp-idmode` so it doesn't touch direction /
742
+ * align / overflow etc. */
743
+ .st-cp-idmode .st-cp-iconseg button.is-active { background: var(--accent-tint); color: var(--accent); }
744
+
745
+ /* ── DDR-171 Designer-mode layout refinement ─────────────────────────────────
746
+ * Why Figma's panel reads cleaner than our raw-CSS panel, and what we borrow
747
+ * for Designer mode ONLY (Advanced mode stays byte-identical — it's the
748
+ * DDR-104-critic-gated developer surface where mono labels + provenance dots
749
+ * ARE the point). Three root causes, three scoped fixes:
750
+ *
751
+ * 1. Figma has NO per-row status dot — our provenance dot on every row builds
752
+ * a "punch-card" rail down the left edge. In Designer mode we hide the dot
753
+ * for INHERITED/unset rows (the common case) and keep it only where a value
754
+ * is genuinely token-bound or overridden — that's a useful "this is
755
+ * customized" marker even for a designer, and rare enough not to form a
756
+ * rail. The 14px grid column stays reserved so labels never shift.
757
+ * 2. Figma section headers are quiet title-case ("Auto layout"), not code
758
+ * labels ("AUTO LAYOUT"). We drop the mono/uppercase/tracking for the body
759
+ * font, sentence case, one step brighter — reads as a group heading, not a
760
+ * token name.
761
+ * 3. Figma row labels are soft sans, not monospace — we switch the label font
762
+ * to the body face so the column reads as prose, not a code editor. */
763
+ .st-cp--designer .st-cp-prov--inherit { visibility: hidden; }
764
+ .st-cp--designer .st-cp-sechd {
765
+ font-family: var(--font-body);
766
+ font-size: var(--type-sm);
767
+ font-weight: 600;
768
+ text-transform: none;
769
+ letter-spacing: normal;
770
+ color: var(--fg-1);
771
+ padding-bottom: var(--space-2);
772
+ }
773
+ .st-cp--designer .st-cp-sechd:hover, .st-cp--designer .st-cp-sechd:hover svg { color: var(--fg-0); }
774
+ .st-cp--designer .st-cp-label { font-family: var(--font-body); font-size: var(--type-sm); color: var(--fg-1); }
775
+ .st-cp--designer .st-cp-modelabel { font-family: var(--font-body); font-size: var(--type-sm); }
776
+ /* a touch more air between clusters — Figma's sections breathe. */
777
+ .st-cp--designer .st-cp-sec { gap: var(--space-3); }
778
+
779
+ /* a Designer cluster's "···" overflow disclosure — same visual weight as the
780
+ * section reset glyph (`.st-cp-secreset`), right-aligned under the cluster's
781
+ * common rows. */
782
+ .st-cp-clustermore-row { display: flex; justify-content: flex-end; }
783
+ .st-cp-clustermore { appearance: none; cursor: pointer; background: transparent; border: 0; color: var(--fg-3); font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); padding: var(--space-1) var(--space-2); border-radius: var(--radius-xs); }
784
+ .st-cp-clustermore:hover { color: var(--accent); background: var(--accent-tint); }
785
+ .st-cp-clustermore:focus-visible { outline: none; color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
623
786
 
624
787
  /* sections */
625
788
  .st-cp-sec { display: flex; flex-direction: column; gap: var(--space-2); }
@@ -638,13 +801,19 @@
638
801
  .st-cp-reset { width: 16px; height: 16px; }
639
802
  .st-cp-reset:hover, .st-cp-secreset:hover { color: var(--accent); background: var(--accent-tint); }
640
803
  .st-cp-reset:focus-visible, .st-cp-secreset:focus-visible { outline: none; color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
641
- .st-cp-secreset { align-self: center; }
804
+ .st-cp-secreset { align-self: center; display: inline-grid; place-items: center; }
805
+ .st-cp-secreset.is-quiet { color: var(--fg-3); opacity: 0.4; cursor: default; }
806
+ .st-cp-secreset.is-quiet:hover { color: var(--fg-3); background: transparent; }
642
807
  /* read-only name field for an existing custom CSS prop / HTML attr row */
643
808
  .st-cp-fin--ro { flex: 0 0 38%; background: var(--bg-2); color: var(--fg-2); cursor: default; }
644
809
  .st-cp-fin--ro:focus { outline: none; border-color: var(--border-strong); box-shadow: none; }
645
810
 
646
- /* a labelled row: [provenance] [css property] [control] */
647
- .st-cp-row { display: grid; grid-template-columns: 10px 92px 1fr; align-items: center; gap: var(--space-2); min-height: 28px; }
811
+ /* a labelled row: [provenance] [css property] [control]. DDR-171 critic pass —
812
+ * the dot column widened 10px→14px (was) so the provenance dot reads as a
813
+ * detached status signal instead of looking glued to the label when several
814
+ * rows stack (dot's own size is unchanged — this only adds breathing room,
815
+ * doesn't shrink an already-small interactive/focusable target). */
816
+ .st-cp-row { display: grid; grid-template-columns: 14px 92px 1fr; align-items: center; column-gap: var(--space-3); min-height: 32px; padding: 3px 0; }
648
817
  /* #1 bigger-bet — unset rows recede so the overridden ones pop; full opacity on
649
818
  * hover/focus so they're still editable. The panel reads as a diff of overrides. */
650
819
  .st-cp-row.is-unset { opacity: 0.5; transition: opacity var(--dur-soft) var(--ease-out); }
@@ -657,7 +826,7 @@
657
826
  /* provenance — SHAPE-coded so token/override/inherited survive small size +
658
827
  * colour-blindness: token = filled accent circle · override = filled neutral
659
828
  * square · inherited = hollow ring. Each carries role=img + aria-label. */
660
- .st-cp-prov { width: 8px; height: 8px; display: inline-block; flex: none; padding: 0; }
829
+ .st-cp-prov { width: 9px; height: 9px; display: inline-block; flex: none; padding: 0; }
661
830
  /* Phase 12.3 (#4) — the row's leading dot is a button: provenance + save status
662
831
  * (glow) + double-click reset. No appearance chrome; the variant fills it. */
663
832
  /* reset native button chrome; the variants own the FILL (a transparent bg here
@@ -670,13 +839,12 @@ button.st-cp-prov { appearance: none; border: 0; cursor: default; }
670
839
  .st-cp-prov.is-saved { box-shadow: 0 0 0 3px color-mix(in oklab, var(--status-success) 45%, transparent); }
671
840
  .st-cp-prov.is-saving { box-shadow: 0 0 0 3px color-mix(in oklab, var(--fg-2) 35%, transparent); }
672
841
  .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); }
673
- /* Phase 12.3 — provenance is SHAPE-coded (token=circle · override=square ·
674
- * inherited=ring) on NEUTRAL fills. Indigo is reserved for its one job on this
675
- * surface (the bound-token ◇ button + the focus ring), so the token dot must NOT
676
- * reuse the accent (design-critic 1.4/1.5). */
677
- .st-cp-prov--bound { background: var(--fg-0); border-radius: 50%; }
678
- .st-cp-prov--raw { background: var(--fg-2); border-radius: 1px; }
679
- .st-cp-prov--inherit { background: transparent; box-shadow: inset 0 0 0 1.5px var(--fg-3); border-radius: 50%; }
842
+ /* handoff — provenance dots match the design specimen (supersedes the older
843
+ * shape-coded/neutral scheme): token-bound = accent · raw override = fg-1 ·
844
+ * inherited = hollow ring. All circles. */
845
+ .st-cp-prov--bound { background: var(--accent); border-radius: 50%; }
846
+ .st-cp-prov--raw { background: var(--fg-1); border-radius: 50%; }
847
+ .st-cp-prov--inherit { background: transparent; box-shadow: inset 0 0 0 1.5px var(--border-strong); border-radius: 50%; }
680
848
 
681
849
  /* colour swatch — standalone (border cluster) + inline (inside the token field) */
682
850
  .st-cp-swatch { flex: none; width: 22px; height: 22px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); }
@@ -717,6 +885,128 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
717
885
  .st-cp-bind:hover::before { border-color: var(--accent); }
718
886
  .st-cp-numin--mini { flex: none; width: 38px; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); }
719
887
 
888
+ /* feature-inspector-controls-redesign — shared control library (inspector-controls.jsx).
889
+ * The drag-to-scrub affordance now lives on the LEADING handle, not the input,
890
+ * so click-to-type + select-all work; the input keeps a plain text caret. */
891
+ .st-cp-handle { cursor: ew-resize; touch-action: none; }
892
+ .st-cp-handle:hover { color: var(--fg-1); background: var(--bg-3); }
893
+ .st-cp-grip { display: inline-block; width: 7px; height: 12px; color: var(--fg-2); background-image: radial-gradient(currentColor 0.8px, transparent 0.8px); background-size: 3px 4px; background-position: center; opacity: 0.7; }
894
+ .st-cp-handle:hover .st-cp-grip { opacity: 1; }
895
+ /* static unit suffix inside a number field (e.g. a SliderField's compact numeric) */
896
+ .st-cp-numsuffix { flex: none; display: inline-flex; align-items: center; padding: 0 6px; color: var(--fg-2); font-family: var(--font-mono); font-size: 10px; border-left: 1px solid var(--border-subtle); background: var(--bg-2); }
897
+ /* compact numeric — the exact-value box paired with a Slider */
898
+ .st-cp-num--compact { flex: 0 0 auto; width: 64px; }
899
+ .st-cp-num--compact .st-cp-numin { text-align: right; }
900
+ /* SliderField row: real slider (flex) + compact numeric (fixed) */
901
+ .st-cp-sfield { flex: 1 1 auto; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
902
+ /* Toggle (immediate-effect boolean) */
903
+ .st-cp-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; cursor: pointer; color: var(--fg-1); }
904
+ .st-cp-toggle-lbl { color: var(--fg-1); }
905
+ /* handoff — Toggle is a real switch (not a checkbox), matching the DS .switch. */
906
+ .st-cp-switch { appearance: none; -webkit-appearance: none; position: relative; flex: none; width: 34px; height: 18px; border-radius: var(--radius-pill); background: var(--bg-4); border: 1px solid var(--border-default); cursor: pointer; transition: background var(--dur-flip) var(--ease-out), border-color var(--dur-flip) var(--ease-out); }
907
+ .st-cp-switch::after { content: ""; position: absolute; top: 1px; left: 1px; width: 14px; height: 14px; border-radius: var(--radius-pill); background: var(--fg-1); transition: transform var(--dur-flip) var(--ease-out), background var(--dur-flip) var(--ease-out); }
908
+ .st-cp-switch:checked { background: var(--accent); border-color: var(--accent); }
909
+ .st-cp-switch:checked::after { transform: translateX(16px); background: var(--accent-fg); }
910
+ .st-cp-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
911
+ /* inline help text under a Field control; wrapping a wide row keeps 3 controls fitting */
912
+ .st-cp-help { flex-basis: 100%; font-size: 10px; color: var(--fg-2); margin-top: 2px; }
913
+ .st-cp-row--wide { flex-wrap: wrap; }
914
+
915
+ /* ════ feature-inspector-controls-redesign — ported design controls ══════════
916
+ * The design-specimen control set promoted into the shared library
917
+ * (inspector-controls.jsx). lucide icons; `.st-cp-*` to match the shell. */
918
+
919
+ /* bipolar slider zero-tick */
920
+ .st-cp-zero { position: absolute; top: -3px; bottom: -3px; width: 1px; background: var(--border-strong); }
921
+ .st-cp-dial--scrub, body.st-scrubbing--dial, body.st-scrubbing--dial * { cursor: grabbing !important; }
922
+
923
+ /* icon button group (flex-direction / justify / align / text-align / overflow) */
924
+ .st-cp-iconseg { display: inline-flex; border: 1px solid var(--border-default); border-radius: var(--radius-sm); overflow: hidden; background: var(--bg-2); }
925
+ .st-cp-iconseg button { appearance: none; border: 0; background: transparent; color: var(--fg-2); min-width: 30px; height: 26px; display: grid; place-items: center; cursor: pointer; transition: background var(--dur-soft) var(--ease-out), color var(--dur-soft) var(--ease-out); }
926
+ .st-cp-iconseg button + button { border-left: 1px solid var(--border-subtle); }
927
+ .st-cp-iconseg button:hover:not(.is-active) { color: var(--fg-0); background: var(--bg-3); }
928
+ .st-cp-iconseg button.is-active { background: var(--bg-4); color: var(--fg-0); }
929
+ .st-cp-iconseg button[aria-pressed="true"] { background: var(--accent-tint); color: var(--accent); }
930
+
931
+ /* DS checkbox */
932
+ .st-cp-check { display: inline-flex; align-items: center; gap: var(--space-2); font-size: 11px; color: var(--fg-1); cursor: pointer; }
933
+ .st-cp-check input { position: absolute; opacity: 0; width: 0; height: 0; }
934
+ .st-cp-check-box { flex: none; width: 15px; height: 15px; border-radius: var(--radius-xs); border: 1px solid var(--border-strong); background: var(--bg-3); display: grid; place-items: center; color: transparent; transition: background var(--dur-soft) var(--ease-out), border-color var(--dur-soft) var(--ease-out); }
935
+ .st-cp-check input:checked + .st-cp-check-box { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
936
+ .st-cp-check input:focus-visible + .st-cp-check-box { box-shadow: 0 0 0 3px var(--accent-tint); }
937
+
938
+ /* 9-point alignment pad */
939
+ .st-cp-alignpad { width: 68px; height: 68px; display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr); border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); flex: none; }
940
+ .st-cp-alignpad button { appearance: none; border: 0; background: transparent; display: grid; place-items: center; cursor: pointer; }
941
+ .st-cp-alignpad button::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--fg-3); transition: background var(--dur-soft) var(--ease-out); }
942
+ .st-cp-alignpad button:hover::before { background: var(--fg-1); }
943
+ .st-cp-alignpad button.is-active::before { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
944
+
945
+ /* angle dial */
946
+ .st-cp-dial { flex: none; width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--border-default); background: var(--bg-3); position: relative; cursor: grab; touch-action: none; padding: 0; }
947
+ .st-cp-dial:active { cursor: grabbing; }
948
+ .st-cp-dial:hover { border-color: var(--border-strong); }
949
+ .st-cp-dial:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
950
+ .st-cp-dial-needle { position: absolute; top: 50%; left: 50%; width: 11px; height: 1.5px; background: var(--accent); border-radius: 1px; transform-origin: left center; transform: rotate(var(--angle, 0deg)); }
951
+ .st-cp-dial::after { content: ""; position: absolute; top: 50%; left: 50%; width: 4px; height: 4px; border-radius: 50%; background: var(--fg-1); transform: translate(-50%, -50%); }
952
+
953
+ /* collapsable section — height animation + caret rotation (on top of .st-cp-sec) */
954
+ .st-cp-sechd[aria-expanded="false"] .st-cp-caret { transform: rotate(-90deg); }
955
+ .st-cp-caret { transition: transform var(--dur-flip) var(--ease-out); display: inline-grid; place-items: center; }
956
+ .st-cp-sec-anim { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--dur-panel) var(--ease-in-out); }
957
+ .st-cp-sec-anim.is-open { grid-template-rows: 1fr; }
958
+ .st-cp-sec-inner { overflow: hidden; min-height: 0; }
959
+ .st-cp-sec-anim.is-open .st-cp-sec-inner { padding-top: var(--space-1); }
960
+
961
+ /* compact composite colour field — swatch flush prefix + divider, value [+alpha+eye] */
962
+ .st-cp-cf { display: flex; align-items: stretch; min-height: 26px; min-width: 0; flex: 1 1 auto; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out); }
963
+ .st-cp-cf:hover { border-color: var(--border-strong); }
964
+ /* handoff — accent frame ONLY when editing the value input, not when the swatch
965
+ * (popover trigger) has focus — clicking the swatch left a persistent blue frame. */
966
+ .st-cp-cf:has(.st-cp-cf-in:focus) { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
967
+ .st-cp-cf .st-cp-tokwrap { display: flex; align-items: stretch; }
968
+ .st-cp-cf > *:last-child { border-top-right-radius: 2px; border-bottom-right-radius: 2px; }
969
+ .st-cp-cf-sw { flex: none; width: 26px; border: 0; border-right: 1px solid var(--border-default); border-radius: 2px 0 0 2px; padding: 0; cursor: pointer; position: relative; overflow: hidden; }
970
+ .st-cp-cf-in { flex: 1 1 auto; min-width: 0; width: 100%; border: 0; background: transparent; color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); text-transform: uppercase; padding: 0 var(--space-2); }
971
+ .st-cp-cf-in.is-bound { color: var(--accent); text-transform: none; }
972
+ .st-cp-cf-in:focus { outline: none; }
973
+ .st-cp-cf-alpha { flex: none; width: 42px; border: 0; border-left: 1px solid var(--border-default); background: transparent; color: var(--fg-1); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); text-align: right; padding: 0 6px; }
974
+ .st-cp-cf-alpha:focus { outline: none; }
975
+ .st-cp-cf-eye { flex: none; width: 26px; border: 0; border-left: 1px solid var(--border-default); background: transparent; color: var(--fg-2); cursor: pointer; display: grid; place-items: center; }
976
+ .st-cp-cf-eye:hover { color: var(--fg-0); background: var(--bg-2); }
977
+ .st-cp-cf-eye.is-off { color: var(--fg-3); }
978
+
979
+ /* value-token binding (◇ + bound chip) */
980
+ .st-cp-tokfield { display: flex; align-items: center; gap: var(--space-2); flex: 1 1 auto; min-width: 0; }
981
+ .st-cp-tokfield > .st-cp-num, .st-cp-tokfield > .st-cp-boundchip { flex: 1 1 auto; min-width: 0; }
982
+ .st-cp-tokbtn { flex: none; width: 24px; height: 24px; display: grid; place-items: center; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-2); color: var(--fg-2); cursor: pointer; position: relative; }
983
+ .st-cp-tokbtn:hover { border-color: var(--border-strong); color: var(--fg-0); }
984
+ .st-cp-tokbtn.is-bound { border-color: var(--accent); color: var(--accent); background: var(--accent-tint); }
985
+ .st-cp-boundchip { display: flex; align-items: center; gap: var(--space-2); min-height: 26px; border: 1px solid var(--accent-muted); border-radius: var(--radius-xs); background: var(--accent-tint); padding: 0 var(--space-2); }
986
+ .st-cp-boundchip-lead { display: inline-grid; place-items: center; color: var(--accent); }
987
+ .st-cp-boundchip-name { flex: 1 1 auto; min-width: 0; font-family: var(--font-mono); font-size: var(--type-xs); color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
988
+ .st-cp-boundchip-x { flex: none; appearance: none; border: 0; background: transparent; color: var(--accent); cursor: pointer; display: grid; place-items: center; padding: 0 2px; }
989
+ .st-cp-boundchip-x:hover { color: var(--fg-0); }
990
+
991
+ /* corner-radius control — uniform field + detach quad with per-corner glyphs */
992
+ .st-cp-radius { display: grid; gap: var(--space-2); flex: 1 1 auto; min-width: 0; }
993
+ .st-cp-radius-main { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
994
+ .st-cp-radius-main > .st-cp-num { flex: 1 1 auto; min-width: 0; }
995
+ .st-cp-splitbtn { flex: none; width: 24px; height: 24px; display: grid; place-items: center; border: 1px solid transparent; border-radius: var(--radius-xs); background: transparent; color: var(--fg-2); cursor: pointer; }
996
+ .st-cp-splitbtn:hover { color: var(--fg-0); background: var(--bg-3); }
997
+ .st-cp-splitbtn.is-on { color: var(--accent); border-color: var(--accent-muted); background: var(--accent-tint); }
998
+ .st-cp-corners { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); }
999
+ .st-cp-corner { display: flex; align-items: center; gap: 6px; min-height: 26px; background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 0 8px; }
1000
+ .st-cp-corner:hover { border-color: var(--border-strong); }
1001
+ .st-cp-corner:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
1002
+ .st-cp-corner 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; }
1003
+ .st-cp-corner input:focus { outline: none; }
1004
+ .st-cp-cnr { flex: none; width: 11px; height: 11px; border: 1.5px solid var(--fg-2); box-sizing: border-box; }
1005
+ .st-cp-cnr--tl { border-right: 0; border-bottom: 0; border-top-left-radius: 4px; }
1006
+ .st-cp-cnr--tr { border-left: 0; border-bottom: 0; border-top-right-radius: 4px; }
1007
+ .st-cp-cnr--bl { border-right: 0; border-top: 0; border-bottom-left-radius: 4px; }
1008
+ .st-cp-cnr--br { border-left: 0; border-top: 0; border-bottom-right-radius: 4px; }
1009
+
720
1010
  /* select (font-weight, border-style) */
721
1011
  .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; }
722
1012
  .st-cp-select span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -746,9 +1036,12 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
746
1036
  .st-cp-bars--just i { width: 100%; }
747
1037
 
748
1038
  /* nested box-model widget (Webflow-style): margin outer · padding inner */
749
- .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; }
750
- .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; }
751
- .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; }
1039
+ .st-cp-box { position: relative; margin-top: var(--space-2); padding: 34px 30px; border: 1px dashed var(--border-default); border-radius: var(--radius-sm); background: var(--bg-2); display: grid; place-items: center; }
1040
+ .st-cp-boxpad { position: relative; width: 100%; padding: 30px 26px; border: 1px dashed var(--border-subtle); border-radius: var(--radius-xs); background: var(--bg-1); display: grid; place-items: center; }
1041
+ /* handoff spacing size core is PLAIN mono text (no box/border), 1:1 with the
1042
+ * design's .icp-box-core. Only the position core (--pos, below) is an accent bar. */
1043
+ .st-cp-boxcore { min-width: 72px; padding: 10px 16px; background: transparent; border: 0; color: var(--fg-2); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 10px; text-align: center; }
1044
+ .st-cp-boxcore--pos { padding: 7px 12px; border-radius: var(--radius-xs); font-size: 11px; }
752
1045
  .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; }
753
1046
  .st-cp-boxtag .st-cp-prov { width: 6px; height: 6px; }
754
1047
  .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; }
@@ -766,27 +1059,33 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
766
1059
  .st-cp-boxv--il { left: 0; top: 50%; transform: translateY(-50%); }
767
1060
  .st-cp-boxv--ir { right: 0; top: 50%; transform: translateY(-50%); }
768
1061
  .st-cp-boxtag--i { color: var(--accent); }
769
- .st-cp-boxcore--pos { text-transform: none; letter-spacing: 0; }
1062
+ /* handoff position core IS an accent bar (design); spacing core is plain text */
1063
+ .st-cp-boxcore--pos { text-transform: none; letter-spacing: 0; background: var(--accent-tint); border: 1px solid var(--accent); color: var(--accent); }
770
1064
  .st-cp-boxhint { display: flex; flex-wrap: wrap; gap: var(--space-1); }
771
1065
  .st-cp-boxhint + .st-cp-row { margin-top: var(--space-1); }
772
1066
  .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; }
773
1067
 
774
1068
  /* opacity slider — role=slider, focusable */
775
1069
  .st-cp-slider { flex: 1 1 auto; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
776
- .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; }
1070
+ .st-cp-track { position: relative; flex: 1 1 auto; height: 6px; border-radius: 3px; background: var(--bg-2); border: 1px solid var(--border-default); cursor: pointer; }
777
1071
  .st-cp-track:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
778
1072
  .st-cp-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; background: var(--accent); }
779
1073
  .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%); }
780
1074
  .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; }
781
1075
 
782
1076
  /* border cluster — fills to the right control rail */
783
- .st-cp-border { flex: 1 1 auto; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
1077
+ .st-cp-border { flex: 1 1 auto; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); min-width: 0; }
784
1078
  .st-cp-border .st-cp-swatch--mini { margin-left: 0; }
785
1079
  /* design-critic 1.1 — the border row was cramming width+style+swatch; the
786
1080
  * width field was eating the flex and clipping the style select to "styl▾".
787
- * Fix the width field, let the style select take the rest. */
1081
+ * Fix the width field, let the style select take the rest. Task 5 (feature-
1082
+ * inspector-controls-redesign) — border-width now skips its unit-select
1083
+ * (px-only, opts.fixedUnit) so the cluster is narrower to start with;
1084
+ * flex-wrap is the fallback so [width][style][swatch] never clips at the
1085
+ * panel's 260px minimum — the style select wraps to its own line rather than
1086
+ * shrinking to an illegible sliver. */
788
1087
  .st-cp-border .st-cp-num { flex: 0 0 58px; }
789
- .st-cp-border .st-cp-nsel { flex: 1 1 auto; max-width: none; }
1088
+ .st-cp-border .st-cp-nsel { flex: 1 1 96px; max-width: none; min-width: 64px; }
790
1089
 
791
1090
  /* per-field save state */
792
1091
  /* #5 — error-only now (idle/saved status moved into each row's leading dot). */
@@ -815,11 +1114,26 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
815
1114
 
816
1115
  /* Stage M — Fixed / Hug / Fill sizing-mode segmented control (per axis). */
817
1116
  .st-cp-modes { display: flex; flex-direction: column; gap: var(--space-1); margin-bottom: var(--space-1); }
818
- .st-cp-modeseg { display: flex; align-items: stretch; gap: var(--space-1); }
819
- .st-cp-modeax { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); }
820
- .st-cp-modebtn { flex: 1; appearance: none; cursor: pointer; border: 1px solid var(--border-default); background: var(--bg-3); color: var(--fg-1); font-family: var(--font-mono); font-size: 10px; min-height: 22px; border-radius: var(--radius-xs); padding: 0 var(--space-1); }
821
- .st-cp-modebtn:hover:not(.is-active):not(:disabled) { background: var(--bg-4); color: var(--fg-0); }
822
- .st-cp-modebtn.is-active { background: var(--accent-tint); border-color: var(--accent); color: var(--accent); }
1117
+ /* handoff Fixed/Hug/Fill uses the shared Segmented (.st-cp-seg) component,
1118
+ * stretched full-width, with a leading W/H axis label. */
1119
+ .st-cp-modeseg { display: flex; align-items: center; gap: var(--space-2); }
1120
+ .st-cp-modeax { display: inline-flex; align-items: center; justify-content: center; min-width: 14px; font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); }
1121
+ /* handoff — Size mode row: grid-aligned with the other rows (label column +
1122
+ * control column), the compact Segmented right-aligned to match the number
1123
+ * inputs below, at the same 26px input height. Neutral active, mono lowercase. */
1124
+ .st-cp-moderow { display: grid; grid-template-columns: 14px 92px 1fr; align-items: center; column-gap: var(--space-3); min-height: 32px; padding: 3px 0; }
1125
+ .st-cp-modelabel { grid-column: 2; font-size: var(--type-xs); color: var(--fg-1); }
1126
+ .st-cp-modeseg { grid-column: 3; display: flex; justify-content: flex-end; }
1127
+ .st-cp-modeseg .st-cp-seg { flex: none; display: inline-flex; height: 26px; background: var(--bg-2); border-radius: var(--radius-sm); }
1128
+ .st-cp-modeseg .st-cp-segbtn { flex: none; display: inline-flex; align-items: center; font-family: var(--font-mono); font-size: var(--type-xs); text-transform: lowercase; color: var(--fg-2); min-width: 0; min-height: 0; padding: 0 var(--space-4); }
1129
+ .st-cp-modeseg .st-cp-segbtn.is-active { background: var(--bg-4); color: var(--fg-0); }
1130
+ .st-cp-modeseg .st-cp-segbtn:hover:not(.is-active) { background: var(--bg-3); color: var(--fg-0); }
1131
+ /* .st-cp-modebtn — still used by the artboard height-sizing control (not CssKnobs). */
1132
+ .st-cp-modebtn { flex: 1; appearance: none; cursor: pointer; border: 1px solid var(--border-default); border-left-width: 0; background: var(--bg-2); color: var(--fg-2); font-family: var(--font-mono); font-size: 10px; text-transform: lowercase; min-height: 24px; padding: 0 var(--space-2); }
1133
+ .st-cp-modebtn:first-of-type { border-left-width: 1px; border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
1134
+ .st-cp-modebtn:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
1135
+ .st-cp-modebtn:hover:not(.is-active):not(:disabled) { background: var(--bg-3); color: var(--fg-0); }
1136
+ .st-cp-modebtn.is-active { background: var(--bg-4); color: var(--fg-0); }
823
1137
  .st-cp-modebtn:disabled { opacity: 0.5; cursor: default; }
824
1138
  /* Stage M — sub-header for the flex-child row group + the make-flex CTA. */
825
1139
  .st-cp-subhd { font-family: var(--font-mono); font-size: 10px; color: var(--fg-2); text-transform: uppercase; letter-spacing: 0.04em; margin-top: var(--space-2); }
@@ -897,6 +1211,17 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
897
1211
  * hue slider + eyedropper + hex field. The swatch on the colour row is the only
898
1212
  * trigger (no separate native picker). */
899
1213
  .st-cp-cpick { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-1); }
1214
+ /* handoff — hex row on top + preview circle + RGB fields (design parity) */
1215
+ .st-cp-cpick-hexrow { display: flex; align-items: center; gap: var(--space-2); }
1216
+ .st-cp-cpick-hexsw { flex: none; width: 34px; height: 26px; border-radius: var(--radius-xs); border: 1px solid var(--border-default); }
1217
+ .st-cp-cpick-hex { flex: 1 1 auto; min-width: 0; appearance: none; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); color: var(--fg-0); font-family: var(--font-mono); font-size: var(--type-xs); padding: 4px var(--space-2); }
1218
+ .st-cp-cpick-hex:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
1219
+ .st-cp-cpick-preview { flex: none; width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--border-default); }
1220
+ .st-cp-cpick-rgb { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); }
1221
+ .st-cp-cpick-rgbf { display: grid; gap: 2px; justify-items: center; }
1222
+ .st-cp-cpick-rgbf input { width: 100%; text-align: center; appearance: none; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-3); color: var(--fg-0); font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--type-xs); padding: 3px 2px; }
1223
+ .st-cp-cpick-rgbf input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
1224
+ .st-cp-cpick-rgbf span { font-family: var(--font-mono); font-size: 9px; color: var(--fg-3); }
900
1225
  .st-cp-swatch--trigger { position: relative; overflow: hidden; cursor: pointer; appearance: none; padding: 0; }
901
1226
  .st-cp-swatch--trigger.is-bound { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); }
902
1227
  .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; }
@@ -1784,6 +2109,9 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
1784
2109
  .ob-eyebrow { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--accent); }
1785
2110
  .ob-head h1 { margin: 0; font-family: var(--font-display); font-size: var(--type-3xl); line-height: var(--lh-2xl); font-weight: 600; letter-spacing: var(--tracking-tight); }
1786
2111
  .ob-head p { margin: 0; max-width: 56ch; color: var(--fg-2); font-size: var(--type-md); line-height: var(--lh-lg); }
2112
+ .ob-watch-intro { align-self: flex-start; display: inline-flex; align-items: center; gap: var(--space-2); margin-top: var(--space-1); padding: var(--space-2) var(--space-3); border: 1px solid var(--border-default); border-radius: var(--radius-pill); background: var(--bg-1); color: var(--fg-1); font-size: var(--type-sm); cursor: pointer; }
2113
+ .ob-watch-intro:hover { border-color: var(--border-strong); color: var(--fg-0); background: var(--bg-2); }
2114
+ .ob-watch-intro:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1787
2115
 
1788
2116
  .ob-doors { display: flex; flex-direction: column; gap: var(--space-4); max-width: 720px; }
1789
2117
  .ob-door { position: relative; display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-4); width: 100%; text-align: left; padding: var(--space-5); border: 1px solid var(--border-default); border-radius: var(--radius-lg); background: var(--bg-1); color: inherit; cursor: pointer; transition: border-color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out), transform var(--dur-soft) var(--ease-out); }
@@ -1887,6 +2215,25 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
1887
2215
  box-shadow: 0 -10px 18px -12px color-mix(in oklab, var(--bg-0) 80%, transparent);
1888
2216
  }
1889
2217
  .rb-dock { position: relative; }
2218
+ /* Proactive "remote has updates" nudge — a full-width primary button above the dock
2219
+ trigger, shown when the tracking remote is ahead (status.remoteAhead). */
2220
+ .rb-getlatest { width: 100%; justify-content: flex-start; gap: var(--space-2); animation: rb-getlatest-in var(--dur-soft, 160ms) var(--ease-out, ease-out); }
2221
+ .rb-getlatest-tx { flex: 0 0 auto; }
2222
+ .rb-getlatest-sub { margin-left: auto; font-weight: 500; opacity: 0.9; font-size: var(--type-xs); white-space: nowrap; }
2223
+ @keyframes rb-getlatest-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
2224
+ @media (prefers-reduced-motion: reduce) { .rb-getlatest, .rb-resume { animation: none; } }
2225
+ /* "Continue on <draft>" resume nudge — a subtle secondary row (not the primary blue),
2226
+ shown above the dock trigger when you're on the Shared version but have a draft. */
2227
+ .rb-resume { display: flex; align-items: center; gap: var(--space-1); width: 100%; animation: rb-getlatest-in var(--dur-soft, 160ms) var(--ease-out, ease-out); }
2228
+ .rb-resume-go { flex: 1 1 auto; display: flex; align-items: center; gap: var(--space-2); min-width: 0; text-align: left; padding: var(--space-2) var(--space-3); border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-2); color: var(--fg-1); cursor: pointer; font-size: var(--type-sm); transition: border-color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out); }
2229
+ .rb-resume-go:hover { border-color: var(--border-strong); background: var(--bg-3); }
2230
+ .rb-resume-go:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
2231
+ .rb-resume-icon { color: var(--status-warn); flex: 0 0 auto; display: grid; place-items: center; }
2232
+ .rb-resume-tx { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2233
+ .rb-resume-arrow { color: var(--fg-3); flex: 0 0 auto; }
2234
+ .rb-resume-x { flex: 0 0 auto; display: grid; place-items: center; width: 28px; height: 28px; border: none; border-radius: var(--radius-md); background: transparent; color: var(--fg-3); cursor: pointer; }
2235
+ .rb-resume-x:hover { background: var(--bg-3); color: var(--fg-1); }
2236
+ .rb-resume-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1890
2237
  /* The compact one-line trigger — "📁 <project> · ◐ <version> ⌃" */
1891
2238
  .rb-trigger {
1892
2239
  display: flex; align-items: center; gap: var(--space-2);
@@ -1983,6 +2330,7 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
1983
2330
  .rb-sheet-body { margin: 0; color: var(--fg-1); font-size: var(--type-md); line-height: var(--lh-md); }
1984
2331
  .rb-sheet-body b { color: var(--fg-0); font-weight: 600; }
1985
2332
  .rb-sheet-meta { margin: 0; color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-md); }
2333
+ .rb-pr-url { font-family: var(--font-mono, ui-monospace, monospace); font-size: var(--type-xs); word-break: break-all; user-select: all; opacity: 0.8; }
1986
2334
  .rb-sheet-actions { display: flex; gap: var(--space-2); justify-content: flex-end; margin-top: var(--space-2); }
1987
2335
  @media (prefers-reduced-motion: reduce) {
1988
2336
  .rb-spin { animation-duration: 1ms; }