@bendyline/docblocks-react 1.0.0 → 1.1.1

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 (133) hide show
  1. package/dist/AppMenu/AppMenu.d.ts +16 -1
  2. package/dist/AppMenu/AppMenu.d.ts.map +1 -1
  3. package/dist/AppMenu/AppMenu.js +3 -2
  4. package/dist/AppMenu/AppMenu.js.map +1 -1
  5. package/dist/AppMenu/index.d.ts +1 -1
  6. package/dist/AppMenu/index.d.ts.map +1 -1
  7. package/dist/DocBlocksShell/DocBlocksShell.d.ts +21 -1
  8. package/dist/DocBlocksShell/DocBlocksShell.d.ts.map +1 -1
  9. package/dist/DocBlocksShell/DocBlocksShell.js +930 -98
  10. package/dist/DocBlocksShell/DocBlocksShell.js.map +1 -1
  11. package/dist/Export/ExportDialog.d.ts.map +1 -1
  12. package/dist/Export/ExportDialog.js +104 -5
  13. package/dist/Export/ExportDialog.js.map +1 -1
  14. package/dist/Export/ExportToolbarControls.d.ts.map +1 -1
  15. package/dist/Export/ExportToolbarControls.js +44 -3
  16. package/dist/Export/ExportToolbarControls.js.map +1 -1
  17. package/dist/Export/export-options.d.ts +35 -0
  18. package/dist/Export/export-options.d.ts.map +1 -1
  19. package/dist/Export/export-options.js +6 -1
  20. package/dist/Export/export-options.js.map +1 -1
  21. package/dist/Export/run-export.d.ts.map +1 -1
  22. package/dist/Export/run-export.js +163 -91
  23. package/dist/Export/run-export.js.map +1 -1
  24. package/dist/FileExplorer/FileExplorer.d.ts.map +1 -1
  25. package/dist/FileExplorer/FileExplorer.js +17 -2
  26. package/dist/FileExplorer/FileExplorer.js.map +1 -1
  27. package/dist/FileExplorer/FileTreeNode.d.ts.map +1 -1
  28. package/dist/FileExplorer/FileTreeNode.js +34 -8
  29. package/dist/FileExplorer/FileTreeNode.js.map +1 -1
  30. package/dist/WorkspacePicker/WorkspacePicker.d.ts.map +1 -1
  31. package/dist/WorkspacePicker/WorkspacePicker.js +9 -3
  32. package/dist/WorkspacePicker/WorkspacePicker.js.map +1 -1
  33. package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts +2 -1
  34. package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts.map +1 -1
  35. package/dist/WorkspacePicker/WorkspaceSettingsButton.js +2 -2
  36. package/dist/WorkspacePicker/WorkspaceSettingsButton.js.map +1 -1
  37. package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts +20 -0
  38. package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts.map +1 -0
  39. package/dist/WorkspacePicker/WorkspaceSettingsDialog.js +36 -0
  40. package/dist/WorkspacePicker/WorkspaceSettingsDialog.js.map +1 -0
  41. package/dist/hooks/useAutoSave.d.ts +8 -2
  42. package/dist/hooks/useAutoSave.d.ts.map +1 -1
  43. package/dist/hooks/useAutoSave.js +65 -30
  44. package/dist/hooks/useAutoSave.js.map +1 -1
  45. package/dist/icons.d.ts +1 -0
  46. package/dist/icons.d.ts.map +1 -1
  47. package/dist/icons.js +3 -0
  48. package/dist/icons.js.map +1 -1
  49. package/dist/index.d.ts +1 -1
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/preferences/versioning.d.ts +27 -0
  52. package/dist/preferences/versioning.d.ts.map +1 -0
  53. package/dist/preferences/versioning.js +62 -0
  54. package/dist/preferences/versioning.js.map +1 -0
  55. package/package.json +10 -8
  56. package/src/AppMenu/AppMenu.tsx +142 -2
  57. package/src/AppMenu/index.ts +1 -1
  58. package/src/DocBlocksShell/DocBlocksShell.tsx +1194 -125
  59. package/src/Export/ExportDialog.tsx +208 -19
  60. package/src/Export/ExportToolbarControls.tsx +45 -3
  61. package/src/Export/export-options.ts +43 -1
  62. package/src/Export/run-export.ts +190 -91
  63. package/src/FileExplorer/FileExplorer.tsx +31 -9
  64. package/src/FileExplorer/FileTreeNode.tsx +68 -26
  65. package/src/WorkspacePicker/WorkspacePicker.tsx +18 -7
  66. package/src/WorkspacePicker/WorkspaceSettingsButton.tsx +9 -0
  67. package/src/WorkspacePicker/WorkspaceSettingsDialog.tsx +121 -0
  68. package/src/fonts/fonts.css +362 -0
  69. package/src/fonts/licenses/LICENSE-cormorant-garamond.txt +93 -0
  70. package/src/fonts/licenses/LICENSE-crimson-text.txt +93 -0
  71. package/src/fonts/licenses/LICENSE-dm-sans.txt +93 -0
  72. package/src/fonts/licenses/LICENSE-dm-serif-display.txt +93 -0
  73. package/src/fonts/licenses/LICENSE-hanken-grotesk.txt +94 -0
  74. package/src/fonts/licenses/LICENSE-ibm-plex-sans.txt +93 -0
  75. package/src/fonts/licenses/LICENSE-inter.txt +93 -0
  76. package/src/fonts/licenses/LICENSE-jetbrains-mono.txt +93 -0
  77. package/src/fonts/licenses/LICENSE-lora.txt +93 -0
  78. package/src/fonts/licenses/LICENSE-merriweather.txt +93 -0
  79. package/src/fonts/licenses/LICENSE-oswald.txt +93 -0
  80. package/src/fonts/licenses/LICENSE-playfair-display.txt +93 -0
  81. package/src/fonts/licenses/LICENSE-pt-serif.txt +93 -0
  82. package/src/fonts/licenses/LICENSE-roboto.txt +93 -0
  83. package/src/fonts/licenses/LICENSE-source-serif-4.txt +93 -0
  84. package/src/fonts/woff2/cormorant-garamond-400.woff2 +0 -0
  85. package/src/fonts/woff2/cormorant-garamond-700.woff2 +0 -0
  86. package/src/fonts/woff2/crimson-text-400.woff2 +0 -0
  87. package/src/fonts/woff2/crimson-text-400i.woff2 +0 -0
  88. package/src/fonts/woff2/crimson-text-700.woff2 +0 -0
  89. package/src/fonts/woff2/dm-sans-400.woff2 +0 -0
  90. package/src/fonts/woff2/dm-sans-400i.woff2 +0 -0
  91. package/src/fonts/woff2/dm-sans-500.woff2 +0 -0
  92. package/src/fonts/woff2/dm-sans-700.woff2 +0 -0
  93. package/src/fonts/woff2/dm-serif-display-400.woff2 +0 -0
  94. package/src/fonts/woff2/hanken-grotesk-400.woff2 +0 -0
  95. package/src/fonts/woff2/hanken-grotesk-400i.woff2 +0 -0
  96. package/src/fonts/woff2/hanken-grotesk-500.woff2 +0 -0
  97. package/src/fonts/woff2/hanken-grotesk-600.woff2 +0 -0
  98. package/src/fonts/woff2/hanken-grotesk-700.woff2 +0 -0
  99. package/src/fonts/woff2/ibm-plex-sans-400.woff2 +0 -0
  100. package/src/fonts/woff2/ibm-plex-sans-400i.woff2 +0 -0
  101. package/src/fonts/woff2/ibm-plex-sans-500.woff2 +0 -0
  102. package/src/fonts/woff2/ibm-plex-sans-600.woff2 +0 -0
  103. package/src/fonts/woff2/ibm-plex-sans-700.woff2 +0 -0
  104. package/src/fonts/woff2/inter-400.woff2 +0 -0
  105. package/src/fonts/woff2/inter-400i.woff2 +0 -0
  106. package/src/fonts/woff2/inter-500.woff2 +0 -0
  107. package/src/fonts/woff2/inter-600.woff2 +0 -0
  108. package/src/fonts/woff2/inter-700.woff2 +0 -0
  109. package/src/fonts/woff2/jetbrains-mono-400.woff2 +0 -0
  110. package/src/fonts/woff2/jetbrains-mono-400i.woff2 +0 -0
  111. package/src/fonts/woff2/jetbrains-mono-700.woff2 +0 -0
  112. package/src/fonts/woff2/lora-400.woff2 +0 -0
  113. package/src/fonts/woff2/lora-400i.woff2 +0 -0
  114. package/src/fonts/woff2/lora-700.woff2 +0 -0
  115. package/src/fonts/woff2/merriweather-400.woff2 +0 -0
  116. package/src/fonts/woff2/merriweather-700.woff2 +0 -0
  117. package/src/fonts/woff2/oswald-400.woff2 +0 -0
  118. package/src/fonts/woff2/oswald-700.woff2 +0 -0
  119. package/src/fonts/woff2/playfair-display-400.woff2 +0 -0
  120. package/src/fonts/woff2/playfair-display-700.woff2 +0 -0
  121. package/src/fonts/woff2/pt-serif-400.woff2 +0 -0
  122. package/src/fonts/woff2/pt-serif-700.woff2 +0 -0
  123. package/src/fonts/woff2/roboto-400.woff2 +0 -0
  124. package/src/fonts/woff2/roboto-400i.woff2 +0 -0
  125. package/src/fonts/woff2/roboto-700.woff2 +0 -0
  126. package/src/fonts/woff2/source-serif-4-400.woff2 +0 -0
  127. package/src/fonts/woff2/source-serif-4-400i.woff2 +0 -0
  128. package/src/fonts/woff2/source-serif-4-700.woff2 +0 -0
  129. package/src/hooks/useAutoSave.ts +87 -29
  130. package/src/icons.tsx +10 -0
  131. package/src/index.ts +1 -1
  132. package/src/preferences/versioning.ts +69 -0
  133. package/src/styles/docblocks.css +1037 -55
@@ -2,62 +2,104 @@
2
2
 
3
3
  /* ── Theme Tokens ────────────────────────────────────────────── */
4
4
 
5
+ /* DocBlocks accent palette — warm brown on a canvas/parchment base.
6
+ Think paper on a wooden desk: the editor itself stays white (paper),
7
+ the chrome around it (sidebar, gutters, panes) reads as cream
8
+ canvas, and the accent picks up a saturated dark brown for CTAs.
9
+ Dark mode inverts the metaphor into espresso wood with light tan
10
+ highlights. Derived shades (`--db-accent-soft-*`, `--db-accent-tint`,
11
+ `--db-accent-deep`) are defined alongside so every place that needs
12
+ a tinted background or a readable-on-tint text color pulls from the
13
+ same source of truth. */
5
14
  .db-shell {
6
15
  --db-bg: #ffffff;
7
- --db-bg-subtle: #f9fafb;
8
- --db-bg-hover: #f3f4f6;
9
- --db-bg-selected: #dbeafe;
10
- --db-bg-selected-hover: #bfdbfe;
11
- --db-border: #e5e7eb;
12
- --db-text: #1f2937;
13
- --db-text-secondary: #374151;
14
- --db-text-muted: #6b7280;
15
- --db-text-placeholder: #9ca3af;
16
- --db-accent: #3b82f6;
17
- --db-accent-hover: #2563eb;
18
- --db-input-border: #93c5fd;
19
- --db-danger: #dc2626;
20
- --db-danger-bg: #fef2f2;
21
- --db-shadow: rgba(0, 0, 0, 0.12);
16
+ --db-bg-subtle: #f3eede;
17
+ --db-bg-hover: #e9e2cb;
18
+ --db-bg-selected: #7d6948;
19
+ --db-bg-selected-hover: #5e4f37;
20
+ --db-border: #d6cdb0;
21
+ --db-border-strong: #b5a985;
22
+ --db-text: #2a2419;
23
+ --db-text-secondary: #3d3528;
24
+ --db-text-muted: #6b614a;
25
+ --db-text-placeholder: #766c54;
26
+ --db-accent: #7d6948;
27
+ --db-accent-hover: #5e4f37;
28
+ --db-accent-soft-08: rgba(125, 105, 72, 0.08);
29
+ --db-accent-soft-12: rgba(125, 105, 72, 0.12);
30
+ --db-accent-soft-15: rgba(125, 105, 72, 0.15);
31
+ --db-accent-soft-25: rgba(125, 105, 72, 0.25);
32
+ --db-accent-tint: #f3eede;
33
+ --db-accent-tint-strong: #d8d0b5;
34
+ --db-accent-deep: #3d3220;
35
+ /* Outline pane + inline-preview gutter background. Sits one step
36
+ lighter than the toolbar (`--db-accent-tint-strong`) so the chrome
37
+ panes read as distinct from the action bar above the canvas. */
38
+ --db-gutter-bg: #efe8d4;
39
+ --db-input-border: #c4b693;
40
+ --db-danger: #b22b1b;
41
+ --db-danger-bg: #fdf0ee;
42
+ --db-shadow: rgba(40, 30, 15, 0.12);
22
43
  }
23
44
 
24
45
  .db-shell[data-theme='dark'] {
25
- --db-bg: #0f172a;
26
- --db-bg-subtle: #1e293b;
27
- --db-bg-hover: #334155;
28
- --db-bg-selected: #1e3a5f;
29
- --db-bg-selected-hover: #1e4a7f;
30
- --db-border: #334155;
31
- --db-text: #e5e7eb;
32
- --db-text-secondary: #cbd5e1;
33
- --db-text-muted: #94a3b8;
34
- --db-text-placeholder: #64748b;
35
- --db-accent: #3b82f6;
36
- --db-accent-hover: #60a5fa;
37
- --db-input-border: #3b82f6;
46
+ --db-bg: #1a1812;
47
+ --db-bg-subtle: #262219;
48
+ --db-bg-hover: #3a3528;
49
+ --db-bg-selected: #3a3528;
50
+ --db-bg-selected-hover: #4d4636;
51
+ --db-border: #4d4636;
52
+ --db-border-strong: #6b6448;
53
+ --db-text: #e8e2d0;
54
+ --db-text-secondary: #d4ccb0;
55
+ --db-text-muted: #a89a7c;
56
+ --db-text-placeholder: #6b614a;
57
+ --db-accent: #c8b48f;
58
+ --db-accent-hover: #dec79d;
59
+ --db-accent-soft-08: rgba(200, 180, 143, 0.08);
60
+ --db-accent-soft-12: rgba(200, 180, 143, 0.12);
61
+ --db-accent-soft-15: rgba(200, 180, 143, 0.18);
62
+ --db-accent-soft-25: rgba(200, 180, 143, 0.28);
63
+ --db-accent-tint: #262219;
64
+ --db-accent-tint-strong: #3a382e;
65
+ --db-accent-deep: #e6dcc0;
66
+ --db-input-border: #c8b48f;
38
67
  --db-danger: #f87171;
39
68
  --db-danger-bg: #1c1917;
40
69
  --db-shadow: rgba(0, 0, 0, 0.4);
70
+ /* In dark mode, "lighter than the toolbar" means brighter — so this
71
+ sits a step above `--db-accent-tint-strong` instead of between it
72
+ and tint. */
73
+ --db-gutter-bg: #4a4538;
41
74
  }
42
75
 
43
76
  @media (prefers-color-scheme: dark) {
44
77
  .db-shell:not([data-theme='light']) {
45
- --db-bg: #0f172a;
46
- --db-bg-subtle: #1e293b;
47
- --db-bg-hover: #334155;
48
- --db-bg-selected: #1e3a5f;
49
- --db-bg-selected-hover: #1e4a7f;
50
- --db-border: #334155;
51
- --db-text: #e5e7eb;
52
- --db-text-secondary: #cbd5e1;
53
- --db-text-muted: #94a3b8;
54
- --db-text-placeholder: #64748b;
55
- --db-accent: #3b82f6;
56
- --db-accent-hover: #60a5fa;
57
- --db-input-border: #3b82f6;
78
+ --db-bg: #1a1812;
79
+ --db-bg-subtle: #262219;
80
+ --db-bg-hover: #3a3528;
81
+ --db-bg-selected: #3a3528;
82
+ --db-bg-selected-hover: #4d4636;
83
+ --db-border: #4d4636;
84
+ --db-border-strong: #6b6448;
85
+ --db-text: #e8e2d0;
86
+ --db-text-secondary: #d4ccb0;
87
+ --db-text-muted: #a89a7c;
88
+ --db-text-placeholder: #6b614a;
89
+ --db-accent: #c8b48f;
90
+ --db-accent-hover: #dec79d;
91
+ --db-accent-soft-08: rgba(200, 180, 143, 0.08);
92
+ --db-accent-soft-12: rgba(200, 180, 143, 0.12);
93
+ --db-accent-soft-15: rgba(200, 180, 143, 0.18);
94
+ --db-accent-soft-25: rgba(200, 180, 143, 0.28);
95
+ --db-accent-tint: #262219;
96
+ --db-accent-tint-strong: #3a382e;
97
+ --db-accent-deep: #e6dcc0;
98
+ --db-input-border: #c8b48f;
58
99
  --db-danger: #f87171;
59
100
  --db-danger-bg: #1c1917;
60
101
  --db-shadow: rgba(0, 0, 0, 0.4);
102
+ --db-gutter-bg: #4a4538;
61
103
  }
62
104
  }
63
105
 
@@ -79,10 +121,10 @@
79
121
  display: flex;
80
122
  align-items: center;
81
123
  justify-content: center;
82
- background: rgba(37, 99, 235, 0.08);
83
- border: 2px dashed #2563eb;
124
+ background: var(--db-accent-soft-08);
125
+ border: 2px dashed var(--db-accent);
84
126
  border-radius: 6px;
85
- color: #2563eb;
127
+ color: var(--db-accent);
86
128
  font-size: 13px;
87
129
  font-weight: 600;
88
130
  z-index: 10;
@@ -94,7 +136,7 @@
94
136
  align-items: center;
95
137
  justify-content: space-between;
96
138
  padding: 6px 8px;
97
- border-bottom: 1px solid var(--db-border);
139
+ border-bottom: 1px solid var(--db-border-strong);
98
140
  flex-shrink: 0;
99
141
  }
100
142
 
@@ -208,18 +250,23 @@
208
250
 
209
251
  .db-tree-row--selected {
210
252
  background: var(--db-bg-selected);
253
+ color: #ffffff;
211
254
  }
212
255
 
213
256
  .db-tree-row--selected:hover {
214
257
  background: var(--db-bg-selected-hover);
258
+ color: #ffffff;
215
259
  }
216
260
 
217
261
  .db-tree-icon {
218
262
  width: 16px;
219
263
  flex-shrink: 0;
220
264
  text-align: center;
221
- font-size: 10px;
222
- color: var(--db-text-placeholder);
265
+ font-size: 14px;
266
+ line-height: 1;
267
+ font-family:
268
+ ui-monospace, 'SF Mono', 'Menlo', 'Consolas', 'Liberation Mono', 'Courier New', monospace;
269
+ color: var(--db-text-secondary);
223
270
  }
224
271
 
225
272
  .db-tree-label {
@@ -239,6 +286,40 @@
239
286
  outline: none;
240
287
  }
241
288
 
289
+ .db-tree-more {
290
+ flex-shrink: 0;
291
+ display: inline-flex;
292
+ align-items: center;
293
+ justify-content: center;
294
+ width: 22px;
295
+ height: 22px;
296
+ margin-right: 4px;
297
+ padding: 0;
298
+ border: none;
299
+ border-radius: 3px;
300
+ background: transparent;
301
+ color: var(--db-text-secondary);
302
+ cursor: pointer;
303
+ visibility: hidden;
304
+ }
305
+
306
+ .db-tree-row:hover .db-tree-more,
307
+ .db-tree-row:focus-within .db-tree-more,
308
+ .db-tree-more:focus-visible,
309
+ .db-tree-more--active {
310
+ visibility: visible;
311
+ }
312
+
313
+ .db-tree-more:hover {
314
+ background: var(--db-bg-hover);
315
+ color: var(--db-text);
316
+ }
317
+
318
+ .db-tree-more--active {
319
+ background: var(--db-bg-selected);
320
+ color: #ffffff;
321
+ }
322
+
242
323
  /* ── Context Menu ────────────────────────────────────────────── */
243
324
 
244
325
  .db-tree-node {
@@ -246,8 +327,8 @@
246
327
  }
247
328
 
248
329
  .db-tree-context {
249
- position: absolute;
250
- z-index: 50;
330
+ position: fixed;
331
+ z-index: 1000;
251
332
  background: var(--db-bg);
252
333
  border: 1px solid var(--db-border);
253
334
  border-radius: 4px;
@@ -315,9 +396,10 @@
315
396
  .db-workspace-dropdown {
316
397
  position: absolute;
317
398
  left: 8px;
318
- right: 8px;
319
399
  top: 100%;
320
400
  z-index: 60;
401
+ min-width: calc(100% - 16px);
402
+ max-width: min(320px, 90vw);
321
403
  background: var(--db-bg);
322
404
  border: 1px solid var(--db-border);
323
405
  border-radius: 4px;
@@ -329,6 +411,7 @@
329
411
  display: flex;
330
412
  align-items: center;
331
413
  justify-content: space-between;
414
+ gap: 8px;
332
415
  width: 100%;
333
416
  padding: 6px 12px;
334
417
  font-size: 13px;
@@ -337,6 +420,7 @@
337
420
  border: none;
338
421
  cursor: pointer;
339
422
  color: var(--db-text-secondary);
423
+ white-space: nowrap;
340
424
  }
341
425
 
342
426
  .db-workspace-dropdown-item:hover {
@@ -345,6 +429,7 @@
345
429
 
346
430
  .db-workspace-dropdown-item--active {
347
431
  background: var(--db-bg-selected);
432
+ color: #ffffff;
348
433
  font-weight: 500;
349
434
  }
350
435
 
@@ -552,17 +637,71 @@
552
637
 
553
638
  .db-shell-sidebar {
554
639
  width: 260px;
555
- border-right: 1px solid var(--db-border);
556
640
  display: flex;
557
641
  flex-direction: column;
558
642
  overflow: hidden;
559
643
  flex-shrink: 0;
560
644
  }
561
645
 
646
+ /* Drag handle between sidebar and editor. The visible line is the
647
+ hairline divider itself — 1px wide, in --db-border-strong so it
648
+ matches the toolbar's bottom border. The hit area extends 3px to
649
+ either side via an absolutely-positioned ::before so the cursor
650
+ can grab it without being pixel-perfect. The sidebar no longer
651
+ carries its own `border-right`; this 1px IS that border. */
652
+ .db-shell-sidebar-resizer {
653
+ flex: 0 0 1px;
654
+ width: 1px;
655
+ /* Custom col-resize cursor — a dark double-arrow with a white halo
656
+ so it stays visible against any background. Windows' custom-color
657
+ cursor setting can render the system col-resize in white, which
658
+ disappears against the light chrome on either side of our 1px
659
+ line; a CSS `url()` cursor always wins over the OS preference.
660
+ Hotspot is the center (11, 8). */
661
+ cursor:
662
+ url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='16' viewBox='0 0 22 16'><g fill='none' stroke-linecap='round' stroke-linejoin='round'><path d='M3 8 L19 8 M3 8 L7 4 M3 8 L7 12 M19 8 L15 4 M19 8 L15 12' stroke='white' stroke-width='3.5'/><path d='M3 8 L19 8 M3 8 L7 4 M3 8 L7 12 M19 8 L15 4 M19 8 L15 12' stroke='%231f2937' stroke-width='1.4'/></g></svg>")
663
+ 11 8,
664
+ col-resize;
665
+ background: var(--db-border-strong);
666
+ position: relative;
667
+ z-index: 5;
668
+ user-select: none;
669
+ touch-action: none;
670
+ transition: background-color 0.12s ease;
671
+ }
672
+
673
+ .db-shell-sidebar-resizer::before {
674
+ /* Invisible hit-extension so the 1px line isn't fiddly to grab. */
675
+ content: '';
676
+ position: absolute;
677
+ top: 0;
678
+ bottom: 0;
679
+ left: -3px;
680
+ right: -3px;
681
+ }
682
+
683
+ .db-shell-sidebar-resizer:hover,
684
+ .db-shell-sidebar-resizer:active {
685
+ background: var(--db-accent);
686
+ }
687
+
688
+ /* Drag-state body cursor — set via JS while a sidebar resize is in
689
+ progress so the col-resize cursor stays painted even when the
690
+ pointer briefly slips off the 7px hit area. Uses the same custom
691
+ SVG as the resizer itself so Windows' white-cursor setting doesn't
692
+ make it invisible against light chrome. */
693
+ body.db-resizing-sidebar,
694
+ body.db-resizing-sidebar * {
695
+ cursor:
696
+ url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='16' viewBox='0 0 22 16'><g fill='none' stroke-linecap='round' stroke-linejoin='round'><path d='M3 8 L19 8 M3 8 L7 4 M3 8 L7 12 M19 8 L15 4 M19 8 L15 12' stroke='white' stroke-width='3.5'/><path d='M3 8 L19 8 M3 8 L7 4 M3 8 L7 12 M19 8 L15 4 M19 8 L15 12' stroke='%231f2937' stroke-width='1.4'/></g></svg>")
697
+ 11 8,
698
+ col-resize !important;
699
+ }
700
+
562
701
  .db-shell-sidebar-header {
563
702
  display: flex;
564
703
  align-items: center;
565
- border-bottom: 1px solid var(--db-border);
704
+ border-bottom: 1px solid var(--db-border-strong);
566
705
  padding: 4px;
567
706
  gap: 4px;
568
707
  flex-shrink: 0;
@@ -571,7 +710,7 @@
571
710
 
572
711
  .db-shell-sidebar-footer {
573
712
  padding: 8px 12px;
574
- border-top: 1px solid var(--db-border);
713
+ border-top: 1px solid var(--db-border-strong);
575
714
  flex-shrink: 0;
576
715
  font-size: 11px;
577
716
  }
@@ -633,6 +772,28 @@
633
772
  background: var(--db-bg-subtle);
634
773
  }
635
774
 
775
+ /* "Restore split view" button — appears on the editor toolbar when
776
+ compact layout was triggered manually on a wide viewport. Lets the
777
+ user pop the sidebar back open alongside the editor. Iconic only,
778
+ no label, so it stays compact in the toolbar's right-slot. */
779
+ .db-restore-split {
780
+ display: inline-flex;
781
+ align-items: center;
782
+ justify-content: center;
783
+ padding: 6px;
784
+ margin-right: 4px;
785
+ border: none;
786
+ border-radius: 4px;
787
+ background: none;
788
+ color: var(--db-text-secondary);
789
+ cursor: pointer;
790
+ }
791
+
792
+ .db-restore-split:hover {
793
+ background: var(--db-bg-hover);
794
+ color: var(--db-text);
795
+ }
796
+
636
797
  /* ── Dialog ───────────────────────────────────────────────────── */
637
798
 
638
799
  .db-dialog-overlay {
@@ -719,6 +880,56 @@
719
880
  color: var(--db-text-placeholder);
720
881
  }
721
882
 
883
+ /* ── Settings Dialog ─────────────────────────────────────────── */
884
+
885
+ .db-settings-fieldset {
886
+ border: none;
887
+ margin: 0;
888
+ padding: 0;
889
+ }
890
+
891
+ .db-settings-fieldset + .db-settings-fieldset {
892
+ margin-top: 20px;
893
+ }
894
+
895
+ .db-settings-legend {
896
+ font-size: 12px;
897
+ font-weight: 600;
898
+ text-transform: uppercase;
899
+ letter-spacing: 0.03em;
900
+ color: var(--db-text-muted);
901
+ margin-bottom: 8px;
902
+ }
903
+
904
+ .db-settings-hint {
905
+ font-size: 12px;
906
+ color: var(--db-text-muted);
907
+ margin: 0 0 6px;
908
+ line-height: 1.5;
909
+ }
910
+
911
+ .db-settings-hint code {
912
+ font-size: 11px;
913
+ background: var(--db-bg-subtle);
914
+ padding: 1px 4px;
915
+ border-radius: 3px;
916
+ }
917
+
918
+ .db-settings-radio {
919
+ display: flex;
920
+ align-items: center;
921
+ gap: 8px;
922
+ padding: 6px 0;
923
+ font-size: 13px;
924
+ color: var(--db-text);
925
+ cursor: pointer;
926
+ }
927
+
928
+ .db-settings-radio input[type='radio'] {
929
+ margin: 0;
930
+ cursor: pointer;
931
+ }
932
+
722
933
  /* ── Folder View ─────────────────────────────────────────────── */
723
934
 
724
935
  .db-folder-view {
@@ -737,7 +948,14 @@
737
948
  }
738
949
 
739
950
  .db-folder-view-icon {
740
- font-size: 20px;
951
+ display: inline-flex;
952
+ align-items: center;
953
+ color: var(--db-text-secondary);
954
+ }
955
+
956
+ .db-folder-view-icon svg {
957
+ width: 24px;
958
+ height: 24px;
741
959
  }
742
960
 
743
961
  .db-folder-view-path {
@@ -773,8 +991,15 @@
773
991
  }
774
992
 
775
993
  .db-folder-view-item-icon {
776
- font-size: 16px;
994
+ display: inline-flex;
995
+ align-items: center;
777
996
  flex-shrink: 0;
997
+ color: var(--db-text-secondary);
998
+ }
999
+
1000
+ .db-folder-view-item-icon svg {
1001
+ width: 18px;
1002
+ height: 18px;
778
1003
  }
779
1004
 
780
1005
  /* ── Toolbar Image Button Override ─────────────────────────── */
@@ -784,10 +1009,31 @@
784
1009
  max-width: none;
785
1010
  }
786
1011
 
1012
+ /* …unless the inline preview gutter is present. The gutter is absolutely
1013
+ positioned to the right of the centered editor "page", so a full-bleed
1014
+ editor pushes it offscreen. Restore squisq's 800px page width when the
1015
+ gutter wrapper is active. The container query at 720px in editor.css
1016
+ auto-hides the gutter on narrow viewports. */
1017
+ .squisq-wysiwyg-with-gutter .squisq-wysiwyg-editor {
1018
+ max-width: 800px;
1019
+ }
1020
+
787
1021
  .squisq-toolbar {
788
1022
  min-height: 48px;
789
1023
  }
790
1024
 
1025
+ /* Squisq's view-tab section is bottom-aligned in the toolbar (so the
1026
+ active-tab underline sits flush with the toolbar's lower edge),
1027
+ with `padding: 8px 14px 4px` calibrated for squisq's natural ~36px
1028
+ toolbar height. We force the toolbar to 48px for breathing room,
1029
+ which drops the label too far down relative to the centered B/I/S
1030
+ buttons. Lift the label ~6px by growing bottom padding — the
1031
+ underline stays anchored to the section's bottom edge, only the
1032
+ text moves up. */
1033
+ .db-shell .squisq-toolbar-view-tab {
1034
+ padding-bottom: 10px;
1035
+ }
1036
+
791
1037
  .squisq-toolbar-button[aria-label='Insert image'] {
792
1038
  font-size: 0;
793
1039
  background: no-repeat center / 18px
@@ -917,6 +1163,66 @@
917
1163
  color: var(--db-text-placeholder);
918
1164
  }
919
1165
 
1166
+ .db-export-checkbox {
1167
+ display: inline-flex;
1168
+ align-items: center;
1169
+ gap: 8px;
1170
+ font-size: 13px;
1171
+ color: var(--db-text);
1172
+ cursor: pointer;
1173
+ user-select: none;
1174
+ }
1175
+
1176
+ .db-export-checkbox input[type='checkbox'] {
1177
+ margin: 0;
1178
+ cursor: pointer;
1179
+ }
1180
+
1181
+ /* Chip radio group — used by the Export dialog for the top three
1182
+ options (Format / Style / Bundle). Wraps to multiple lines on narrow
1183
+ widths so the format row doesn't truncate. */
1184
+ .db-export-chips {
1185
+ display: flex;
1186
+ flex-wrap: wrap;
1187
+ gap: 6px;
1188
+ }
1189
+
1190
+ .db-export-chip {
1191
+ flex: 0 0 auto;
1192
+ padding: 6px 12px;
1193
+ font: inherit;
1194
+ font-size: 13px;
1195
+ color: var(--db-text);
1196
+ background: var(--db-bg-subtle);
1197
+ border: 1px solid var(--db-border);
1198
+ border-radius: 3px;
1199
+ cursor: pointer;
1200
+ transition:
1201
+ background-color 0.12s ease,
1202
+ border-color 0.12s ease,
1203
+ color 0.12s ease;
1204
+ }
1205
+
1206
+ .db-export-chip:hover {
1207
+ background: var(--db-bg-hover);
1208
+ }
1209
+
1210
+ .db-export-chip--active {
1211
+ background: var(--db-accent);
1212
+ border-color: var(--db-accent);
1213
+ color: #ffffff;
1214
+ }
1215
+
1216
+ .db-export-chip--active:hover {
1217
+ background: var(--db-accent-hover);
1218
+ border-color: var(--db-accent-hover);
1219
+ }
1220
+
1221
+ .db-export-chip:focus-visible {
1222
+ outline: 2px solid var(--db-accent);
1223
+ outline-offset: 2px;
1224
+ }
1225
+
920
1226
  .db-export-footer {
921
1227
  display: flex;
922
1228
  justify-content: flex-end;
@@ -959,3 +1265,679 @@
959
1265
  background: var(--db-accent-hover);
960
1266
  border-color: var(--db-accent-hover);
961
1267
  }
1268
+
1269
+ /* ── Squisq editor chrome separators ─────────────────────────── */
1270
+ /* Strengthen the dividers so the toolbar, tabs, and editor body
1271
+ read as three distinct zones instead of near-identical whites. */
1272
+
1273
+ .db-shell .squisq-editor-header {
1274
+ border-bottom-color: var(--db-border-strong);
1275
+ }
1276
+
1277
+ .db-shell .squisq-toolbar-view-tabs {
1278
+ border-right-color: var(--db-border-strong);
1279
+ }
1280
+
1281
+ .db-shell[data-theme='light'] .squisq-toolbar {
1282
+ background: var(--db-accent-tint);
1283
+ }
1284
+
1285
+ .db-shell[data-theme='light'] .squisq-toolbar-view-tabs {
1286
+ background: var(--db-gutter-bg);
1287
+ box-shadow: 1px 0 0 rgba(0, 0, 0, 0.04);
1288
+ }
1289
+
1290
+ .db-shell[data-theme='dark'] .squisq-toolbar {
1291
+ background: rgba(255, 255, 255, 0.04);
1292
+ }
1293
+
1294
+ .db-shell[data-theme='dark'] .squisq-toolbar-view-tabs {
1295
+ background: #16110b;
1296
+ }
1297
+
1298
+ /* ── Inline preview gutter: thematic green ──────────────────── */
1299
+ /* Rebind squisq's `--squisq-preview-*` custom properties so the
1300
+ gutter chrome (vertical bracket, diagonal connector + dots,
1301
+ "FACTCARD" template label) reads as sage green instead of indigo,
1302
+ and the card surface tones harmonize with the rest of docblocks.
1303
+ The preview-block renderer's own theme is unaffected — that's a
1304
+ document-level concern, not chrome. */
1305
+ .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] {
1306
+ --squisq-preview-accent: var(--db-accent);
1307
+ --squisq-preview-accent-muted: var(--db-text-muted);
1308
+ --squisq-preview-gutter-bg: var(--db-gutter-bg);
1309
+ --squisq-preview-card-bg: #ffffff;
1310
+ --squisq-preview-card-border: var(--db-border);
1311
+ --squisq-preview-card-shadow: 0 1px 2px rgba(40, 30, 15, 0.08);
1312
+ --squisq-preview-card-title: var(--db-accent-deep);
1313
+ --squisq-preview-card-svg-bg: var(--db-accent-tint);
1314
+ --squisq-preview-dot-halo: var(--db-gutter-bg);
1315
+ --squisq-preview-empty-bg: #ffffff;
1316
+ --squisq-preview-empty-border: var(--db-border);
1317
+ --squisq-preview-empty-text: var(--db-accent-deep);
1318
+ }
1319
+
1320
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] {
1321
+ --squisq-preview-accent: var(--db-accent-hover);
1322
+ --squisq-preview-accent-muted: var(--db-text-muted);
1323
+ --squisq-preview-gutter-bg: var(--db-gutter-bg);
1324
+ --squisq-preview-card-bg: var(--db-bg);
1325
+ --squisq-preview-card-border: var(--db-border);
1326
+ --squisq-preview-card-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
1327
+ --squisq-preview-card-title: var(--db-text);
1328
+ --squisq-preview-card-svg-bg: var(--db-bg-subtle);
1329
+ --squisq-preview-dot-halo: var(--db-gutter-bg);
1330
+ --squisq-preview-empty-bg: var(--db-bg);
1331
+ --squisq-preview-empty-border: var(--db-border);
1332
+ --squisq-preview-empty-text: var(--db-text-muted);
1333
+ }
1334
+
1335
+ /* ── Squisq dark-theme override ──────────────────────────────── */
1336
+ /* Squisq has hardcoded slate-blue surfaces in its dark mode. We re-tone
1337
+ them via the DocBlocks dark palette so the editor reads as warm dark
1338
+ wood instead of cold slate. If squisq ever accepts a theme-color
1339
+ prop, replace this block with that mechanism. */
1340
+
1341
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] {
1342
+ --squisq-bg: var(--db-bg-subtle);
1343
+ --squisq-border: var(--db-border);
1344
+ --squisq-input-bg: var(--db-bg-hover);
1345
+ background: var(--db-bg);
1346
+ }
1347
+
1348
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-editor-header {
1349
+ background: var(--db-bg-subtle);
1350
+ border-bottom-color: var(--db-border-strong);
1351
+ }
1352
+
1353
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-toolbar-view-tabs {
1354
+ background: var(--db-bg);
1355
+ }
1356
+
1357
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-wysiwyg-container {
1358
+ background: #16110b;
1359
+ }
1360
+
1361
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-wysiwyg-editor {
1362
+ background: var(--db-bg);
1363
+ }
1364
+
1365
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-wysiwyg-editor pre {
1366
+ background: #16110b;
1367
+ }
1368
+
1369
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-wysiwyg-editor code {
1370
+ background: var(--db-bg-hover);
1371
+ }
1372
+
1373
+ .db-shell[data-theme='dark']
1374
+ .squisq-editor-shell[data-theme='dark']
1375
+ .squisq-wysiwyg-editor
1376
+ blockquote {
1377
+ border-left-color: var(--db-border);
1378
+ }
1379
+
1380
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-preview-player {
1381
+ background: var(--db-bg);
1382
+ }
1383
+
1384
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-preview-codeblock {
1385
+ background: #16110b;
1386
+ }
1387
+
1388
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-status-bar {
1389
+ background: var(--db-bg-subtle);
1390
+ border-top-color: var(--db-border);
1391
+ }
1392
+
1393
+ .db-shell[data-theme='dark'] .squisq-image-viewer--dark,
1394
+ .db-shell[data-theme='dark'] .squisq-image-viewer--dark .squisq-image-viewer-stage {
1395
+ background: var(--db-bg);
1396
+ }
1397
+
1398
+ /* ── Squisq accent override (blue → thematic green) ──────────── */
1399
+
1400
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-view-tab--active {
1401
+ color: var(--db-accent-hover);
1402
+ border-bottom-color: var(--db-accent-hover);
1403
+ }
1404
+
1405
+ .db-shell[data-theme='dark']
1406
+ .squisq-editor-shell[data-theme='dark']
1407
+ .squisq-toolbar-view-tab--active {
1408
+ color: var(--db-accent-deep);
1409
+ border-bottom-color: var(--db-accent-hover);
1410
+ }
1411
+
1412
+ .db-shell[data-theme='dark']
1413
+ .squisq-editor-shell[data-theme='dark']
1414
+ .squisq-toolbar-button--active {
1415
+ background: var(--db-accent-tint-strong);
1416
+ color: var(--db-accent-hover);
1417
+ }
1418
+
1419
+ .db-shell[data-theme='dark']
1420
+ .squisq-editor-shell[data-theme='dark']
1421
+ .squisq-toolbar-button--active:hover {
1422
+ background: var(--db-accent-tint-strong);
1423
+ color: var(--db-accent-deep);
1424
+ }
1425
+
1426
+ .db-shell[data-theme='dark']
1427
+ .squisq-editor-shell[data-theme='dark']
1428
+ .squisq-toolbar-overflow-item--active {
1429
+ color: var(--db-accent-hover);
1430
+ background: var(--db-accent-tint-strong);
1431
+ }
1432
+
1433
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-wysiwyg-editor a {
1434
+ color: var(--db-accent-hover);
1435
+ }
1436
+
1437
+ .db-shell[data-theme='dark']
1438
+ .squisq-editor-shell[data-theme='dark']
1439
+ .squisq-wysiwyg-editor
1440
+ .column-resize-handle {
1441
+ background: var(--db-accent-hover);
1442
+ }
1443
+
1444
+ .db-shell[data-theme='dark']
1445
+ .squisq-editor-shell[data-theme='dark']
1446
+ .squisq-wysiwyg-editor
1447
+ .selectedCell::after {
1448
+ background: var(--db-accent-soft-15);
1449
+ }
1450
+
1451
+ .db-shell[data-theme='dark']
1452
+ .squisq-editor-shell[data-theme='dark']
1453
+ .squisq-template-picker-select {
1454
+ background: var(--db-bg-hover);
1455
+ border-color: var(--db-border);
1456
+ color: var(--db-text-secondary);
1457
+ }
1458
+
1459
+ .db-shell[data-theme='dark']
1460
+ .squisq-editor-shell[data-theme='dark']
1461
+ .squisq-template-picker-select:focus {
1462
+ outline-color: var(--db-accent);
1463
+ }
1464
+
1465
+ .db-shell[data-theme='dark']
1466
+ .squisq-editor-shell[data-theme='dark']
1467
+ .squisq-toolbar-button:disabled,
1468
+ .db-shell[data-theme='dark']
1469
+ .squisq-editor-shell[data-theme='dark']
1470
+ .squisq-toolbar-button:disabled:hover {
1471
+ color: var(--db-text-muted);
1472
+ background: transparent;
1473
+ cursor: not-allowed;
1474
+ opacity: 0.6;
1475
+ /* Desaturate colored emoji glyphs (e.g. 🖼) so they don't read as blue
1476
+ against the warm-brown dark surface when disabled. */
1477
+ filter: grayscale(1);
1478
+ }
1479
+
1480
+ /* Closed-state template trigger: neutralize squisq's slate-navy bg ── */
1481
+ .db-shell[data-theme='dark']
1482
+ .squisq-editor-shell[data-theme='dark']
1483
+ .squisq-template-picker-trigger {
1484
+ background: var(--db-bg-subtle);
1485
+ border-color: var(--db-border);
1486
+ color: var(--db-text);
1487
+ }
1488
+
1489
+ .db-shell[data-theme='dark']
1490
+ .squisq-editor-shell[data-theme='dark']
1491
+ .squisq-template-picker-trigger:hover {
1492
+ background: var(--db-bg-hover);
1493
+ border-color: var(--db-border-strong);
1494
+ }
1495
+
1496
+ /* ── Tooltips (portal): sans-serif + thematic chip ───────────── */
1497
+ /* Tooltips render via portal into document.body, OUTSIDE `.db-shell`
1498
+ — so the `--db-accent-*` variables (scoped to `.db-shell`) don't
1499
+ cascade into them. We reach the portaled element with
1500
+ `html:has(.db-shell)` and emit explicit colors per theme; using
1501
+ `var(--db-accent-…)` here drops to the squisq fallback (dark slate
1502
+ bg + near-white text) because the vars never resolve. */
1503
+ html:has(.db-shell) .squisq-tooltip {
1504
+ font-family:
1505
+ ui-sans-serif,
1506
+ system-ui,
1507
+ -apple-system,
1508
+ 'Segoe UI',
1509
+ Roboto,
1510
+ 'Helvetica Neue',
1511
+ Arial,
1512
+ sans-serif;
1513
+ box-shadow: 0 2px 8px rgba(15, 30, 20, 0.35);
1514
+ /* Default (light mode + system-light): dark espresso chip, cream
1515
+ text — an inverted floating chip against the cream UI. */
1516
+ background: #3d3220;
1517
+ color: #f3eede;
1518
+ }
1519
+
1520
+ html:has(.db-shell[data-theme='dark']) .squisq-tooltip {
1521
+ /* Dark mode: cream chip, dark text — an inverted floating chip
1522
+ against the espresso UI. Contrast ratio ~12:1 between
1523
+ `#e6dcc0` and `#1f1a10`. */
1524
+ background: #e6dcc0;
1525
+ color: #1f1a10;
1526
+ }
1527
+
1528
+ @media (prefers-color-scheme: dark) {
1529
+ /* Shell defaults to system theme when `data-theme` is unset —
1530
+ mirror the dark-mode override so the tooltip stays readable
1531
+ without an explicit user choice. */
1532
+ html:has(.db-shell:not([data-theme='light'])) .squisq-tooltip {
1533
+ background: #e6dcc0;
1534
+ color: #1f1a10;
1535
+ }
1536
+ }
1537
+
1538
+ /* ── Template picker accents (dark): indigo → thematic green ─── */
1539
+ /* The gallery popover renders into document.body via createPortal, so
1540
+ neither .db-shell nor .squisq-editor-shell are ancestors. We use
1541
+ `html:has(.db-shell[data-theme='dark'])` to detect docblocks' dark
1542
+ theme from outside the shell, then style the portaled gallery (its
1543
+ root has id="squisq-template-gallery-portal"). */
1544
+
1545
+ .db-shell[data-theme='dark']
1546
+ .squisq-editor-shell[data-theme='dark']
1547
+ .squisq-template-picker-trigger--open {
1548
+ border-color: var(--db-accent-hover);
1549
+ outline-color: var(--db-accent-soft-25);
1550
+ }
1551
+
1552
+ /* The template gallery is rendered into document.body via createPortal,
1553
+ so it lives outside `.db-shell`. Hoist the same brown/canvas tokens
1554
+ onto the html element (gated by `:has(.db-shell[data-theme=…])`) so
1555
+ the portal rules below can pull from the same source of truth. */
1556
+ html:has(.db-shell[data-theme='dark']) {
1557
+ --db-bg: #1a1812;
1558
+ --db-bg-subtle: #262219;
1559
+ --db-bg-hover: #3a3528;
1560
+ --db-border: #4d4636;
1561
+ --db-border-strong: #6b6448;
1562
+ --db-text: #e8e2d0;
1563
+ --db-text-muted: #a89a7c;
1564
+ --db-accent: #c8b48f;
1565
+ --db-accent-hover: #dec79d;
1566
+ --db-accent-soft-15: rgba(200, 180, 143, 0.18);
1567
+ --db-accent-soft-25: rgba(200, 180, 143, 0.28);
1568
+ --db-accent-tint-strong: #3a382e;
1569
+ --db-gutter-bg: #4a4538;
1570
+ }
1571
+
1572
+ html:has(.db-shell[data-theme='light']) {
1573
+ --db-bg: #ffffff;
1574
+ --db-bg-subtle: #f3eede;
1575
+ --db-bg-hover: #e9e2cb;
1576
+ --db-border: #d6cdb0;
1577
+ --db-border-strong: #b5a985;
1578
+ --db-text: #2a2419;
1579
+ --db-text-muted: #6b614a;
1580
+ --db-accent: #7d6948;
1581
+ --db-accent-hover: #5e4f37;
1582
+ --db-accent-soft-15: rgba(125, 105, 72, 0.15);
1583
+ --db-accent-soft-25: rgba(125, 105, 72, 0.25);
1584
+ --db-accent-tint-strong: #d8d0b5;
1585
+ --db-gutter-bg: #efe8d4;
1586
+ }
1587
+
1588
+ html:has(.db-shell[data-theme='dark']) #squisq-template-gallery-portal {
1589
+ background: var(--db-bg-subtle);
1590
+ border-color: var(--db-border);
1591
+ box-shadow:
1592
+ 0 8px 24px rgba(0, 0, 0, 0.5),
1593
+ 0 2px 6px rgba(0, 0, 0, 0.3);
1594
+ }
1595
+
1596
+ html:has(.db-shell[data-theme='dark'])
1597
+ #squisq-template-gallery-portal
1598
+ .squisq-template-gallery-none {
1599
+ background: transparent;
1600
+ border-color: var(--db-border);
1601
+ }
1602
+
1603
+ html:has(.db-shell[data-theme='dark'])
1604
+ #squisq-template-gallery-portal
1605
+ .squisq-template-gallery-none:hover {
1606
+ background: var(--db-bg-hover);
1607
+ }
1608
+
1609
+ html:has(.db-shell[data-theme='dark'])
1610
+ #squisq-template-gallery-portal
1611
+ .squisq-template-gallery-none.squisq-template-gallery-card--selected {
1612
+ background: var(--db-accent-tint-strong);
1613
+ border-color: var(--db-accent);
1614
+ }
1615
+
1616
+ html:has(.db-shell[data-theme='dark'])
1617
+ #squisq-template-gallery-portal
1618
+ .squisq-template-gallery-none-label {
1619
+ color: var(--db-text);
1620
+ }
1621
+
1622
+ html:has(.db-shell[data-theme='dark'])
1623
+ #squisq-template-gallery-portal
1624
+ .squisq-template-gallery-none-desc {
1625
+ color: var(--db-text-muted);
1626
+ }
1627
+
1628
+ html:has(.db-shell[data-theme='dark'])
1629
+ #squisq-template-gallery-portal
1630
+ .squisq-template-gallery-card {
1631
+ background: transparent;
1632
+ border-color: var(--db-border);
1633
+ }
1634
+
1635
+ html:has(.db-shell[data-theme='dark'])
1636
+ #squisq-template-gallery-portal
1637
+ .squisq-template-gallery-card:hover {
1638
+ background: var(--db-bg-hover);
1639
+ border-color: var(--db-accent);
1640
+ box-shadow: 0 1px 4px var(--db-accent-soft-15);
1641
+ }
1642
+
1643
+ html:has(.db-shell[data-theme='dark'])
1644
+ #squisq-template-gallery-portal
1645
+ .squisq-template-gallery-card--selected {
1646
+ background: var(--db-accent-tint-strong);
1647
+ border-color: var(--db-accent-hover);
1648
+ box-shadow: 0 0 0 2px var(--db-accent-soft-25);
1649
+ }
1650
+
1651
+ html:has(.db-shell[data-theme='dark'])
1652
+ #squisq-template-gallery-portal
1653
+ .squisq-template-gallery-card-icon {
1654
+ background: var(--db-bg);
1655
+ border-color: var(--db-border);
1656
+ }
1657
+
1658
+ html:has(.db-shell[data-theme='dark'])
1659
+ #squisq-template-gallery-portal
1660
+ .squisq-template-gallery-card-name {
1661
+ color: var(--db-text);
1662
+ }
1663
+
1664
+ html:has(.db-shell[data-theme='dark'])
1665
+ #squisq-template-gallery-portal
1666
+ .squisq-template-gallery-card-desc {
1667
+ color: var(--db-text-muted);
1668
+ }
1669
+
1670
+ /* Recolor the indigo accent fills inside template thumbnail SVGs */
1671
+ html:has(.db-shell[data-theme='dark'])
1672
+ #squisq-template-gallery-portal
1673
+ .squisq-template-picker-icon
1674
+ [fill='#818cf8'] {
1675
+ fill: var(--db-accent-hover);
1676
+ }
1677
+
1678
+ /* ── Template picker accents (light): indigo → thematic green ── */
1679
+
1680
+ .db-shell[data-theme='light']
1681
+ .squisq-editor-shell[data-theme='light']
1682
+ .squisq-template-picker-trigger--open {
1683
+ border-color: var(--db-accent);
1684
+ outline-color: var(--db-accent-soft-25);
1685
+ }
1686
+
1687
+ .db-shell[data-theme='light']
1688
+ .squisq-editor-shell[data-theme='light']
1689
+ .squisq-template-gallery-card:hover {
1690
+ border-color: var(--db-input-border);
1691
+ box-shadow: 0 1px 4px var(--db-accent-soft-08);
1692
+ }
1693
+
1694
+ .db-shell[data-theme='light']
1695
+ .squisq-editor-shell[data-theme='light']
1696
+ .squisq-template-gallery-card--selected {
1697
+ background: var(--db-accent-tint);
1698
+ border-color: var(--db-accent);
1699
+ box-shadow: 0 0 0 2px var(--db-accent-soft-15);
1700
+ }
1701
+
1702
+ .db-shell[data-theme='light']
1703
+ .squisq-editor-shell[data-theme='light']
1704
+ .squisq-template-gallery-none.squisq-template-gallery-card--selected {
1705
+ background: var(--db-accent-tint);
1706
+ border-color: var(--db-accent-tint-strong);
1707
+ }
1708
+
1709
+ .db-shell[data-theme='light']
1710
+ .squisq-editor-shell[data-theme='light']
1711
+ .squisq-template-picker-icon
1712
+ [fill='#818cf8'] {
1713
+ fill: var(--db-accent);
1714
+ }
1715
+
1716
+ /* ── Template badge: inherit OS font, amber palette ──────────── */
1717
+
1718
+ .db-shell .squisq-template-badge {
1719
+ font-family: inherit;
1720
+ }
1721
+
1722
+ .db-shell[data-theme='light'] .squisq-template-badge {
1723
+ color: #92400e;
1724
+ background: #fef3c7;
1725
+ border-color: #fcd34d;
1726
+ }
1727
+
1728
+ .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] .squisq-template-badge {
1729
+ color: #fbbf24;
1730
+ background: #2a1e08;
1731
+ border-color: #92400e;
1732
+ }
1733
+
1734
+ /* Light mode squisq surfaces (toolbar, header, status bar) */
1735
+ .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] .squisq-editor-header {
1736
+ background: var(--db-accent-tint);
1737
+ border-bottom-color: var(--db-border-strong);
1738
+ }
1739
+
1740
+ /* Toolbar / view-tabs: the formatting area sits LIGHTER than the
1741
+ mode-switcher tabs on its left, so the cluster of buttons fades
1742
+ into the canvas while the mode switcher reads as the anchor. */
1743
+ .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] .squisq-toolbar {
1744
+ background: var(--db-accent-tint);
1745
+ }
1746
+
1747
+ .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] .squisq-toolbar-view-tabs {
1748
+ background: var(--db-gutter-bg);
1749
+ border-right-color: var(--db-border);
1750
+ }
1751
+
1752
+ .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] .squisq-status-bar {
1753
+ background: var(--db-accent-tint-strong);
1754
+ border-top-color: var(--db-border);
1755
+ }
1756
+
1757
+ /* Status bar "✓ OK" indicator — squisq paints this in saturated emerald
1758
+ (#059669 light, #34d399 dark). Re-tone to the sage accent so the
1759
+ parse-status indicator harmonizes with the rest of the chrome. */
1760
+ .db-shell .squisq-status-ok {
1761
+ color: var(--db-accent);
1762
+ }
1763
+
1764
+ .db-shell[data-theme='dark'] .squisq-status-ok {
1765
+ color: var(--db-accent-hover);
1766
+ }
1767
+
1768
+ /* Outline pane (left of the editor) — squisq paints a warm beige
1769
+ (#dcd8d0 light / dark slate in dark mode). Re-tone to `--db-gutter-bg`
1770
+ so it matches the inline-preview gutter on the right and reads as
1771
+ one step lighter than the toolbar above. */
1772
+ .db-shell[data-theme='light'] .squisq-outline {
1773
+ background: var(--db-gutter-bg);
1774
+ color: var(--db-text);
1775
+ }
1776
+
1777
+ .db-shell[data-theme='light'] .squisq-outline-row:hover {
1778
+ background: var(--db-accent-soft-15);
1779
+ }
1780
+
1781
+ .db-shell[data-theme='dark'] .squisq-outline {
1782
+ background: var(--db-gutter-bg);
1783
+ color: var(--db-text);
1784
+ }
1785
+
1786
+ .db-shell[data-theme='dark'] .squisq-outline-row:hover {
1787
+ background: var(--db-accent-soft-15);
1788
+ }
1789
+
1790
+ /* Explicit borders on the canvas side of each chrome pane so the
1791
+ white editor area reads as a clearly-edged "page" rather than
1792
+ blending into the cream gutters. Uses --db-border-strong to match
1793
+ the hairline under the toolbar. */
1794
+ .db-shell .squisq-outline {
1795
+ border-right: 1px solid var(--db-border-strong);
1796
+ }
1797
+
1798
+ .db-shell .squisq-inline-preview-gutter {
1799
+ border-left: 1px solid var(--db-border-strong);
1800
+ }
1801
+
1802
+ /* Monaco's line-number gutter ("editorGutter.background") is set via
1803
+ squisq's JS-side theme registration — those colors can't be CSS
1804
+ variables. To make the gutter blend with the outline/preview chrome
1805
+ on either side, we override the painted bg on `.margin` and its
1806
+ `.margin-view-overlays` child with our --db-gutter-bg. `!important`
1807
+ is required because Monaco inlines the color via the style attribute.
1808
+ The right-edge seam pseudo-element (`.margin::after`) also retones
1809
+ to --db-border so it's a single hairline matching the toolbar's
1810
+ bottom border, not a contrast stripe of its own. */
1811
+ .db-shell .squisq-raw-editor-container .monaco-editor .margin,
1812
+ .db-shell .squisq-raw-editor-container .monaco-editor .margin-view-overlays {
1813
+ background-color: var(--db-gutter-bg) !important;
1814
+ }
1815
+
1816
+ .db-shell .squisq-raw-editor-container .monaco-editor .margin::after {
1817
+ background: var(--db-border);
1818
+ }
1819
+
1820
+ /* Light mode squisq accents */
1821
+ .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] .squisq-view-tab--active,
1822
+ .db-shell[data-theme='light']
1823
+ .squisq-editor-shell[data-theme='light']
1824
+ .squisq-toolbar-view-tab--active {
1825
+ color: var(--db-accent-hover);
1826
+ border-bottom-color: var(--db-accent);
1827
+ }
1828
+
1829
+ .db-shell[data-theme='light']
1830
+ .squisq-editor-shell[data-theme='light']
1831
+ .squisq-toolbar-button--active {
1832
+ background: var(--db-accent-tint);
1833
+ color: var(--db-accent-hover);
1834
+ }
1835
+
1836
+ .db-shell[data-theme='light']
1837
+ .squisq-editor-shell[data-theme='light']
1838
+ .squisq-toolbar-button--active:hover {
1839
+ background: var(--db-accent-tint-strong);
1840
+ color: var(--db-accent-deep);
1841
+ }
1842
+
1843
+ .db-shell[data-theme='light']
1844
+ .squisq-editor-shell[data-theme='light']
1845
+ .squisq-toolbar-overflow-item--active {
1846
+ background: var(--db-accent-tint);
1847
+ color: var(--db-accent-hover);
1848
+ }
1849
+
1850
+ .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] .squisq-wysiwyg-editor a {
1851
+ color: var(--db-accent-hover);
1852
+ }
1853
+
1854
+ .db-shell[data-theme='light']
1855
+ .squisq-editor-shell[data-theme='light']
1856
+ .squisq-wysiwyg-editor
1857
+ .column-resize-handle {
1858
+ background: var(--db-accent);
1859
+ }
1860
+
1861
+ .db-shell[data-theme='light']
1862
+ .squisq-editor-shell[data-theme='light']
1863
+ .squisq-wysiwyg-editor
1864
+ .selectedCell::after {
1865
+ background: var(--db-accent-soft-12);
1866
+ }
1867
+
1868
+ /* Version history popover — DocBlocks-specific overrides.
1869
+ The upstream squisq popover uses Tailwind's slate-blue palette
1870
+ (#1f2937 bg, #374151 border, #2563eb selection). Inside DocBlocks we
1871
+ want the same dark surface used by the rest of the shell (--db-bg /
1872
+ --db-border). Selected rows pick up the sage accent at low alpha. */
1873
+ .db-shell .squisq-version-history-row--selected {
1874
+ background: var(--db-accent-soft-15);
1875
+ }
1876
+
1877
+ .db-shell[data-theme='dark'] .squisq-version-history-row--selected {
1878
+ background: var(--db-accent-soft-25);
1879
+ }
1880
+
1881
+ .db-shell[data-theme='dark'] .squisq-version-history-popover {
1882
+ background: var(--db-bg);
1883
+ border-color: var(--db-border);
1884
+ color: var(--db-text);
1885
+ }
1886
+
1887
+ .db-shell[data-theme='dark'] .squisq-version-history-header,
1888
+ .db-shell[data-theme='dark'] .squisq-version-history-diff-header,
1889
+ .db-shell[data-theme='dark']
1890
+ .squisq-version-history-popover--with-diff
1891
+ .squisq-version-history-list-pane,
1892
+ .db-shell[data-theme='dark'] .squisq-version-history-row--current {
1893
+ border-color: var(--db-border);
1894
+ }
1895
+
1896
+ .db-shell[data-theme='dark'] .squisq-version-history-row:hover {
1897
+ background: var(--db-bg-hover);
1898
+ }
1899
+
1900
+ /* ── Save toast ──────────────────────────────────────────────
1901
+ Comfort-blanket flyover triggered by Ctrl/Cmd+S. Files are
1902
+ already autosaved on every keystroke; this just confirms it
1903
+ so muscle-memory savers feel at ease. */
1904
+
1905
+ .db-save-toast {
1906
+ position: fixed;
1907
+ bottom: 32px;
1908
+ left: 50%;
1909
+ transform: translateX(-50%);
1910
+ z-index: 200;
1911
+ padding: 8px 16px;
1912
+ font-size: 13px;
1913
+ line-height: 1.4;
1914
+ color: #fff;
1915
+ background: rgba(31, 41, 55, 0.92);
1916
+ border-radius: 6px;
1917
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
1918
+ pointer-events: none;
1919
+ animation: db-save-toast-fade 1.8s ease-out forwards;
1920
+ }
1921
+
1922
+ .db-shell[data-theme='light'] .db-save-toast {
1923
+ background: rgba(17, 24, 39, 0.88);
1924
+ }
1925
+
1926
+ @keyframes db-save-toast-fade {
1927
+ 0% {
1928
+ opacity: 0;
1929
+ transform: translate(-50%, 6px);
1930
+ }
1931
+ 10% {
1932
+ opacity: 1;
1933
+ transform: translate(-50%, 0);
1934
+ }
1935
+ 80% {
1936
+ opacity: 1;
1937
+ transform: translate(-50%, 0);
1938
+ }
1939
+ 100% {
1940
+ opacity: 0;
1941
+ transform: translate(-50%, -4px);
1942
+ }
1943
+ }