@bendyline/squisq-editor-react 1.6.2 → 2.0.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 (200) hide show
  1. package/README.md +12 -3
  2. package/dist/index.d.ts +1229 -179
  3. package/dist/index.js +18017 -11231
  4. package/dist/index.js.map +1 -1
  5. package/dist/monaco.d.ts +1 -0
  6. package/dist/monaco.js +4 -0
  7. package/dist/monaco.js.map +1 -0
  8. package/dist/styles/index.css +1471 -245
  9. package/package.json +9 -5
  10. package/src/BlockPropertiesPopover.tsx +30 -15
  11. package/src/DocumentSettingsDialog.tsx +13 -21
  12. package/src/EditorContext.tsx +199 -42
  13. package/src/EditorShell.tsx +348 -260
  14. package/src/ImageEditor.tsx +22 -1
  15. package/src/InlinePreviewGutter.tsx +16 -8
  16. package/src/MediaBin.tsx +107 -14
  17. package/src/OutlinePanel.tsx +202 -7
  18. package/src/PlainHtmlPreview.tsx +40 -1
  19. package/src/PreviewControls.tsx +309 -69
  20. package/src/PreviewPanel.tsx +312 -78
  21. package/src/RawEditor.tsx +13 -2
  22. package/src/StatusBar.tsx +5 -2
  23. package/src/TemplateAnnotation.ts +12 -3
  24. package/src/TemplatePicker.tsx +75 -21
  25. package/src/ThemeCustomizerPanel.tsx +8 -0
  26. package/src/ThemePicker.tsx +10 -5
  27. package/src/TimelineBlockPreview.tsx +1 -1
  28. package/src/Toolbar.tsx +202 -41
  29. package/src/TransitionPicker.tsx +36 -4
  30. package/src/ViewMenuPanel.tsx +12 -14
  31. package/src/WysiwygEditor.tsx +124 -91
  32. package/src/__tests__/blockPropertiesPopoverTheme.test.tsx +33 -0
  33. package/src/__tests__/blockTagActivity.test.ts +183 -0
  34. package/src/__tests__/buildDocumentPreviewMarkdown.test.ts +75 -0
  35. package/src/__tests__/buildPreviewDocContent.test.ts +48 -0
  36. package/src/__tests__/buildPreviewDocTransition.test.ts +21 -1
  37. package/src/__tests__/canvasSurfaceTextEditing.test.tsx +60 -0
  38. package/src/__tests__/customLayoutManagerTheme.test.tsx +34 -0
  39. package/src/__tests__/documentSettingsDialog.test.tsx +29 -1
  40. package/src/__tests__/editorScrollHandoff.test.tsx +102 -0
  41. package/src/__tests__/editorScrollSync.test.ts +65 -0
  42. package/src/__tests__/editorShellProps.test.tsx +123 -1
  43. package/src/__tests__/emojiPicker.test.tsx +2 -42
  44. package/src/__tests__/headingTransition.test.ts +0 -12
  45. package/src/__tests__/imageEditAffordance.test.tsx +5 -1
  46. package/src/__tests__/imageEditModalContract.test.tsx +119 -0
  47. package/src/__tests__/imageEditorShell.test.tsx +15 -1
  48. package/src/__tests__/jsonEditor.test.tsx +56 -1
  49. package/src/__tests__/layersPanel.test.tsx +75 -5
  50. package/src/__tests__/majorApiTypes.test.ts +26 -0
  51. package/src/__tests__/mediaBinDrop.test.tsx +90 -0
  52. package/src/__tests__/narrationSave.test.ts +148 -0
  53. package/src/__tests__/outlinePanel.test.tsx +93 -3
  54. package/src/__tests__/outlineSource.test.ts +217 -0
  55. package/src/__tests__/plainHtmlPreview.test.tsx +17 -1
  56. package/src/__tests__/presentationMode.test.tsx +290 -0
  57. package/src/__tests__/previewControls.test.tsx +218 -5
  58. package/src/__tests__/previewPanelAudioFailure.test.tsx +46 -0
  59. package/src/__tests__/previewPanelPresentation.test.tsx +126 -0
  60. package/src/__tests__/previewPanelTransforms.test.tsx +117 -0
  61. package/src/__tests__/rawEditorModelIsolation.test.ts +19 -0
  62. package/src/__tests__/resolveBlockVisual.test.ts +43 -0
  63. package/src/__tests__/statusBar.test.tsx +27 -0
  64. package/src/__tests__/teleprompter.test.tsx +190 -0
  65. package/src/__tests__/templateAnnotationRoundTrip.test.ts +26 -0
  66. package/src/__tests__/templatePickerPortal.test.tsx +62 -0
  67. package/src/__tests__/tiptapBridge.test.ts +23 -0
  68. package/src/__tests__/tiptapCodeBlockRoundTrip.test.ts +109 -0
  69. package/src/__tests__/transformStyleId.test.ts +13 -0
  70. package/src/__tests__/useImageEditor.test.tsx +67 -0
  71. package/src/__tests__/useMediaRecorder.test.ts +75 -0
  72. package/src/__tests__/viewMenuPanel.test.tsx +130 -0
  73. package/src/__tests__/wysiwygImageUpload.test.ts +69 -0
  74. package/src/__tests__/wysiwygTemplateBadgeFocus.test.tsx +56 -0
  75. package/src/asciiDiagram/AsciiDiagramExtension.ts +343 -0
  76. package/src/asciiDiagram/AsciiDiagramWidget.tsx +224 -0
  77. package/src/asciiDiagram/RepairableDiagramExtension.ts +200 -0
  78. package/src/asciiDiagram/__tests__/AsciiDiagramExtension.test.ts +145 -0
  79. package/src/asciiDiagram/__tests__/RepairableDiagramExtension.test.ts +159 -0
  80. package/src/asciiDiagram/__tests__/asciiDiagramCommands.test.ts +227 -0
  81. package/src/asciiDiagram/__tests__/asciiDiagramOps.test.ts +114 -0
  82. package/src/asciiDiagram/__tests__/asciiPaste.test.ts +43 -0
  83. package/src/asciiDiagram/asciiDiagramCommands.ts +148 -0
  84. package/src/asciiDiagram/asciiDiagramData.ts +116 -0
  85. package/src/asciiDiagram/asciiDiagramOps.ts +219 -0
  86. package/src/asciiDiagram/asciiPaste.ts +19 -0
  87. package/src/blockTagActivity.ts +233 -0
  88. package/src/buildDocumentPreviewMarkdown.ts +168 -0
  89. package/src/buildPreviewDoc.ts +19 -12
  90. package/src/customTemplates/CustomLayoutManager.tsx +3 -2
  91. package/src/customTemplates/CustomTemplateContext.tsx +6 -0
  92. package/src/customTemplates/TemplateDesigner.tsx +7 -4
  93. package/src/customTemplates/__tests__/library.test.ts +8 -0
  94. package/src/customTemplates/designer.css +158 -99
  95. package/src/customTemplates/library.ts +16 -3
  96. package/src/customThemes/CustomThemeContext.tsx +6 -0
  97. package/src/customThemes/CustomThemeDialog.tsx +35 -5
  98. package/src/customThemes/ImportThemeSection.tsx +178 -0
  99. package/src/customThemes/__tests__/customThemeLibrary.test.ts +9 -0
  100. package/src/customThemes/__tests__/importThemeSection.test.tsx +192 -0
  101. package/src/customThemes/customThemeLibrary.ts +7 -4
  102. package/src/customThemes/index.ts +7 -1
  103. package/src/customThemes/themeDraft.ts +23 -7
  104. package/src/diagram/DiagramCanvas.tsx +9 -4
  105. package/src/diagram/types.ts +35 -0
  106. package/src/editorScrollSync.ts +73 -0
  107. package/src/emojiData.ts +3 -23
  108. package/src/headingTransition.ts +0 -15
  109. package/src/imageEditor/CanvasSurface.tsx +29 -23
  110. package/src/imageEditor/LayersPanel.tsx +78 -3
  111. package/src/imageEditor/Toolbar.tsx +5 -1
  112. package/src/imageEditor/icons.tsx +4 -0
  113. package/src/imageEditor/image-editor.css +75 -0
  114. package/src/imageEditor/layers/SelectionHandles.tsx +1 -1
  115. package/src/imageEditor/useImageEditor.ts +71 -14
  116. package/src/index.ts +191 -19
  117. package/src/jsonEditor/JsonEditorContext.tsx +12 -6
  118. package/src/jsonEditor/RenderNode.tsx +24 -3
  119. package/src/jsonEditor/editors.tsx +86 -19
  120. package/src/mediaEntries.ts +12 -0
  121. package/src/monaco.ts +35 -0
  122. package/src/monacoWorkers.ts +89 -0
  123. package/src/outlineSource.ts +171 -0
  124. package/src/presentation/PresentationMode.tsx +596 -0
  125. package/src/rawEditorIsolation.ts +18 -0
  126. package/src/recorder/hooks/useMediaRecorder.ts +97 -53
  127. package/src/resolveBlockVisual.ts +10 -4
  128. package/src/scene/Scene.tsx +48 -18
  129. package/src/scene/SceneBlockExtension.ts +17 -10
  130. package/src/scene/SceneBlockWidget.tsx +5 -1
  131. package/src/scene/SceneViewport.tsx +7 -3
  132. package/src/scene/ShapePalette.tsx +17 -2
  133. package/src/scene/__tests__/DiagramAdapter.test.ts +86 -0
  134. package/src/scene/__tests__/SceneBlockExtension.test.ts +33 -0
  135. package/src/scene/__tests__/sceneIsolation.test.tsx +93 -0
  136. package/src/scene/adapters/DiagramAdapter.ts +12 -101
  137. package/src/scene/commands/SceneCommand.ts +4 -1
  138. package/src/scene/index.ts +1 -6
  139. package/src/scene/layers/DiagramEdges.tsx +21 -7
  140. package/src/scene/layers/edgeGeometry.ts +9 -1
  141. package/src/scene/layers/nodeCard.tsx +27 -8
  142. package/src/scene/scene.css +5 -2
  143. package/src/scene/text/SceneTextOverlay.tsx +5 -5
  144. package/src/scene/text/sceneTextChannel.ts +26 -20
  145. package/src/scene/text/sceneTextConfig.ts +4 -0
  146. package/src/scene/tools/ConnectTool.ts +13 -4
  147. package/src/scene/tools/SceneTool.ts +8 -0
  148. package/src/scene/tools/SelectTool.ts +34 -18
  149. package/src/scene/tools/ShapeTool.ts +2 -3
  150. package/src/styles/ascii-diagram.css +79 -0
  151. package/src/styles/ascii-timeline.css +499 -0
  152. package/src/styles/editor.css +706 -120
  153. package/src/styles/index.css +3 -0
  154. package/src/styles/tree-view.css +139 -0
  155. package/src/teleprompter/TeleprompterControls.tsx +218 -0
  156. package/src/teleprompter/TeleprompterSelfView.tsx +22 -0
  157. package/src/teleprompter/TeleprompterSurface.tsx +267 -0
  158. package/src/teleprompter/TeleprompterView.tsx +338 -0
  159. package/src/teleprompter/canvasRenderer.ts +161 -0
  160. package/src/teleprompter/floatingWindow.ts +352 -0
  161. package/src/teleprompter/index.ts +61 -0
  162. package/src/teleprompter/pcmWorklet.ts +62 -0
  163. package/src/teleprompter/recording/insertPreamble.ts +80 -0
  164. package/src/teleprompter/recording/narrationSave.ts +134 -0
  165. package/src/teleprompter/recording/useNarrationRecorder.ts +367 -0
  166. package/src/teleprompter/scrollModel.ts +85 -0
  167. package/src/teleprompter/teleprompterTheme.ts +303 -0
  168. package/src/teleprompter/types.ts +38 -0
  169. package/src/teleprompter/useFloatingWindow.ts +74 -0
  170. package/src/teleprompter/useMicAnalysis.ts +211 -0
  171. package/src/teleprompter/useTeleprompter.ts +421 -0
  172. package/src/templateContentPreviewResolver.ts +12 -5
  173. package/src/timeline/TimelineEditorWidget.tsx +702 -0
  174. package/src/timeline/TimelineViewExtension.ts +252 -0
  175. package/src/timeline/__tests__/TimelineEditorWidget.test.tsx +355 -0
  176. package/src/timeline/__tests__/TimelineViewExtension.test.ts +163 -0
  177. package/src/timeline/__tests__/timelineCommands.test.ts +327 -0
  178. package/src/timeline/__tests__/timelineOps.test.ts +222 -0
  179. package/src/timeline/__tests__/timelinePaste.test.ts +34 -0
  180. package/src/timeline/timelineCommands.ts +367 -0
  181. package/src/timeline/timelineData.ts +54 -0
  182. package/src/timeline/timelineOps.ts +277 -0
  183. package/src/timeline/timelinePaste.ts +8 -0
  184. package/src/tiptapBridge.ts +24 -16
  185. package/src/transformStyleId.ts +17 -0
  186. package/src/treeview/TreeOutlineWidget.tsx +240 -0
  187. package/src/treeview/TreeViewExtension.ts +250 -0
  188. package/src/treeview/__tests__/TreeViewExtension.test.ts +122 -0
  189. package/src/treeview/__tests__/treeOps.test.ts +125 -0
  190. package/src/treeview/__tests__/treePaste.test.ts +40 -0
  191. package/src/treeview/__tests__/treeViewCommands.test.ts +163 -0
  192. package/src/treeview/treeOps.ts +172 -0
  193. package/src/treeview/treePaste.ts +13 -0
  194. package/src/treeview/treeViewCommands.ts +94 -0
  195. package/src/treeview/treeViewData.ts +41 -0
  196. package/src/useMonacoLoader.ts +11 -34
  197. package/src/wysiwygImageUpload.ts +113 -0
  198. package/src/diagram/DiagramExtension.ts +0 -209
  199. package/src/diagram/DiagramWidget.tsx +0 -272
  200. package/src/diagram/useDiagramData.ts +0 -126
@@ -131,6 +131,216 @@
131
131
  box-sizing: border-box;
132
132
  }
133
133
 
134
+ .squisq-toolbar-view-tab-wrap {
135
+ display: flex;
136
+ align-items: flex-end;
137
+ align-self: stretch;
138
+ }
139
+
140
+ /* The Use tab owns the primary preview-mode chooser. Keeping the arrow in the
141
+ tab cluster makes mode selection available before entering Use and frees the
142
+ preview toolbar for format/theme/output settings. */
143
+ .squisq-toolbar-use-tab {
144
+ border-bottom: 2px solid transparent;
145
+ }
146
+
147
+ .squisq-toolbar-use-tab > .squisq-toolbar-view-tab {
148
+ padding-right: 4px;
149
+ padding-bottom: 4px;
150
+ border-bottom: 0;
151
+ }
152
+
153
+ .squisq-toolbar-use-tab--active {
154
+ border-bottom-color: #2563eb;
155
+ }
156
+
157
+ .squisq-use-mode-trigger {
158
+ align-self: stretch;
159
+ display: inline-flex;
160
+ align-items: flex-end;
161
+ justify-content: center;
162
+ width: 20px;
163
+ padding: 0 6px 9px 0;
164
+ border: 0;
165
+ background: transparent;
166
+ color: #4b5563;
167
+ cursor: pointer;
168
+ box-sizing: content-box;
169
+ }
170
+
171
+ .squisq-use-mode-trigger > svg {
172
+ display: block;
173
+ transform: translateY(-1px);
174
+ }
175
+
176
+ .squisq-use-mode-trigger:hover,
177
+ .squisq-use-mode-trigger--open {
178
+ color: #111827;
179
+ }
180
+
181
+ .squisq-toolbar-use-tab--active .squisq-use-mode-trigger {
182
+ color: #1d4ed8;
183
+ }
184
+
185
+ .squisq-use-mode-menu {
186
+ position: fixed;
187
+ z-index: 120;
188
+ width: min(340px, calc(100vw - 16px));
189
+ padding: 6px;
190
+ border: 1px solid #d1d5db;
191
+ border-radius: 10px;
192
+ background: #ffffff;
193
+ box-shadow:
194
+ 0 12px 32px rgba(15, 23, 42, 0.2),
195
+ 0 2px 6px rgba(15, 23, 42, 0.08);
196
+ box-sizing: border-box;
197
+ font-family:
198
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
199
+ animation: squisq-use-mode-menu-in 0.12s ease-out;
200
+ }
201
+
202
+ .squisq-use-mode-menu-item {
203
+ display: flex;
204
+ align-items: center;
205
+ gap: 10px;
206
+ width: 100%;
207
+ min-height: 52px;
208
+ padding: 7px 9px;
209
+ border: 0;
210
+ border-radius: 7px;
211
+ background: transparent;
212
+ color: #374151;
213
+ font: inherit;
214
+ text-align: left;
215
+ cursor: pointer;
216
+ transition:
217
+ background 0.12s ease,
218
+ color 0.12s ease;
219
+ }
220
+
221
+ .squisq-use-mode-menu-item:hover,
222
+ .squisq-use-mode-menu-item:focus-visible {
223
+ outline: none;
224
+ background: #f3f4f6;
225
+ color: #111827;
226
+ }
227
+
228
+ .squisq-use-mode-menu-item--selected {
229
+ background: #eff6ff;
230
+ color: #1d4ed8;
231
+ }
232
+
233
+ .squisq-use-mode-menu-icon {
234
+ display: inline-flex;
235
+ align-items: center;
236
+ justify-content: center;
237
+ width: 32px;
238
+ height: 32px;
239
+ flex: 0 0 32px;
240
+ border-radius: 8px;
241
+ background: #f1f5f9;
242
+ color: #64748b;
243
+ font-size: 14px;
244
+ }
245
+
246
+ .squisq-use-mode-menu-item--selected .squisq-use-mode-menu-icon {
247
+ background: #dbeafe;
248
+ color: #2563eb;
249
+ }
250
+
251
+ .squisq-use-mode-menu-copy {
252
+ display: flex;
253
+ flex: 1 1 auto;
254
+ min-width: 0;
255
+ flex-direction: column;
256
+ gap: 2px;
257
+ }
258
+
259
+ .squisq-use-mode-menu-label {
260
+ color: inherit;
261
+ font-size: 12.5px;
262
+ font-weight: 650;
263
+ line-height: 1.2;
264
+ }
265
+
266
+ .squisq-use-mode-menu-summary {
267
+ overflow: hidden;
268
+ color: #6b7280;
269
+ font-size: 11.5px;
270
+ font-weight: 400;
271
+ line-height: 1.3;
272
+ text-overflow: ellipsis;
273
+ white-space: nowrap;
274
+ }
275
+
276
+ .squisq-use-mode-menu-check {
277
+ display: inline-flex;
278
+ align-items: center;
279
+ justify-content: center;
280
+ width: 16px;
281
+ flex: 0 0 16px;
282
+ color: #2563eb;
283
+ font-size: 11px;
284
+ text-align: center;
285
+ }
286
+
287
+ @keyframes squisq-use-mode-menu-in {
288
+ from {
289
+ opacity: 0;
290
+ transform: translateY(-3px) scale(0.99);
291
+ }
292
+ to {
293
+ opacity: 1;
294
+ transform: translateY(0) scale(1);
295
+ }
296
+ }
297
+
298
+ @media (prefers-reduced-motion: reduce) {
299
+ .squisq-use-mode-menu {
300
+ animation: none;
301
+ }
302
+ }
303
+
304
+ .squisq-use-mode-menu[data-theme='dark'] {
305
+ border-color: #4b5563;
306
+ background: #1f2937;
307
+ }
308
+
309
+ .squisq-use-mode-menu[data-theme='dark'] .squisq-use-mode-menu-item {
310
+ color: #d1d5db;
311
+ }
312
+
313
+ .squisq-use-mode-menu[data-theme='dark'] .squisq-use-mode-menu-item:hover,
314
+ .squisq-use-mode-menu[data-theme='dark'] .squisq-use-mode-menu-item:focus-visible {
315
+ background: #374151;
316
+ color: #f9fafb;
317
+ }
318
+
319
+ .squisq-use-mode-menu[data-theme='dark'] .squisq-use-mode-menu-item--selected {
320
+ background: #172f4f;
321
+ color: #93c5fd;
322
+ }
323
+
324
+ .squisq-use-mode-menu[data-theme='dark'] .squisq-use-mode-menu-icon {
325
+ background: #334155;
326
+ color: #cbd5e1;
327
+ }
328
+
329
+ .squisq-use-mode-menu[data-theme='dark']
330
+ .squisq-use-mode-menu-item--selected
331
+ .squisq-use-mode-menu-icon {
332
+ background: #1e4976;
333
+ color: #bfdbfe;
334
+ }
335
+
336
+ .squisq-use-mode-menu[data-theme='dark'] .squisq-use-mode-menu-summary {
337
+ color: #94a3b8;
338
+ }
339
+
340
+ .squisq-use-mode-menu[data-theme='dark'] .squisq-use-mode-menu-check {
341
+ color: #93c5fd;
342
+ }
343
+
134
344
  /* When the outline pane is visible, anchor the toolbar's view-tabs section
135
345
  * to the outline pane's width so their right-edge dividers line up
136
346
  * vertically — otherwise the view-tabs border and the outline's right edge
@@ -1385,7 +1595,7 @@
1385
1595
  border: 0;
1386
1596
  border-radius: 0;
1387
1597
  vertical-align: baseline;
1388
- transform: translateY(2px);
1598
+ transform: translate(3px, 0);
1389
1599
  user-select: none;
1390
1600
  line-height: 1;
1391
1601
  cursor: pointer;
@@ -1499,6 +1709,26 @@
1499
1709
  display: none;
1500
1710
  }
1501
1711
 
1712
+ /* In active mode the selection and pointer classes are independent, so tags
1713
+ * can be visible on two heading-defined blocks at once. Gate both on the
1714
+ * ProseMirror focus class: the document keeps its selection after blur, but a
1715
+ * non-blinking caret should not leave that remembered block's tags behind. */
1716
+ .squisq-wysiwyg-container[data-block-tags='active'] .squisq-template-badge,
1717
+ .squisq-wysiwyg-container[data-block-tags='active'] .squisq-props-badge {
1718
+ display: none;
1719
+ }
1720
+
1721
+ .squisq-wysiwyg-container[data-block-tags='active']
1722
+ .squisq-wysiwyg-editor.ProseMirror-focused
1723
+ :is(.squisq-block-tags--selected, .squisq-block-tags--hovered)
1724
+ > .squisq-template-badge,
1725
+ .squisq-wysiwyg-container[data-block-tags='active']
1726
+ .squisq-wysiwyg-editor.ProseMirror-focused
1727
+ :is(.squisq-block-tags--selected, .squisq-block-tags--hovered)
1728
+ > .squisq-props-badge {
1729
+ display: inline-flex;
1730
+ }
1731
+
1502
1732
  /* ─── Block-properties badge (sibling of the template badge) ───────────
1503
1733
  The on-canvas entry point to the block-properties palette: a small
1504
1734
  sliders chip just after the template badge. Quiet by default like the
@@ -1521,6 +1751,7 @@
1521
1751
  border: 1px solid #d1d5db;
1522
1752
  border-radius: 10px;
1523
1753
  vertical-align: middle;
1754
+ transform: translate(3px, -2px);
1524
1755
  user-select: none;
1525
1756
  cursor: pointer;
1526
1757
  opacity: 0.5;
@@ -1532,11 +1763,12 @@
1532
1763
 
1533
1764
  /* Sliders glyph painted via CSS so the badge span stays empty in the DOM
1534
1765
  (see propsBadgeSpec — a real child could leak into serialized markdown).
1535
- `\f1de` is Font Awesome's "sliders"; the font is already loaded for the
1536
- editor's inline-icon glyph decorations. */
1766
+ `\f1de` is Font Awesome's "sliders"; use Font Awesome's own family
1767
+ variable so this follows the bundled major version instead of resolving
1768
+ against a stale hard-coded family name. */
1537
1769
  .squisq-props-badge::before {
1538
1770
  content: '\f1de';
1539
- font-family: 'Font Awesome 6 Free';
1771
+ font-family: var(--fa-family-classic, 'Font Awesome 7 Free');
1540
1772
  font-weight: 900;
1541
1773
  font-size: 10px;
1542
1774
  line-height: 1;
@@ -1546,9 +1778,9 @@
1546
1778
  it after the glyph — and reads as an active (not just affordance) chip. */
1547
1779
  .squisq-props-badge[data-props-summary] {
1548
1780
  opacity: 1;
1549
- color: #6d28d9;
1550
- background: #f5f3ff;
1551
- border-color: #c4b5fd;
1781
+ color: var(--squisq-block-props-accent, inherit);
1782
+ background: color-mix(in oklch, currentColor 12%, transparent);
1783
+ border-color: color-mix(in oklch, currentColor 35%, transparent);
1552
1784
  }
1553
1785
 
1554
1786
  .squisq-props-badge[data-props-summary]::after {
@@ -1565,13 +1797,39 @@
1565
1797
  .squisq-props-badge:hover,
1566
1798
  .squisq-props-badge:focus-visible {
1567
1799
  opacity: 1;
1568
- color: #6d28d9;
1569
- background: #ede9fe;
1570
- border-color: #c4b5fd;
1800
+ color: var(--squisq-block-props-accent, inherit);
1801
+ background: color-mix(in oklch, currentColor 16%, transparent);
1802
+ border-color: color-mix(in oklch, currentColor 42%, transparent);
1571
1803
  outline: none;
1572
1804
  }
1573
1805
 
1574
1806
  /* ─── Block-properties palette popover (portaled to <body>) ──────────── */
1807
+ :is(.squisq-block-props-popover, .squisq-transition-picker, .squisq-transition-flyout) {
1808
+ --squisq-block-props-surface: #ffffff;
1809
+ --squisq-block-props-surface-hover: #f3f4f6;
1810
+ --squisq-block-props-input: #ffffff;
1811
+ --squisq-block-props-text: #111827;
1812
+ --squisq-block-props-muted: #6b7280;
1813
+ --squisq-block-props-quiet: #9ca3af;
1814
+ --squisq-block-props-border: #d1d5db;
1815
+ --squisq-block-props-divider: #e5e7eb;
1816
+ }
1817
+
1818
+ :is(
1819
+ .squisq-block-props-popover,
1820
+ .squisq-transition-picker,
1821
+ .squisq-transition-flyout
1822
+ )[data-theme='dark'] {
1823
+ --squisq-block-props-surface: #1f2937;
1824
+ --squisq-block-props-surface-hover: #374151;
1825
+ --squisq-block-props-input: #111827;
1826
+ --squisq-block-props-text: #f9fafb;
1827
+ --squisq-block-props-muted: #d1d5db;
1828
+ --squisq-block-props-quiet: #9ca3af;
1829
+ --squisq-block-props-border: #4b5563;
1830
+ --squisq-block-props-divider: #374151;
1831
+ }
1832
+
1575
1833
  .squisq-block-props-popover {
1576
1834
  width: 280px;
1577
1835
  max-width: calc(100vw - 24px);
@@ -1579,8 +1837,9 @@
1579
1837
  display: flex;
1580
1838
  flex-direction: column;
1581
1839
  gap: 10px;
1582
- background: #fff;
1583
- border: 1px solid #e5e7eb;
1840
+ color: var(--squisq-block-props-text);
1841
+ background: var(--squisq-block-props-surface);
1842
+ border: 1px solid var(--squisq-block-props-divider);
1584
1843
  border-radius: 10px;
1585
1844
  box-shadow:
1586
1845
  0 8px 24px rgba(0, 0, 0, 0.12),
@@ -1597,7 +1856,7 @@
1597
1856
  .squisq-block-props-label {
1598
1857
  font-size: 11px;
1599
1858
  font-weight: 600;
1600
- color: #6b7280;
1859
+ color: var(--squisq-block-props-muted);
1601
1860
  flex-shrink: 0;
1602
1861
  }
1603
1862
 
@@ -1611,54 +1870,47 @@
1611
1870
  width: 72px;
1612
1871
  padding: 4px 6px;
1613
1872
  font-size: 12px;
1614
- color: #111827;
1615
- border: 1px solid #d1d5db;
1873
+ color: var(--squisq-block-props-text);
1874
+ background: var(--squisq-block-props-input);
1875
+ border: 1px solid var(--squisq-block-props-border);
1616
1876
  border-radius: 5px;
1617
1877
  outline: none;
1618
1878
  }
1619
1879
 
1620
1880
  .squisq-block-props-input:focus {
1621
- border-color: #6366f1;
1881
+ border-color: var(--squisq-block-props-accent, #6366f1);
1622
1882
  }
1623
1883
 
1624
1884
  .squisq-block-props-unit {
1625
1885
  font-size: 11px;
1626
- color: #9ca3af;
1886
+ color: var(--squisq-block-props-quiet);
1627
1887
  }
1628
1888
 
1629
1889
  /* Dark theme */
1630
- .squisq-editor-shell[data-theme='dark'] .squisq-props-badge {
1890
+ .squisq-editor-shell[data-theme='dark'] .squisq-props-badge:not([data-props-summary]) {
1631
1891
  border-color: #4b5563;
1632
1892
  color: #9ca3af;
1633
1893
  }
1634
1894
 
1635
1895
  .squisq-editor-shell[data-theme='dark'] .squisq-props-badge[data-props-summary] {
1636
- color: #ddd6fe;
1637
- background: #3730a3;
1638
- border-color: #6d5fd6;
1896
+ color: var(--squisq-block-props-accent, inherit);
1897
+ background: color-mix(in oklch, currentColor 24%, transparent);
1898
+ border-color: color-mix(in oklch, currentColor 52%, transparent);
1639
1899
  }
1640
1900
 
1641
1901
  .squisq-editor-shell[data-theme='dark'] .squisq-props-badge:hover,
1642
1902
  .squisq-editor-shell[data-theme='dark'] .squisq-props-badge:focus-visible {
1643
- color: #ede9fe;
1644
- background: #4c1d95;
1645
- border-color: #7c3aed;
1903
+ color: var(--squisq-block-props-accent, inherit);
1904
+ background: color-mix(in oklch, currentColor 28%, transparent);
1905
+ border-color: color-mix(in oklch, currentColor 58%, transparent);
1646
1906
  }
1647
1907
 
1648
- .squisq-editor-shell[data-theme='dark'] .squisq-block-props-popover {
1649
- background: #1f2937;
1650
- border-color: #374151;
1908
+ .squisq-block-props-popover[data-theme='dark'] {
1651
1909
  box-shadow:
1652
1910
  0 8px 24px rgba(0, 0, 0, 0.4),
1653
1911
  0 2px 6px rgba(0, 0, 0, 0.2);
1654
1912
  }
1655
1913
 
1656
- .squisq-editor-shell[data-theme='dark'] .squisq-block-props-input {
1657
- background: #111827;
1658
- color: #f9fafb;
1659
- border-color: #4b5563;
1660
- }
1661
-
1662
1914
  /* ─── Status Bar ─────────────────────────────────────── */
1663
1915
 
1664
1916
  .squisq-status-bar {
@@ -1771,10 +2023,14 @@
1771
2023
  }
1772
2024
  .squisq-wysiwyg-editor h2 {
1773
2025
  font-size: 1.5em;
1774
- margin: 0.65em 0 0.35em;
2026
+ margin: 0.8em 0 0.25em;
1775
2027
  }
1776
2028
  .squisq-wysiwyg-editor h3 {
1777
2029
  font-size: 1.17em;
2030
+ /* The inline template/property controls are 22–23px tall. Reserve their
2031
+ line-box height while they are hidden so active-mode hover does not make
2032
+ an H3 (and the content below it) jump by a pixel or two. */
2033
+ min-height: 26px;
1778
2034
  margin: 1.3em 0 0.3em;
1779
2035
  }
1780
2036
  .squisq-wysiwyg-editor h4 {
@@ -1800,7 +2056,7 @@
1800
2056
 
1801
2057
  .squisq-wysiwyg-editor p {
1802
2058
  margin: 0.5em 0;
1803
- line-height: 1.6;
2059
+ line-height: 1.7;
1804
2060
  }
1805
2061
 
1806
2062
  .squisq-wysiwyg-editor blockquote {
@@ -1824,6 +2080,10 @@
1824
2080
  overflow-x: auto;
1825
2081
  font-size: 13px;
1826
2082
  line-height: 1.5;
2083
+ /* Explicit monospace: the container sets a themed sans body font, so
2084
+ UA defaults for <pre> are not reliable inside it. Column-aligned
2085
+ content (ASCII diagrams) depends on this. */
2086
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
1827
2087
  }
1828
2088
 
1829
2089
  .squisq-wysiwyg-editor code {
@@ -1832,6 +2092,7 @@
1832
2092
  padding: 1px 4px;
1833
2093
  border-radius: 3px;
1834
2094
  font-size: 0.9em;
2095
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
1835
2096
  }
1836
2097
 
1837
2098
  .squisq-wysiwyg-editor pre code {
@@ -2163,6 +2424,54 @@
2163
2424
  cursor: pointer;
2164
2425
  }
2165
2426
 
2427
+ /* Presentation is a fixed split button after the adaptive Use controls, so
2428
+ it remains available even when individual preview settings overflow. */
2429
+ .squisq-presentation-control {
2430
+ display: inline-flex;
2431
+ align-items: center;
2432
+ flex: 0 0 auto;
2433
+ margin: 0 5px 0 3px;
2434
+ border: 1px solid var(--squisq-border, #d1d5db);
2435
+ border-radius: 5px;
2436
+ background: var(--squisq-input-bg, #fff);
2437
+ overflow: hidden;
2438
+ }
2439
+
2440
+ .squisq-presentation-control .squisq-presentation-start {
2441
+ width: 30px;
2442
+ border-radius: 0;
2443
+ }
2444
+
2445
+ .squisq-presentation-menu-trigger {
2446
+ align-self: stretch;
2447
+ display: inline-flex;
2448
+ align-items: center;
2449
+ justify-content: center;
2450
+ width: 18px;
2451
+ padding: 0;
2452
+ border: 0;
2453
+ border-left: 1px solid var(--squisq-border, #d1d5db);
2454
+ background: transparent;
2455
+ color: var(--squisq-text-muted, #6b7280);
2456
+ cursor: pointer;
2457
+ }
2458
+
2459
+ .squisq-presentation-menu-trigger:hover,
2460
+ .squisq-presentation-menu-trigger--open {
2461
+ background: rgba(107, 114, 128, 0.2);
2462
+ color: var(--squisq-text, #111827);
2463
+ }
2464
+
2465
+ .squisq-presentation-menu-item:disabled {
2466
+ cursor: not-allowed;
2467
+ opacity: 0.55;
2468
+ }
2469
+
2470
+ .squisq-presentation-menu-item:disabled:hover {
2471
+ background: transparent;
2472
+ color: inherit;
2473
+ }
2474
+
2166
2475
  /* Link color follows the active theme's primary when "Theme styling →
2167
2476
  Fonts & colors" is on, otherwise falls back to the historical blue.
2168
2477
  In both cases we blend toward the surface text color so the link
@@ -2223,6 +2532,136 @@
2223
2532
  color: #dc2626;
2224
2533
  }
2225
2534
 
2535
+ /* Bounded presentation keeps the host page intact while giving the entire
2536
+ EditorShell to the active Use surface. Browser fullscreen uses the same
2537
+ chrome suppression, then lets the Fullscreen API size the shell. */
2538
+ .squisq-editor-shell[data-presentation-mode='control'],
2539
+ .squisq-editor-shell[data-presentation-mode='fullscreen'] {
2540
+ position: relative;
2541
+ background: #000;
2542
+ }
2543
+
2544
+ .squisq-editor-shell[data-presentation-mode='control'] > .squisq-editor-header,
2545
+ .squisq-editor-shell[data-presentation-mode='fullscreen'] > .squisq-editor-header,
2546
+ .squisq-editor-shell[data-presentation-mode='control'] > .squisq-status-bar,
2547
+ .squisq-editor-shell[data-presentation-mode='fullscreen'] > .squisq-status-bar,
2548
+ .squisq-editor-shell[data-presentation-mode='control'] > .squisq-timeline,
2549
+ .squisq-editor-shell[data-presentation-mode='fullscreen'] > .squisq-timeline {
2550
+ display: none;
2551
+ }
2552
+
2553
+ .squisq-editor-shell[data-presentation-mode='control'] .squisq-media-bin,
2554
+ .squisq-editor-shell[data-presentation-mode='fullscreen'] .squisq-media-bin,
2555
+ .squisq-editor-shell[data-presentation-mode='control'] .squisq-custom-theme-pane,
2556
+ .squisq-editor-shell[data-presentation-mode='fullscreen'] .squisq-custom-theme-pane {
2557
+ display: none;
2558
+ }
2559
+
2560
+ .squisq-editor-shell[data-presentation-mode='control'] .squisq-preview-player,
2561
+ .squisq-editor-shell[data-presentation-mode='fullscreen'] .squisq-preview-player {
2562
+ padding: 0;
2563
+ background: #000;
2564
+ }
2565
+
2566
+ .squisq-editor-shell[data-presentation-mode='fullscreen']:fullscreen {
2567
+ width: 100vw !important;
2568
+ height: 100vh !important;
2569
+ min-width: 0 !important;
2570
+ min-height: 0 !important;
2571
+ max-width: none !important;
2572
+ max-height: none !important;
2573
+ }
2574
+
2575
+ .squisq-presentation-exit {
2576
+ position: absolute;
2577
+ z-index: 1001;
2578
+ top: 12px;
2579
+ right: 12px;
2580
+ display: inline-flex;
2581
+ align-items: center;
2582
+ gap: 7px;
2583
+ min-height: 34px;
2584
+ padding: 7px 11px;
2585
+ border: 1px solid rgba(255, 255, 255, 0.35);
2586
+ border-radius: 7px;
2587
+ background: rgba(15, 23, 42, 0.78);
2588
+ color: #fff;
2589
+ font: 600 12px/1 var(--squisq-ux-font, sans-serif);
2590
+ cursor: pointer;
2591
+ opacity: 0.72;
2592
+ backdrop-filter: blur(8px);
2593
+ transition:
2594
+ opacity 0.12s ease,
2595
+ background 0.12s ease;
2596
+ }
2597
+
2598
+ .squisq-presentation-exit:hover,
2599
+ .squisq-presentation-exit:focus-visible {
2600
+ outline: none;
2601
+ background: rgba(15, 23, 42, 0.94);
2602
+ opacity: 1;
2603
+ }
2604
+
2605
+ .squisq-presentation-window {
2606
+ width: 100%;
2607
+ height: 100%;
2608
+ display: flex;
2609
+ overflow: hidden;
2610
+ background: #000;
2611
+ }
2612
+
2613
+ .squisq-presentation-window-preview,
2614
+ .squisq-presentation-window-surface,
2615
+ .squisq-presentation-teleprompter {
2616
+ width: 100%;
2617
+ height: 100%;
2618
+ min-width: 0;
2619
+ min-height: 0;
2620
+ }
2621
+
2622
+ .squisq-presentation-window-preview {
2623
+ display: flex;
2624
+ }
2625
+
2626
+ .squisq-presentation-window-surface {
2627
+ padding: 0;
2628
+ background: #000;
2629
+ pointer-events: none;
2630
+ }
2631
+
2632
+ .squisq-presentation-teleprompter {
2633
+ display: flex;
2634
+ overflow: hidden;
2635
+ pointer-events: none;
2636
+ }
2637
+
2638
+ .squisq-presentation-connecting {
2639
+ color: rgba(255, 255, 255, 0.72);
2640
+ font: 500 14px/1.4 var(--squisq-ux-font, sans-serif);
2641
+ }
2642
+
2643
+ .squisq-presentation-error {
2644
+ position: fixed;
2645
+ z-index: 10000;
2646
+ top: 16px;
2647
+ left: 50%;
2648
+ max-width: min(420px, calc(100vw - 32px));
2649
+ padding: 10px 14px;
2650
+ border: 1px solid #fecaca;
2651
+ border-radius: 8px;
2652
+ background: #fff1f2;
2653
+ color: #991b1b;
2654
+ box-shadow: 0 10px 30px rgba(15, 23, 42, 0.2);
2655
+ font: 500 13px/1.4 var(--squisq-ux-font, sans-serif);
2656
+ transform: translateX(-50%);
2657
+ }
2658
+
2659
+ .squisq-presentation-error[data-theme='dark'] {
2660
+ border-color: #7f1d1d;
2661
+ background: #3f151b;
2662
+ color: #fecdd3;
2663
+ }
2664
+
2226
2665
  /* ─── CSS custom properties ──────────────────────────── */
2227
2666
 
2228
2667
  .squisq-editor-shell {
@@ -2295,6 +2734,20 @@
2295
2734
  border-bottom-color: #60a5fa;
2296
2735
  }
2297
2736
 
2737
+ .squisq-editor-shell[data-theme='dark'] .squisq-toolbar-use-tab--active {
2738
+ border-bottom-color: #60a5fa;
2739
+ }
2740
+
2741
+ .squisq-editor-shell[data-theme='dark'] .squisq-use-mode-trigger {
2742
+ color: #d1d5db;
2743
+ }
2744
+
2745
+ .squisq-editor-shell[data-theme='dark'] .squisq-use-mode-trigger:hover,
2746
+ .squisq-editor-shell[data-theme='dark'] .squisq-use-mode-trigger--open,
2747
+ .squisq-editor-shell[data-theme='dark'] .squisq-toolbar-use-tab--active .squisq-use-mode-trigger {
2748
+ color: #93c5fd;
2749
+ }
2750
+
2298
2751
  .squisq-editor-shell[data-theme='dark'] .squisq-toolbar-button {
2299
2752
  color: #d1d5db;
2300
2753
  }
@@ -2708,6 +3161,7 @@
2708
3161
  /* ─── Media Bin ──────────────────────────────────────── */
2709
3162
 
2710
3163
  .squisq-media-bin {
3164
+ position: relative;
2711
3165
  width: 220px;
2712
3166
  border-left: 1px solid #e5e7eb;
2713
3167
  background: #f9fafb;
@@ -2717,6 +3171,46 @@
2717
3171
  overflow: hidden;
2718
3172
  }
2719
3173
 
3174
+ .squisq-media-bin-drop-target {
3175
+ position: absolute;
3176
+ inset: 6px;
3177
+ z-index: 5;
3178
+ display: flex;
3179
+ flex-direction: column;
3180
+ align-items: center;
3181
+ justify-content: center;
3182
+ gap: 4px;
3183
+ border: 2px dashed #2563eb;
3184
+ border-radius: 6px;
3185
+ background: rgba(239, 246, 255, 0.96);
3186
+ color: #1d4ed8;
3187
+ font-size: 12px;
3188
+ text-align: center;
3189
+ pointer-events: none;
3190
+ }
3191
+
3192
+ .squisq-media-bin-drop-target-icon {
3193
+ display: flex;
3194
+ align-items: center;
3195
+ justify-content: center;
3196
+ width: 28px;
3197
+ height: 28px;
3198
+ border-radius: 999px;
3199
+ background: #2563eb;
3200
+ color: #fff;
3201
+ font-size: 22px;
3202
+ font-weight: 400;
3203
+ line-height: 1;
3204
+ }
3205
+
3206
+ .squisq-media-bin-drop-target strong {
3207
+ font-size: 13px;
3208
+ }
3209
+
3210
+ .squisq-media-bin-drop-target span:last-child {
3211
+ color: #64748b;
3212
+ }
3213
+
2720
3214
  .squisq-media-bin-header {
2721
3215
  display: flex;
2722
3216
  align-items: center;
@@ -2904,6 +3398,21 @@
2904
3398
  border-left-color: #374151;
2905
3399
  }
2906
3400
 
3401
+ .squisq-media-bin--dark .squisq-media-bin-drop-target,
3402
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin .squisq-media-bin-drop-target {
3403
+ border-color: #60a5fa;
3404
+ background: rgba(15, 23, 42, 0.96);
3405
+ color: #bfdbfe;
3406
+ }
3407
+
3408
+ .squisq-media-bin--dark .squisq-media-bin-drop-target span:last-child,
3409
+ .squisq-editor-shell[data-theme='dark']
3410
+ .squisq-media-bin
3411
+ .squisq-media-bin-drop-target
3412
+ span:last-child {
3413
+ color: #94a3b8;
3414
+ }
3415
+
2907
3416
  .squisq-media-bin--dark .squisq-media-bin-header,
2908
3417
  .squisq-editor-shell[data-theme='dark'] .squisq-media-bin .squisq-media-bin-header {
2909
3418
  border-bottom-color: #374151;
@@ -3991,6 +4500,69 @@
3991
4500
  background: #1d4ed8;
3992
4501
  }
3993
4502
 
4503
+ /* "Import from file" affordance (shared by the customizer popover + designer pane) */
4504
+ .squisq-theme-import {
4505
+ display: flex;
4506
+ flex-direction: column;
4507
+ gap: 6px;
4508
+ }
4509
+
4510
+ .squisq-theme-import-drop {
4511
+ display: flex;
4512
+ align-items: center;
4513
+ gap: 8px;
4514
+ padding: 8px;
4515
+ border: 1px dashed var(--squisq-border, #d1d5db);
4516
+ border-radius: 6px;
4517
+ background: var(--squisq-input-bg, #f9fafb);
4518
+ }
4519
+
4520
+ .squisq-theme-import-drop--active {
4521
+ border-color: #2563eb;
4522
+ background: rgba(37, 99, 235, 0.08);
4523
+ }
4524
+
4525
+ .squisq-theme-import-drop--busy {
4526
+ opacity: 0.7;
4527
+ pointer-events: none;
4528
+ }
4529
+
4530
+ .squisq-theme-import-hint {
4531
+ font-size: 11px;
4532
+ color: var(--squisq-text-muted, #6b7280);
4533
+ }
4534
+
4535
+ .squisq-theme-import-status {
4536
+ font-size: 11px;
4537
+ color: var(--squisq-text-muted, #6b7280);
4538
+ }
4539
+
4540
+ .squisq-theme-import-error {
4541
+ font-size: 11px;
4542
+ color: #dc2626;
4543
+ }
4544
+
4545
+ .squisq-theme-import-warnings {
4546
+ margin: 0;
4547
+ padding-left: 16px;
4548
+ font-size: 11px;
4549
+ color: var(--squisq-text-muted, #6b7280);
4550
+ }
4551
+
4552
+ .squisq-editor-shell[data-theme='dark'] .squisq-theme-import-drop {
4553
+ border-color: #374151;
4554
+ background: #111827;
4555
+ }
4556
+
4557
+ .squisq-editor-shell[data-theme='dark'] .squisq-theme-import-drop--active {
4558
+ border-color: #3b82f6;
4559
+ background: rgba(59, 130, 246, 0.12);
4560
+ }
4561
+
4562
+ .squisq-editor-shell[data-theme='dark'] .squisq-theme-import-error {
4563
+ color: #f87171;
4564
+ }
4565
+
3994
4566
  .squisq-editor-shell[data-theme='dark'] .squisq-theme-customizer-popover {
3995
4567
  background: #1f2937;
3996
4568
  border-color: #374151;
@@ -4803,6 +5375,7 @@
4803
5375
  }
4804
5376
 
4805
5377
  .squisq-outline-item {
5378
+ position: relative;
4806
5379
  margin: 0;
4807
5380
  }
4808
5381
 
@@ -4827,6 +5400,56 @@
4827
5400
  background: #f3f4f6;
4828
5401
  }
4829
5402
 
5403
+ .squisq-outline-row[draggable='true'] {
5404
+ cursor: grab;
5405
+ }
5406
+
5407
+ .squisq-outline-row[draggable='true']:active {
5408
+ cursor: grabbing;
5409
+ }
5410
+
5411
+ .squisq-outline-drag-handle {
5412
+ display: inline-flex;
5413
+ align-items: center;
5414
+ justify-content: center;
5415
+ flex: 0 0 8px;
5416
+ color: currentColor;
5417
+ opacity: 0.35;
5418
+ transition: opacity 0.1s ease;
5419
+ }
5420
+
5421
+ .squisq-outline-row:hover .squisq-outline-drag-handle,
5422
+ .squisq-outline-row:focus-visible .squisq-outline-drag-handle {
5423
+ opacity: 0.75;
5424
+ }
5425
+
5426
+ .squisq-outline-item--dragging {
5427
+ opacity: 0.42;
5428
+ }
5429
+
5430
+ .squisq-outline-item--drop-before > .squisq-outline-row-wrap::before,
5431
+ .squisq-outline-item--drop-after::after {
5432
+ content: '';
5433
+ position: absolute;
5434
+ z-index: 2;
5435
+ left: 4px;
5436
+ right: 4px;
5437
+ height: 2px;
5438
+ border-radius: 999px;
5439
+ background: var(--squisq-outline-accent, #4338ca);
5440
+ pointer-events: none;
5441
+ }
5442
+
5443
+ .squisq-outline-item--drop-before > .squisq-outline-row-wrap::before {
5444
+ top: -1px;
5445
+ }
5446
+
5447
+ /* The after marker belongs to the whole tree item so a parent section's
5448
+ insertion boundary appears below its complete nested subtree. */
5449
+ .squisq-outline-item--drop-after::after {
5450
+ bottom: -1px;
5451
+ }
5452
+
4830
5453
  .squisq-outline-row-text {
4831
5454
  overflow: hidden;
4832
5455
  text-overflow: ellipsis;
@@ -4997,10 +5620,7 @@
4997
5620
  color: #d1d5db;
4998
5621
  }
4999
5622
 
5000
- /* Dark-mode rebind for all preview-gutter custom properties. Individual
5001
- rules below remain as no-ops kept for back-compat with any host CSS
5002
- that may still target them — the variable redefinition is the single
5003
- source of truth going forward. */
5623
+ /* Dark-mode rebind for all preview-gutter custom properties. */
5004
5624
  .squisq-editor-shell[data-theme='dark'] {
5005
5625
  --squisq-preview-accent: #818cf8;
5006
5626
  --squisq-preview-accent-muted: #475569;
@@ -5016,10 +5636,6 @@
5016
5636
  --squisq-preview-empty-text: #94a3b8;
5017
5637
  }
5018
5638
 
5019
- .squisq-editor-shell[data-theme='dark'] .squisq-inline-preview-gutter {
5020
- background: var(--squisq-preview-gutter-bg);
5021
- }
5022
-
5023
5639
  .squisq-editor-shell[data-theme='dark'] .squisq-outline-empty {
5024
5640
  color: #94a3b8;
5025
5641
  }
@@ -5891,9 +6507,9 @@
5891
6507
  padding: 3px 8px;
5892
6508
  font-size: 12px;
5893
6509
  font-weight: 500;
5894
- color: #374151;
5895
- background: #fff;
5896
- border: 1px solid #d1d5db;
6510
+ color: var(--squisq-block-props-text);
6511
+ background: var(--squisq-block-props-surface);
6512
+ border: 1px solid var(--squisq-block-props-border);
5897
6513
  border-radius: 5px;
5898
6514
  cursor: pointer;
5899
6515
  white-space: nowrap;
@@ -5903,23 +6519,23 @@
5903
6519
  }
5904
6520
 
5905
6521
  .squisq-transition-picker-trigger:hover {
5906
- background: #f3f4f6;
5907
- border-color: #9ca3af;
6522
+ background: var(--squisq-block-props-surface-hover);
6523
+ border-color: var(--squisq-block-props-quiet);
5908
6524
  }
5909
6525
 
5910
6526
  .squisq-transition-picker-trigger--open {
5911
- background: #f3f4f6;
5912
- border-color: #6366f1;
5913
- outline: 2px solid rgba(99, 102, 241, 0.25);
6527
+ background: var(--squisq-block-props-surface-hover);
6528
+ border-color: var(--squisq-block-props-accent, #6366f1);
6529
+ outline: 2px solid color-mix(in oklch, var(--squisq-block-props-accent, #6366f1) 25%, transparent);
5914
6530
  outline-offset: -1px;
5915
6531
  }
5916
6532
 
5917
6533
  .squisq-transition-picker-trigger-label {
5918
- color: #6b7280;
6534
+ color: var(--squisq-block-props-muted);
5919
6535
  }
5920
6536
 
5921
6537
  .squisq-transition-picker-trigger-value {
5922
- color: #111827;
6538
+ color: var(--squisq-block-props-text);
5923
6539
  font-weight: 400;
5924
6540
  max-width: 110px;
5925
6541
  overflow: hidden;
@@ -5927,7 +6543,7 @@
5927
6543
  }
5928
6544
 
5929
6545
  .squisq-transition-picker-trigger svg {
5930
- color: #9ca3af;
6546
+ color: var(--squisq-block-props-quiet);
5931
6547
  flex-shrink: 0;
5932
6548
  }
5933
6549
 
@@ -5946,8 +6562,9 @@
5946
6562
  max-width: calc(100vw - 24px);
5947
6563
  display: flex;
5948
6564
  flex-direction: column;
5949
- background: #fff;
5950
- border: 1px solid #e5e7eb;
6565
+ color: var(--squisq-block-props-text);
6566
+ background: var(--squisq-block-props-surface);
6567
+ border: 1px solid var(--squisq-block-props-divider);
5951
6568
  border-radius: 10px;
5952
6569
  box-shadow:
5953
6570
  0 8px 24px rgba(0, 0, 0, 0.12),
@@ -5957,21 +6574,22 @@
5957
6574
 
5958
6575
  .squisq-transition-flyout-search {
5959
6576
  padding: 8px;
5960
- border-bottom: 1px solid #f0f0f0;
6577
+ border-bottom: 1px solid var(--squisq-block-props-divider);
5961
6578
  }
5962
6579
 
5963
6580
  .squisq-transition-flyout-search-input {
5964
6581
  width: 100%;
5965
6582
  padding: 6px 8px;
5966
6583
  font-size: 13px;
5967
- color: #111827;
5968
- border: 1px solid #d1d5db;
6584
+ color: var(--squisq-block-props-text);
6585
+ background: var(--squisq-block-props-input);
6586
+ border: 1px solid var(--squisq-block-props-border);
5969
6587
  border-radius: 6px;
5970
6588
  outline: none;
5971
6589
  }
5972
6590
 
5973
6591
  .squisq-transition-flyout-search-input:focus {
5974
- border-color: #6366f1;
6592
+ border-color: var(--squisq-block-props-accent, #6366f1);
5975
6593
  }
5976
6594
 
5977
6595
  .squisq-transition-flyout-list {
@@ -5993,7 +6611,7 @@
5993
6611
  font-weight: 600;
5994
6612
  letter-spacing: 0.04em;
5995
6613
  text-transform: uppercase;
5996
- color: #9ca3af;
6614
+ color: var(--squisq-block-props-quiet);
5997
6615
  }
5998
6616
 
5999
6617
  .squisq-transition-flyout-grid {
@@ -6008,9 +6626,9 @@
6008
6626
  text-align: left;
6009
6627
  padding: 6px 8px;
6010
6628
  font-size: 12px;
6011
- color: #374151;
6012
- background: #fff;
6013
- border: 1px solid #e5e7eb;
6629
+ color: var(--squisq-block-props-text);
6630
+ background: var(--squisq-block-props-surface);
6631
+ border: 1px solid var(--squisq-block-props-divider);
6014
6632
  border-radius: 6px;
6015
6633
  cursor: pointer;
6016
6634
  white-space: nowrap;
@@ -6019,14 +6637,14 @@
6019
6637
  }
6020
6638
 
6021
6639
  .squisq-transition-option:hover {
6022
- background: #f3f4f6;
6023
- border-color: #d1d5db;
6640
+ background: var(--squisq-block-props-surface-hover);
6641
+ border-color: var(--squisq-block-props-border);
6024
6642
  }
6025
6643
 
6026
6644
  .squisq-transition-option--selected {
6027
- background: #eef2ff;
6028
- border-color: #6366f1;
6029
- color: #4338ca;
6645
+ color: var(--squisq-block-props-accent, #4338ca);
6646
+ background: color-mix(in oklch, var(--squisq-block-props-accent, #6366f1) 14%, transparent);
6647
+ border-color: var(--squisq-block-props-accent, #6366f1);
6030
6648
  font-weight: 600;
6031
6649
  }
6032
6650
 
@@ -6055,13 +6673,13 @@
6055
6673
  .squisq-transition-flyout-empty {
6056
6674
  padding: 12px 8px;
6057
6675
  font-size: 12px;
6058
- color: #9ca3af;
6676
+ color: var(--squisq-block-props-quiet);
6059
6677
  text-align: center;
6060
6678
  }
6061
6679
 
6062
6680
  /* Direction + duration controls, shown below the list once a type is set. */
6063
6681
  .squisq-transition-flyout-controls {
6064
- border-top: 1px solid #f0f0f0;
6682
+ border-top: 1px solid var(--squisq-block-props-divider);
6065
6683
  padding: 10px 12px;
6066
6684
  display: flex;
6067
6685
  flex-direction: column;
@@ -6078,7 +6696,7 @@
6078
6696
  .squisq-transition-flyout-control-label {
6079
6697
  font-size: 11px;
6080
6698
  font-weight: 600;
6081
- color: #6b7280;
6699
+ color: var(--squisq-block-props-muted);
6082
6700
  }
6083
6701
 
6084
6702
  .squisq-transition-direction-row {
@@ -6089,21 +6707,21 @@
6089
6707
  .squisq-transition-direction-button {
6090
6708
  padding: 4px 8px;
6091
6709
  font-size: 11px;
6092
- color: #374151;
6093
- background: #fff;
6094
- border: 1px solid #d1d5db;
6710
+ color: var(--squisq-block-props-text);
6711
+ background: var(--squisq-block-props-surface);
6712
+ border: 1px solid var(--squisq-block-props-border);
6095
6713
  border-radius: 5px;
6096
6714
  cursor: pointer;
6097
6715
  }
6098
6716
 
6099
6717
  .squisq-transition-direction-button:hover {
6100
- background: #f3f4f6;
6718
+ background: var(--squisq-block-props-surface-hover);
6101
6719
  }
6102
6720
 
6103
6721
  .squisq-transition-direction-button--selected {
6104
- background: #eef2ff;
6105
- border-color: #6366f1;
6106
- color: #4338ca;
6722
+ color: var(--squisq-block-props-accent, #4338ca);
6723
+ background: color-mix(in oklch, var(--squisq-block-props-accent, #6366f1) 14%, transparent);
6724
+ border-color: var(--squisq-block-props-accent, #6366f1);
6107
6725
  font-weight: 600;
6108
6726
  }
6109
6727
 
@@ -6117,19 +6735,20 @@
6117
6735
  width: 64px;
6118
6736
  padding: 4px 6px;
6119
6737
  font-size: 12px;
6120
- color: #111827;
6121
- border: 1px solid #d1d5db;
6738
+ color: var(--squisq-block-props-text);
6739
+ background: var(--squisq-block-props-input);
6740
+ border: 1px solid var(--squisq-block-props-border);
6122
6741
  border-radius: 5px;
6123
6742
  outline: none;
6124
6743
  }
6125
6744
 
6126
6745
  .squisq-transition-duration-input:focus {
6127
- border-color: #6366f1;
6746
+ border-color: var(--squisq-block-props-accent, #6366f1);
6128
6747
  }
6129
6748
 
6130
6749
  .squisq-transition-duration-unit {
6131
6750
  font-size: 11px;
6132
- color: #9ca3af;
6751
+ color: var(--squisq-block-props-quiet);
6133
6752
  }
6134
6753
 
6135
6754
  /* Dark theme */
@@ -6146,50 +6765,17 @@
6146
6765
 
6147
6766
  .squisq-editor-shell[data-theme='dark'] .squisq-transition-picker-trigger--open {
6148
6767
  background: #374151;
6149
- border-color: #818cf8;
6768
+ border-color: var(--squisq-block-props-accent, #818cf8);
6150
6769
  }
6151
6770
 
6152
6771
  .squisq-editor-shell[data-theme='dark'] .squisq-transition-picker-trigger-value {
6153
6772
  color: #f9fafb;
6154
6773
  }
6155
6774
 
6156
- /* Dark styling for the portaled flyout keyed off the editor shell the same
6157
- way the template gallery popover is (see `.squisq-template-gallery` above). */
6158
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-flyout {
6159
- background: #1f2937;
6160
- border-color: #374151;
6775
+ /* Portaled to <body>, so the flyout's own data-theme is the reliable dark-mode
6776
+ boundary. Child colors come from the local surface tokens above. */
6777
+ .squisq-transition-flyout[data-theme='dark'] {
6161
6778
  box-shadow:
6162
6779
  0 8px 24px rgba(0, 0, 0, 0.4),
6163
6780
  0 2px 6px rgba(0, 0, 0, 0.2);
6164
6781
  }
6165
-
6166
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-flyout-search,
6167
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-flyout-controls {
6168
- border-color: #374151;
6169
- }
6170
-
6171
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-flyout-search-input,
6172
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-duration-input {
6173
- background: #111827;
6174
- color: #f9fafb;
6175
- border-color: #4b5563;
6176
- }
6177
-
6178
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-option,
6179
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-direction-button {
6180
- background: #1f2937;
6181
- color: #e5e7eb;
6182
- border-color: #4b5563;
6183
- }
6184
-
6185
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-option:hover,
6186
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-direction-button:hover {
6187
- background: #374151;
6188
- }
6189
-
6190
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-option--selected,
6191
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-direction-button--selected {
6192
- background: #3730a3;
6193
- border-color: #818cf8;
6194
- color: #e0e7ff;
6195
- }