@bendyline/squisq-editor-react 1.6.1 → 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 (208) hide show
  1. package/README.md +12 -3
  2. package/dist/index.d.ts +1304 -208
  3. package/dist/index.js +22838 -14494
  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 +2384 -408
  9. package/package.json +9 -5
  10. package/src/BlockPropertiesPopover.tsx +48 -17
  11. package/src/DocumentSettingsDialog.tsx +13 -21
  12. package/src/EditorContext.tsx +199 -42
  13. package/src/EditorShell.tsx +403 -270
  14. package/src/ImageEditor.tsx +22 -1
  15. package/src/InlinePreviewGutter.tsx +16 -8
  16. package/src/MediaBin.tsx +276 -40
  17. package/src/OutlinePanel.tsx +202 -7
  18. package/src/PlainHtmlPreview.tsx +40 -1
  19. package/src/PreviewControls.tsx +466 -93
  20. package/src/PreviewPanel.tsx +313 -77
  21. package/src/RawEditor.tsx +13 -2
  22. package/src/StatusBar.tsx +5 -2
  23. package/src/TemplateAnnotation.ts +34 -10
  24. package/src/TemplateContentPreview.tsx +56 -0
  25. package/src/TemplatePicker.tsx +355 -134
  26. package/src/ThemeCustomizerPanel.tsx +30 -15
  27. package/src/ThemePicker.tsx +10 -5
  28. package/src/TimelineBlockPreview.tsx +1 -1
  29. package/src/Toolbar.tsx +719 -238
  30. package/src/TransitionPicker.tsx +44 -5
  31. package/src/ViewMenuPanel.tsx +12 -14
  32. package/src/ViewSwitcher.tsx +4 -4
  33. package/src/WysiwygEditor.tsx +167 -92
  34. package/src/__tests__/blockPropertiesPopoverTheme.test.tsx +33 -0
  35. package/src/__tests__/blockTagActivity.test.ts +183 -0
  36. package/src/__tests__/buildDocumentPreviewMarkdown.test.ts +75 -0
  37. package/src/__tests__/buildPreviewDocContent.test.ts +48 -0
  38. package/src/__tests__/buildPreviewDocTransition.test.ts +22 -3
  39. package/src/__tests__/canvasSurfaceTextEditing.test.tsx +60 -0
  40. package/src/__tests__/customLayoutManagerTheme.test.tsx +34 -0
  41. package/src/__tests__/documentSettingsDialog.test.tsx +29 -1
  42. package/src/__tests__/editorScrollHandoff.test.tsx +102 -0
  43. package/src/__tests__/editorScrollSync.test.ts +65 -0
  44. package/src/__tests__/editorShellProps.test.tsx +390 -1
  45. package/src/__tests__/emojiPicker.test.tsx +2 -42
  46. package/src/__tests__/headingTransition.test.ts +53 -15
  47. package/src/__tests__/imageEditAffordance.test.tsx +5 -1
  48. package/src/__tests__/imageEditModalContract.test.tsx +119 -0
  49. package/src/__tests__/imageEditorShell.test.tsx +38 -1
  50. package/src/__tests__/jsonEditor.test.tsx +56 -1
  51. package/src/__tests__/layersPanel.test.tsx +75 -5
  52. package/src/__tests__/majorApiTypes.test.ts +26 -0
  53. package/src/__tests__/mediaBinDrop.test.tsx +90 -0
  54. package/src/__tests__/mediaReferences.test.ts +82 -0
  55. package/src/__tests__/narrationSave.test.ts +148 -0
  56. package/src/__tests__/outlinePanel.test.tsx +93 -3
  57. package/src/__tests__/outlineSource.test.ts +217 -0
  58. package/src/__tests__/plainHtmlPreview.test.tsx +17 -1
  59. package/src/__tests__/presentationMode.test.tsx +290 -0
  60. package/src/__tests__/previewControls.test.tsx +312 -6
  61. package/src/__tests__/previewPanelAudioFailure.test.tsx +46 -0
  62. package/src/__tests__/previewPanelPresentation.test.tsx +126 -0
  63. package/src/__tests__/previewPanelTransforms.test.tsx +117 -0
  64. package/src/__tests__/rawEditorModelIsolation.test.ts +19 -0
  65. package/src/__tests__/resolveBlockVisual.test.ts +43 -0
  66. package/src/__tests__/statusBar.test.tsx +27 -0
  67. package/src/__tests__/teleprompter.test.tsx +190 -0
  68. package/src/__tests__/templateAnnotationRoundTrip.test.ts +49 -2
  69. package/src/__tests__/templateContentPreview.test.ts +101 -0
  70. package/src/__tests__/templatePickerPortal.test.tsx +62 -0
  71. package/src/__tests__/tiptapBridge.test.ts +70 -0
  72. package/src/__tests__/tiptapCodeBlockRoundTrip.test.ts +109 -0
  73. package/src/__tests__/transformStyleId.test.ts +13 -0
  74. package/src/__tests__/useImageEditor.test.tsx +67 -0
  75. package/src/__tests__/useMediaRecorder.test.ts +75 -0
  76. package/src/__tests__/viewMenuPanel.test.tsx +130 -0
  77. package/src/__tests__/wysiwygImageUpload.test.ts +69 -0
  78. package/src/__tests__/wysiwygTemplateBadgeFocus.test.tsx +56 -0
  79. package/src/asciiDiagram/AsciiDiagramExtension.ts +343 -0
  80. package/src/asciiDiagram/AsciiDiagramWidget.tsx +224 -0
  81. package/src/asciiDiagram/RepairableDiagramExtension.ts +200 -0
  82. package/src/asciiDiagram/__tests__/AsciiDiagramExtension.test.ts +145 -0
  83. package/src/asciiDiagram/__tests__/RepairableDiagramExtension.test.ts +159 -0
  84. package/src/asciiDiagram/__tests__/asciiDiagramCommands.test.ts +227 -0
  85. package/src/asciiDiagram/__tests__/asciiDiagramOps.test.ts +114 -0
  86. package/src/asciiDiagram/__tests__/asciiPaste.test.ts +43 -0
  87. package/src/asciiDiagram/asciiDiagramCommands.ts +148 -0
  88. package/src/asciiDiagram/asciiDiagramData.ts +116 -0
  89. package/src/asciiDiagram/asciiDiagramOps.ts +219 -0
  90. package/src/asciiDiagram/asciiPaste.ts +19 -0
  91. package/src/blockTagActivity.ts +233 -0
  92. package/src/buildDocumentPreviewMarkdown.ts +168 -0
  93. package/src/buildPreviewDoc.ts +19 -12
  94. package/src/customTemplates/CustomLayoutManager.tsx +3 -2
  95. package/src/customTemplates/CustomTemplateContext.tsx +6 -0
  96. package/src/customTemplates/TemplateDesigner.tsx +7 -4
  97. package/src/customTemplates/__tests__/library.test.ts +8 -0
  98. package/src/customTemplates/designer.css +158 -99
  99. package/src/customTemplates/library.ts +16 -3
  100. package/src/customThemes/CustomThemeContext.tsx +6 -0
  101. package/src/customThemes/CustomThemeDialog.tsx +35 -5
  102. package/src/customThemes/ImportThemeSection.tsx +178 -0
  103. package/src/customThemes/__tests__/customThemeLibrary.test.ts +9 -0
  104. package/src/customThemes/__tests__/importThemeSection.test.tsx +192 -0
  105. package/src/customThemes/customThemeLibrary.ts +7 -4
  106. package/src/customThemes/index.ts +7 -1
  107. package/src/customThemes/themeDraft.ts +23 -7
  108. package/src/diagram/DiagramCanvas.tsx +9 -4
  109. package/src/diagram/types.ts +35 -0
  110. package/src/editorScrollSync.ts +73 -0
  111. package/src/emojiData.ts +3 -23
  112. package/src/headingTransition.ts +85 -25
  113. package/src/imageEditor/CanvasSurface.tsx +29 -23
  114. package/src/imageEditor/LayersPanel.tsx +78 -3
  115. package/src/imageEditor/Toolbar.tsx +5 -1
  116. package/src/imageEditor/icons.tsx +4 -0
  117. package/src/imageEditor/image-editor.css +75 -0
  118. package/src/imageEditor/layers/SelectionHandles.tsx +1 -1
  119. package/src/imageEditor/useImageEditor.ts +71 -14
  120. package/src/index.ts +193 -20
  121. package/src/jsonEditor/JsonEditorContext.tsx +12 -6
  122. package/src/jsonEditor/RenderNode.tsx +24 -3
  123. package/src/jsonEditor/editors.tsx +86 -19
  124. package/src/mediaEntries.ts +12 -0
  125. package/src/mediaReferences.ts +299 -0
  126. package/src/monaco.ts +35 -0
  127. package/src/monacoWorkers.ts +89 -0
  128. package/src/outlineSource.ts +171 -0
  129. package/src/presentation/PresentationMode.tsx +596 -0
  130. package/src/rawEditorIsolation.ts +18 -0
  131. package/src/recorder/hooks/useMediaRecorder.ts +97 -53
  132. package/src/resolveBlockVisual.ts +10 -4
  133. package/src/scene/Scene.tsx +101 -25
  134. package/src/scene/SceneBlockExtension.ts +17 -10
  135. package/src/scene/SceneBlockWidget.tsx +11 -4
  136. package/src/scene/SceneSelection.tsx +19 -15
  137. package/src/scene/SceneSideToolbar.tsx +89 -0
  138. package/src/scene/SceneViewport.tsx +7 -3
  139. package/src/scene/ShapePalette.tsx +17 -2
  140. package/src/scene/__tests__/DiagramAdapter.test.ts +86 -0
  141. package/src/scene/__tests__/SceneBlockExtension.test.ts +33 -0
  142. package/src/scene/__tests__/sceneIsolation.test.tsx +93 -0
  143. package/src/scene/adapters/DiagramAdapter.ts +12 -101
  144. package/src/scene/commands/SceneCommand.ts +4 -1
  145. package/src/scene/index.ts +1 -6
  146. package/src/scene/layers/DiagramEdges.tsx +24 -9
  147. package/src/scene/layers/edgeGeometry.ts +31 -4
  148. package/src/scene/layers/nodeCard.tsx +27 -8
  149. package/src/scene/scene.css +145 -2
  150. package/src/scene/text/SceneTextOverlay.tsx +5 -5
  151. package/src/scene/text/sceneTextChannel.ts +26 -20
  152. package/src/scene/text/sceneTextConfig.ts +4 -0
  153. package/src/scene/tools/ConnectTool.ts +126 -28
  154. package/src/scene/tools/DrawingConnectTool.ts +86 -16
  155. package/src/scene/tools/SceneTool.ts +10 -0
  156. package/src/scene/tools/SelectTool.ts +34 -18
  157. package/src/scene/tools/ShapeTool.ts +2 -3
  158. package/src/styles/ascii-diagram.css +79 -0
  159. package/src/styles/ascii-timeline.css +499 -0
  160. package/src/styles/editor.css +1566 -219
  161. package/src/styles/index.css +3 -0
  162. package/src/styles/tree-view.css +139 -0
  163. package/src/teleprompter/TeleprompterControls.tsx +218 -0
  164. package/src/teleprompter/TeleprompterSelfView.tsx +22 -0
  165. package/src/teleprompter/TeleprompterSurface.tsx +267 -0
  166. package/src/teleprompter/TeleprompterView.tsx +338 -0
  167. package/src/teleprompter/canvasRenderer.ts +161 -0
  168. package/src/teleprompter/floatingWindow.ts +352 -0
  169. package/src/teleprompter/index.ts +61 -0
  170. package/src/teleprompter/pcmWorklet.ts +62 -0
  171. package/src/teleprompter/recording/insertPreamble.ts +80 -0
  172. package/src/teleprompter/recording/narrationSave.ts +134 -0
  173. package/src/teleprompter/recording/useNarrationRecorder.ts +367 -0
  174. package/src/teleprompter/scrollModel.ts +85 -0
  175. package/src/teleprompter/teleprompterTheme.ts +303 -0
  176. package/src/teleprompter/types.ts +38 -0
  177. package/src/teleprompter/useFloatingWindow.ts +74 -0
  178. package/src/teleprompter/useMicAnalysis.ts +211 -0
  179. package/src/teleprompter/useTeleprompter.ts +421 -0
  180. package/src/templateContentPreviewResolver.ts +360 -0
  181. package/src/timeline/TimelineEditorWidget.tsx +702 -0
  182. package/src/timeline/TimelineViewExtension.ts +252 -0
  183. package/src/timeline/__tests__/TimelineEditorWidget.test.tsx +355 -0
  184. package/src/timeline/__tests__/TimelineViewExtension.test.ts +163 -0
  185. package/src/timeline/__tests__/timelineCommands.test.ts +327 -0
  186. package/src/timeline/__tests__/timelineOps.test.ts +222 -0
  187. package/src/timeline/__tests__/timelinePaste.test.ts +34 -0
  188. package/src/timeline/timelineCommands.ts +367 -0
  189. package/src/timeline/timelineData.ts +54 -0
  190. package/src/timeline/timelineOps.ts +277 -0
  191. package/src/timeline/timelinePaste.ts +8 -0
  192. package/src/tiptapBridge.ts +84 -49
  193. package/src/transformStyleId.ts +17 -0
  194. package/src/treeview/TreeOutlineWidget.tsx +240 -0
  195. package/src/treeview/TreeViewExtension.ts +250 -0
  196. package/src/treeview/__tests__/TreeViewExtension.test.ts +122 -0
  197. package/src/treeview/__tests__/treeOps.test.ts +125 -0
  198. package/src/treeview/__tests__/treePaste.test.ts +40 -0
  199. package/src/treeview/__tests__/treeViewCommands.test.ts +163 -0
  200. package/src/treeview/treeOps.ts +172 -0
  201. package/src/treeview/treePaste.ts +13 -0
  202. package/src/treeview/treeViewCommands.ts +94 -0
  203. package/src/treeview/treeViewData.ts +41 -0
  204. package/src/useMonacoLoader.ts +11 -34
  205. package/src/wysiwygImageUpload.ts +113 -0
  206. package/src/diagram/DiagramExtension.ts +0 -209
  207. package/src/diagram/DiagramWidget.tsx +0 -270
  208. package/src/diagram/useDiagramData.ts +0 -126
@@ -103,7 +103,7 @@
103
103
  align-items: center;
104
104
  flex-wrap: nowrap;
105
105
  padding: 0 12px 0 0;
106
- gap: 2px;
106
+ gap: 1px;
107
107
  background: rgba(0, 0, 0, 0.07);
108
108
  container-type: inline-size;
109
109
  container-name: squisq-toolbar;
@@ -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
@@ -149,6 +359,15 @@
149
359
  min-width: 0;
150
360
  }
151
361
 
362
+ /* Contextual groups (template/transition pickers, table controls) sit at the
363
+ end of the actions row. When measurement marks one as clipped it moves into
364
+ the ··· overflow menu; hide the cropped inline original rather than painting
365
+ half of it. `visibility` (not `display`) keeps its layout box so the
366
+ measurement still notices when it fits again. */
367
+ .squisq-toolbar-contextual--clipped {
368
+ visibility: hidden;
369
+ }
370
+
152
371
  .squisq-toolbar-view-tab {
153
372
  /* Top padding is asymmetric — bumped 4px above the bottom — so the
154
373
  label sits more vertically centered alongside the neighboring
@@ -224,6 +443,7 @@
224
443
  justify-content: center;
225
444
  width: 32px;
226
445
  height: 28px;
446
+ flex-shrink: 0;
227
447
  border: none;
228
448
  border-radius: 4px;
229
449
  background: transparent;
@@ -256,6 +476,32 @@
256
476
  color: #1d4ed8;
257
477
  }
258
478
 
479
+ .squisq-toolbar-files-toggle {
480
+ position: relative;
481
+ }
482
+
483
+ .squisq-toolbar-files-badge {
484
+ position: absolute;
485
+ right: 1px;
486
+ bottom: 1px;
487
+ min-width: 14px;
488
+ height: 14px;
489
+ padding: 0 3px;
490
+ border: 1.5px solid #e5e7eb;
491
+ border-radius: 999px;
492
+ background: #2563eb;
493
+ color: #ffffff;
494
+ box-sizing: border-box;
495
+ display: inline-flex;
496
+ align-items: center;
497
+ justify-content: center;
498
+ font-size: 9px;
499
+ font-weight: 700;
500
+ line-height: 1;
501
+ pointer-events: none;
502
+ z-index: 1;
503
+ }
504
+
259
505
  /* Font Awesome glyphs sit a touch larger than the 13px text labels so
260
506
  icon buttons read at a comfortable weight against H1–H6 etc. They
261
507
  render in a lighter color than the text labels by default. */
@@ -381,6 +627,18 @@
381
627
  max-width: 100%;
382
628
  }
383
629
 
630
+ /* Section heading for the per-block controls (template/transition pickers)
631
+ when they fold into the overflow menu — names the block they configure. */
632
+ .squisq-toolbar-overflow-heading {
633
+ padding: 4px 12px 2px;
634
+ font-size: 11px;
635
+ font-weight: 600;
636
+ letter-spacing: 0.04em;
637
+ text-transform: uppercase;
638
+ color: #9ca3af;
639
+ user-select: none;
640
+ }
641
+
384
642
  /* ─── Insert Menu Dropdown ──────────────────────────── */
385
643
 
386
644
  .squisq-insert-menu {
@@ -539,6 +797,154 @@
539
797
  }
540
798
 
541
799
  /* The gallery popover panel — rendered in a portal with fixed positioning */
800
+ .squisq-template-gallery-dialog {
801
+ --squisq-template-gallery-backdrop: rgba(17, 24, 39, 0.34);
802
+ --squisq-template-gallery-backdrop-blur: 1px;
803
+ --squisq-template-gallery-panel-bg: #ffffff;
804
+ --squisq-template-gallery-panel-border: #e5e7eb;
805
+ --squisq-template-gallery-panel-shadow:
806
+ 0 24px 70px rgba(15, 23, 42, 0.24), 0 8px 24px rgba(15, 23, 42, 0.16);
807
+ --squisq-template-gallery-header-bg: #ffffff;
808
+ --squisq-template-gallery-header-border: #e5e7eb;
809
+ --squisq-template-gallery-title: #111827;
810
+ --squisq-template-gallery-close-color: #64748b;
811
+ --squisq-template-gallery-close-bg: rgba(255, 255, 255, 0.9);
812
+ --squisq-template-gallery-close-border: #e2e8f0;
813
+ --squisq-template-gallery-close-hover-color: #0f172a;
814
+ --squisq-template-gallery-close-hover-border: #c7d2fe;
815
+ --squisq-template-gallery-close-hover-shadow: 0 1px 4px rgba(99, 102, 241, 0.16);
816
+ --squisq-template-gallery-bg: #ffffff;
817
+ --squisq-template-gallery-text: #111827;
818
+ --squisq-template-gallery-border: #e5e7eb;
819
+ --squisq-template-gallery-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.06);
820
+ --squisq-template-gallery-search-bg: #ffffff;
821
+ --squisq-template-gallery-search-border: #f3f4f6;
822
+ --squisq-template-gallery-search-icon: #9ca3af;
823
+ --squisq-template-gallery-search-input: #111827;
824
+ --squisq-template-gallery-search-placeholder: #9ca3af;
825
+ --squisq-template-gallery-empty: #6b7280;
826
+ --squisq-template-gallery-option-bg: #fbfdff;
827
+ --squisq-template-gallery-option-border: #e5e7eb;
828
+ --squisq-template-gallery-option-hover-bg: #f9fafb;
829
+ --squisq-template-gallery-option-hover-border: #c7d2fe;
830
+ --squisq-template-gallery-option-hover-shadow: 0 1px 3px rgba(99, 102, 241, 0.08);
831
+ --squisq-template-gallery-card-bg: transparent;
832
+ --squisq-template-gallery-card-border: #e5e7eb;
833
+ --squisq-template-gallery-card-hover-bg: #f9fafb;
834
+ --squisq-template-gallery-card-hover-border: #a5b4fc;
835
+ --squisq-template-gallery-card-hover-shadow: 0 1px 4px rgba(99, 102, 241, 0.1);
836
+ --squisq-template-gallery-selected-bg: #eef2ff;
837
+ --squisq-template-gallery-selected-border: #6366f1;
838
+ --squisq-template-gallery-selected-shadow: 0 0 0 2px rgba(99, 102, 241, 0.15);
839
+ --squisq-template-gallery-card-icon-bg: #f8fafc;
840
+ --squisq-template-gallery-card-icon-border: #e5e7eb;
841
+ --squisq-template-gallery-content-preview-bg: #f1f5f9;
842
+ --squisq-template-gallery-preview-warning-bg: rgba(17, 24, 39, 0.9);
843
+ --squisq-template-gallery-preview-warning-border: rgba(255, 255, 255, 0.22);
844
+ --squisq-template-gallery-preview-warning-text: #ffffff;
845
+ --squisq-template-gallery-name: #111827;
846
+ --squisq-template-gallery-description: #6b7280;
847
+ --squisq-template-gallery-new-bg: #f5f3ff;
848
+ --squisq-template-gallery-new-border: #a5b4fc;
849
+ --squisq-template-gallery-new-hover-bg: #ede9fe;
850
+ --squisq-template-gallery-new-hover-border: #818cf8;
851
+ --squisq-template-gallery-new-plus-color: #6366f1;
852
+ --squisq-template-gallery-new-plus-bg: #ffffff;
853
+ --squisq-template-gallery-new-plus-border: #c4b5fd;
854
+ --squisq-template-gallery-new-label: #4338ca;
855
+ --squisq-template-gallery-new-desc: #6b7280;
856
+ --squisq-template-gallery-section-border: #e5e7eb;
857
+ --squisq-template-gallery-section-title: #6b7280;
858
+ box-sizing: border-box;
859
+ display: flex;
860
+ align-items: center;
861
+ justify-content: center;
862
+ min-width: 0;
863
+ min-height: 0;
864
+ padding: 0;
865
+ background: var(--squisq-template-gallery-backdrop);
866
+ backdrop-filter: blur(var(--squisq-template-gallery-backdrop-blur));
867
+ font-family: var(
868
+ --squisq-ux-font,
869
+ -apple-system,
870
+ BlinkMacSystemFont,
871
+ 'Segoe UI',
872
+ 'Noto Sans',
873
+ Helvetica,
874
+ Arial,
875
+ sans-serif
876
+ );
877
+ }
878
+
879
+ .squisq-template-gallery-dialog-panel {
880
+ position: relative;
881
+ display: flex;
882
+ flex-direction: column;
883
+ width: min(90vw, calc(100% - 32px));
884
+ height: calc(100% - 32px);
885
+ max-height: calc(100% - 32px);
886
+ min-width: 0;
887
+ min-height: 0;
888
+ overflow: hidden;
889
+ background: var(--squisq-template-gallery-panel-bg);
890
+ border: 1px solid var(--squisq-template-gallery-panel-border);
891
+ border-radius: 12px;
892
+ box-shadow: var(--squisq-template-gallery-panel-shadow);
893
+ }
894
+
895
+ .squisq-template-gallery-dialog-header {
896
+ display: flex;
897
+ align-items: center;
898
+ justify-content: space-between;
899
+ gap: 12px;
900
+ flex: 0 0 auto;
901
+ min-width: 0;
902
+ padding: 12px 14px 12px 16px;
903
+ background: var(--squisq-template-gallery-header-bg);
904
+ border-bottom: 1px solid var(--squisq-template-gallery-header-border);
905
+ }
906
+
907
+ .squisq-template-gallery-dialog-title {
908
+ min-width: 0;
909
+ margin: 0;
910
+ overflow: hidden;
911
+ color: var(--squisq-template-gallery-title);
912
+ font-size: 15px;
913
+ font-weight: 700;
914
+ line-height: 1.3;
915
+ text-overflow: ellipsis;
916
+ white-space: nowrap;
917
+ }
918
+
919
+ .squisq-template-gallery-dialog-close {
920
+ display: inline-flex;
921
+ align-items: center;
922
+ justify-content: center;
923
+ flex: 0 0 auto;
924
+ width: 28px;
925
+ height: 28px;
926
+ padding: 0;
927
+ color: var(--squisq-template-gallery-close-color);
928
+ background: var(--squisq-template-gallery-close-bg);
929
+ border: 1px solid var(--squisq-template-gallery-close-border);
930
+ border-radius: 6px;
931
+ cursor: pointer;
932
+ }
933
+
934
+ .squisq-template-gallery-dialog-close:hover {
935
+ color: var(--squisq-template-gallery-close-hover-color);
936
+ border-color: var(--squisq-template-gallery-close-hover-border);
937
+ box-shadow: var(--squisq-template-gallery-close-hover-shadow);
938
+ }
939
+
940
+ .squisq-template-gallery-dialog-body {
941
+ display: flex;
942
+ flex: 1 1 auto;
943
+ min-width: 0;
944
+ min-height: 0;
945
+ overflow: hidden;
946
+ }
947
+
542
948
  .squisq-template-gallery {
543
949
  width: 420px;
544
950
  max-width: calc(100vw - 24px);
@@ -548,16 +954,256 @@
548
954
  stretching alongside the page scrollbar. */
549
955
  max-height: calc(100vh - 72px);
550
956
  overflow-y: auto;
551
- background: #fff;
552
- border: 1px solid #e5e7eb;
957
+ background: var(--squisq-template-gallery-bg, #fff);
958
+ border: 1px solid var(--squisq-template-gallery-border, #e5e7eb);
553
959
  border-radius: 10px;
554
- box-shadow:
960
+ box-shadow: var(
961
+ --squisq-template-gallery-shadow,
555
962
  0 8px 24px rgba(0, 0, 0, 0.12),
556
- 0 2px 6px rgba(0, 0, 0, 0.06);
963
+ 0 2px 6px rgba(0, 0, 0, 0.06)
964
+ );
557
965
  padding: 8px;
558
966
  animation: squisq-gallery-appear 0.12s ease-out;
559
967
  }
560
968
 
969
+ .squisq-template-gallery-dialog .squisq-template-gallery {
970
+ flex: 1 1 auto;
971
+ width: 100%;
972
+ height: auto;
973
+ max-width: none;
974
+ max-height: none;
975
+ min-height: 0;
976
+ box-sizing: border-box;
977
+ padding: 0 12px 12px;
978
+ border: 0;
979
+ border-radius: 0;
980
+ box-shadow: none;
981
+ animation: none;
982
+ }
983
+
984
+ .squisq-template-gallery-dialog .squisq-template-gallery-search {
985
+ z-index: 3;
986
+ margin: 0 -12px;
987
+ padding: 2px 16px 26px;
988
+ border-bottom: 0;
989
+ }
990
+
991
+ .squisq-template-gallery-dialog .squisq-template-gallery-search::after {
992
+ content: '';
993
+ position: absolute;
994
+ left: 0;
995
+ right: 0;
996
+ bottom: 18px;
997
+ height: 1px;
998
+ background: var(--squisq-template-gallery-search-border, #f3f4f6);
999
+ pointer-events: none;
1000
+ }
1001
+
1002
+ .squisq-template-gallery-dialog .squisq-template-gallery-grid {
1003
+ grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
1004
+ }
1005
+
1006
+ .squisq-template-gallery-dialog[data-theme='dark'] {
1007
+ --squisq-template-gallery-backdrop: rgba(2, 6, 23, 0.64);
1008
+ --squisq-template-gallery-backdrop-blur: 2px;
1009
+ --squisq-template-gallery-panel-bg: #111827;
1010
+ --squisq-template-gallery-panel-border: #334155;
1011
+ --squisq-template-gallery-panel-shadow:
1012
+ 0 24px 70px rgba(0, 0, 0, 0.55), 0 8px 24px rgba(0, 0, 0, 0.35);
1013
+ --squisq-template-gallery-header-bg: #111827;
1014
+ --squisq-template-gallery-header-border: #334155;
1015
+ --squisq-template-gallery-title: #f3f4f6;
1016
+ --squisq-template-gallery-close-color: #cbd5e1;
1017
+ --squisq-template-gallery-close-bg: #0f172a;
1018
+ --squisq-template-gallery-close-border: #334155;
1019
+ --squisq-template-gallery-close-hover-color: #ffffff;
1020
+ --squisq-template-gallery-close-hover-border: #818cf8;
1021
+ --squisq-template-gallery-close-hover-shadow: 0 1px 6px rgba(129, 140, 248, 0.22);
1022
+ --squisq-template-gallery-bg: #111827;
1023
+ --squisq-template-gallery-text: #e5e7eb;
1024
+ --squisq-template-gallery-search-bg: #111827;
1025
+ --squisq-template-gallery-search-border: #334155;
1026
+ --squisq-template-gallery-search-icon: #64748b;
1027
+ --squisq-template-gallery-search-input: #f9fafb;
1028
+ --squisq-template-gallery-search-placeholder: #64748b;
1029
+ --squisq-template-gallery-empty: #94a3b8;
1030
+ --squisq-template-gallery-option-bg: #0f172a;
1031
+ --squisq-template-gallery-option-border: #334155;
1032
+ --squisq-template-gallery-option-hover-bg: #1e293b;
1033
+ --squisq-template-gallery-option-hover-border: #6366f1;
1034
+ --squisq-template-gallery-option-hover-shadow: 0 1px 5px rgba(99, 102, 241, 0.18);
1035
+ --squisq-template-gallery-card-bg: #0f172a;
1036
+ --squisq-template-gallery-card-border: #334155;
1037
+ --squisq-template-gallery-card-hover-bg: #1e293b;
1038
+ --squisq-template-gallery-card-hover-border: #6366f1;
1039
+ --squisq-template-gallery-card-hover-shadow: 0 1px 5px rgba(99, 102, 241, 0.18);
1040
+ --squisq-template-gallery-selected-bg: #1e1b4b;
1041
+ --squisq-template-gallery-selected-border: #818cf8;
1042
+ --squisq-template-gallery-selected-shadow: 0 0 0 2px rgba(129, 140, 248, 0.24);
1043
+ --squisq-template-gallery-card-icon-bg: #020617;
1044
+ --squisq-template-gallery-card-icon-border: #334155;
1045
+ --squisq-template-gallery-content-preview-bg: #020617;
1046
+ --squisq-template-gallery-preview-warning-bg: rgba(15, 23, 42, 0.94);
1047
+ --squisq-template-gallery-preview-warning-border: #475569;
1048
+ --squisq-template-gallery-preview-warning-text: #f8fafc;
1049
+ --squisq-template-gallery-name: #f3f4f6;
1050
+ --squisq-template-gallery-description: #94a3b8;
1051
+ --squisq-template-gallery-new-bg: #151437;
1052
+ --squisq-template-gallery-new-border: #4f46e5;
1053
+ --squisq-template-gallery-new-hover-bg: #1e1b4b;
1054
+ --squisq-template-gallery-new-hover-border: #818cf8;
1055
+ --squisq-template-gallery-new-plus-color: #c4b5fd;
1056
+ --squisq-template-gallery-new-plus-bg: #0f172a;
1057
+ --squisq-template-gallery-new-plus-border: #6366f1;
1058
+ --squisq-template-gallery-new-label: #f3f4f6;
1059
+ --squisq-template-gallery-new-desc: #94a3b8;
1060
+ --squisq-template-gallery-section-border: #334155;
1061
+ --squisq-template-gallery-section-title: #cbd5e1;
1062
+ background: var(--squisq-template-gallery-backdrop);
1063
+ backdrop-filter: blur(var(--squisq-template-gallery-backdrop-blur));
1064
+ }
1065
+
1066
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-dialog-panel {
1067
+ background: var(--squisq-template-gallery-panel-bg);
1068
+ border-color: var(--squisq-template-gallery-panel-border);
1069
+ box-shadow: var(--squisq-template-gallery-panel-shadow);
1070
+ }
1071
+
1072
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-dialog-header {
1073
+ background: var(--squisq-template-gallery-header-bg);
1074
+ border-bottom-color: var(--squisq-template-gallery-header-border);
1075
+ }
1076
+
1077
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-dialog-title {
1078
+ color: var(--squisq-template-gallery-title);
1079
+ }
1080
+
1081
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-dialog-close {
1082
+ color: var(--squisq-template-gallery-close-color);
1083
+ background: var(--squisq-template-gallery-close-bg);
1084
+ border-color: var(--squisq-template-gallery-close-border);
1085
+ }
1086
+
1087
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-dialog-close:hover {
1088
+ color: var(--squisq-template-gallery-close-hover-color);
1089
+ border-color: var(--squisq-template-gallery-close-hover-border);
1090
+ box-shadow: var(--squisq-template-gallery-close-hover-shadow);
1091
+ }
1092
+
1093
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery {
1094
+ background: var(--squisq-template-gallery-bg);
1095
+ color: var(--squisq-template-gallery-text);
1096
+ }
1097
+
1098
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-search {
1099
+ background: var(--squisq-template-gallery-search-bg);
1100
+ border-bottom-color: var(--squisq-template-gallery-search-border);
1101
+ }
1102
+
1103
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-search-icon {
1104
+ color: var(--squisq-template-gallery-search-icon);
1105
+ }
1106
+
1107
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-search-input {
1108
+ color: var(--squisq-template-gallery-search-input);
1109
+ }
1110
+
1111
+ .squisq-template-gallery-dialog[data-theme='dark']
1112
+ .squisq-template-gallery-search-input::placeholder {
1113
+ color: var(--squisq-template-gallery-search-placeholder);
1114
+ }
1115
+
1116
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-empty {
1117
+ color: var(--squisq-template-gallery-empty);
1118
+ }
1119
+
1120
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-none {
1121
+ background: var(--squisq-template-gallery-option-bg);
1122
+ border-color: var(--squisq-template-gallery-option-border);
1123
+ }
1124
+
1125
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-none:hover {
1126
+ background: var(--squisq-template-gallery-option-hover-bg);
1127
+ border-color: var(--squisq-template-gallery-option-hover-border);
1128
+ box-shadow: var(--squisq-template-gallery-option-hover-shadow);
1129
+ }
1130
+
1131
+ .squisq-template-gallery-dialog[data-theme='dark']
1132
+ .squisq-template-gallery-none.squisq-template-gallery-card--selected {
1133
+ background: var(--squisq-template-gallery-selected-bg);
1134
+ border-color: var(--squisq-template-gallery-selected-border);
1135
+ }
1136
+
1137
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-none-label {
1138
+ color: var(--squisq-template-gallery-section-title);
1139
+ }
1140
+
1141
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-none-desc {
1142
+ color: var(--squisq-template-gallery-description);
1143
+ }
1144
+
1145
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-card {
1146
+ background: var(--squisq-template-gallery-card-bg);
1147
+ border-color: var(--squisq-template-gallery-card-border);
1148
+ }
1149
+
1150
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-card:hover {
1151
+ background: var(--squisq-template-gallery-card-hover-bg);
1152
+ border-color: var(--squisq-template-gallery-card-hover-border);
1153
+ box-shadow: var(--squisq-template-gallery-card-hover-shadow);
1154
+ }
1155
+
1156
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-card--selected {
1157
+ background: var(--squisq-template-gallery-selected-bg);
1158
+ border-color: var(--squisq-template-gallery-selected-border);
1159
+ box-shadow: var(--squisq-template-gallery-selected-shadow);
1160
+ }
1161
+
1162
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-card-icon {
1163
+ background: var(--squisq-template-gallery-card-icon-bg);
1164
+ border-color: var(--squisq-template-gallery-card-icon-border);
1165
+ }
1166
+
1167
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-content-preview {
1168
+ background: var(--squisq-template-gallery-content-preview-bg);
1169
+ }
1170
+
1171
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-card-name,
1172
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-new-label {
1173
+ color: var(--squisq-template-gallery-name);
1174
+ }
1175
+
1176
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-card-desc,
1177
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-new-desc {
1178
+ color: var(--squisq-template-gallery-description);
1179
+ }
1180
+
1181
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-new {
1182
+ background: var(--squisq-template-gallery-new-bg);
1183
+ border-color: var(--squisq-template-gallery-new-border);
1184
+ }
1185
+
1186
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-new:hover {
1187
+ background: var(--squisq-template-gallery-new-hover-bg);
1188
+ border-color: var(--squisq-template-gallery-new-hover-border);
1189
+ }
1190
+
1191
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-new-plus {
1192
+ color: var(--squisq-template-gallery-new-plus-color);
1193
+ background: var(--squisq-template-gallery-new-plus-bg);
1194
+ border-color: var(--squisq-template-gallery-new-plus-border);
1195
+ }
1196
+
1197
+ .squisq-template-gallery-dialog[data-theme='dark']
1198
+ .squisq-template-gallery-section
1199
+ + .squisq-template-gallery-section {
1200
+ border-top-color: var(--squisq-template-gallery-section-border);
1201
+ }
1202
+
1203
+ .squisq-template-gallery-dialog[data-theme='dark'] .squisq-template-gallery-section-title {
1204
+ color: var(--squisq-template-gallery-section-title);
1205
+ }
1206
+
561
1207
  @keyframes squisq-gallery-appear {
562
1208
  from {
563
1209
  opacity: 0;
@@ -580,12 +1226,12 @@
580
1226
  gap: 6px;
581
1227
  padding: 4px 8px;
582
1228
  margin: -4px -4px 8px;
583
- background: #fff;
584
- border-bottom: 1px solid #f3f4f6;
1229
+ background: var(--squisq-template-gallery-search-bg, #fff);
1230
+ border-bottom: 1px solid var(--squisq-template-gallery-search-border, #f3f4f6);
585
1231
  }
586
1232
 
587
1233
  .squisq-template-gallery-search-icon {
588
- color: #9ca3af;
1234
+ color: var(--squisq-template-gallery-search-icon, #9ca3af);
589
1235
  flex-shrink: 0;
590
1236
  }
591
1237
 
@@ -597,12 +1243,12 @@
597
1243
  outline: none;
598
1244
  font: inherit;
599
1245
  font-size: 13px;
600
- color: #111827;
1246
+ color: var(--squisq-template-gallery-search-input, #111827);
601
1247
  background: transparent;
602
1248
  }
603
1249
 
604
1250
  .squisq-template-gallery-search-input::placeholder {
605
- color: #9ca3af;
1251
+ color: var(--squisq-template-gallery-search-placeholder, #9ca3af);
606
1252
  }
607
1253
 
608
1254
  /* Hide the native clear button on type="search" — the popover handles
@@ -615,7 +1261,7 @@
615
1261
  padding: 24px 12px;
616
1262
  text-align: center;
617
1263
  font-size: 12px;
618
- color: #6b7280;
1264
+ color: var(--squisq-template-gallery-empty, #6b7280);
619
1265
  }
620
1266
 
621
1267
  /* "— none —" row at the top */
@@ -625,34 +1271,42 @@
625
1271
  gap: 10px;
626
1272
  width: 100%;
627
1273
  padding: 6px 10px;
628
- border: 1px solid transparent;
1274
+ border: 1px solid var(--squisq-template-gallery-option-border, #e5e7eb);
629
1275
  border-radius: 7px;
630
- background: none;
1276
+ background: var(--squisq-template-gallery-option-bg, #fbfdff);
631
1277
  cursor: pointer;
632
1278
  text-align: left;
633
1279
  margin-bottom: 6px;
634
- transition: background 0.1s;
1280
+ transition:
1281
+ background 0.1s,
1282
+ border-color 0.1s,
1283
+ box-shadow 0.1s;
635
1284
  }
636
1285
 
637
1286
  .squisq-template-gallery-none:hover {
638
- background: #f9fafb;
1287
+ background: var(--squisq-template-gallery-option-hover-bg, #f9fafb);
1288
+ border-color: var(--squisq-template-gallery-option-hover-border, #c7d2fe);
1289
+ box-shadow: var(
1290
+ --squisq-template-gallery-option-hover-shadow,
1291
+ 0 1px 3px rgba(99, 102, 241, 0.08)
1292
+ );
639
1293
  }
640
1294
 
641
1295
  .squisq-template-gallery-none.squisq-template-gallery-card--selected {
642
- background: #eef2ff;
643
- border-color: #c7d2fe;
1296
+ background: var(--squisq-template-gallery-selected-bg, #eef2ff);
1297
+ border-color: var(--squisq-template-gallery-selected-border, #c7d2fe);
644
1298
  }
645
1299
 
646
1300
  .squisq-template-gallery-none-label {
647
1301
  font-size: 12px;
648
1302
  font-weight: 600;
649
- color: #6b7280;
1303
+ color: var(--squisq-template-gallery-section-title, #6b7280);
650
1304
  white-space: nowrap;
651
1305
  }
652
1306
 
653
1307
  .squisq-template-gallery-none-desc {
654
1308
  font-size: 11px;
655
- color: #9ca3af;
1309
+ color: var(--squisq-template-gallery-description, #9ca3af);
656
1310
  }
657
1311
 
658
1312
  /* Grid of template cards */
@@ -675,12 +1329,13 @@
675
1329
  /* Individual template card */
676
1330
  .squisq-template-gallery-card {
677
1331
  display: flex;
1332
+ flex-direction: column;
678
1333
  align-items: flex-start;
679
- gap: 10px;
680
- padding: 8px 10px;
681
- border: 1px solid #e5e7eb;
1334
+ gap: 8px;
1335
+ padding: 8px;
1336
+ border: 1px solid var(--squisq-template-gallery-card-border, #e5e7eb);
682
1337
  border-radius: 7px;
683
- background: none;
1338
+ background: var(--squisq-template-gallery-card-bg, transparent);
684
1339
  cursor: pointer;
685
1340
  text-align: left;
686
1341
  transition:
@@ -690,23 +1345,29 @@
690
1345
  }
691
1346
 
692
1347
  .squisq-template-gallery-card:hover {
693
- background: #f9fafb;
694
- border-color: #a5b4fc;
695
- box-shadow: 0 1px 4px rgba(99, 102, 241, 0.1);
1348
+ background: var(--squisq-template-gallery-card-hover-bg, #f9fafb);
1349
+ border-color: var(--squisq-template-gallery-card-hover-border, #a5b4fc);
1350
+ box-shadow: var(--squisq-template-gallery-card-hover-shadow, 0 1px 4px rgba(99, 102, 241, 0.1));
696
1351
  }
697
1352
 
698
1353
  .squisq-template-gallery-card--selected {
699
- background: #eef2ff;
700
- border-color: #6366f1;
701
- box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.15);
1354
+ background: var(--squisq-template-gallery-selected-bg, #eef2ff);
1355
+ border-color: var(--squisq-template-gallery-selected-border, #6366f1);
1356
+ box-shadow: var(--squisq-template-gallery-selected-shadow, 0 0 0 2px rgba(99, 102, 241, 0.15));
702
1357
  }
703
1358
 
704
1359
  .squisq-template-gallery-card-icon {
1360
+ display: flex;
1361
+ align-items: center;
1362
+ justify-content: center;
1363
+ width: 100%;
1364
+ aspect-ratio: 16 / 9;
1365
+ min-height: 64px;
705
1366
  flex-shrink: 0;
706
1367
  border-radius: 4px;
707
1368
  overflow: hidden;
708
- background: #f8fafc;
709
- border: 1px solid #e5e7eb;
1369
+ background: var(--squisq-template-gallery-card-icon-bg, #f8fafc);
1370
+ border: 1px solid var(--squisq-template-gallery-card-icon-border, #e5e7eb);
710
1371
  line-height: 0;
711
1372
  }
712
1373
 
@@ -714,24 +1375,94 @@
714
1375
  display: block;
715
1376
  }
716
1377
 
1378
+ .squisq-template-gallery-card-icon .squisq-template-picker-icon {
1379
+ width: 100%;
1380
+ height: 100%;
1381
+ }
1382
+
1383
+ .squisq-template-gallery-none > .squisq-template-picker-icon {
1384
+ width: 56px;
1385
+ height: 40px;
1386
+ flex-shrink: 0;
1387
+ }
1388
+
1389
+ .squisq-template-gallery-card-icon .squisq-template-thumbnail {
1390
+ display: block;
1391
+ width: 100%;
1392
+ height: 100%;
1393
+ }
1394
+
1395
+ .squisq-template-gallery-content-preview {
1396
+ position: relative;
1397
+ width: 100%;
1398
+ height: 100%;
1399
+ background: var(--squisq-template-gallery-content-preview-bg, #f1f5f9);
1400
+ }
1401
+
1402
+ .squisq-template-gallery-content-preview svg {
1403
+ width: 100%;
1404
+ height: 100%;
1405
+ display: block;
1406
+ }
1407
+
1408
+ .squisq-template-gallery-content-preview-fallback {
1409
+ display: flex;
1410
+ align-items: center;
1411
+ justify-content: center;
1412
+ width: 100%;
1413
+ height: 100%;
1414
+ }
1415
+
1416
+ .squisq-template-gallery-content-preview-fallback > svg {
1417
+ width: 100%;
1418
+ height: 100%;
1419
+ display: block;
1420
+ }
1421
+
1422
+ .squisq-template-gallery-content-preview-warning {
1423
+ position: absolute;
1424
+ left: 50%;
1425
+ top: 50%;
1426
+ max-width: calc(100% - 16px);
1427
+ padding: 3px 6px;
1428
+ transform: translate(-50%, -50%);
1429
+ border: 1px solid var(--squisq-template-gallery-preview-warning-border, rgba(255, 255, 255, 0.22));
1430
+ border-radius: 4px;
1431
+ background: var(--squisq-template-gallery-preview-warning-bg, rgba(17, 24, 39, 0.9));
1432
+ color: var(--squisq-template-gallery-preview-warning-text, #ffffff);
1433
+ font-size: 10px;
1434
+ font-weight: 600;
1435
+ line-height: 1.2;
1436
+ text-align: center;
1437
+ pointer-events: none;
1438
+ }
1439
+
717
1440
  .squisq-template-gallery-card-body {
718
1441
  display: flex;
719
1442
  flex-direction: column;
720
1443
  gap: 3px;
1444
+ width: 100%;
721
1445
  min-width: 0;
722
1446
  }
723
1447
 
724
1448
  .squisq-template-gallery-card-name {
725
1449
  font-size: 12px;
726
1450
  font-weight: 600;
727
- color: #111827;
1451
+ color: var(--squisq-template-gallery-name, #111827);
728
1452
  line-height: 1.3;
1453
+ overflow: hidden;
1454
+ text-overflow: ellipsis;
1455
+ white-space: nowrap;
729
1456
  }
730
1457
 
731
1458
  .squisq-template-gallery-card-desc {
732
1459
  font-size: 11px;
733
- color: #6b7280;
1460
+ color: var(--squisq-template-gallery-description, #6b7280);
734
1461
  line-height: 1.4;
1462
+ display: -webkit-box;
1463
+ -webkit-line-clamp: 2;
1464
+ -webkit-box-orient: vertical;
1465
+ overflow: hidden;
735
1466
  }
736
1467
 
737
1468
  /* "+ New custom template" card pinned at the top of the gallery */
@@ -742,9 +1473,9 @@
742
1473
  width: 100%;
743
1474
  padding: 8px 12px;
744
1475
  margin-bottom: 6px;
745
- border: 1px dashed #a5b4fc;
1476
+ border: 1px dashed var(--squisq-template-gallery-new-border, #a5b4fc);
746
1477
  border-radius: 7px;
747
- background: #f5f3ff;
1478
+ background: var(--squisq-template-gallery-new-bg, #f5f3ff);
748
1479
  cursor: pointer;
749
1480
  text-align: left;
750
1481
  transition:
@@ -753,8 +1484,8 @@
753
1484
  }
754
1485
 
755
1486
  .squisq-template-gallery-new:hover {
756
- background: #ede9fe;
757
- border-color: #818cf8;
1487
+ background: var(--squisq-template-gallery-new-hover-bg, #ede9fe);
1488
+ border-color: var(--squisq-template-gallery-new-hover-border, #818cf8);
758
1489
  border-style: solid;
759
1490
  }
760
1491
 
@@ -768,9 +1499,9 @@
768
1499
  font-size: 20px;
769
1500
  font-weight: 600;
770
1501
  line-height: 1;
771
- color: #6366f1;
772
- background: #ffffff;
773
- border: 1px solid #c4b5fd;
1502
+ color: var(--squisq-template-gallery-new-plus-color, #6366f1);
1503
+ background: var(--squisq-template-gallery-new-plus-bg, #ffffff);
1504
+ border: 1px solid var(--squisq-template-gallery-new-plus-border, #c4b5fd);
774
1505
  border-radius: 6px;
775
1506
  }
776
1507
 
@@ -784,12 +1515,12 @@
784
1515
  .squisq-template-gallery-new-label {
785
1516
  font-size: 12px;
786
1517
  font-weight: 600;
787
- color: #4338ca;
1518
+ color: var(--squisq-template-gallery-new-label, #4338ca);
788
1519
  }
789
1520
 
790
1521
  .squisq-template-gallery-new-desc {
791
1522
  font-size: 11px;
792
- color: #6b7280;
1523
+ color: var(--squisq-template-gallery-new-desc, #6b7280);
793
1524
  line-height: 1.4;
794
1525
  }
795
1526
 
@@ -797,14 +1528,14 @@
797
1528
  .squisq-template-gallery-section + .squisq-template-gallery-section {
798
1529
  margin-top: 14px;
799
1530
  padding-top: 10px;
800
- border-top: 1px solid #e5e7eb;
1531
+ border-top: 1px solid var(--squisq-template-gallery-section-border, #e5e7eb);
801
1532
  }
802
1533
 
803
1534
  .squisq-template-gallery-section-title {
804
1535
  margin: 4px 4px 8px;
805
1536
  font-size: 10px;
806
1537
  font-weight: 700;
807
- color: #6b7280;
1538
+ color: var(--squisq-template-gallery-section-title, #6b7280);
808
1539
  text-transform: uppercase;
809
1540
  letter-spacing: 0.06em;
810
1541
  }
@@ -853,41 +1584,86 @@
853
1584
  .squisq-template-badge {
854
1585
  display: inline-flex;
855
1586
  align-items: center;
856
- gap: 4px;
1587
+ gap: 1px;
857
1588
  margin-left: 8px;
858
- padding: 1px 6px 1px 8px;
1589
+ padding: 0;
859
1590
  font-size: 11px;
860
1591
  font-weight: 600;
861
1592
  font-family: inherit;
862
- color: #6d28d9;
863
- background: #ede9fe;
864
- border: 1px solid #c4b5fd;
865
- border-radius: 10px;
866
- vertical-align: middle;
1593
+ color: #c3a47d;
1594
+ background: transparent;
1595
+ border: 0;
1596
+ border-radius: 0;
1597
+ vertical-align: baseline;
1598
+ transform: translate(3px, 0);
867
1599
  user-select: none;
868
- line-height: 1.6;
1600
+ line-height: 1;
869
1601
  cursor: pointer;
1602
+ transition:
1603
+ color 0.15s ease,
1604
+ opacity 0.15s ease;
1605
+ }
1606
+
1607
+ .squisq-template-badge-core {
1608
+ display: inline-flex;
1609
+ align-items: center;
1610
+ gap: 4px;
1611
+ padding: 1px 7px;
1612
+ color: #7c4a16;
1613
+ background: #f8f0e3;
1614
+ border: 1px solid #d8c2a2;
1615
+ border-radius: 0;
1616
+ line-height: 1.6;
870
1617
  transition:
871
1618
  background 0.15s ease,
872
1619
  border-color 0.15s ease;
873
1620
  }
874
1621
 
875
- .squisq-template-badge:hover,
1622
+ .squisq-template-badge:hover .squisq-template-badge-core,
1623
+ .squisq-template-badge:focus-visible .squisq-template-badge-core {
1624
+ background: #ead6b8;
1625
+ border-color: #bb9563;
1626
+ }
1627
+
876
1628
  .squisq-template-badge:focus-visible {
877
- background: #ddd6fe;
878
- border-color: #a78bfa;
879
1629
  outline: none;
880
1630
  }
881
1631
 
882
1632
  .squisq-template-badge::before {
883
- content: attr(data-template-label);
1633
+ content: '{';
1634
+ }
1635
+
1636
+ .squisq-template-badge::after {
1637
+ content: '}';
884
1638
  }
885
1639
 
1640
+ .squisq-template-badge::before,
886
1641
  .squisq-template-badge::after {
1642
+ display: inline-flex;
1643
+ position: relative;
1644
+ top: -1px;
1645
+ align-items: center;
1646
+ min-height: 22px;
1647
+ font-size: 22px;
1648
+ font-weight: 500;
1649
+ line-height: 1;
1650
+ opacity: 0.64;
1651
+ }
1652
+
1653
+ .squisq-template-badge-core::before {
1654
+ content: attr(data-template-label);
1655
+ }
1656
+
1657
+ .squisq-template-badge-core::before,
1658
+ .squisq-template-badge-core::after {
1659
+ transform: translateY(1px);
1660
+ }
1661
+
1662
+ .squisq-template-badge-core::after {
887
1663
  content: '▾';
888
1664
  font-size: 9px;
889
1665
  line-height: 1;
890
- opacity: 0.7;
1666
+ opacity: 0.62;
891
1667
  }
892
1668
 
893
1669
  /* Empty variant — subtle affordance on plain headings that opens the
@@ -896,13 +1672,14 @@
896
1672
  .squisq-template-badge.squisq-template-badge--empty {
897
1673
  color: #94a3b8;
898
1674
  background: transparent;
899
- border-color: #d1d5db;
900
- border-style: dashed;
901
1675
  opacity: 0.5;
902
1676
  }
903
1677
 
904
- .squisq-template-badge.squisq-template-badge--empty::before {
905
- content: 'Block';
1678
+ .squisq-template-badge.squisq-template-badge--empty .squisq-template-badge-core {
1679
+ color: #94a3b8;
1680
+ background: transparent;
1681
+ border-color: #d1d5db;
1682
+ border-style: dashed;
906
1683
  font-weight: 500;
907
1684
  }
908
1685
 
@@ -913,9 +1690,14 @@
913
1690
  .squisq-template-badge.squisq-template-badge--empty:hover,
914
1691
  .squisq-template-badge.squisq-template-badge--empty:focus-visible {
915
1692
  opacity: 1;
916
- color: #6d28d9;
917
- background: #ede9fe;
918
- border-color: #c4b5fd;
1693
+ color: #b89266;
1694
+ }
1695
+
1696
+ .squisq-template-badge.squisq-template-badge--empty:hover .squisq-template-badge-core,
1697
+ .squisq-template-badge.squisq-template-badge--empty:focus-visible .squisq-template-badge-core {
1698
+ color: #7c4a16;
1699
+ background: #f1e2ca;
1700
+ border-color: #d8c2a2;
919
1701
  border-style: solid;
920
1702
  }
921
1703
 
@@ -927,6 +1709,26 @@
927
1709
  display: none;
928
1710
  }
929
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
+
930
1732
  /* ─── Block-properties badge (sibling of the template badge) ───────────
931
1733
  The on-canvas entry point to the block-properties palette: a small
932
1734
  sliders chip just after the template badge. Quiet by default like the
@@ -949,6 +1751,7 @@
949
1751
  border: 1px solid #d1d5db;
950
1752
  border-radius: 10px;
951
1753
  vertical-align: middle;
1754
+ transform: translate(3px, -2px);
952
1755
  user-select: none;
953
1756
  cursor: pointer;
954
1757
  opacity: 0.5;
@@ -960,11 +1763,12 @@
960
1763
 
961
1764
  /* Sliders glyph painted via CSS so the badge span stays empty in the DOM
962
1765
  (see propsBadgeSpec — a real child could leak into serialized markdown).
963
- `\f1de` is Font Awesome's "sliders"; the font is already loaded for the
964
- 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. */
965
1769
  .squisq-props-badge::before {
966
1770
  content: '\f1de';
967
- font-family: 'Font Awesome 6 Free';
1771
+ font-family: var(--fa-family-classic, 'Font Awesome 7 Free');
968
1772
  font-weight: 900;
969
1773
  font-size: 10px;
970
1774
  line-height: 1;
@@ -974,9 +1778,9 @@
974
1778
  it after the glyph — and reads as an active (not just affordance) chip. */
975
1779
  .squisq-props-badge[data-props-summary] {
976
1780
  opacity: 1;
977
- color: #6d28d9;
978
- background: #f5f3ff;
979
- 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);
980
1784
  }
981
1785
 
982
1786
  .squisq-props-badge[data-props-summary]::after {
@@ -993,13 +1797,39 @@
993
1797
  .squisq-props-badge:hover,
994
1798
  .squisq-props-badge:focus-visible {
995
1799
  opacity: 1;
996
- color: #6d28d9;
997
- background: #ede9fe;
998
- 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);
999
1803
  outline: none;
1000
1804
  }
1001
1805
 
1002
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
+
1003
1833
  .squisq-block-props-popover {
1004
1834
  width: 280px;
1005
1835
  max-width: calc(100vw - 24px);
@@ -1007,8 +1837,9 @@
1007
1837
  display: flex;
1008
1838
  flex-direction: column;
1009
1839
  gap: 10px;
1010
- background: #fff;
1011
- 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);
1012
1843
  border-radius: 10px;
1013
1844
  box-shadow:
1014
1845
  0 8px 24px rgba(0, 0, 0, 0.12),
@@ -1025,7 +1856,7 @@
1025
1856
  .squisq-block-props-label {
1026
1857
  font-size: 11px;
1027
1858
  font-weight: 600;
1028
- color: #6b7280;
1859
+ color: var(--squisq-block-props-muted);
1029
1860
  flex-shrink: 0;
1030
1861
  }
1031
1862
 
@@ -1039,54 +1870,47 @@
1039
1870
  width: 72px;
1040
1871
  padding: 4px 6px;
1041
1872
  font-size: 12px;
1042
- color: #111827;
1043
- 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);
1044
1876
  border-radius: 5px;
1045
1877
  outline: none;
1046
1878
  }
1047
1879
 
1048
1880
  .squisq-block-props-input:focus {
1049
- border-color: #6366f1;
1881
+ border-color: var(--squisq-block-props-accent, #6366f1);
1050
1882
  }
1051
1883
 
1052
1884
  .squisq-block-props-unit {
1053
1885
  font-size: 11px;
1054
- color: #9ca3af;
1886
+ color: var(--squisq-block-props-quiet);
1055
1887
  }
1056
1888
 
1057
1889
  /* Dark theme */
1058
- .squisq-editor-shell[data-theme='dark'] .squisq-props-badge {
1890
+ .squisq-editor-shell[data-theme='dark'] .squisq-props-badge:not([data-props-summary]) {
1059
1891
  border-color: #4b5563;
1060
1892
  color: #9ca3af;
1061
1893
  }
1062
1894
 
1063
1895
  .squisq-editor-shell[data-theme='dark'] .squisq-props-badge[data-props-summary] {
1064
- color: #ddd6fe;
1065
- background: #3730a3;
1066
- 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);
1067
1899
  }
1068
1900
 
1069
1901
  .squisq-editor-shell[data-theme='dark'] .squisq-props-badge:hover,
1070
1902
  .squisq-editor-shell[data-theme='dark'] .squisq-props-badge:focus-visible {
1071
- color: #ede9fe;
1072
- background: #4c1d95;
1073
- 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);
1074
1906
  }
1075
1907
 
1076
- .squisq-editor-shell[data-theme='dark'] .squisq-block-props-popover {
1077
- background: #1f2937;
1078
- border-color: #374151;
1908
+ .squisq-block-props-popover[data-theme='dark'] {
1079
1909
  box-shadow:
1080
1910
  0 8px 24px rgba(0, 0, 0, 0.4),
1081
1911
  0 2px 6px rgba(0, 0, 0, 0.2);
1082
1912
  }
1083
1913
 
1084
- .squisq-editor-shell[data-theme='dark'] .squisq-block-props-input {
1085
- background: #111827;
1086
- color: #f9fafb;
1087
- border-color: #4b5563;
1088
- }
1089
-
1090
1914
  /* ─── Status Bar ─────────────────────────────────────── */
1091
1915
 
1092
1916
  .squisq-status-bar {
@@ -1190,19 +2014,23 @@
1190
2014
  font-family: var(--squisq-theme-title-font, var(--squisq-theme-body-font, inherit));
1191
2015
  }
1192
2016
 
1193
- /* Headings start blocks, so they get generous space ABOVE (a clear break from
1194
- the previous block) and a tighter margin BELOW so the heading stays visually
1195
- grouped with the content it introduces. */
2017
+ /* Headings start blocks, so they get a clear break from the previous block and
2018
+ tighter space below to stay visually grouped with their content. H1/H2 use
2019
+ modest top margins because their themed font size already creates separation. */
1196
2020
  .squisq-wysiwyg-editor h1 {
1197
2021
  font-size: 2em;
1198
- margin: 1em 0 0.4em;
2022
+ margin: 0.45em 0 0.4em;
1199
2023
  }
1200
2024
  .squisq-wysiwyg-editor h2 {
1201
2025
  font-size: 1.5em;
1202
- margin: 1.15em 0 0.35em;
2026
+ margin: 0.8em 0 0.25em;
1203
2027
  }
1204
2028
  .squisq-wysiwyg-editor h3 {
1205
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;
1206
2034
  margin: 1.3em 0 0.3em;
1207
2035
  }
1208
2036
  .squisq-wysiwyg-editor h4 {
@@ -1228,7 +2056,7 @@
1228
2056
 
1229
2057
  .squisq-wysiwyg-editor p {
1230
2058
  margin: 0.5em 0;
1231
- line-height: 1.6;
2059
+ line-height: 1.7;
1232
2060
  }
1233
2061
 
1234
2062
  .squisq-wysiwyg-editor blockquote {
@@ -1252,6 +2080,10 @@
1252
2080
  overflow-x: auto;
1253
2081
  font-size: 13px;
1254
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;
1255
2087
  }
1256
2088
 
1257
2089
  .squisq-wysiwyg-editor code {
@@ -1260,6 +2092,7 @@
1260
2092
  padding: 1px 4px;
1261
2093
  border-radius: 3px;
1262
2094
  font-size: 0.9em;
2095
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
1263
2096
  }
1264
2097
 
1265
2098
  .squisq-wysiwyg-editor pre code {
@@ -1416,24 +2249,6 @@
1416
2249
 
1417
2250
  /* ─── Preview Controls ──────────────────────────────── */
1418
2251
 
1419
- /* Left-side preview switches: the segmented mode switch and the aspect-ratio
1420
- switch, separated by a divider. Natural width; sits just after the view
1421
- tabs and never shrinks. */
1422
- .squisq-preview-left-controls {
1423
- display: flex;
1424
- align-items: center;
1425
- gap: 8px;
1426
- margin-left: 8px;
1427
- flex: 0 0 auto;
1428
- }
1429
-
1430
- .squisq-preview-seg-divider {
1431
- width: 1px;
1432
- height: 20px;
1433
- background: var(--squisq-border, #d1d5db);
1434
- flex: 0 0 auto;
1435
- }
1436
-
1437
2252
  /* Segmented switch — a row of connected buttons (display mode: Video /
1438
2253
  Slideshow / Document / Page; aspect ratio: 16:9 / 1:1 / 9:16 / 4:3),
1439
2254
  replacing the old "Mode:" / "Format:" dropdowns. */
@@ -1509,12 +2324,19 @@
1509
2324
  display: flex;
1510
2325
  align-items: center;
1511
2326
  gap: 6px;
1512
- flex: 1 1 auto;
2327
+ flex: 1 1 0;
1513
2328
  min-width: 0;
1514
2329
  position: relative;
1515
2330
  padding-left: 9px;
1516
2331
  }
1517
2332
 
2333
+ .squisq-preview-controls[data-has-overflow='true'] {
2334
+ /* The compact ellipsis trigger needs real flex-row width. Without this, the
2335
+ filler can shrink below the trigger's painted width and the next toolbar
2336
+ buttons visually collide with it at intermediate widths. */
2337
+ min-width: 41px;
2338
+ }
2339
+
1518
2340
  /* Hidden probe: renders every control at natural width so the fit measurement
1519
2341
  has per-control widths to work from. Absolutely positioned + hidden so it
1520
2342
  never affects layout or catches pointer events. */
@@ -1531,7 +2353,7 @@
1531
2353
  pointer-events: none;
1532
2354
  }
1533
2355
 
1534
- /* Inline row sits at its natural width (the overflow gear, when present, sits
2356
+ /* Inline row sits at its natural width (the ellipsis trigger, when present, sits
1535
2357
  just after it); it never wraps — controls that don't fit move to the menu. */
1536
2358
  .squisq-preview-controls-inline {
1537
2359
  display: flex;
@@ -1555,20 +2377,19 @@
1555
2377
  }
1556
2378
 
1557
2379
  .squisq-preview-controls-popover {
1558
- position: absolute;
1559
- top: 100%;
1560
- right: 0;
2380
+ position: fixed;
1561
2381
  z-index: 80;
1562
2382
  background: var(--squisq-bg, #fff);
1563
2383
  border: 1px solid var(--squisq-border, #d1d5db);
1564
2384
  border-radius: 6px;
1565
2385
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
1566
2386
  padding: 8px 12px;
1567
- margin-top: 4px;
2387
+ box-sizing: border-box;
1568
2388
  display: flex;
1569
2389
  flex-direction: column;
1570
2390
  gap: 8px;
1571
2391
  min-width: 180px;
2392
+ max-width: calc(100vw - 16px);
1572
2393
  }
1573
2394
 
1574
2395
  .squisq-preview-control--compact {
@@ -1583,6 +2404,74 @@
1583
2404
  min-width: 0;
1584
2405
  }
1585
2406
 
2407
+ .squisq-preview-checkbox {
2408
+ display: inline-flex;
2409
+ align-items: center;
2410
+ gap: 6px;
2411
+ color: var(--squisq-text, #1f2937);
2412
+ font-size: 12px;
2413
+ font-weight: 500;
2414
+ line-height: 1;
2415
+ white-space: nowrap;
2416
+ cursor: pointer;
2417
+ }
2418
+
2419
+ .squisq-preview-checkbox input {
2420
+ width: 13px;
2421
+ height: 13px;
2422
+ margin: 0;
2423
+ accent-color: #2563eb;
2424
+ cursor: pointer;
2425
+ }
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
+
1586
2475
  /* Link color follows the active theme's primary when "Theme styling →
1587
2476
  Fonts & colors" is on, otherwise falls back to the historical blue.
1588
2477
  In both cases we blend toward the surface text color so the link
@@ -1643,6 +2532,136 @@
1643
2532
  color: #dc2626;
1644
2533
  }
1645
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
+
1646
2665
  /* ─── CSS custom properties ──────────────────────────── */
1647
2666
 
1648
2667
  .squisq-editor-shell {
@@ -1715,6 +2734,20 @@
1715
2734
  border-bottom-color: #60a5fa;
1716
2735
  }
1717
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
+
1718
2751
  .squisq-editor-shell[data-theme='dark'] .squisq-toolbar-button {
1719
2752
  color: #d1d5db;
1720
2753
  }
@@ -1738,6 +2771,12 @@
1738
2771
  color: #93c5fd;
1739
2772
  }
1740
2773
 
2774
+ .squisq-editor-shell[data-theme='dark'] .squisq-toolbar-files-badge {
2775
+ border-color: #111827;
2776
+ background: #60a5fa;
2777
+ color: #111827;
2778
+ }
2779
+
1741
2780
  .squisq-editor-shell[data-theme='dark'] .squisq-toolbar-separator {
1742
2781
  background: #4b5563;
1743
2782
  }
@@ -1779,6 +2818,10 @@
1779
2818
  color: #d1d5db;
1780
2819
  }
1781
2820
 
2821
+ .squisq-editor-shell[data-theme='dark'] .squisq-toolbar-overflow-heading {
2822
+ color: #6b7280;
2823
+ }
2824
+
1782
2825
  .squisq-editor-shell[data-theme='dark'] .squisq-toolbar-overflow-item:hover {
1783
2826
  background: #374151;
1784
2827
  }
@@ -1896,6 +2939,10 @@
1896
2939
  border-color: #374151;
1897
2940
  }
1898
2941
 
2942
+ .squisq-editor-shell[data-theme='dark'] .squisq-template-gallery-content-preview {
2943
+ background: #0f172a;
2944
+ }
2945
+
1899
2946
  .squisq-editor-shell[data-theme='dark'] .squisq-template-gallery-card-name {
1900
2947
  color: #f3f4f6;
1901
2948
  }
@@ -1906,24 +2953,53 @@
1906
2953
 
1907
2954
  /* Template badge (dark) */
1908
2955
  .squisq-editor-shell[data-theme='dark'] .squisq-template-badge {
1909
- color: #a78bfa;
1910
- background: #2e1065;
1911
- border-color: #6d28d9;
2956
+ color: #f0b75a;
2957
+ background: transparent;
2958
+ border-color: transparent;
2959
+ }
2960
+
2961
+ .squisq-editor-shell[data-theme='dark'] .squisq-template-badge::before,
2962
+ .squisq-editor-shell[data-theme='dark'] .squisq-template-badge::after {
2963
+ color: #d79a45;
2964
+ opacity: 0.82;
2965
+ }
2966
+
2967
+ .squisq-editor-shell[data-theme='dark'] .squisq-template-badge-core {
2968
+ color: #ffe3ad;
2969
+ background: #3a2818;
2970
+ border-color: #d79a45;
1912
2971
  }
1913
2972
 
1914
2973
  .squisq-editor-shell[data-theme='dark'] .squisq-template-badge.squisq-template-badge--empty {
1915
- color: #64748b;
2974
+ color: #e0a84d;
1916
2975
  background: transparent;
1917
- border-color: #374151;
2976
+ opacity: 0.92;
2977
+ }
2978
+
2979
+ .squisq-editor-shell[data-theme='dark']
2980
+ .squisq-template-badge.squisq-template-badge--empty
2981
+ .squisq-template-badge-core {
2982
+ color: #e7c08a;
2983
+ background: rgba(58, 40, 24, 0.34);
2984
+ border-color: #c6842e;
1918
2985
  border-style: dashed;
1919
2986
  }
1920
2987
 
1921
2988
  .squisq-editor-shell[data-theme='dark'] .squisq-template-badge.squisq-template-badge--empty:hover,
1922
2989
  .squisq-editor-shell[data-theme='dark']
1923
2990
  .squisq-template-badge.squisq-template-badge--empty:focus-visible {
1924
- color: #c4b5fd;
1925
- background: #2e1065;
1926
- border-color: #6d28d9;
2991
+ color: #f0b75a;
2992
+ }
2993
+
2994
+ .squisq-editor-shell[data-theme='dark']
2995
+ .squisq-template-badge.squisq-template-badge--empty:hover
2996
+ .squisq-template-badge-core,
2997
+ .squisq-editor-shell[data-theme='dark']
2998
+ .squisq-template-badge.squisq-template-badge--empty:focus-visible
2999
+ .squisq-template-badge-core {
3000
+ color: #ffe3ad;
3001
+ background: #3a2818;
3002
+ border-color: #d79a45;
1927
3003
  border-style: solid;
1928
3004
  }
1929
3005
 
@@ -2085,6 +3161,7 @@
2085
3161
  /* ─── Media Bin ──────────────────────────────────────── */
2086
3162
 
2087
3163
  .squisq-media-bin {
3164
+ position: relative;
2088
3165
  width: 220px;
2089
3166
  border-left: 1px solid #e5e7eb;
2090
3167
  background: #f9fafb;
@@ -2094,6 +3171,46 @@
2094
3171
  overflow: hidden;
2095
3172
  }
2096
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
+
2097
3214
  .squisq-media-bin-header {
2098
3215
  display: flex;
2099
3216
  align-items: center;
@@ -2155,6 +3272,16 @@
2155
3272
  border-bottom: 1px solid #f3f4f6;
2156
3273
  }
2157
3274
 
3275
+ .squisq-media-bin-item:hover,
3276
+ .squisq-media-bin-item:focus-visible {
3277
+ background: #f3f4f6;
3278
+ }
3279
+
3280
+ .squisq-media-bin-item:focus-visible {
3281
+ outline: 2px solid #93c5fd;
3282
+ outline-offset: -2px;
3283
+ }
3284
+
2158
3285
  .squisq-media-bin-thumb {
2159
3286
  width: 32px;
2160
3287
  height: 32px;
@@ -2187,11 +3314,82 @@
2187
3314
  white-space: nowrap;
2188
3315
  }
2189
3316
 
3317
+ .squisq-media-bin-detail-row {
3318
+ display: flex;
3319
+ align-items: center;
3320
+ gap: 6px;
3321
+ min-height: 14px;
3322
+ }
3323
+
2190
3324
  .squisq-media-bin-size {
2191
3325
  font-size: 10px;
2192
3326
  color: #9ca3af;
2193
3327
  }
2194
3328
 
3329
+ .squisq-media-bin-unused-badge {
3330
+ display: inline-flex;
3331
+ align-items: center;
3332
+ height: 14px;
3333
+ padding: 0 5px;
3334
+ border-radius: 999px;
3335
+ background: #fef3c7;
3336
+ color: #92400e;
3337
+ font-size: 9px;
3338
+ font-weight: 700;
3339
+ line-height: 1;
3340
+ text-transform: uppercase;
3341
+ }
3342
+
3343
+ .squisq-media-bin-context-menu {
3344
+ position: fixed;
3345
+ z-index: 1000;
3346
+ min-width: 152px;
3347
+ padding: 4px;
3348
+ border: 1px solid #d1d5db;
3349
+ border-radius: 6px;
3350
+ background: #fff;
3351
+ box-shadow:
3352
+ 0 12px 28px rgba(15, 23, 42, 0.18),
3353
+ 0 2px 6px rgba(15, 23, 42, 0.12);
3354
+ }
3355
+
3356
+ .squisq-media-bin-context-menu-item {
3357
+ width: 100%;
3358
+ display: flex;
3359
+ align-items: center;
3360
+ gap: 8px;
3361
+ padding: 7px 9px;
3362
+ border: 0;
3363
+ border-radius: 4px;
3364
+ background: transparent;
3365
+ color: #374151;
3366
+ cursor: pointer;
3367
+ font: inherit;
3368
+ font-size: 12px;
3369
+ text-align: left;
3370
+ }
3371
+
3372
+ .squisq-media-bin-context-menu-item:hover,
3373
+ .squisq-media-bin-context-menu-item:focus-visible {
3374
+ background: #f3f4f6;
3375
+ outline: none;
3376
+ }
3377
+
3378
+ .squisq-media-bin-context-menu-item--danger {
3379
+ color: #b91c1c;
3380
+ }
3381
+
3382
+ .squisq-media-bin-context-menu-item--danger:hover,
3383
+ .squisq-media-bin-context-menu-item--danger:focus-visible {
3384
+ background: #fee2e2;
3385
+ color: #991b1b;
3386
+ }
3387
+
3388
+ .squisq-media-bin-context-menu-item:disabled {
3389
+ cursor: default;
3390
+ opacity: 0.55;
3391
+ }
3392
+
2195
3393
  /* ─── Media Bin (dark) ───────────────────────────────── */
2196
3394
 
2197
3395
  .squisq-media-bin--dark,
@@ -2200,6 +3398,21 @@
2200
3398
  border-left-color: #374151;
2201
3399
  }
2202
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
+
2203
3416
  .squisq-media-bin--dark .squisq-media-bin-header,
2204
3417
  .squisq-editor-shell[data-theme='dark'] .squisq-media-bin .squisq-media-bin-header {
2205
3418
  border-bottom-color: #374151;
@@ -2228,6 +3441,13 @@
2228
3441
  border-bottom-color: #2d3748;
2229
3442
  }
2230
3443
 
3444
+ .squisq-media-bin--dark .squisq-media-bin-item:hover,
3445
+ .squisq-media-bin--dark .squisq-media-bin-item:focus-visible,
3446
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin .squisq-media-bin-item:hover,
3447
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin .squisq-media-bin-item:focus-visible {
3448
+ background: #273449;
3449
+ }
3450
+
2231
3451
  .squisq-media-bin--dark .squisq-media-bin-icon,
2232
3452
  .squisq-editor-shell[data-theme='dark'] .squisq-media-bin .squisq-media-bin-icon {
2233
3453
  background: #374151;
@@ -2243,11 +3463,51 @@
2243
3463
  color: #6b7280;
2244
3464
  }
2245
3465
 
3466
+ .squisq-media-bin--dark .squisq-media-bin-unused-badge,
3467
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin .squisq-media-bin-unused-badge {
3468
+ background: #78350f;
3469
+ color: #fde68a;
3470
+ }
3471
+
2246
3472
  .squisq-media-bin--dark .squisq-media-bin-empty,
2247
3473
  .squisq-editor-shell[data-theme='dark'] .squisq-media-bin .squisq-media-bin-empty {
2248
3474
  color: #6b7280;
2249
3475
  }
2250
3476
 
3477
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin-context-menu,
3478
+ .squisq-media-bin--dark .squisq-media-bin-context-menu {
3479
+ border-color: #4b5563;
3480
+ background: #111827;
3481
+ box-shadow:
3482
+ 0 12px 28px rgba(0, 0, 0, 0.42),
3483
+ 0 2px 6px rgba(0, 0, 0, 0.3);
3484
+ }
3485
+
3486
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin-context-menu-item,
3487
+ .squisq-media-bin--dark .squisq-media-bin-context-menu-item {
3488
+ color: #d1d5db;
3489
+ }
3490
+
3491
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin-context-menu-item:hover,
3492
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin-context-menu-item:focus-visible,
3493
+ .squisq-media-bin--dark .squisq-media-bin-context-menu-item:hover,
3494
+ .squisq-media-bin--dark .squisq-media-bin-context-menu-item:focus-visible {
3495
+ background: #1f2937;
3496
+ }
3497
+
3498
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin-context-menu-item--danger,
3499
+ .squisq-media-bin--dark .squisq-media-bin-context-menu-item--danger {
3500
+ color: #fca5a5;
3501
+ }
3502
+
3503
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin-context-menu-item--danger:hover,
3504
+ .squisq-editor-shell[data-theme='dark'] .squisq-media-bin-context-menu-item--danger:focus-visible,
3505
+ .squisq-media-bin--dark .squisq-media-bin-context-menu-item--danger:hover,
3506
+ .squisq-media-bin--dark .squisq-media-bin-context-menu-item--danger:focus-visible {
3507
+ background: #450a0a;
3508
+ color: #fecaca;
3509
+ }
3510
+
2251
3511
  /* ============================================
2252
3512
  Drop Zone Overlay
2253
3513
  ============================================ */
@@ -3071,6 +4331,16 @@
3071
4331
  margin-left: 2px;
3072
4332
  }
3073
4333
 
4334
+ .squisq-theme-customizer-trigger--label {
4335
+ width: auto;
4336
+ min-width: 0;
4337
+ padding: 4px 12px;
4338
+ }
4339
+
4340
+ .squisq-theme-customizer-trigger-label {
4341
+ line-height: 1;
4342
+ }
4343
+
3074
4344
  .squisq-theme-customizer-popover {
3075
4345
  position: absolute;
3076
4346
  top: 100%;
@@ -3230,6 +4500,69 @@
3230
4500
  background: #1d4ed8;
3231
4501
  }
3232
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
+
3233
4566
  .squisq-editor-shell[data-theme='dark'] .squisq-theme-customizer-popover {
3234
4567
  background: #1f2937;
3235
4568
  border-color: #374151;
@@ -4042,6 +5375,7 @@
4042
5375
  }
4043
5376
 
4044
5377
  .squisq-outline-item {
5378
+ position: relative;
4045
5379
  margin: 0;
4046
5380
  }
4047
5381
 
@@ -4066,6 +5400,56 @@
4066
5400
  background: #f3f4f6;
4067
5401
  }
4068
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
+
4069
5453
  .squisq-outline-row-text {
4070
5454
  overflow: hidden;
4071
5455
  text-overflow: ellipsis;
@@ -4236,10 +5620,7 @@
4236
5620
  color: #d1d5db;
4237
5621
  }
4238
5622
 
4239
- /* Dark-mode rebind for all preview-gutter custom properties. Individual
4240
- rules below remain as no-ops kept for back-compat with any host CSS
4241
- that may still target them — the variable redefinition is the single
4242
- source of truth going forward. */
5623
+ /* Dark-mode rebind for all preview-gutter custom properties. */
4243
5624
  .squisq-editor-shell[data-theme='dark'] {
4244
5625
  --squisq-preview-accent: #818cf8;
4245
5626
  --squisq-preview-accent-muted: #475569;
@@ -4255,10 +5636,6 @@
4255
5636
  --squisq-preview-empty-text: #94a3b8;
4256
5637
  }
4257
5638
 
4258
- .squisq-editor-shell[data-theme='dark'] .squisq-inline-preview-gutter {
4259
- background: var(--squisq-preview-gutter-bg);
4260
- }
4261
-
4262
5639
  .squisq-editor-shell[data-theme='dark'] .squisq-outline-empty {
4263
5640
  color: #94a3b8;
4264
5641
  }
@@ -5130,9 +6507,9 @@
5130
6507
  padding: 3px 8px;
5131
6508
  font-size: 12px;
5132
6509
  font-weight: 500;
5133
- color: #374151;
5134
- background: #fff;
5135
- 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);
5136
6513
  border-radius: 5px;
5137
6514
  cursor: pointer;
5138
6515
  white-space: nowrap;
@@ -5142,23 +6519,23 @@
5142
6519
  }
5143
6520
 
5144
6521
  .squisq-transition-picker-trigger:hover {
5145
- background: #f3f4f6;
5146
- border-color: #9ca3af;
6522
+ background: var(--squisq-block-props-surface-hover);
6523
+ border-color: var(--squisq-block-props-quiet);
5147
6524
  }
5148
6525
 
5149
6526
  .squisq-transition-picker-trigger--open {
5150
- background: #f3f4f6;
5151
- border-color: #6366f1;
5152
- 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);
5153
6530
  outline-offset: -1px;
5154
6531
  }
5155
6532
 
5156
6533
  .squisq-transition-picker-trigger-label {
5157
- color: #6b7280;
6534
+ color: var(--squisq-block-props-muted);
5158
6535
  }
5159
6536
 
5160
6537
  .squisq-transition-picker-trigger-value {
5161
- color: #111827;
6538
+ color: var(--squisq-block-props-text);
5162
6539
  font-weight: 400;
5163
6540
  max-width: 110px;
5164
6541
  overflow: hidden;
@@ -5166,7 +6543,7 @@
5166
6543
  }
5167
6544
 
5168
6545
  .squisq-transition-picker-trigger svg {
5169
- color: #9ca3af;
6546
+ color: var(--squisq-block-props-quiet);
5170
6547
  flex-shrink: 0;
5171
6548
  }
5172
6549
 
@@ -5185,8 +6562,9 @@
5185
6562
  max-width: calc(100vw - 24px);
5186
6563
  display: flex;
5187
6564
  flex-direction: column;
5188
- background: #fff;
5189
- 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);
5190
6568
  border-radius: 10px;
5191
6569
  box-shadow:
5192
6570
  0 8px 24px rgba(0, 0, 0, 0.12),
@@ -5196,21 +6574,22 @@
5196
6574
 
5197
6575
  .squisq-transition-flyout-search {
5198
6576
  padding: 8px;
5199
- border-bottom: 1px solid #f0f0f0;
6577
+ border-bottom: 1px solid var(--squisq-block-props-divider);
5200
6578
  }
5201
6579
 
5202
6580
  .squisq-transition-flyout-search-input {
5203
6581
  width: 100%;
5204
6582
  padding: 6px 8px;
5205
6583
  font-size: 13px;
5206
- color: #111827;
5207
- 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);
5208
6587
  border-radius: 6px;
5209
6588
  outline: none;
5210
6589
  }
5211
6590
 
5212
6591
  .squisq-transition-flyout-search-input:focus {
5213
- border-color: #6366f1;
6592
+ border-color: var(--squisq-block-props-accent, #6366f1);
5214
6593
  }
5215
6594
 
5216
6595
  .squisq-transition-flyout-list {
@@ -5232,7 +6611,7 @@
5232
6611
  font-weight: 600;
5233
6612
  letter-spacing: 0.04em;
5234
6613
  text-transform: uppercase;
5235
- color: #9ca3af;
6614
+ color: var(--squisq-block-props-quiet);
5236
6615
  }
5237
6616
 
5238
6617
  .squisq-transition-flyout-grid {
@@ -5247,9 +6626,9 @@
5247
6626
  text-align: left;
5248
6627
  padding: 6px 8px;
5249
6628
  font-size: 12px;
5250
- color: #374151;
5251
- background: #fff;
5252
- 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);
5253
6632
  border-radius: 6px;
5254
6633
  cursor: pointer;
5255
6634
  white-space: nowrap;
@@ -5258,14 +6637,14 @@
5258
6637
  }
5259
6638
 
5260
6639
  .squisq-transition-option:hover {
5261
- background: #f3f4f6;
5262
- border-color: #d1d5db;
6640
+ background: var(--squisq-block-props-surface-hover);
6641
+ border-color: var(--squisq-block-props-border);
5263
6642
  }
5264
6643
 
5265
6644
  .squisq-transition-option--selected {
5266
- background: #eef2ff;
5267
- border-color: #6366f1;
5268
- 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);
5269
6648
  font-weight: 600;
5270
6649
  }
5271
6650
 
@@ -5294,13 +6673,13 @@
5294
6673
  .squisq-transition-flyout-empty {
5295
6674
  padding: 12px 8px;
5296
6675
  font-size: 12px;
5297
- color: #9ca3af;
6676
+ color: var(--squisq-block-props-quiet);
5298
6677
  text-align: center;
5299
6678
  }
5300
6679
 
5301
6680
  /* Direction + duration controls, shown below the list once a type is set. */
5302
6681
  .squisq-transition-flyout-controls {
5303
- border-top: 1px solid #f0f0f0;
6682
+ border-top: 1px solid var(--squisq-block-props-divider);
5304
6683
  padding: 10px 12px;
5305
6684
  display: flex;
5306
6685
  flex-direction: column;
@@ -5317,7 +6696,7 @@
5317
6696
  .squisq-transition-flyout-control-label {
5318
6697
  font-size: 11px;
5319
6698
  font-weight: 600;
5320
- color: #6b7280;
6699
+ color: var(--squisq-block-props-muted);
5321
6700
  }
5322
6701
 
5323
6702
  .squisq-transition-direction-row {
@@ -5328,21 +6707,21 @@
5328
6707
  .squisq-transition-direction-button {
5329
6708
  padding: 4px 8px;
5330
6709
  font-size: 11px;
5331
- color: #374151;
5332
- background: #fff;
5333
- 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);
5334
6713
  border-radius: 5px;
5335
6714
  cursor: pointer;
5336
6715
  }
5337
6716
 
5338
6717
  .squisq-transition-direction-button:hover {
5339
- background: #f3f4f6;
6718
+ background: var(--squisq-block-props-surface-hover);
5340
6719
  }
5341
6720
 
5342
6721
  .squisq-transition-direction-button--selected {
5343
- background: #eef2ff;
5344
- border-color: #6366f1;
5345
- 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);
5346
6725
  font-weight: 600;
5347
6726
  }
5348
6727
 
@@ -5356,19 +6735,20 @@
5356
6735
  width: 64px;
5357
6736
  padding: 4px 6px;
5358
6737
  font-size: 12px;
5359
- color: #111827;
5360
- 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);
5361
6741
  border-radius: 5px;
5362
6742
  outline: none;
5363
6743
  }
5364
6744
 
5365
6745
  .squisq-transition-duration-input:focus {
5366
- border-color: #6366f1;
6746
+ border-color: var(--squisq-block-props-accent, #6366f1);
5367
6747
  }
5368
6748
 
5369
6749
  .squisq-transition-duration-unit {
5370
6750
  font-size: 11px;
5371
- color: #9ca3af;
6751
+ color: var(--squisq-block-props-quiet);
5372
6752
  }
5373
6753
 
5374
6754
  /* Dark theme */
@@ -5385,50 +6765,17 @@
5385
6765
 
5386
6766
  .squisq-editor-shell[data-theme='dark'] .squisq-transition-picker-trigger--open {
5387
6767
  background: #374151;
5388
- border-color: #818cf8;
6768
+ border-color: var(--squisq-block-props-accent, #818cf8);
5389
6769
  }
5390
6770
 
5391
6771
  .squisq-editor-shell[data-theme='dark'] .squisq-transition-picker-trigger-value {
5392
6772
  color: #f9fafb;
5393
6773
  }
5394
6774
 
5395
- /* Dark styling for the portaled flyout keyed off the editor shell the same
5396
- way the template gallery popover is (see `.squisq-template-gallery` above). */
5397
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-flyout {
5398
- background: #1f2937;
5399
- 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'] {
5400
6778
  box-shadow:
5401
6779
  0 8px 24px rgba(0, 0, 0, 0.4),
5402
6780
  0 2px 6px rgba(0, 0, 0, 0.2);
5403
6781
  }
5404
-
5405
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-flyout-search,
5406
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-flyout-controls {
5407
- border-color: #374151;
5408
- }
5409
-
5410
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-flyout-search-input,
5411
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-duration-input {
5412
- background: #111827;
5413
- color: #f9fafb;
5414
- border-color: #4b5563;
5415
- }
5416
-
5417
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-option,
5418
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-direction-button {
5419
- background: #1f2937;
5420
- color: #e5e7eb;
5421
- border-color: #4b5563;
5422
- }
5423
-
5424
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-option:hover,
5425
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-direction-button:hover {
5426
- background: #374151;
5427
- }
5428
-
5429
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-option--selected,
5430
- .squisq-editor-shell[data-theme='dark'] .squisq-transition-direction-button--selected {
5431
- background: #3730a3;
5432
- border-color: #818cf8;
5433
- color: #e0e7ff;
5434
- }