@jxsuite/studio 2.0.0 → 2.1.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 (419) hide show
  1. package/canvas.html +21 -0
  2. package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
  3. package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
  4. package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
  5. package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
  6. package/dist/chunks/{components-0hzentwq.js → components-2bpqp4mq.js} +5 -7
  7. package/dist/chunks/{components-0hzentwq.js.map → components-2bpqp4mq.js.map} +1 -1
  8. package/dist/chunks/content-source-34gnkbnn.js +38 -0
  9. package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
  10. package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
  11. package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
  12. package/dist/chunks/extension-sections-6mqydz35.js +301 -0
  13. package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
  14. package/dist/chunks/files-8kn321h1.js +70 -0
  15. package/dist/chunks/files-8kn321h1.js.map +9 -0
  16. package/dist/chunks/{format-host-2c188n41.js → format-host-mkwsmt8d.js} +3 -3
  17. package/dist/chunks/git-panel-tjbr191d.js +51 -0
  18. package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
  19. package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
  20. package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
  21. package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
  22. package/dist/chunks/layers-panel-87pb25km.js +58 -0
  23. package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
  24. package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
  25. package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
  26. package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
  27. package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
  28. package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
  29. package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
  30. package/dist/chunks/right-panel-zpdxd98t.js +37 -0
  31. package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
  32. package/dist/chunks/section-registry-zmckaxf4.js +30 -0
  33. package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
  34. package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
  35. package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
  36. package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
  37. package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
  38. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
  39. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
  40. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
  41. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
  42. package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
  43. package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
  44. package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
  45. package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
  46. package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
  47. package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
  48. package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
  49. package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
  50. package/dist/chunks/studio-41exgzhq.js +6690 -0
  51. package/dist/chunks/studio-41exgzhq.js.map +38 -0
  52. package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
  53. package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
  54. package/dist/chunks/studio-50k77cca.js +1787 -0
  55. package/dist/chunks/studio-50k77cca.js.map +18 -0
  56. package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
  57. package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
  58. package/dist/chunks/studio-6f0am8f2.js +53 -0
  59. package/dist/chunks/studio-6f0am8f2.js.map +10 -0
  60. package/dist/chunks/studio-6nmjc5qk.js +7002 -0
  61. package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
  62. package/dist/chunks/studio-7afd21nw.js +67 -0
  63. package/dist/chunks/studio-7afd21nw.js.map +10 -0
  64. package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
  65. package/dist/chunks/studio-7bmdvzne.js.map +10 -0
  66. package/dist/chunks/studio-8jpzqk5s.js +128 -0
  67. package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
  68. package/dist/chunks/studio-94m77tgk.js +1482 -0
  69. package/dist/chunks/studio-94m77tgk.js.map +13 -0
  70. package/dist/chunks/studio-9je6w5sq.js +1000 -0
  71. package/dist/chunks/studio-9je6w5sq.js.map +16 -0
  72. package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
  73. package/dist/chunks/{studio-97qcgvdn.js → studio-adn0z1k3.js} +14 -8
  74. package/dist/chunks/{studio-97qcgvdn.js.map → studio-adn0z1k3.js.map} +3 -3
  75. package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
  76. package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
  77. package/dist/chunks/studio-bw5dz6km.js +608 -0
  78. package/dist/chunks/studio-bw5dz6km.js.map +21 -0
  79. package/dist/chunks/studio-c6s5getc.js +4232 -0
  80. package/dist/chunks/studio-c6s5getc.js.map +39 -0
  81. package/dist/chunks/studio-cjm7fdjf.js +451 -0
  82. package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
  83. package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
  84. package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
  85. package/dist/chunks/studio-dg7zyt5x.js +28 -0
  86. package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
  87. package/dist/chunks/studio-dzcyvvvz.js +166 -0
  88. package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
  89. package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
  90. package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
  91. package/dist/chunks/studio-f12h6177.js +411 -0
  92. package/dist/chunks/studio-f12h6177.js.map +13 -0
  93. package/dist/chunks/studio-hbp1s8m9.js +1817 -0
  94. package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
  95. package/dist/chunks/studio-k2sxjph5.js +15295 -0
  96. package/dist/chunks/studio-k2sxjph5.js.map +235 -0
  97. package/dist/chunks/studio-myje51t3.js +385 -0
  98. package/dist/chunks/studio-myje51t3.js.map +12 -0
  99. package/dist/chunks/studio-na6rwzhw.js +353 -0
  100. package/dist/chunks/studio-na6rwzhw.js.map +11 -0
  101. package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
  102. package/dist/chunks/studio-p471gg5n.js.map +14 -0
  103. package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
  104. package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
  105. package/dist/chunks/{studio-hhj92gcr.js → studio-s519zc99.js} +3 -3
  106. package/dist/chunks/studio-sas7mt3k.js +75 -0
  107. package/dist/chunks/studio-sas7mt3k.js.map +10 -0
  108. package/dist/chunks/studio-t5wqwzdh.js +74 -0
  109. package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
  110. package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
  111. package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
  112. package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
  113. package/dist/chunks/studio-tr20m8g8.js.map +9 -0
  114. package/dist/chunks/{studio-ygzav7z5.js → studio-v96qfnww.js} +5514 -4291
  115. package/dist/chunks/studio-v96qfnww.js.map +54 -0
  116. package/dist/chunks/studio-vcetc91k.js +659 -0
  117. package/dist/chunks/studio-vcetc91k.js.map +10 -0
  118. package/dist/chunks/{studio-n9zmpxjg.js → studio-vmymjefp.js} +2972 -4937
  119. package/dist/chunks/studio-vmymjefp.js.map +98 -0
  120. package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
  121. package/dist/chunks/studio-x9hmy5kr.js +390 -0
  122. package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
  123. package/dist/chunks/studio-xa0ce0n7.js +335 -0
  124. package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
  125. package/dist/chunks/studio-xm3dbxvn.js +378 -0
  126. package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
  127. package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
  128. package/dist/chunks/studio-zv37yrfa.js +1054 -0
  129. package/dist/chunks/studio-zv37yrfa.js.map +13 -0
  130. package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
  131. package/dist/chunks/ws-client-654ts66j.js.map +11 -0
  132. package/dist/iframe-entry.js +668 -230
  133. package/dist/studio.js +23711 -35185
  134. package/index.html +35 -4685
  135. package/package.json +17 -15
  136. package/src/about/about-modal.ts +42 -11
  137. package/src/browse/library-commands.ts +240 -0
  138. package/src/browse/library-layouts.ts +369 -0
  139. package/src/browse/library-model.ts +396 -0
  140. package/src/browse/library-pane.ts +1049 -0
  141. package/src/browse/library-preview.ts +252 -0
  142. package/src/browse/library-source.ts +150 -0
  143. package/src/canvas/canvas-helpers.ts +33 -9
  144. package/src/canvas/canvas-live-render.ts +45 -29
  145. package/src/canvas/canvas-patcher.ts +151 -31
  146. package/src/canvas/canvas-perf.ts +46 -7
  147. package/src/canvas/canvas-render.ts +1092 -220
  148. package/src/canvas/canvas-surface.ts +240 -0
  149. package/src/canvas/canvas-utils.ts +1166 -124
  150. package/src/canvas/iframe-drop.ts +2 -1
  151. package/src/canvas/iframe-entry.ts +241 -4
  152. package/src/canvas/iframe-host.ts +1226 -143
  153. package/src/canvas/iframe-inline-edit.ts +31 -0
  154. package/src/canvas/iframe-interaction.ts +76 -16
  155. package/src/canvas/iframe-keys.ts +107 -45
  156. package/src/canvas/iframe-overlay.ts +38 -1
  157. package/src/canvas/iframe-protocol.ts +137 -2
  158. package/src/canvas/iframe-render.ts +70 -2
  159. package/src/canvas/iframe-slash.ts +6 -0
  160. package/src/canvas/path-mapping.ts +56 -6
  161. package/src/canvas/surface-registry.ts +292 -0
  162. package/src/collab/collab-commands.ts +244 -0
  163. package/src/collab/collab-session.ts +198 -32
  164. package/src/collab/collab-state.ts +28 -2
  165. package/src/collab/presence-chips.ts +100 -9
  166. package/src/commands/active-registry.ts +42 -0
  167. package/src/commands/app-commands.ts +176 -0
  168. package/src/commands/budget.ts +158 -0
  169. package/src/commands/command-args.ts +253 -0
  170. package/src/commands/context.ts +387 -0
  171. package/src/commands/defaults.ts +580 -0
  172. package/src/commands/keymap.ts +571 -0
  173. package/src/commands/levels.ts +345 -0
  174. package/src/commands/live-context.ts +193 -0
  175. package/src/commands/reference.ts +227 -0
  176. package/src/commands/registry.ts +293 -0
  177. package/src/component-props.ts +3 -2
  178. package/src/content/draft-state.ts +106 -0
  179. package/src/content/entry-commands.ts +282 -0
  180. package/src/content/entry-editor.ts +327 -0
  181. package/src/content/entry-fields.ts +116 -0
  182. package/src/content/entry-model.ts +175 -0
  183. package/src/editor/canvas-context-menu.ts +17 -11
  184. package/src/editor/canvas-slash-bridge.ts +11 -4
  185. package/src/editor/context-menu.ts +804 -204
  186. package/src/editor/convert-to-component.ts +31 -10
  187. package/src/editor/convert-to-repeater.ts +3 -2
  188. package/src/editor/inline-edit-apply.ts +5 -5
  189. package/src/editor/inline-edit.ts +86 -50
  190. package/src/editor/insert-zone-action.ts +1 -1
  191. package/src/editor/shortcuts.ts +1043 -329
  192. package/src/editor/slash-menu.ts +1 -0
  193. package/src/files/elements.ts +166 -0
  194. package/src/files/file-ops.ts +178 -31
  195. package/src/files/files.ts +898 -268
  196. package/src/files/fs-events.ts +21 -0
  197. package/src/files/media-meta.ts +203 -0
  198. package/src/files/media-paths.ts +141 -0
  199. package/src/files/media-upload.ts +7 -3
  200. package/src/files/media-usage.ts +189 -0
  201. package/src/github/github-auth.ts +235 -33
  202. package/src/github/github-publish.ts +80 -21
  203. package/src/grid/grid-controller.ts +152 -12
  204. package/src/grid/grid-layout.ts +225 -20
  205. package/src/grid/grid-open.ts +120 -0
  206. package/src/grid/grid-panel.ts +554 -39
  207. package/src/grid/grid-source.ts +27 -1
  208. package/src/grid/redirects-grid.ts +599 -0
  209. package/src/grid/redirects.ts +398 -0
  210. package/src/grid/sources/content-source.ts +108 -2
  211. package/src/i18n/i18n-commands.ts +322 -0
  212. package/src/new-project/add-repo-modal.ts +8 -10
  213. package/src/new-project/import-tab.ts +34 -9
  214. package/src/new-project/location-fields.ts +9 -1
  215. package/src/new-project/new-project-modal.ts +270 -262
  216. package/src/packages/jxsuite-update.ts +97 -48
  217. package/src/packages/pull-package-sync.ts +18 -9
  218. package/src/page-params.ts +2 -1
  219. package/src/panels/activity-bar.ts +152 -91
  220. package/src/panels/activity-panel.ts +481 -0
  221. package/src/panels/ai-chat/chat-markdown.ts +8 -3
  222. package/src/panels/ai-chat/chat-view.ts +245 -18
  223. package/src/panels/ai-chat/composer.ts +31 -5
  224. package/src/panels/ai-chat/sessions-view.ts +17 -10
  225. package/src/panels/ai-panel.ts +279 -120
  226. package/src/panels/block-action-bar.ts +1115 -224
  227. package/src/panels/bottom-dock.ts +337 -0
  228. package/src/panels/canvas-dnd-bridge.ts +37 -8
  229. package/src/panels/chat-panel.ts +29 -12
  230. package/src/panels/data-explorer.ts +254 -112
  231. package/src/panels/data-grid.ts +10 -4
  232. package/src/panels/dnd.ts +28 -51
  233. package/src/panels/editors.ts +434 -107
  234. package/src/panels/elements-panel.ts +66 -2
  235. package/src/panels/empty-state.ts +112 -0
  236. package/src/panels/events-panel.ts +596 -82
  237. package/src/panels/formula-workspace.ts +408 -218
  238. package/src/panels/frontmatter-fields.ts +51 -10
  239. package/src/panels/frontmatter-panel.ts +357 -79
  240. package/src/panels/git-panel.ts +375 -164
  241. package/src/panels/head-panel.ts +791 -85
  242. package/src/panels/i18n-panel.ts +592 -0
  243. package/src/panels/imports-panel.ts +95 -85
  244. package/src/panels/jump-bar.ts +584 -0
  245. package/src/panels/layers-panel.ts +1106 -328
  246. package/src/panels/left-panel.ts +109 -204
  247. package/src/panels/navigator-panels.ts +131 -0
  248. package/src/panels/overlays.ts +7 -2
  249. package/src/panels/pane-context.ts +1477 -0
  250. package/src/panels/pane-grid.ts +406 -0
  251. package/src/panels/panel-registry.ts +340 -0
  252. package/src/panels/panel-scheduler.ts +75 -0
  253. package/src/panels/problems-panel.ts +234 -0
  254. package/src/panels/properties-panel.ts +946 -1139
  255. package/src/panels/provenance.ts +258 -0
  256. package/src/panels/quick-search.ts +791 -122
  257. package/src/panels/right-panel.ts +228 -102
  258. package/src/panels/seo-modal.ts +395 -0
  259. package/src/panels/settings-pane.ts +203 -0
  260. package/src/panels/signals-panel.ts +354 -137
  261. package/src/panels/statement-editor.ts +41 -25
  262. package/src/panels/statusbar.ts +342 -106
  263. package/src/panels/style-panel.ts +974 -463
  264. package/src/panels/style-utils.ts +3 -3
  265. package/src/panels/stylebook-doc.ts +4 -2
  266. package/src/panels/stylebook-layers-panel.ts +3 -2
  267. package/src/panels/stylebook-panel.ts +51 -26
  268. package/src/panels/tab-strip.ts +1058 -78
  269. package/src/panels/target-line.ts +274 -0
  270. package/src/panels/toolbar.ts +631 -484
  271. package/src/panels/welcome-screen.ts +301 -198
  272. package/src/platform-errors.ts +26 -3
  273. package/src/platform.ts +96 -2
  274. package/src/platforms/cloud.ts +71 -8
  275. package/src/platforms/devserver.ts +92 -29
  276. package/src/publish/deploy-checklist.ts +383 -0
  277. package/src/publish/pages-service.ts +10 -1
  278. package/src/publish/publish-commands.ts +218 -0
  279. package/src/publish/publish-panel.ts +110 -16
  280. package/src/recent-projects.ts +3 -2
  281. package/src/services/a11y-report.ts +505 -0
  282. package/src/services/ai-models.ts +75 -2
  283. package/src/services/ai-project-tools.ts +29 -10
  284. package/src/services/ai-system-prompt.ts +53 -14
  285. package/src/services/ai-tools.ts +39 -3
  286. package/src/services/ai-writes.ts +154 -0
  287. package/src/services/announce.ts +97 -0
  288. package/src/services/automation.ts +424 -175
  289. package/src/services/cem-export.ts +9 -4
  290. package/src/services/clock.ts +61 -0
  291. package/src/services/document-assistant.ts +36 -8
  292. package/src/services/idle.ts +179 -0
  293. package/src/services/import-client.ts +26 -0
  294. package/src/services/monaco-buffer.ts +627 -0
  295. package/src/services/monaco-lazy.ts +36 -0
  296. package/src/services/notify.ts +271 -0
  297. package/src/services/profile.ts +155 -0
  298. package/src/services/references.ts +0 -0
  299. package/src/services/token-lint.ts +3 -2
  300. package/src/services/tool-executor.ts +53 -7
  301. package/src/services/trusted-types.ts +123 -0
  302. package/src/settings/contexts-section.ts +427 -0
  303. package/src/settings/contributed-section.ts +149 -11
  304. package/src/settings/css-vars-editor.ts +306 -349
  305. package/src/settings/defs-editor.ts +93 -34
  306. package/src/settings/dependencies-editor.ts +7 -7
  307. package/src/settings/extension-sections.ts +37 -5
  308. package/src/settings/general-settings.ts +204 -121
  309. package/src/settings/locales-section.ts +347 -0
  310. package/src/settings/preferences-accounts.ts +140 -0
  311. package/src/settings/preferences-dialog.ts +620 -0
  312. package/src/settings/preferences-keymap.ts +270 -0
  313. package/src/settings/project-sections.ts +260 -0
  314. package/src/settings/section-registry.ts +169 -0
  315. package/src/settings/settings-document.ts +385 -0
  316. package/src/shell.ts +1549 -0
  317. package/src/site-context.ts +45 -20
  318. package/src/state.ts +14 -275
  319. package/src/store.ts +88 -43
  320. package/src/studio.ts +790 -346
  321. package/src/style/live-preview.ts +36 -0
  322. package/src/style/project-styles.ts +349 -0
  323. package/src/style/token-ref.ts +123 -0
  324. package/src/tabs/patch-ops.ts +16 -4
  325. package/src/tabs/project-config.ts +416 -0
  326. package/src/tabs/selection.ts +323 -0
  327. package/src/tabs/tab.ts +182 -47
  328. package/src/tabs/transact.ts +209 -28
  329. package/src/types.ts +68 -13
  330. package/src/ui/ai-credentials-form.ts +39 -35
  331. package/src/ui/ai-managed-connect.ts +113 -0
  332. package/src/ui/dynamic-slot.ts +224 -81
  333. package/src/ui/expression-editor.ts +71 -63
  334. package/src/ui/field-input.ts +4 -6
  335. package/src/ui/field-row.ts +215 -38
  336. package/src/ui/form-controls.ts +194 -7
  337. package/src/ui/layers.ts +492 -69
  338. package/src/ui/media-picker.ts +115 -25
  339. package/src/ui/panel-resize.ts +109 -91
  340. package/src/ui/progress-modal.ts +131 -50
  341. package/src/ui/regions.ts +462 -0
  342. package/src/ui/schema-form.ts +229 -45
  343. package/src/ui/spectrum.ts +24 -8
  344. package/src/ui/timing.ts +49 -0
  345. package/src/ui/value-selector.ts +20 -0
  346. package/src/ui/value-source.ts +348 -0
  347. package/src/ui/virtual-window.ts +400 -0
  348. package/src/utils/edit-display.ts +3 -2
  349. package/src/utils/inherited-style.ts +67 -37
  350. package/src/view.ts +64 -78
  351. package/src/workspace/pane-derive.ts +1258 -0
  352. package/src/workspace/session.ts +317 -0
  353. package/src/workspace/workspace.ts +1345 -23
  354. package/styles/canvas.css +653 -0
  355. package/styles/forced-colors.css +106 -0
  356. package/styles/inspector.css +1454 -0
  357. package/styles/overlays.css +2704 -0
  358. package/styles/panels.css +1701 -0
  359. package/styles/shell.css +1423 -0
  360. package/styles/tokens.css +151 -0
  361. package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
  362. package/dist/chunks/extension-sections-qct0gt8f.js +0 -531
  363. package/dist/chunks/extension-sections-qct0gt8f.js.map +0 -12
  364. package/dist/chunks/files-02zn5y24.js +0 -50
  365. package/dist/chunks/files-02zn5y24.js.map +0 -9
  366. package/dist/chunks/git-panel-mbb0y0hz.js +0 -28
  367. package/dist/chunks/git-panel-mbb0y0hz.js.map +0 -9
  368. package/dist/chunks/layers-panel-9qekmqk1.js +0 -26
  369. package/dist/chunks/layers-panel-9qekmqk1.js.map +0 -9
  370. package/dist/chunks/settings-modal-gj0hrah4.js +0 -29
  371. package/dist/chunks/settings-modal-gj0hrah4.js.map +0 -9
  372. package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
  373. package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
  374. package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
  375. package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
  376. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
  377. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
  378. package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
  379. package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
  380. package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
  381. package/dist/chunks/studio-568nx4t5.js +0 -469
  382. package/dist/chunks/studio-568nx4t5.js.map +0 -14
  383. package/dist/chunks/studio-9smfzqhc.js +0 -19
  384. package/dist/chunks/studio-9smfzqhc.js.map +0 -10
  385. package/dist/chunks/studio-asvf0j9e.js +0 -429
  386. package/dist/chunks/studio-asvf0j9e.js.map +0 -13
  387. package/dist/chunks/studio-d77qm3pk.js +0 -3427
  388. package/dist/chunks/studio-d77qm3pk.js.map +0 -26
  389. package/dist/chunks/studio-j6gqyjf4.js +0 -1854
  390. package/dist/chunks/studio-j6gqyjf4.js.map +0 -18
  391. package/dist/chunks/studio-n9zmpxjg.js.map +0 -115
  392. package/dist/chunks/studio-qkvt37c0.js.map +0 -9
  393. package/dist/chunks/studio-rq0vxb19.js +0 -3744
  394. package/dist/chunks/studio-rq0vxb19.js.map +0 -22
  395. package/dist/chunks/studio-wd6ewdvd.js +0 -853
  396. package/dist/chunks/studio-wd6ewdvd.js.map +0 -12
  397. package/dist/chunks/studio-xq0t7n5t.js +0 -140
  398. package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
  399. package/dist/chunks/studio-xze4zrs1.js.map +0 -10
  400. package/dist/chunks/studio-ygzav7z5.js.map +0 -46
  401. package/dist/chunks/studio-zmy7241e.js +0 -399
  402. package/dist/chunks/studio-zmy7241e.js.map +0 -12
  403. package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
  404. package/src/browse/browse-modal.ts +0 -69
  405. package/src/browse/browse.ts +0 -904
  406. package/src/canvas/canvas-diff.ts +0 -216
  407. package/src/canvas/nested-site-style.ts +0 -58
  408. package/src/new-project/design-fields.ts +0 -264
  409. package/src/new-project/templates.ts +0 -61
  410. package/src/panels/tab-bar.ts +0 -548
  411. package/src/settings/settings-modal.ts +0 -203
  412. /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
  413. /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
  414. /package/dist/chunks/{format-host-2c188n41.js.map → format-host-mkwsmt8d.js.map} +0 -0
  415. /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
  416. /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
  417. /package/dist/chunks/{studio-hhj92gcr.js.map → studio-s519zc99.js.map} +0 -0
  418. /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
  419. /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
@@ -0,0 +1,1454 @@
1
+ /* Jx Studio — inspector.
2
+ Load after tokens.css, after shell.css, canvas.css and panels.css.
3
+
4
+ Owns everything rendered inside the inspector rail: the field list, the
5
+ key-value style editor, the Spectrum-accordion style sidebar and its
6
+ grid Size panel, the signals tab, the data explorer, the binding toggle
7
+ and the events section. */
8
+
9
+ /* ─── The Inspector dock: header, four tabs, one scrolling body ──────────────
10
+ #right-panel is a flex column (shell.css). The header and the tab strip are
11
+ fixed; exactly one tab body is displayed and it is the only scroller. The
12
+ Assistant's body is the exception — the chat owns its own scrolling, so its
13
+ container is a nested flex column with overflow hidden. */
14
+ #right-panel > .panel-header,
15
+ #right-panel > .panel-tabs {
16
+ flex: 0 0 auto;
17
+ }
18
+ #right-panel > .panel-body {
19
+ flex: 1;
20
+ min-height: 0;
21
+ overflow-y: auto;
22
+ }
23
+ #right-panel > .panel-body[data-jx-region="inspector/tab:assistant"] {
24
+ display: flex;
25
+ flex-direction: column;
26
+ overflow: hidden;
27
+ }
28
+ .ai-panel-host {
29
+ flex: 1;
30
+ min-height: 0;
31
+ display: flex;
32
+ flex-direction: column;
33
+ overflow: hidden;
34
+ }
35
+ /* Text labels, not icons: four words in a 280px dock, allowed to compress rather
36
+ than to become anonymous. */
37
+ .inspector-tabs sp-tabs {
38
+ --mod-tabs-font-size: var(--spectrum-font-size-50, 11px);
39
+
40
+ width: 100%;
41
+ }
42
+
43
+ /* ─── Inspector ──────────────────────────────── */
44
+ .inspector-fields {
45
+ padding: 4px 8px 8px;
46
+ }
47
+ .inspector-fields.hidden {
48
+ display: none;
49
+ }
50
+ .field-row {
51
+ display: flex;
52
+ align-items: center;
53
+ gap: 6px;
54
+ margin-bottom: 4px;
55
+ }
56
+ .field-label {
57
+ width: 80px;
58
+ flex-shrink: 0;
59
+ font-size: var(--spectrum-font-size-50, 11px);
60
+ color: var(--fg-dim);
61
+ text-align: right;
62
+ overflow: hidden;
63
+ text-overflow: ellipsis;
64
+ white-space: nowrap;
65
+ }
66
+ .field-input {
67
+ flex: 1;
68
+ min-width: 0;
69
+ padding: 3px 6px;
70
+ font: inherit;
71
+ font-size: var(--spectrum-font-size-50, 11px);
72
+ color: var(--fg);
73
+ background: var(--bg-input);
74
+ border: 1px solid var(--border);
75
+ border-radius: var(--radius);
76
+ }
77
+ .field-input:focus {
78
+ border-color: var(--accent);
79
+ }
80
+ .field-input:focus-visible {
81
+ outline: 2px solid var(--accent);
82
+ outline-offset: -1px;
83
+ }
84
+ .field-input[type="checkbox"] {
85
+ width: auto;
86
+ flex: none;
87
+ }
88
+ textarea.field-input {
89
+ resize: vertical;
90
+ min-height: 60px;
91
+ font-family: var(--font-mono);
92
+ }
93
+ /* Spectrum components inside field rows */
94
+ .field-row sp-textfield,
95
+ .field-row sp-picker {
96
+ flex: 1;
97
+ min-width: 0;
98
+ }
99
+ .field-row sp-textfield {
100
+ --spectrum-textfield-height: 26px;
101
+ }
102
+ .field-row sp-picker {
103
+ --spectrum-picker-min-width: 0;
104
+ }
105
+ .field-row sp-checkbox {
106
+ flex: none;
107
+ }
108
+ .field-row sp-field-label {
109
+ width: 80px;
110
+ flex-shrink: 0;
111
+ font-size: var(--spectrum-font-size-50, 11px);
112
+ color: var(--fg-dim);
113
+ text-align: right;
114
+ }
115
+ .signal-editor .field-row sp-field-label {
116
+ width: 65px;
117
+ font-size: 10px;
118
+ }
119
+ .signal-editor .field-row sp-textfield {
120
+ --spectrum-textfield-height: 24px;
121
+ }
122
+
123
+ /* ─── Style editor (key-value list) ──────────── */
124
+ .kv-row {
125
+ display: flex;
126
+ gap: 4px;
127
+ margin-bottom: 3px;
128
+ }
129
+ .kv-key {
130
+ width: 90px;
131
+ flex-shrink: 0;
132
+ }
133
+ .kv-val {
134
+ flex: 1;
135
+ min-width: 0;
136
+ }
137
+ .kv-del {
138
+ width: 20px;
139
+ text-align: center;
140
+ cursor: pointer;
141
+ color: var(--danger);
142
+ font-size: 13px;
143
+ line-height: 24px;
144
+ }
145
+ .kv-add {
146
+ display: inline-block;
147
+ padding: 2px 8px;
148
+ font-size: var(--spectrum-font-size-50, 11px);
149
+ cursor: pointer;
150
+ color: var(--accent);
151
+ }
152
+ .kv-add:hover {
153
+ text-decoration: underline;
154
+ }
155
+
156
+ /* ─── The Target Line (plan §6.1) ─────────────────────────────────────────────
157
+ One sentence at the top of the Style tab, stating the compound coordinate an
158
+ edit lands in: element · breakpoint · scheme variant · selector, then the
159
+ scope chip. Every segment is a control, so every segment is a button with the
160
+ chrome taken off — the row must read as a sentence, not as a toolbar, which is
161
+ exactly what the three widgets it replaces failed to do. */
162
+ .target-line {
163
+ display: flex;
164
+ align-items: center;
165
+ gap: 4px;
166
+ padding: 5px 8px;
167
+ border-bottom: 1px solid var(--border);
168
+ font-size: var(--spectrum-font-size-50, 11px);
169
+ line-height: 1.4;
170
+ }
171
+ .tl-glyph {
172
+ flex-shrink: 0;
173
+ color: var(--accent);
174
+ }
175
+ .tl-segments {
176
+ display: flex;
177
+ flex-wrap: wrap;
178
+ align-items: center;
179
+ gap: 2px;
180
+ min-width: 0;
181
+ flex: 1;
182
+ }
183
+ .tl-sep {
184
+ color: var(--fg-dim);
185
+ opacity: 0.6;
186
+ }
187
+ .tl-seg {
188
+ padding: 1px 3px;
189
+ border: none;
190
+ border-radius: var(--radius);
191
+ background: none;
192
+ color: var(--fg);
193
+ font: inherit;
194
+ font-family: var(--font-mono);
195
+ cursor: pointer;
196
+ }
197
+ button.tl-seg:hover {
198
+ background: var(--hover-bg);
199
+ color: var(--accent);
200
+ }
201
+ button.tl-seg:focus-visible {
202
+ outline: 2px solid var(--accent);
203
+ outline-offset: -1px;
204
+ }
205
+ .tl-seg--element {
206
+ color: var(--tag);
207
+ }
208
+ .tl-seg--media,
209
+ .tl-seg--scheme {
210
+ color: var(--fg-dim);
211
+ }
212
+ .tl-seg--selector {
213
+ color: var(--signal);
214
+ }
215
+ .tl-selector-popover {
216
+ max-height: 320px;
217
+ overflow-y: auto;
218
+ }
219
+ .tl-selector-menu {
220
+ min-width: 160px;
221
+ }
222
+ /* The scope chip. Element scope is ambient and reads as ambient; the two tag-wide
223
+ scopes are the ones a reader has to notice before typing, so they carry weight. */
224
+ .tl-scope {
225
+ flex-shrink: 0;
226
+ padding: 1px 6px;
227
+ border: 1px solid var(--border);
228
+ border-radius: 999px;
229
+ color: var(--fg-dim);
230
+ white-space: nowrap;
231
+ }
232
+ .tl-scope--document {
233
+ border-color: var(--accent-50);
234
+ color: var(--accent);
235
+ }
236
+ .tl-scope--project {
237
+ border-color: var(--warning);
238
+ color: var(--warning);
239
+ }
240
+ .tl-warning {
241
+ padding: 6px 8px;
242
+ border-bottom: 1px solid var(--border);
243
+ border-left: 2px solid var(--warning);
244
+ background: var(--bg-panel);
245
+ font-size: var(--spectrum-font-size-50, 11px);
246
+ }
247
+ .tl-warning-text {
248
+ margin: 0;
249
+ color: var(--warning);
250
+ }
251
+ .tl-warning-action {
252
+ margin-top: 4px;
253
+ padding: 0;
254
+ border: none;
255
+ background: none;
256
+ color: var(--accent);
257
+ font: inherit;
258
+ cursor: pointer;
259
+ text-decoration: underline;
260
+ }
261
+ .tl-affected {
262
+ margin: 4px 0 0;
263
+ padding: 0;
264
+ max-height: 140px;
265
+ overflow-y: auto;
266
+ list-style: none;
267
+ }
268
+ .tl-affected-row {
269
+ display: flex;
270
+ justify-content: space-between;
271
+ gap: 8px;
272
+ padding: 1px 0;
273
+ color: var(--fg-dim);
274
+ }
275
+ .tl-affected-path {
276
+ overflow: hidden;
277
+ text-overflow: ellipsis;
278
+ white-space: nowrap;
279
+ font-family: var(--font-mono);
280
+ }
281
+ .tl-affected-count {
282
+ flex-shrink: 0;
283
+ font-family: var(--font-mono);
284
+ }
285
+ .tl-affected-empty {
286
+ margin: 4px 0 0;
287
+ color: var(--fg-dim);
288
+ }
289
+
290
+ /* ─── Provenance dots on a section heading (plan §6.2) ────────────────────────
291
+ The chip itself is styled with the rest of the row vocabulary further down —
292
+ one block, because Style and Component Props are the same chip in two
293
+ cascades. What is only needed here is the DOT form: a collapsed accordion
294
+ heading has room for a tally, not for three labelled chips, so the two states
295
+ that normally carry text collapse to coloured dots beside the accent one.
296
+ That tally is what retired the Style tab's "Active" filter toggle. */
297
+ .set-dot.provenance-chip--inherited {
298
+ background: var(--warning);
299
+ border: none;
300
+ cursor: default;
301
+ }
302
+ .set-dot.provenance-chip--bound {
303
+ background: var(--handler);
304
+ border: none;
305
+ cursor: default;
306
+ }
307
+ /* `mixed` (§6.5) — the multi-selection's own state. Neutral on purpose: unlike the other three it
308
+ says nothing about WHERE the value came from, only that the selected elements disagree, so it
309
+ must not borrow the accent that means "set here" or the amber that means "inherited". */
310
+ .set-dot.provenance-chip--mixed {
311
+ background: var(--text-secondary);
312
+ border: none;
313
+ cursor: default;
314
+ }
315
+ .provenance-dots {
316
+ display: inline-flex;
317
+ align-items: center;
318
+ gap: 3px;
319
+ }
320
+ /* Heading dots are the 7x7 size `.set-dot--section` established, so a section heading reads at the
321
+ same weight it always did — it just now has up to three of them and a tally on hover. */
322
+ .provenance-dots .set-dot {
323
+ width: 7px;
324
+ height: 7px;
325
+ }
326
+ .style-section-heading {
327
+ display: flex;
328
+ align-items: center;
329
+ gap: 6px;
330
+ }
331
+
332
+ /* ─── Style sidebar (Spectrum accordion) ──────── */
333
+ .style-sidebar sp-accordion {
334
+ border: none;
335
+ }
336
+ .style-sidebar sp-accordion-item {
337
+ --spectrum-accordion-item-header-font-size: var(--spectrum-font-size-50, 11px);
338
+ }
339
+ .style-sidebar sp-accordion-item [slot="heading"] {
340
+ display: flex;
341
+ align-items: center;
342
+ gap: 4px;
343
+ }
344
+ .style-row {
345
+ display: flex;
346
+ flex-direction: column;
347
+ align-items: stretch;
348
+ gap: 2px;
349
+ padding: 2px 0;
350
+ }
351
+ .style-row--child {
352
+ padding-left: 16px;
353
+ }
354
+ /* removed: .style-row--horizontal — all rows use top labels now */
355
+ .style-row-label {
356
+ display: flex;
357
+ align-items: center;
358
+ gap: 4px;
359
+ font-size: 10px;
360
+ color: var(--fg-dim);
361
+ }
362
+ .set-dot {
363
+ display: inline-block;
364
+ width: 6px;
365
+ height: 6px;
366
+ border-radius: 50%;
367
+ background: var(--accent);
368
+ cursor: pointer;
369
+ flex-shrink: 0;
370
+ vertical-align: middle;
371
+ }
372
+ .set-dot:hover {
373
+ background: var(--danger);
374
+ }
375
+ .style-row--warning .style-row-label {
376
+ color: var(--warning);
377
+ }
378
+ .style-row--warning .style-row-label::before {
379
+ content: "⚠ ";
380
+ }
381
+ /* §7.1's third notification tier: a bad value, said AT the control that refuses it, for exactly as
382
+ long as the value stays bad. A toast expires and a problem is a list entry somewhere else; this
383
+ one is a property of the field, so it is styled as part of the row rather than as a floating
384
+ surface. The left rule is what makes it read as belonging to the widget above it. */
385
+ .style-row--invalid .style-row-label {
386
+ color: var(--danger);
387
+ }
388
+ .style-row-error {
389
+ margin: 2px 0 0;
390
+ padding-left: 6px;
391
+ border-left: 2px solid var(--danger);
392
+ font-size: 10px;
393
+ line-height: 1.35;
394
+ color: var(--danger);
395
+ }
396
+ /* The repeat counter — "it refused me AGAIN" is otherwise indistinguishable from "the field is
397
+ still red from last time" when the second attempt fails the same way. */
398
+ .style-row-error-count {
399
+ margin-left: 4px;
400
+ font-family: var(--font-mono);
401
+ opacity: 0.75;
402
+ }
403
+ .style-row > sp-textfield,
404
+ .style-row > sp-number-field,
405
+ .style-row > sp-picker,
406
+ .style-row > sp-combobox,
407
+ .style-row > textarea {
408
+ width: 100%;
409
+ }
410
+ .style-input-color {
411
+ display: flex;
412
+ align-items: center;
413
+ gap: 6px;
414
+ flex: 1;
415
+ min-width: 0;
416
+ }
417
+ .style-input-color sp-swatch {
418
+ flex-shrink: 0;
419
+ cursor: pointer;
420
+ }
421
+ .style-input-color sp-textfield {
422
+ flex: 1;
423
+ min-width: 0;
424
+ }
425
+ .color-popover-inner {
426
+ display: flex;
427
+ flex-direction: column;
428
+ gap: 8px;
429
+ width: 200px;
430
+ overflow: hidden;
431
+ }
432
+ .color-popover-inner sp-textfield {
433
+ width: 100%;
434
+ }
435
+ .color-popover-swatches-label {
436
+ font-size: 10px;
437
+ color: var(--spectrum-gray-600);
438
+ text-transform: uppercase;
439
+ letter-spacing: 0.05em;
440
+ }
441
+ .color-popover-inner sp-swatch-group {
442
+ --mod-swatch-border-color: var(--spectrum-gray-400);
443
+ }
444
+ .font-token-item {
445
+ display: flex;
446
+ flex-direction: column;
447
+ gap: 1px;
448
+ }
449
+ .font-token-preview {
450
+ font-size: var(--spectrum-font-size-75, 12px);
451
+ line-height: 1.3;
452
+ }
453
+ .font-token-name {
454
+ font-size: 9px;
455
+ color: var(--spectrum-gray-600);
456
+ font-family: monospace;
457
+ }
458
+ /* jx-styled-combobox — dual-mode styled combobox component */
459
+ jx-styled-combobox {
460
+ display: contents;
461
+ }
462
+ jx-styled-combobox sp-picker {
463
+ width: 100%;
464
+ }
465
+ .jx-combobox-group {
466
+ display: inline-flex;
467
+ position: relative;
468
+ width: 100%;
469
+ }
470
+ .jx-combobox-group sp-textfield {
471
+ flex: 1 1 auto;
472
+ min-width: 0;
473
+ --mod-textfield-border-start-end-radius: 0;
474
+ --mod-textfield-border-end-end-radius: 0;
475
+ margin-inline-end: calc(-1 * var(--spectrum-border-width-100, 1px));
476
+ }
477
+ .jx-combobox-group sp-picker-button {
478
+ flex: 0 0 auto;
479
+ --mod-picker-button-border-start-start-radius: 0;
480
+ --mod-picker-button-border-end-start-radius: 0;
481
+ --mod-picker-button-border-color: var(--spectrum-gray-400);
482
+ }
483
+ /* Number-unit compound input: textfield + picker-button */
484
+ .style-input-number-unit {
485
+ flex: 1;
486
+ min-width: 0;
487
+ }
488
+ /* Combobox-like composite: textfield + picker-button, matching sp-combobox visually */
489
+ .input-group {
490
+ display: inline-flex;
491
+ position: relative;
492
+ width: 100%;
493
+ }
494
+ .input-group sp-textfield {
495
+ flex: 1 1 auto;
496
+ min-width: 0;
497
+ /* Zero out the inline-end corners so the textfield abuts the picker-button */
498
+ --mod-textfield-border-start-end-radius: 0;
499
+ --mod-textfield-border-end-end-radius: 0;
500
+ /* Pull textfield's border into the picker-button so they share one line */
501
+ margin-inline-end: calc(-1 * var(--spectrum-border-width-100, 1px));
502
+ }
503
+ .input-group sp-picker-button {
504
+ flex: 0 0 auto;
505
+ /* Zero out the inline-start corners to abut the textfield */
506
+ --mod-picker-button-border-start-start-radius: 0;
507
+ --mod-picker-button-border-end-start-radius: 0;
508
+ --mod-picker-button-border-color: var(--spectrum-gray-400);
509
+ }
510
+ .input-group.is-expression sp-picker-button {
511
+ display: none;
512
+ }
513
+ .input-group.is-expression sp-textfield {
514
+ --mod-textfield-text-color-default: var(--spectrum-accent-color-800);
515
+ --mod-textfield-border-start-end-radius: var(--spectrum-corner-radius-100);
516
+ --mod-textfield-border-end-end-radius: var(--spectrum-corner-radius-100);
517
+ margin-inline-end: 0;
518
+ }
519
+ .style-shorthand-header {
520
+ display: flex;
521
+ align-items: center;
522
+ gap: 4px;
523
+ }
524
+ .style-shorthand-header sp-textfield {
525
+ flex: 1;
526
+ min-width: 0;
527
+ }
528
+
529
+ /* Button-group + overflow picker-button combo */
530
+ .button-group-combo {
531
+ display: inline-flex;
532
+ align-items: stretch;
533
+ }
534
+ .button-group-combo.has-overflow sp-action-group {
535
+ --mod-actionbutton-border-radius: 0;
536
+ }
537
+ .button-group-combo sp-picker-button {
538
+ flex: 0 0 auto;
539
+ --mod-picker-button-border-start-start-radius: 0;
540
+ --mod-picker-button-border-end-start-radius: 0;
541
+ --mod-picker-button-border-color: var(--spectrum-gray-400);
542
+ margin-inline-start: calc(-1 * var(--spectrum-border-width-100, 1px));
543
+ }
544
+ .button-group-combo sp-picker-button.has-selection {
545
+ --mod-picker-button-background-color: var(--spectrum-accent-background-color-default);
546
+ }
547
+
548
+ /* ─── Grid section layout (Size panel) ─── */
549
+ .style-section-body--grid {
550
+ display: grid;
551
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
552
+ gap: 6px 8px;
553
+ }
554
+ .style-section-body--grid .style-row {
555
+ min-width: 0;
556
+ overflow: hidden;
557
+ }
558
+
559
+ /* ─── Signals tab ────────────────────────────── */
560
+ .signal-row {
561
+ display: flex;
562
+ align-items: center;
563
+ gap: 4px;
564
+ padding: 4px 8px;
565
+ cursor: pointer;
566
+ border-left: 2px solid transparent;
567
+ user-select: none;
568
+ }
569
+ .signal-row:hover {
570
+ background: var(--hover-bg);
571
+ }
572
+ .signal-row.expanded {
573
+ background: var(--accent-10);
574
+ border-left-color: var(--accent);
575
+ }
576
+ .signal-badge {
577
+ padding: 0 4px;
578
+ font-size: 10px;
579
+ border-radius: var(--spectrum-corner-radius-75, 2px);
580
+ font-weight: 600;
581
+ flex-shrink: 0;
582
+ min-width: 18px;
583
+ text-align: center;
584
+ }
585
+ .signal-badge.state {
586
+ background: color-mix(in srgb, var(--signal) 25%, transparent);
587
+ color: var(--signal);
588
+ }
589
+ .signal-badge.computed {
590
+ background: color-mix(in srgb, var(--success) 25%, transparent);
591
+ color: var(--success);
592
+ }
593
+ .signal-badge.data {
594
+ background: color-mix(in srgb, var(--tag) 25%, transparent);
595
+ color: var(--tag);
596
+ }
597
+ .signal-badge.handler {
598
+ background: color-mix(in srgb, var(--handler) 25%, transparent);
599
+ color: var(--handler);
600
+ }
601
+ /* The NAME is what you came for, so it is the last thing to be elided. It used to sit at `flex: 1`
602
+ beside a hint pinned at `flex-shrink: 0`, so a long-prototype row rendered as `re… ContentCollect…`
603
+ — the summary intact and the identity gone. */
604
+ .signal-name {
605
+ flex: 1 1 auto;
606
+ min-width: 8em;
607
+ white-space: nowrap;
608
+ font-family: var(--font-mono);
609
+ font-size: var(--spectrum-font-size-50, 11px);
610
+ overflow: hidden;
611
+ text-overflow: ellipsis;
612
+ }
613
+ .signal-hint {
614
+ font-size: 10px;
615
+ color: var(--fg-dim);
616
+ flex: 0 1 auto;
617
+ min-width: 0;
618
+ max-width: 64px;
619
+ white-space: nowrap;
620
+ overflow: hidden;
621
+ text-overflow: ellipsis;
622
+ }
623
+ .signal-del {
624
+ visibility: hidden;
625
+ cursor: pointer;
626
+ color: var(--danger);
627
+ font-size: var(--spectrum-font-size-50, 11px);
628
+ flex-shrink: 0;
629
+ }
630
+ .signal-row:hover .signal-del {
631
+ visibility: visible;
632
+ }
633
+ .signal-editor {
634
+ padding: 4px 8px 8px 26px;
635
+ border-bottom: 1px solid var(--border);
636
+ }
637
+ /* Signals panel accordion (matches style-sidebar pattern) */
638
+ .signals-panel sp-accordion {
639
+ border: none;
640
+ }
641
+ .signals-panel sp-accordion-item {
642
+ --spectrum-accordion-item-header-font-size: var(--spectrum-font-size-50, 11px);
643
+ }
644
+ .signals-add {
645
+ display: flex;
646
+ align-items: center;
647
+ gap: 4px;
648
+ padding: 6px 8px;
649
+ }
650
+
651
+ /* ─── Data explorer ──────────────────────────── */
652
+ .data-explorer-toolbar {
653
+ padding: 4px 8px;
654
+ border-bottom: 1px solid var(--border);
655
+ display: flex;
656
+ justify-content: flex-end;
657
+ }
658
+ .data-refresh-btn {
659
+ font-size: var(--spectrum-font-size-50, 11px);
660
+ padding: 2px 8px;
661
+ background: var(--bg-input);
662
+ border: 1px solid var(--border);
663
+ border-radius: var(--radius);
664
+ color: var(--fg);
665
+ cursor: pointer;
666
+ }
667
+ .data-refresh-btn:hover {
668
+ border-color: var(--accent);
669
+ }
670
+ /* The Data panel's own row list is gone — the definition rows carry the resolved value now
671
+ (plan §11.2). `.data-row`, `.data-row-header` and `.data-name` went with it; what is left here
672
+ dresses the value INSIDE a `.signal-editor`. */
673
+ .data-type {
674
+ font-size: 10px;
675
+ color: var(--fg-dim);
676
+ flex-shrink: 0;
677
+ }
678
+ /* A truncation marker is a control, not a caption — it shows more of what the panel already has.
679
+ Styled as the text it replaced so the tree does not sprout buttons, but focusable and hoverable
680
+ so it reads as pressable. */
681
+ .data-more {
682
+ display: block;
683
+ width: 100%;
684
+ text-align: left;
685
+ background: none;
686
+ border: none;
687
+ font: inherit;
688
+ color: inherit;
689
+ cursor: pointer;
690
+ }
691
+ .data-more:hover,
692
+ .data-more:focus-visible {
693
+ color: var(--accent);
694
+ text-decoration: underline;
695
+ }
696
+
697
+ /* The resolved value, under the fields that define it. The rule above it is the seam between
698
+ "what this is" and "what it became" — the two halves that used to be two panels. */
699
+ .signal-live {
700
+ margin-top: 8px;
701
+ padding-top: 6px;
702
+ border-top: 1px solid var(--border);
703
+ }
704
+ .signal-live-label {
705
+ display: block;
706
+ font-size: 10px;
707
+ text-transform: uppercase;
708
+ letter-spacing: 0.04em;
709
+ color: var(--fg-dim);
710
+ margin-bottom: 2px;
711
+ }
712
+ .data-tree {
713
+ padding: 2px 0;
714
+ max-height: 300px;
715
+ overflow-y: auto;
716
+ }
717
+ .data-leaf,
718
+ .data-branch {
719
+ font-size: var(--spectrum-font-size-50, 11px);
720
+ font-family: var(--font-mono, monospace);
721
+ padding: 1px 8px;
722
+ line-height: 1.5;
723
+ white-space: nowrap;
724
+ overflow: hidden;
725
+ text-overflow: ellipsis;
726
+ }
727
+ .data-key {
728
+ color: var(--data-key);
729
+ }
730
+ .data-value {
731
+ color: var(--fg);
732
+ }
733
+ .data-null {
734
+ color: var(--fg-dim);
735
+ font-style: italic;
736
+ }
737
+ .data-string {
738
+ color: var(--data-string);
739
+ }
740
+ .data-number {
741
+ color: var(--data-number);
742
+ }
743
+ .data-boolean {
744
+ color: var(--data-boolean);
745
+ }
746
+ .data-object-label {
747
+ color: var(--fg-dim);
748
+ font-style: italic;
749
+ }
750
+ .data-ellipsis {
751
+ color: var(--fg-dim);
752
+ font-style: italic;
753
+ }
754
+ /* PENDING IS A RESTING STATE, not progress. While you are editing, an automatic `Request` is
755
+ deliberately not fetched — so a value that has not arrived is dim and STILL, and the pulse is
756
+ kept for the one moment something is actually in flight. An animation that never stops is a
757
+ spinner for a thing that is not loading, and it is why `probe.idle()` could never call this panel
758
+ quiet: the screenshot lane timed out on "2 animation(s) running" in a panel at rest. */
759
+ .data-pending {
760
+ opacity: 0.55;
761
+ }
762
+ .signals-panel.is-refreshing .data-pending {
763
+ opacity: 1;
764
+ animation: pulse 1.5s ease-in-out infinite;
765
+ }
766
+ @keyframes pulse {
767
+ 0%,
768
+ 100% {
769
+ opacity: 1;
770
+ }
771
+ 50% {
772
+ opacity: 0.4;
773
+ }
774
+ }
775
+ .field-check {
776
+ width: auto;
777
+ margin: 0;
778
+ }
779
+
780
+ /* ─── Binding toggle ─────────────────────────── */
781
+ .bind-toggle {
782
+ width: 20px;
783
+ height: 20px;
784
+ display: flex;
785
+ align-items: center;
786
+ justify-content: center;
787
+ font-size: var(--spectrum-font-size-50, 11px);
788
+ cursor: pointer;
789
+ color: var(--fg-dim);
790
+ border: 1px solid transparent;
791
+ border-radius: var(--radius);
792
+ flex-shrink: 0;
793
+ }
794
+ .bind-toggle:hover {
795
+ color: var(--fg);
796
+ background: var(--hover-bg);
797
+ }
798
+ .bind-toggle.bound {
799
+ color: var(--accent);
800
+ }
801
+
802
+ /* ─── Events section ─────────────────────────── */
803
+ .events-panel {
804
+ padding: 8px;
805
+ }
806
+ .events-section {
807
+ margin-bottom: 8px;
808
+ }
809
+ .declared-event-row {
810
+ display: flex;
811
+ gap: 6px;
812
+ align-items: center;
813
+ padding: 2px 0;
814
+ font-size: var(--spectrum-font-size-50, 11px);
815
+ }
816
+ .event-code {
817
+ font-family: monospace;
818
+ color: var(--accent);
819
+ }
820
+ .event-source {
821
+ color: var(--fg-dim);
822
+ font-size: 10px;
823
+ }
824
+ .event-type {
825
+ margin-left: auto;
826
+ color: var(--fg-dim);
827
+ font-size: 10px;
828
+ }
829
+ .event-binding {
830
+ margin-bottom: 8px;
831
+ }
832
+ .event-row {
833
+ display: flex;
834
+ gap: 4px;
835
+ align-items: center;
836
+ }
837
+ .event-name {
838
+ flex: 1;
839
+ min-width: 0;
840
+ }
841
+ .event-mode {
842
+ width: 72px;
843
+ flex-shrink: 0;
844
+ }
845
+ .event-handler {
846
+ width: 100%;
847
+ }
848
+ .event-body-row {
849
+ display: flex;
850
+ gap: 4px;
851
+ align-items: start;
852
+ margin-top: 3px;
853
+ }
854
+ .event-body-row sp-textfield {
855
+ flex: 1;
856
+ font-size: var(--spectrum-font-size-50, 11px);
857
+ }
858
+
859
+ /* ── Usage ("Used on N pages →") ──────────────────────────────────────────────
860
+ The reference index rendered in the inspector. The heading carries the count, so the rows are
861
+ the answer's detail rather than its headline — collapsed by default, one row per referencing
862
+ file, each a button that opens it. */
863
+ .usage-note {
864
+ color: var(--fg-dim);
865
+ font-size: var(--spectrum-font-size-50, 11px);
866
+ line-height: 1.5;
867
+ padding: 2px 0;
868
+ }
869
+ .usage-row {
870
+ display: flex;
871
+ gap: 6px;
872
+ align-items: center;
873
+ width: 100%;
874
+ padding: 3px 4px;
875
+ border: none;
876
+ border-radius: var(--radius);
877
+ background: none;
878
+ color: inherit;
879
+ font: inherit;
880
+ font-size: var(--spectrum-font-size-50, 11px);
881
+ text-align: left;
882
+ cursor: pointer;
883
+ }
884
+ .usage-row:hover,
885
+ .usage-row:focus-visible {
886
+ background: var(--hover-bg);
887
+ }
888
+ .usage-row-path {
889
+ flex: 1;
890
+ min-width: 0;
891
+ overflow: hidden;
892
+ text-overflow: ellipsis;
893
+ white-space: nowrap;
894
+ }
895
+ .usage-row-count {
896
+ flex-shrink: 0;
897
+ color: var(--fg-dim);
898
+ font-variant-numeric: tabular-nums;
899
+ }
900
+
901
+ /* ─── P5 · Provenance chips (UX-REDESIGN-PLAN §6.2) ─────────────────────────
902
+ Four states, one vocabulary, reused in every cascade: `set` keeps the accent
903
+ dot it has always been (see .set-dot above); `inherited` is amber and names
904
+ its donor; `bound` is violet and names the signal or formula; `default`
905
+ renders nothing at all, because a ghost dot on every unset row is 138 dots
906
+ on the Style tab. Rendered by panels/provenance.ts:renderProvenanceChip, which
907
+ ui/field-row.ts calls for every row that states its provenance. */
908
+ .provenance-chip {
909
+ flex-shrink: 0;
910
+ }
911
+ button.provenance-chip {
912
+ display: inline-flex;
913
+ align-items: center;
914
+ max-width: 14ch;
915
+ overflow: hidden;
916
+ padding: 0 5px;
917
+ border: 1px solid currentcolor;
918
+ border-radius: var(--radius);
919
+ background: transparent;
920
+ font: inherit;
921
+ font-size: 9px;
922
+ line-height: 14px;
923
+ white-space: nowrap;
924
+ text-overflow: ellipsis;
925
+ cursor: default;
926
+ }
927
+ button.provenance-chip:not(:disabled) {
928
+ cursor: pointer;
929
+ }
930
+ .provenance-chip--inherited {
931
+ color: var(--warning);
932
+ }
933
+ .provenance-chip--bound {
934
+ color: var(--handler);
935
+ }
936
+ .provenance-chip--mixed {
937
+ color: var(--text-secondary);
938
+ }
939
+ button.provenance-chip:hover,
940
+ button.provenance-chip:focus-visible {
941
+ background: var(--hover-bg);
942
+ }
943
+ /* The collapsed-header dot is an INDICATOR, not a control: it inherited
944
+ .set-dot's pointer cursor and danger hover and had no handler behind either.
945
+ §6.2 keeps the dot (a closed section must still say whether anything in it is
946
+ set) and drops the affordance. */
947
+ .set-dot--section {
948
+ width: 7px;
949
+ height: 7px;
950
+ cursor: default;
951
+ }
952
+ .set-dot--section:hover {
953
+ background: var(--accent);
954
+ }
955
+
956
+ /* ─── The read-only name/value line ─────────────────────────────────────────
957
+ Observed Attributes, CSS Properties and CSS Parts were three copies of the
958
+ same inline-styled flex row. One row, one rule, and it responds to the theme
959
+ now that it has a class at all. */
960
+ .kv-static-row {
961
+ display: flex;
962
+ gap: 6px;
963
+ align-items: center;
964
+ padding: 2px 0;
965
+ font-size: var(--spectrum-font-size-50, 11px);
966
+ }
967
+ .kv-static-name {
968
+ font-family: var(--font-mono);
969
+ color: var(--accent);
970
+ }
971
+ .kv-static-detail {
972
+ color: var(--fg-dim);
973
+ }
974
+ .kv-static-value {
975
+ margin-left: auto;
976
+ color: var(--fg-dim);
977
+ }
978
+ .kv-static-tag {
979
+ padding: 1px 4px;
980
+ border-radius: var(--radius);
981
+ background: var(--hover-bg);
982
+ font-size: 9px;
983
+ }
984
+ .kv-static-value + .kv-static-tag,
985
+ .kv-static-detail + .kv-static-tag {
986
+ margin-left: auto;
987
+ }
988
+ .kv-static-value ~ .kv-static-tag {
989
+ margin-left: 0;
990
+ }
991
+
992
+ /* ─── Logic tab structure ───────────────────────────────────────────────────
993
+ The Repeater and Switch sections used to carry their layout in inline style=
994
+ attributes, which is how they also ended up as the last rows in the inspector
995
+ without a set-dot or a clear affordance. */
996
+ .logic-edit-template {
997
+ margin-top: 8px;
998
+ width: 100%;
999
+ }
1000
+ .logic-subhead {
1001
+ margin: 8px 0 4px;
1002
+ font-size: var(--spectrum-font-size-50, 11px);
1003
+ font-weight: 600;
1004
+ color: var(--fg-dim);
1005
+ text-transform: uppercase;
1006
+ letter-spacing: 0.05em;
1007
+ }
1008
+ .logic-case-row {
1009
+ display: flex;
1010
+ align-items: center;
1011
+ gap: 4px;
1012
+ }
1013
+ .logic-case-name {
1014
+ flex: 1;
1015
+ min-width: 0;
1016
+ }
1017
+ .logic-case-open {
1018
+ flex-shrink: 0;
1019
+ }
1020
+
1021
+ /* ─── The Layout-element card ───────────────────────────────────────────────
1022
+ What the inspector says when you click page chrome — §8.2's first click. */
1023
+ .layout-origin {
1024
+ display: flex;
1025
+ align-items: center;
1026
+ gap: 6px;
1027
+ margin-bottom: 8px;
1028
+ }
1029
+ .layout-origin-badge {
1030
+ padding: 2px 6px;
1031
+ border-radius: var(--radius);
1032
+ background: var(--map);
1033
+ color: var(--accent-fg);
1034
+ font-size: 9px;
1035
+ text-transform: uppercase;
1036
+ letter-spacing: 0.5px;
1037
+ }
1038
+ .layout-origin-tag {
1039
+ font-family: var(--font-mono);
1040
+ font-size: var(--spectrum-font-size-75, 12px);
1041
+ }
1042
+ .layout-origin-class {
1043
+ font-size: var(--spectrum-font-size-50, 11px);
1044
+ color: var(--fg-dim);
1045
+ word-break: break-all;
1046
+ }
1047
+ .layout-origin-note {
1048
+ margin: 0;
1049
+ padding: 4px 0;
1050
+ font-size: 10px;
1051
+ font-style: italic;
1052
+ color: var(--fg-dim);
1053
+ }
1054
+
1055
+ /* ─── P6 · Project Styles: token chips and the override affordance (§9.4) ────
1056
+ A style value that is exactly `var(--token)` is a REFERENCE, and raw text is
1057
+ the one rendering that hides which token and what it currently is. The chip
1058
+ reuses the provenance-chip vocabulary above — same border, same 9px, same
1059
+ radius — because "this value comes from somewhere else" is the same sentence
1060
+ in both places; only the donor differs. It is a <span>, not a button: it
1061
+ states, it does not navigate (§6.2). */
1062
+ .style-token-chip {
1063
+ display: inline-flex;
1064
+ align-items: center;
1065
+ gap: 4px;
1066
+ flex-shrink: 0;
1067
+ max-width: 14ch;
1068
+ overflow: hidden;
1069
+ padding: 0 5px;
1070
+ border: 1px solid currentcolor;
1071
+ border-radius: var(--radius);
1072
+ color: var(--handler);
1073
+ font-size: 9px;
1074
+ line-height: 14px;
1075
+ white-space: nowrap;
1076
+ }
1077
+ .style-token-chip-swatch {
1078
+ width: 8px;
1079
+ height: 8px;
1080
+ flex-shrink: 0;
1081
+ border: 1px solid var(--border);
1082
+ border-radius: var(--spectrum-corner-radius-75, 2px);
1083
+ }
1084
+ .style-token-chip-label {
1085
+ overflow: hidden;
1086
+ text-overflow: ellipsis;
1087
+ }
1088
+
1089
+ /* The add-an-override picker, under a token's existing context rows. It aligns
1090
+ with them rather than with the token name, because it belongs to the override
1091
+ list and not to the token — the affordance that was missing is "give this
1092
+ token a value in a context it has none in", and a control that lined up with
1093
+ the base value would read as a second base value. */
1094
+ .css-var-override-add {
1095
+ display: flex;
1096
+ align-items: center;
1097
+ padding: 2px 0;
1098
+ }
1099
+ .css-var-override-add sp-picker {
1100
+ font-size: var(--spectrum-font-size-50, 11px);
1101
+ }
1102
+
1103
+ /* ─── The reference control (ui/form-controls.ts) ────────────────────────────
1104
+ A property whose `$ref` names another collection. One registration, so this
1105
+ is the only block that styles a relationship field wherever it is drawn — the
1106
+ entry editor, a settings form, the frontmatter card. The note carries the two
1107
+ states a dropdown alone cannot express: "no entries yet" and "the read
1108
+ failed", and the failed one is coloured because it is a fault, not a fact. */
1109
+ .reference-control {
1110
+ display: flex;
1111
+ flex: 1;
1112
+ min-width: 0;
1113
+ align-items: center;
1114
+ gap: 6px;
1115
+ }
1116
+ .reference-field {
1117
+ flex: 1;
1118
+ min-width: 0;
1119
+ }
1120
+ .reference-note {
1121
+ color: var(--fg-dim);
1122
+ font-size: var(--spectrum-font-size-50, 11px);
1123
+ line-height: 1.4;
1124
+ }
1125
+ .reference-note--failed {
1126
+ color: var(--spectrum-red-600, #e34850);
1127
+ }
1128
+ /* The entry the value names is not on disk. Kept in the list — see the control's
1129
+ note on dangling references — and marked so it cannot be mistaken for one. */
1130
+ .reference-missing {
1131
+ color: var(--spectrum-red-600, #e34850);
1132
+ }
1133
+
1134
+ /* ─── The statement editor (studio-ui-guidelines.md §4.6) ────────────────────────────────────────
1135
+ A Function body as cards on a connector line — `panels/statement-editor.ts`.
1136
+ Until this block existed the surface had NO stylesheet at all: every frame,
1137
+ indent and connector was an inline `style=` attribute, and twenty class names
1138
+ sat in check-styles.ts's orphan list.
1139
+
1140
+ An attribute cannot carry the one declaration the layout needs. A flex item's
1141
+ automatic minimum size is its min-content width, so a chain with no
1142
+ `min-width: 0` on it refuses to shrink: an operand row asking for a 112px
1143
+ picker + a 56px picker + a Spectrum field (192px by default) is wider than a
1144
+ 280px Inspector, and Operator, Target and Value were clipped by the right
1145
+ edge of the WINDOW. The editor is drawn in three docks of very different
1146
+ widths — the Navigator's State panel, the Inspector's Events tab and the
1147
+ Bottom dock's Logic tab — so a pixel layout is wrong by construction.
1148
+
1149
+ Colours here are the ones the attributes already carried: this is a layout
1150
+ change and nothing else. */
1151
+ .statement-editor {
1152
+ min-width: 0;
1153
+ }
1154
+ /* One indent per nesting level, drawn once. The lane used to add a 6px margin of
1155
+ its own on top of the list's 4px + 2px + 8px, so a three-deep branch spent
1156
+ 48px of a 240px panel on indentation alone. */
1157
+ .statement-list {
1158
+ min-width: 0;
1159
+ padding: 2px 0 0 8px;
1160
+ border-left: 2px solid var(--spectrum-gray-300, #3c3c3c);
1161
+ }
1162
+ .statement-lane {
1163
+ min-width: 0;
1164
+ margin: 4px 0;
1165
+ }
1166
+ .statement-lane-header {
1167
+ display: flex;
1168
+ flex-wrap: wrap;
1169
+ align-items: center;
1170
+ gap: 4px;
1171
+ min-width: 0;
1172
+ }
1173
+ /* The card is the draggable object, so its frame is what carries the weight. */
1174
+ .statement-card {
1175
+ min-width: 0;
1176
+ margin: 0 0 6px;
1177
+ padding: 4px 6px;
1178
+ border: 1px solid var(--spectrum-gray-300, #3c3c3c);
1179
+ border-radius: var(--radius);
1180
+ background: var(--spectrum-gray-75, #1e1e1e);
1181
+ }
1182
+ .statement-card-header {
1183
+ display: flex;
1184
+ align-items: center;
1185
+ gap: 6px;
1186
+ min-width: 0;
1187
+ }
1188
+ .statement-card-body {
1189
+ min-width: 0;
1190
+ }
1191
+ .statement-drag-handle {
1192
+ flex-shrink: 0;
1193
+ color: var(--spectrum-gray-500, #6e6e6e);
1194
+ font-size: var(--spectrum-font-size-50, 11px);
1195
+ line-height: 1;
1196
+ cursor: grab;
1197
+ user-select: none;
1198
+ }
1199
+ /* The kind label and a lane's name are the same 10px caption. */
1200
+ .statement-kind-label,
1201
+ .statement-lane-label {
1202
+ min-width: 0;
1203
+ color: var(--fg-dim);
1204
+ font-size: 10px;
1205
+ font-weight: 600;
1206
+ letter-spacing: 0.04em;
1207
+ text-transform: uppercase;
1208
+ }
1209
+ /* "Dispatch event" beside a drag handle and a delete button is already most of a
1210
+ narrow header, so the kind ellipsizes rather than widening the card. */
1211
+ .statement-kind-label {
1212
+ overflow: hidden;
1213
+ white-space: nowrap;
1214
+ text-overflow: ellipsis;
1215
+ }
1216
+ /* A `$switch` case renames itself in the lane header, so this label slot holds a
1217
+ text FIELD rather than a word — hence a flex row and no `overflow: hidden`,
1218
+ which would clip the field's focus ring. */
1219
+ .statement-lane-label {
1220
+ display: flex;
1221
+ align-items: center;
1222
+ }
1223
+ /* The uppercase and the 10px belong to the label, not to the value: inherited
1224
+ properties cross the shadow boundary, so `case 1` rendered as `CASE 1` in the
1225
+ field you were about to type into. */
1226
+ .statement-case-key {
1227
+ /* It may not GROW: the lane's remove button shares this header, and a key
1228
+ field that takes the whole line pushes it onto one of its own. */
1229
+ flex: 0 1 6rem;
1230
+ min-width: 0;
1231
+ font-size: var(--spectrum-font-size-50, 11px);
1232
+ font-weight: 400;
1233
+ letter-spacing: normal;
1234
+ text-transform: none;
1235
+ }
1236
+ /* Hard right, and it used to take a `<span style="flex:1">` spacer to get there. */
1237
+ .statement-delete {
1238
+ flex-shrink: 0;
1239
+ margin-left: auto;
1240
+ }
1241
+ .statement-lane-remove {
1242
+ flex-shrink: 0;
1243
+ }
1244
+ .statement-add,
1245
+ .statement-add-case,
1246
+ .statement-add-else {
1247
+ max-width: 100%;
1248
+ }
1249
+ /* A direct child of `.style-row`, which is a flex COLUMN — so `flex: 1` here was
1250
+ never a width, it was permission to grow TALL, and a flex-basis would have been
1251
+ a height outright. That is the empty column the bug report photographed. Width
1252
+ comes from the `.style-row > sp-textfield` stretch rule above; all this row
1253
+ needs of its own is permission to shrink. */
1254
+ .statement-dispatch-name {
1255
+ min-width: 0;
1256
+ }
1257
+ /* `bubbles` and `composed` read as one row and stack when they cannot. */
1258
+ .statement-dispatch-options {
1259
+ display: flex;
1260
+ flex-wrap: wrap;
1261
+ align-items: center;
1262
+ gap: 4px 12px;
1263
+ min-width: 0;
1264
+ }
1265
+ .statement-dispatch-bubbles,
1266
+ .statement-dispatch-composed {
1267
+ flex: 0 0 auto;
1268
+ max-width: 100%;
1269
+ }
1270
+ /* Drag feedback. `dragging`, `drop-above` and `drop-below` are toggled by
1271
+ registerStatementsDnD and had no rule anywhere, so a drag showed the cursor
1272
+ moving and nothing else until the drop landed. */
1273
+ .statement-card.dragging {
1274
+ opacity: 0.4;
1275
+ }
1276
+ .statement-card.drop-above {
1277
+ box-shadow: inset 0 2px 0 0 var(--accent);
1278
+ }
1279
+ .statement-card.drop-below {
1280
+ box-shadow: inset 0 -2px 0 0 var(--accent);
1281
+ }
1282
+
1283
+ /* ─── The expression editor ──────────────────────────────────────────────────
1284
+ `ui/expression-editor.ts`, drawn inside a statement card, inside the Data
1285
+ panel's signal editor, and on its own in the Bottom dock's formula workspace.
1286
+ Same story as above: no stylesheet, so no `min-width: 0`, so the operand
1287
+ controls could not shrink to the dock they were in. */
1288
+ .expression-editor {
1289
+ min-width: 0;
1290
+ }
1291
+ /* Nesting depth, from CSS rather than from a `style=` string built in TS. */
1292
+ .expression-editor--nested {
1293
+ margin-left: 4px;
1294
+ padding-left: 6px;
1295
+ border-left: 2px solid var(--spectrum-gray-300, #3c3c3c);
1296
+ }
1297
+ .expr-subsection {
1298
+ min-width: 0;
1299
+ margin-top: 4px;
1300
+ }
1301
+ .expr-error {
1302
+ padding: 2px 0;
1303
+ color: var(--danger);
1304
+ font-size: 10px;
1305
+ }
1306
+ /* Two of the editor's three row primitives — the operand is the third, just
1307
+ below, and differs only in how it aligns a tall widget. Between them they are
1308
+ the rule that makes the whole thing hold at any width: a row when there is
1309
+ room for one, a stack when there is not. The break is decided by a flex-basis,
1310
+ never by a fixed width, so the same markup is two columns in a 600px dock and
1311
+ two lines in a 240px rail and neither is a special case. */
1312
+ .expr-widget,
1313
+ .expr-literal {
1314
+ display: flex;
1315
+ flex: 1 1 auto;
1316
+ flex-wrap: wrap;
1317
+ align-items: center;
1318
+ gap: 4px;
1319
+ min-width: 0;
1320
+ }
1321
+ /* An operand may be a nested editor several rows tall; its mode picker belongs
1322
+ at the top of that block, not at the middle of it. */
1323
+ .expr-operand {
1324
+ display: flex;
1325
+ flex: 1 1 auto;
1326
+ flex-wrap: wrap;
1327
+ align-items: flex-start;
1328
+ gap: 4px;
1329
+ min-width: 0;
1330
+ }
1331
+ .expr-operand-mode {
1332
+ flex: 0 1 6.5rem;
1333
+ }
1334
+ .expr-literal {
1335
+ flex: 1 1 8rem;
1336
+ }
1337
+ /* The operator is two or three glyphs, so it may compress a long way before the
1338
+ Browse-catalog button beside it is pushed onto a line of its own. */
1339
+ .expr-operator {
1340
+ flex: 1 1 4rem;
1341
+ }
1342
+ .expr-ref {
1343
+ flex: 1 1 6rem;
1344
+ }
1345
+ /* A nested formula is a BLOCK of rows, not a control, so it always takes a line
1346
+ of its own under the mode picker that names it. Sizing it as a sibling instead
1347
+ is what put a lone "Formula ▾" at the top of a tall empty column in the bug
1348
+ report — the picker labels what follows it, and a label does not want a column
1349
+ to itself. A `flex-basis: 100%` is the wrap, said once. */
1350
+ .expr-operand > .expression-editor {
1351
+ flex: 1 1 100%;
1352
+ min-width: 0;
1353
+ }
1354
+ .expr-literal-type {
1355
+ flex: 0 1 4rem;
1356
+ }
1357
+ .expr-literal-value {
1358
+ flex: 1 1 4.5rem;
1359
+ }
1360
+ .expr-browse-catalog,
1361
+ .expr-literal-bool {
1362
+ flex: 0 0 auto;
1363
+ }
1364
+ .expr-literal-null {
1365
+ color: var(--fg-dim);
1366
+ font-size: var(--spectrum-font-size-75, 12px);
1367
+ }
1368
+ /* The live value (spec §19.9). A resolved formula is arbitrary text — an object,
1369
+ a URL, a paragraph — so it ellipsizes inside the row it annotates and never
1370
+ sets the row's width. The same badge is drawn on the chip strip
1371
+ (ui/formula-chips.ts), which still carries its own inline copy. */
1372
+ .expr-live-badge {
1373
+ flex: 0 1 auto;
1374
+ min-width: 0;
1375
+ max-width: 100%;
1376
+ overflow: hidden;
1377
+ padding: 0 5px;
1378
+ border-radius: var(--radius);
1379
+ background: var(--spectrum-gray-200, #323232);
1380
+ color: var(--spectrum-seafoam-900, #35a690);
1381
+ font-family: var(--font-mono);
1382
+ font-size: 10px;
1383
+ line-height: 16px;
1384
+ white-space: nowrap;
1385
+ text-overflow: ellipsis;
1386
+ }
1387
+ /* Positional args (`splice`, `call`) — also drawn by ui/schema-form.ts, which
1388
+ still passes its own inline flex; the wrap and the shrink are what it gains. */
1389
+ .array-object-field {
1390
+ min-width: 0;
1391
+ }
1392
+ .array-object-row {
1393
+ display: flex;
1394
+ flex-wrap: wrap;
1395
+ align-items: center;
1396
+ gap: 4px;
1397
+ min-width: 0;
1398
+ margin-bottom: 4px;
1399
+ }
1400
+ .array-object-label {
1401
+ flex: 0 0 auto;
1402
+ min-width: 30px;
1403
+ color: var(--fg-dim);
1404
+ font-size: 10px;
1405
+ }
1406
+ .array-object-row sp-action-button {
1407
+ flex: 0 0 auto;
1408
+ }
1409
+ /* `switch` cases: matched value → result operand, plus the default row. The
1410
+ default's label keeps the key column's width so the two align. */
1411
+ .switch-cases {
1412
+ min-width: 0;
1413
+ margin-top: 4px;
1414
+ }
1415
+ .switch-case-row {
1416
+ display: flex;
1417
+ flex-wrap: wrap;
1418
+ align-items: flex-start;
1419
+ gap: 4px;
1420
+ min-width: 0;
1421
+ margin-bottom: 4px;
1422
+ }
1423
+ .switch-case-key {
1424
+ flex: 0 1 5rem;
1425
+ min-width: 0;
1426
+ }
1427
+ .switch-case-default {
1428
+ color: var(--fg-dim);
1429
+ font-size: 10px;
1430
+ line-height: 24px;
1431
+ }
1432
+ .switch-cases sp-action-button {
1433
+ flex: 0 0 auto;
1434
+ }
1435
+ /* The belt, for both editors. A Spectrum field is `--spectrum-field-width` wide
1436
+ by default (192px) and declares its own min-inline-size; a field row that
1437
+ never says otherwise is therefore ~200px of demand per control, which is the
1438
+ whole width of the rail. Outer-tree rules win over a shadow root's `:host`,
1439
+ so this is where that demand is answered. */
1440
+ .statement-editor .style-row,
1441
+ .expression-editor .style-row {
1442
+ min-width: 0;
1443
+ }
1444
+ .statement-editor sp-picker,
1445
+ .statement-editor sp-textfield,
1446
+ .statement-editor sp-number-field,
1447
+ .statement-editor sp-combobox,
1448
+ .expression-editor sp-picker,
1449
+ .expression-editor sp-textfield,
1450
+ .expression-editor sp-number-field,
1451
+ .expression-editor sp-combobox {
1452
+ min-width: 0;
1453
+ max-width: 100%;
1454
+ }