@bendyline/docblocks-react 2.7.1 → 2.7.3

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 (38) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.txt +290 -48
  3. package/dist/{AiDiagrams-LFV4YU6W.js → AiDiagrams-QE3LVYFK.js} +2 -2
  4. package/dist/{AiEditorAssistant-GN2KXKZD.js → AiEditorAssistant-YLJ5OZK2.js} +203 -164
  5. package/dist/AiStudyDialog-4TQZZGU3.js +1150 -0
  6. package/dist/{ExportDialog-IMBVGRYG.js → ExportDialog-JRVZCG3J.js} +2 -2
  7. package/dist/{ExportToolbarControls-MUM6HM3K.js → ExportToolbarControls-A2YBKUUD.js} +46 -9
  8. package/dist/KeyboardShortcutsDialog-G5OBDTNR.js +145 -0
  9. package/dist/{PresentationMaker-W2JIBHRN.js → PresentationMaker-P2JP6UUX.js} +2 -2
  10. package/dist/{Settings-DuXk6baH.d.ts → Settings-ByNImjk5.d.ts} +13 -13
  11. package/dist/{SpeechToolbarControl-OSQS7NVY.js → SpeechToolbarControl-CLU7RB2G.js} +1 -1
  12. package/dist/{TextFromNarration-XYRAB6O2.js → TextFromNarration-NITJQ4IB.js} +1 -1
  13. package/dist/{WorkspaceSearchPanel-BKZJRPMY.js → WorkspaceSearchPanel-J6BKEZQJ.js} +1 -1
  14. package/dist/{chunk-X3DDTJKR.js → chunk-3CE5RH2B.js} +255 -17
  15. package/dist/{chunk-UG4G7PJ4.js → chunk-5O5YTOXG.js} +1 -1
  16. package/dist/{chunk-VO2JYYQZ.js → chunk-6JJOGV6M.js} +5 -13
  17. package/dist/{chunk-X437UAF7.js → chunk-6MSHXQNB.js} +7 -2
  18. package/dist/{chunk-BCQZTWE5.js → chunk-6PA7QBZT.js} +107 -24
  19. package/dist/chunk-ACQF63SB.js +136 -0
  20. package/dist/chunk-DICE7VBJ.js +77 -0
  21. package/dist/{chunk-EPOLZNFD.js → chunk-EOU2JWAQ.js} +186 -71
  22. package/dist/{chunk-G4MFB3IO.js → chunk-VG434562.js} +2 -70
  23. package/dist/chunk-XNT66JC2.js +168 -0
  24. package/dist/{chunk-BD54Z5XP.js → chunk-Y5OE3HJC.js} +4 -3
  25. package/dist/{chunk-NAH52736.js → chunk-YPIVCCTB.js} +969 -98
  26. package/dist/{chunk-W55E6TE2.js → chunk-ZMCQO57Q.js} +28 -23
  27. package/dist/editor.js +7 -5
  28. package/dist/export/index.d.ts +27 -8
  29. package/dist/export/index.js +4 -4
  30. package/dist/index.d.ts +36 -8
  31. package/dist/index.js +629 -446
  32. package/dist/run-export-OHRNT2TP.js +13 -0
  33. package/dist/settings/index.d.ts +1 -1
  34. package/dist/settings/index.js +1 -1
  35. package/package.json +9 -8
  36. package/src/styles/docblocks.css +968 -329
  37. package/dist/chunk-EA4BO6E4.js +0 -73
  38. package/dist/run-export-47X5FTYZ.js +0 -11
@@ -4,15 +4,19 @@
4
4
 
5
5
  /* ── Theme Tokens ────────────────────────────────────────────── */
6
6
 
7
- /* DocBlocks accent palette — warm brown on a canvas/parchment base.
8
- Think paper on a wooden desk: the editor itself stays white (paper),
9
- the chrome around it (sidebar, gutters, panes) reads as cream
10
- canvas, and the accent picks up a saturated dark brown for CTAs.
11
- Dark mode inverts the metaphor into espresso wood with light tan
12
- highlights. Derived shades (`--db-accent-soft-*`,
13
- `--db-accent-tint-strong`, `--db-accent-deep`) are defined alongside so every place that needs
14
- a tinted background or a readable-on-tint text color pulls from the
15
- same source of truth. */
7
+ /* DocBlocks palette — paper, ink, and rust.
8
+ The page is the one white sheet. Every chrome pane around it (sidebar,
9
+ toolbar, status bar) shares the cream `--db-bg-subtle`, so nothing but
10
+ the document competes for attention. Text is ink. The default accent
11
+ palette, Rust, paints primary buttons, active tabs and toggles in rust,
12
+ and a selected row is a quiet rust tint marked by a 2px
13
+ `--db-selected-rule` instead of a filled slab. The other accent palettes
14
+ (Green, Blue, …) follow the same model in their own hues. Dark mode
15
+ mirrors it: espresso panes, light ink, a lighter rust.
16
+ Derived shades (`--db-accent-soft-*`, `--db-accent-tint-strong`,
17
+ `--db-accent-deep`) are defined alongside so every place that needs a
18
+ tinted background or a readable-on-tint text color pulls from the same
19
+ source of truth. */
16
20
  /* The palette binds on the document root as well as on the shell. Squisq
17
21
  mounts its menus, dialogs and flyouts in PORTALS on <body>, outside the
18
22
  shell — without a root binding they cannot see --db-*, which is why the
@@ -20,44 +24,59 @@
20
24
  follows whichever appearance the shell in the page resolved to. */
21
25
  :root,
22
26
  .db-shell {
23
- /* Chrome typeface. `system-ui` first so DocBlocks looks native by default.
24
- Settings > Appearance > Interface font swaps this for the bundled face
25
- below; the visual-regression suite forces that, because under the system
26
- stack the same screenshot renders in a different typeface on every OS. */
27
+ /* Chrome typeface: the bundled `DocBlocks Fixed UI` face, which is Hanken
28
+ Grotesk — the sans docblocks.com is set in — so the app and the site
29
+ read as one product and the chrome renders identically on every OS.
30
+ Settings > Appearance > Interface font > System swaps it for the
31
+ platform's own face (the block below). */
27
32
  --db-ui-font:
28
- system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
29
- sans-serif;
30
- --db-bg: #ffffff;
33
+ 'DocBlocks Fixed UI', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
34
+ 'Helvetica Neue', Arial, sans-serif;
35
+ /* Metadata face: counts, timestamps, version strings, section labels. A
36
+ small mono sets what you read apart from what you act on. */
37
+ --db-meta-font: 'JetBrains Mono', ui-monospace, SFMono-Regular, Consolas, monospace;
38
+ /* Squisq's chrome reads `--squisq-ux-font` with a `system-ui` fallback, the
39
+ same bridge shape as the `--squisq-*` color tokens further down. Binding
40
+ it carries the chrome face into the editor toolbar, menus and dialogs.
41
+ DOCUMENT typography is never touched — a theme's fonts are content the
42
+ author chose, not chrome. */
43
+ --squisq-ux-font: var(--db-ui-font);
44
+ --db-bg: #fffdf9;
31
45
  --db-bg-subtle: #f3eede;
32
46
  --db-bg-hover: #e9e2cb;
33
- --db-bg-selected: #7d6948;
34
- --db-bg-selected-hover: #5e4f37;
35
- --db-border: #d6cdb0;
36
- --db-border-strong: #b5a985;
37
- --db-text: #2a2419;
47
+ --db-bg-selected: #e5ccb6;
48
+ --db-bg-selected-hover: #e0c0a8;
49
+ --db-border: #ddd5c3;
50
+ --db-border-strong: #c7bca3;
51
+ --db-text: #231f18;
38
52
  --db-text-secondary: #3d3528;
39
- --db-text-muted: #6b614a;
53
+ --db-text-muted: #6b6252;
40
54
  --db-text-placeholder: #766c54;
41
- --db-accent: #7d6948;
42
- --db-accent-hover: #5e4f37;
43
- --db-text-on-accent: #ffffff;
44
- --db-text-on-selected: #ffffff;
45
- /* Keyboard focus ring. Deliberately darker than --db-accent: the accent
46
- is also the *selected row* fill, so an accent ring vanished against
47
- it. Any surface that paints itself --db-bg-selected re-points this
48
- token at a contrasting value (see .db-tree-row--selected). */
49
- --db-focus: #3d3220;
50
- --db-accent-soft-08: rgba(125, 105, 72, 0.08);
51
- --db-accent-soft-10: rgba(125, 105, 72, 0.1);
52
- --db-accent-soft-12: rgba(125, 105, 72, 0.12);
53
- --db-accent-soft-15: rgba(125, 105, 72, 0.15);
54
- --db-accent-soft-25: rgba(125, 105, 72, 0.25);
55
- --db-accent-tint-strong: #d8d0b5;
56
- --db-accent-deep: #3d3220;
57
- --db-editor-canvas: #ffffff;
55
+ --db-accent: #a0461f;
56
+ --db-accent-hover: #8a3a1a;
57
+ --db-text-on-accent: #fffdf9;
58
+ --db-text-on-selected: #231f18;
59
+ /* The 2px mark down the leading edge of a selected row. Selection is a
60
+ tint, so this is what carries the state at a glance. */
61
+ --db-selected-rule: #a0461f;
62
+ /* Keyboard focus ring, in ink. The accent is rust and paints buttons and
63
+ the selected-row rule, so a rust ring would vanish against them; ink
64
+ holds at 14:1 on the cream panes. */
65
+ --db-focus: #231f18;
66
+ --db-accent-soft-08: rgba(160, 70, 31, 0.08);
67
+ --db-accent-soft-10: rgba(160, 70, 31, 0.1);
68
+ --db-accent-soft-12: rgba(160, 70, 31, 0.12);
69
+ --db-accent-soft-15: rgba(160, 70, 31, 0.15);
70
+ --db-accent-soft-25: rgba(160, 70, 31, 0.25);
71
+ --db-accent-tint-strong: #e8d2be;
72
+ --db-accent-deep: #7a3418;
73
+ --db-editor-canvas: #fffdf9;
74
+ /* Surfaces that float over the chrome: menus, dialogs, popovers. In light
75
+ mode they are the same warm-white sheet as the page. */
76
+ --db-bg-raised: var(--db-bg);
58
77
  --db-badge-bg: #f3eede;
59
78
  --db-badge-text: #3d3220;
60
- --db-badge-text-hover: #2a2419;
79
+ --db-badge-text-hover: #231f18;
61
80
  /* The editor "desk": every chrome surface the page floats on — the
62
81
  outline pane, the inline-preview gutter, the Monaco line-number
63
82
  margin, and (via `--squisq-desk-bg`) the field behind the WYSIWYG
@@ -144,53 +163,63 @@
144
163
  }
145
164
  }
146
165
 
147
- /* Interface font: fixed.
148
- `DocBlocks Fixed UI` is the Roboto variable binary each surface already ships
149
- for the document theme of that name, redeclared over the full 100-900 range
150
- so the chrome's 400/500/600/650/700 weights render exactly rather than
151
- snapping to the nearest static face. Bound on the root, not only the shell,
152
- because Squisq portals its menus onto <body>. */
153
- :root[data-db-interface-font='fixed'],
154
- :root[data-db-interface-font='fixed'] .db-shell {
166
+ /* Interface font: system.
167
+ `DocBlocks Fixed UI` (above) is the Hanken Grotesk variable binary each
168
+ surface already ships for the document theme of that name, redeclared over
169
+ the full 100-900 range so the chrome's 400/500/600/650/700 weights render
170
+ exactly. This block is the opt-out for anyone who wants DocBlocks to look
171
+ native: the platform UI face, and the platform mono for metadata, so the
172
+ chrome fetches nothing. Bound on the root, not only the shell, because
173
+ Squisq portals its menus onto <body>. */
174
+ :root[data-db-interface-font='system'],
175
+ :root[data-db-interface-font='system'] .db-shell {
155
176
  --db-ui-font:
156
- 'DocBlocks Fixed UI', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
157
- 'Helvetica Neue', Arial, sans-serif;
158
- /* Squisq's chrome reads `--squisq-ux-font` with a `system-ui` fallback, the
159
- same bridge shape as the `--squisq-*` colour tokens further down. Setting
160
- it here carries the fixed face into the editor toolbar, menus and dialogs,
161
- which is most of what a shell screenshot actually contains.
162
-
163
- Scoped to fixed mode on purpose: the token is left unset by default so
164
- Squisq keeps its own chrome font, and DOCUMENT typography is never touched
165
- — a theme's fonts are content the author chose, not chrome. */
177
+ system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
178
+ sans-serif;
179
+ --db-meta-font: ui-monospace, SFMono-Regular, Consolas, monospace;
166
180
  --squisq-ux-font: var(--db-ui-font);
167
181
  }
168
182
 
183
+ /* Form controls take the chrome face. Browsers give <button>, <input>,
184
+ <select> and <textarea> a UA font of their own (Arial in Chromium on
185
+ Windows), so every label inside a button — the view tabs, H1–H3, the
186
+ workspace picker — rendered in a second sans beside the chrome's.
187
+ Zero specificity, so any rule that names a font still wins; unscoped,
188
+ because Squisq portals its menus and dialogs onto <body>. */
189
+ :where(button, input, select, textarea) {
190
+ font-family: inherit;
191
+ }
192
+
169
193
  :root:has(.db-shell[data-theme='dark']),
170
194
  .db-shell[data-theme='dark'] {
171
195
  --db-bg: #1a1812;
172
196
  --db-bg-subtle: #262219;
173
197
  --db-bg-hover: #3a3528;
174
- --db-bg-selected: #3a3528;
175
- --db-bg-selected-hover: #4d4636;
176
- --db-border: #4d4636;
177
- --db-border-strong: #6b6448;
178
- --db-text: #e8e2d0;
198
+ --db-bg-selected: #433021;
199
+ --db-bg-selected-hover: #513625;
200
+ --db-border: #342e27;
201
+ --db-border-strong: #4a4238;
202
+ --db-text: #ece6d8;
179
203
  --db-text-secondary: #d4ccb0;
180
- --db-text-muted: #a89a7c;
204
+ --db-text-muted: #a39885;
181
205
  --db-text-placeholder: #6b614a;
182
- --db-accent: #c8b48f;
183
- --db-accent-hover: #dec79d;
206
+ --db-accent: #e0835a;
207
+ --db-accent-hover: #eb9a76;
184
208
  --db-text-on-accent: #1a1812;
185
- --db-text-on-selected: #e8e2d0;
186
- --db-focus: #e8e2d0;
187
- --db-accent-soft-08: rgba(200, 180, 143, 0.08);
188
- --db-accent-soft-10: rgba(200, 180, 143, 0.1);
189
- --db-accent-soft-12: rgba(200, 180, 143, 0.12);
190
- --db-accent-soft-15: rgba(200, 180, 143, 0.18);
191
- --db-accent-soft-25: rgba(200, 180, 143, 0.28);
192
- --db-accent-tint-strong: #3a382e;
193
- --db-accent-deep: #e6dcc0;
209
+ --db-text-on-selected: #ece6d8;
210
+ --db-selected-rule: #e0835a;
211
+ --db-focus: #ece6d8;
212
+ /* Dark mode reverses that: a floating surface must sit LIGHTER than the
213
+ panes it opens over, or a menu reads as a hole in the chrome. Derived
214
+ from the palette's own steps, so every accent palette gets one. */
215
+ --db-bg-raised: color-mix(in srgb, var(--db-bg-subtle), var(--db-bg-hover) 40%);
216
+ --db-accent-soft-08: rgba(224, 131, 90, 0.08);
217
+ --db-accent-soft-10: rgba(224, 131, 90, 0.1);
218
+ --db-accent-soft-12: rgba(224, 131, 90, 0.12);
219
+ --db-accent-soft-15: rgba(224, 131, 90, 0.18);
220
+ --db-accent-soft-25: rgba(224, 131, 90, 0.28);
221
+ --db-accent-tint-strong: #533725;
222
+ --db-accent-deep: #f0c2aa;
194
223
  --db-editor-canvas: #16110b;
195
224
  --db-badge-bg: #3a2f1f;
196
225
  --db-badge-text: #fff4d6;
@@ -220,25 +249,30 @@
220
249
  --db-bg: #1a1812;
221
250
  --db-bg-subtle: #262219;
222
251
  --db-bg-hover: #3a3528;
223
- --db-bg-selected: #3a3528;
224
- --db-bg-selected-hover: #4d4636;
225
- --db-border: #4d4636;
226
- --db-border-strong: #6b6448;
227
- --db-text: #e8e2d0;
252
+ --db-bg-selected: #433021;
253
+ --db-bg-selected-hover: #513625;
254
+ --db-border: #342e27;
255
+ --db-border-strong: #4a4238;
256
+ --db-text: #ece6d8;
228
257
  --db-text-secondary: #d4ccb0;
229
- --db-text-muted: #a89a7c;
258
+ --db-text-muted: #a39885;
230
259
  --db-text-placeholder: #6b614a;
231
- --db-accent: #c8b48f;
232
- --db-accent-hover: #dec79d;
260
+ --db-accent: #e0835a;
261
+ --db-accent-hover: #eb9a76;
233
262
  --db-text-on-accent: #1a1812;
234
- --db-text-on-selected: #e8e2d0;
235
- --db-focus: #e8e2d0;
236
- --db-accent-soft-08: rgba(200, 180, 143, 0.08);
237
- --db-accent-soft-12: rgba(200, 180, 143, 0.12);
238
- --db-accent-soft-15: rgba(200, 180, 143, 0.18);
239
- --db-accent-soft-25: rgba(200, 180, 143, 0.28);
240
- --db-accent-tint-strong: #3a382e;
241
- --db-accent-deep: #e6dcc0;
263
+ --db-text-on-selected: #ece6d8;
264
+ --db-selected-rule: #e0835a;
265
+ --db-focus: #ece6d8;
266
+ /* Dark mode reverses that: a floating surface must sit LIGHTER than the
267
+ panes it opens over, or a menu reads as a hole in the chrome. Derived
268
+ from the palette's own steps, so every accent palette gets one. */
269
+ --db-bg-raised: color-mix(in srgb, var(--db-bg-subtle), var(--db-bg-hover) 40%);
270
+ --db-accent-soft-08: rgba(224, 131, 90, 0.08);
271
+ --db-accent-soft-12: rgba(224, 131, 90, 0.12);
272
+ --db-accent-soft-15: rgba(224, 131, 90, 0.18);
273
+ --db-accent-soft-25: rgba(224, 131, 90, 0.28);
274
+ --db-accent-tint-strong: #533725;
275
+ --db-accent-deep: #f0c2aa;
242
276
  --db-input-border: #c8b48f;
243
277
  --db-danger: #f87171;
244
278
  --db-danger-bg: #1c1917;
@@ -293,10 +327,11 @@
293
327
  }
294
328
 
295
329
  .db-explorer-title {
296
- font-weight: 600;
297
- font-size: 12px;
330
+ font-family: var(--db-meta-font);
331
+ font-weight: 500;
332
+ font-size: 11px;
298
333
  text-transform: uppercase;
299
- letter-spacing: 0.03em;
334
+ letter-spacing: 0.06em;
300
335
  color: var(--db-text-muted);
301
336
  }
302
337
 
@@ -337,7 +372,7 @@
337
372
  padding: 8px 10px 5px;
338
373
  }
339
374
 
340
- .db-pinned-documents-title i {
375
+ .db-pinned-documents-title svg {
341
376
  font-size: 10px;
342
377
  }
343
378
 
@@ -383,9 +418,9 @@
383
418
  .db-pinned-document-row--selected,
384
419
  .db-pinned-document-row--selected:hover,
385
420
  .db-pinned-document-row--selected:has(:focus-visible) {
386
- --db-focus: #ffffff;
387
421
  background: var(--db-bg-selected);
388
422
  color: var(--db-text-on-selected);
423
+ box-shadow: inset 2px 0 0 var(--db-selected-rule);
389
424
  }
390
425
 
391
426
  .db-pinned-document-more {
@@ -445,7 +480,7 @@
445
480
  right: 4px;
446
481
  left: 4px;
447
482
  margin: 0;
448
- background: var(--db-bg);
483
+ background: var(--db-bg-raised);
449
484
  }
450
485
 
451
486
  .db-explorer-btn {
@@ -695,6 +730,14 @@
695
730
  opacity: 0.65;
696
731
  }
697
732
 
733
+ /* What a non-Markdown type means: written in Markdown, saved as that format. */
734
+ .db-new-item-hint {
735
+ margin: 4px 8px 0;
736
+ color: var(--db-text-muted);
737
+ font-size: 12px;
738
+ line-height: 1.35;
739
+ }
740
+
698
741
  /* ── Tree ────────────────────────────────────────────────────── */
699
742
 
700
743
  .db-tree {
@@ -793,14 +836,6 @@
793
836
  outline-offset: -2px;
794
837
  }
795
838
 
796
- /* A selected/drop-target row is filled with --db-bg-selected, which in
797
- light mode *is* the accent brown — the default ring would disappear
798
- into it. Re-point the token rather than duplicating the rule. */
799
- .db-tree-row--selected,
800
- .db-tree-row--drop-target {
801
- --db-focus: #ffffff;
802
- }
803
-
804
839
  .db-tree-row--dragging {
805
840
  opacity: 0.45;
806
841
  }
@@ -816,6 +851,7 @@
816
851
  .db-tree-row--selected {
817
852
  background: var(--db-bg-selected);
818
853
  color: var(--db-text-on-selected);
854
+ box-shadow: inset 2px 0 0 var(--db-selected-rule);
819
855
  }
820
856
 
821
857
  .db-tree-row--selected:hover {
@@ -846,7 +882,8 @@
846
882
  margin-left: 8px;
847
883
  overflow: hidden;
848
884
  color: var(--db-text-secondary);
849
- font-size: 11px;
885
+ font-family: var(--db-meta-font);
886
+ font-size: 10.5px;
850
887
  font-variant-numeric: tabular-nums;
851
888
  text-align: right;
852
889
  text-overflow: ellipsis;
@@ -946,7 +983,7 @@
946
983
  .db-tree-context {
947
984
  position: fixed;
948
985
  z-index: 1000;
949
- background: var(--db-bg);
986
+ background: var(--db-bg-raised);
950
987
  border: 1px solid var(--db-border);
951
988
  border-radius: 4px;
952
989
  box-shadow: 0 4px 12px var(--db-shadow);
@@ -1049,7 +1086,7 @@
1049
1086
  z-index: 60;
1050
1087
  min-width: calc(100% - 16px);
1051
1088
  max-width: min(320px, 90vw);
1052
- background: var(--db-bg);
1089
+ background: var(--db-bg-raised);
1053
1090
  border: 1px solid var(--db-border);
1054
1091
  border-radius: 4px;
1055
1092
  box-shadow: 0 4px 12px var(--db-shadow);
@@ -1288,11 +1325,21 @@
1288
1325
  display: block;
1289
1326
  }
1290
1327
 
1291
- /* The logo is black lettering on a pale extruded edge. On espresso the black
1292
- fill vanished and only the edges showed, so it read as a hollow outline.
1293
- Inverting makes the letters solid and sinks the edge into the background,
1294
- and the sepia warms them toward --db-text. */
1295
- .db-shell[data-theme='dark'] .db-app-menu-logo {
1328
+ /* Hosts pass a light and a dark wordmark; the shell shows the one drawn for
1329
+ its resolved appearance. The dark one is painted as on a hull (white faces,
1330
+ black shade), which an inverted light logo can't reproduce. */
1331
+ .db-app-menu-logo--dark,
1332
+ .db-shell[data-theme='dark'] .db-app-menu-logo--light {
1333
+ display: none;
1334
+ }
1335
+
1336
+ .db-shell[data-theme='dark'] .db-app-menu-logo--dark {
1337
+ display: block;
1338
+ }
1339
+
1340
+ /* A host with only one logo gets it inverted in dark mode — fine for a flat
1341
+ black-on-transparent mark, the case this fallback exists for. */
1342
+ .db-shell[data-theme='dark'] .db-app-menu-logo--invert {
1296
1343
  filter: invert(1) brightness(0.88) sepia(0.15);
1297
1344
  }
1298
1345
 
@@ -1318,7 +1365,7 @@
1318
1365
  left: 0;
1319
1366
  z-index: 70;
1320
1367
  min-width: 200px;
1321
- background: var(--db-bg);
1368
+ background: var(--db-bg-raised);
1322
1369
  border: 1px solid var(--db-border);
1323
1370
  border-radius: 4px;
1324
1371
  box-shadow: 0 4px 12px var(--db-shadow);
@@ -1342,6 +1389,18 @@
1342
1389
  background: var(--db-bg-hover);
1343
1390
  }
1344
1391
 
1392
+ .db-app-menu-item--with-shortcut {
1393
+ display: flex;
1394
+ align-items: baseline;
1395
+ justify-content: space-between;
1396
+ gap: 16px;
1397
+ }
1398
+
1399
+ .db-app-menu-shortcut {
1400
+ color: var(--db-text-muted);
1401
+ font-size: 12px;
1402
+ }
1403
+
1345
1404
  .db-app-menu-item--danger {
1346
1405
  color: var(--db-danger);
1347
1406
  }
@@ -1392,7 +1451,7 @@
1392
1451
  right: 0;
1393
1452
  z-index: 100;
1394
1453
  min-width: 200px;
1395
- background: var(--db-bg);
1454
+ background: var(--db-bg-raised);
1396
1455
  border: 1px solid var(--db-border);
1397
1456
  border-radius: 6px;
1398
1457
  box-shadow: 0 4px 12px var(--db-shadow);
@@ -1517,6 +1576,9 @@
1517
1576
 
1518
1577
  .db-shell-sidebar {
1519
1578
  width: 260px;
1579
+ /* The sidebar is chrome, so it shares the toolbar's paper; only the page
1580
+ itself is white. */
1581
+ background: var(--db-bg-subtle);
1520
1582
  display: flex;
1521
1583
  flex-direction: column;
1522
1584
  overflow: hidden;
@@ -1539,7 +1601,7 @@
1539
1601
  inset-block: 0;
1540
1602
  inset-inline-start: 0;
1541
1603
  z-index: 30;
1542
- background: var(--db-bg);
1604
+ background: var(--db-bg-subtle);
1543
1605
  width: var(--db-drawer-width);
1544
1606
  padding-inline-start: var(--db-safe-left);
1545
1607
  border-inline-end: 1px solid var(--db-border-strong);
@@ -1729,6 +1791,7 @@ body.db-resizing-sidebar * {
1729
1791
  box here so both chrome regions are 25px everywhere. */
1730
1792
  .db-shell .squisq-status-bar {
1731
1793
  line-height: 16px;
1794
+ font-family: var(--db-meta-font);
1732
1795
  }
1733
1796
 
1734
1797
  .db-shell-sidebar-footer {
@@ -1761,8 +1824,7 @@ body.db-resizing-sidebar * {
1761
1824
  text-decoration: underline;
1762
1825
  }
1763
1826
 
1764
- .db-shell-sidebar-footer-separator,
1765
- .db-shell-sidebar-footer-action {
1827
+ .db-shell-sidebar-footer-separator {
1766
1828
  color: var(--db-text-muted);
1767
1829
  }
1768
1830
 
@@ -1771,20 +1833,37 @@ body.db-resizing-sidebar * {
1771
1833
  opacity: 0.65;
1772
1834
  }
1773
1835
 
1836
+ /* The backup action is the footer's one control that protects work, so it is a
1837
+ bordered button with a 22px target (24px including the spacing around it)
1838
+ rather than another 11px text link. */
1774
1839
  .db-shell-sidebar-footer-action {
1840
+ display: inline-flex;
1841
+ align-items: center;
1842
+ gap: 4px;
1775
1843
  flex-shrink: 0;
1776
- padding: 0;
1777
- border: 0;
1778
- background: transparent;
1844
+ min-height: 22px;
1845
+ margin-left: auto;
1846
+ padding: 0 8px;
1847
+ border: 1px solid var(--db-border-strong);
1848
+ border-radius: 999px;
1849
+ background: var(--db-bg);
1850
+ color: var(--db-text-secondary);
1779
1851
  font: inherit;
1780
- line-height: inherit;
1781
- text-decoration: underline;
1852
+ font-size: 12px;
1853
+ font-weight: 600;
1854
+ line-height: 1;
1782
1855
  white-space: nowrap;
1783
1856
  cursor: pointer;
1784
1857
  }
1785
1858
 
1786
1859
  .db-shell-sidebar-footer-action:hover {
1787
- color: var(--db-text-secondary);
1860
+ border-color: var(--db-accent);
1861
+ color: var(--db-text);
1862
+ }
1863
+
1864
+ .db-shell-sidebar-footer-action:focus-visible {
1865
+ outline: 2px solid var(--db-focus);
1866
+ outline-offset: 1px;
1788
1867
  }
1789
1868
 
1790
1869
  .db-shell-empty {
@@ -1938,7 +2017,7 @@ body.db-resizing-sidebar * {
1938
2017
  position: static;
1939
2018
  }
1940
2019
 
1941
- .db-shell--mobile .squisq-editor-shell .squisq-toolbar-overflow-menu {
2020
+ html:has(.db-shell--mobile) .squisq-toolbar-overflow-menu {
1942
2021
  right: auto !important;
1943
2022
  left: max(4px, env(safe-area-inset-left)) !important;
1944
2023
  max-width: calc(100vw - 8px);
@@ -2184,7 +2263,7 @@ body.db-resizing-sidebar * {
2184
2263
 
2185
2264
  .db-dialog {
2186
2265
  box-sizing: border-box;
2187
- background: var(--db-bg);
2266
+ background: var(--db-bg-raised);
2188
2267
  border: 1px solid var(--db-border);
2189
2268
  border-radius: 8px;
2190
2269
  box-shadow: 0 8px 32px var(--db-shadow);
@@ -2262,21 +2341,6 @@ body.db-resizing-sidebar * {
2262
2341
  gap: 6px 16px;
2263
2342
  }
2264
2343
 
2265
- .db-about-beta {
2266
- margin-bottom: 10px;
2267
- padding: 10px 12px;
2268
- border: 1px solid var(--db-accent);
2269
- border-radius: 6px;
2270
- background: var(--db-accent-soft-08);
2271
- color: var(--db-text-secondary);
2272
- font-size: 12px;
2273
- line-height: 1.5;
2274
- }
2275
-
2276
- .db-about-beta strong {
2277
- color: var(--db-accent-deep);
2278
- }
2279
-
2280
2344
  .db-about-version {
2281
2345
  display: flex;
2282
2346
  align-items: center;
@@ -2297,7 +2361,7 @@ body.db-resizing-sidebar * {
2297
2361
 
2298
2362
  .db-about-version code {
2299
2363
  color: var(--db-text);
2300
- font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
2364
+ font-family: var(--db-meta-font);
2301
2365
  user-select: all;
2302
2366
  }
2303
2367
 
@@ -2314,10 +2378,11 @@ body.db-resizing-sidebar * {
2314
2378
  }
2315
2379
 
2316
2380
  .db-settings-legend {
2317
- font-size: 12px;
2318
- font-weight: 600;
2381
+ font-family: var(--db-meta-font);
2382
+ font-size: 11px;
2383
+ font-weight: 500;
2319
2384
  text-transform: uppercase;
2320
- letter-spacing: 0.03em;
2385
+ letter-spacing: 0.06em;
2321
2386
  color: var(--db-text-muted);
2322
2387
  margin-bottom: 8px;
2323
2388
  }
@@ -2632,7 +2697,7 @@ body.db-resizing-sidebar * {
2632
2697
  border: 1px solid var(--db-border-strong);
2633
2698
  border-radius: 6px;
2634
2699
  outline: none;
2635
- background: var(--db-bg);
2700
+ background: var(--db-bg-raised);
2636
2701
  color: var(--db-text);
2637
2702
  box-shadow: 0 10px 28px var(--db-shadow);
2638
2703
  }
@@ -2904,8 +2969,8 @@ body.db-resizing-sidebar * {
2904
2969
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.18);
2905
2970
  }
2906
2971
 
2907
- .db-settings-accent-swatch--brown {
2908
- background: #7d6948;
2972
+ .db-settings-accent-swatch--rust {
2973
+ background: #a0461f;
2909
2974
  }
2910
2975
 
2911
2976
  .db-settings-accent-swatch--green {
@@ -3133,7 +3198,7 @@ body.db-resizing-sidebar * {
3133
3198
  margin-top: 4px;
3134
3199
  z-index: 70;
3135
3200
  min-width: 200px;
3136
- background: var(--db-bg);
3201
+ background: var(--db-bg-raised);
3137
3202
  border: 1px solid var(--db-border);
3138
3203
  border-radius: 4px;
3139
3204
  box-shadow: 0 4px 12px var(--db-shadow);
@@ -3598,6 +3663,7 @@ body.db-resizing-sidebar * {
3598
3663
  --squisq-row-hover: var(--db-bg-hover);
3599
3664
  --squisq-hover-bg: var(--db-bg-hover);
3600
3665
  --squisq-panel-bg: var(--db-bg);
3666
+ --squisq-surface-overlay: var(--db-bg-raised);
3601
3667
 
3602
3668
  /* The desk the editing page floats on — the WYSIWYG backing, the block
3603
3669
  card and its preview panel, the outline pane, the Monaco margin. */
@@ -3755,31 +3821,30 @@ body.db-resizing-sidebar * {
3755
3821
  background: var(--squisq-desk-bg);
3756
3822
  }
3757
3823
 
3758
- /* ── Inline preview gutter: thematic green ──────────────────── */
3824
+ /* ── Inline preview gutter ──────────────────────────────────── */
3759
3825
  /* Rebind squisq's `--squisq-preview-*` custom properties so the
3760
- gutter chrome (vertical bracket, diagonal connector + dots,
3761
- "FACTCARD" template label) reads as sage green instead of indigo,
3762
- and the card surface tones harmonize with the rest of docblocks.
3763
- The preview-block renderer's own theme is unaffected — that's a
3764
- document-level concern, not chrome. */
3826
+ gutter chrome (vertical bracket, diagonal connector + dots)
3827
+ draws as hairlines in the rule color rather than in the accent,
3828
+ and the card surface tones harmonize with the rest of docblocks. The preview-block renderer's own theme is unaffected —
3829
+ that's a document-level concern, not chrome. */
3765
3830
  .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] {
3766
- --squisq-preview-accent: var(--db-accent);
3767
- --squisq-preview-accent-muted: var(--db-text-muted);
3831
+ --squisq-preview-accent: var(--db-border-strong);
3832
+ --squisq-preview-accent-muted: var(--db-border);
3768
3833
  --squisq-preview-gutter-bg: var(--db-gutter-bg);
3769
- --squisq-preview-card-bg: #ffffff;
3834
+ --squisq-preview-card-bg: var(--db-bg);
3770
3835
  --squisq-preview-card-border: var(--db-border);
3771
3836
  --squisq-preview-card-shadow: 0 1px 2px rgba(40, 30, 15, 0.08);
3772
3837
  --squisq-preview-card-title: var(--db-accent-deep);
3773
3838
  --squisq-preview-card-svg-bg: var(--db-bg-subtle);
3774
3839
  --squisq-preview-dot-halo: var(--db-gutter-bg);
3775
- --squisq-preview-empty-bg: #ffffff;
3840
+ --squisq-preview-empty-bg: var(--db-bg);
3776
3841
  --squisq-preview-empty-border: var(--db-border);
3777
3842
  --squisq-preview-empty-text: var(--db-accent-deep);
3778
3843
  }
3779
3844
 
3780
3845
  .db-shell[data-theme='dark'] .squisq-editor-shell[data-theme='dark'] {
3781
- --squisq-preview-accent: var(--db-accent-hover);
3782
- --squisq-preview-accent-muted: var(--db-text-muted);
3846
+ --squisq-preview-accent: var(--db-border-strong);
3847
+ --squisq-preview-accent-muted: var(--db-border);
3783
3848
  --squisq-preview-gutter-bg: var(--db-gutter-bg);
3784
3849
  --squisq-preview-card-bg: var(--db-bg);
3785
3850
  --squisq-preview-card-border: var(--db-border);
@@ -3792,6 +3857,24 @@ body.db-resizing-sidebar * {
3792
3857
  --squisq-preview-empty-text: var(--db-text-muted);
3793
3858
  }
3794
3859
 
3860
+ /* Squisq colors the card's template label with the same
3861
+ `--squisq-preview-accent` as the hairlines above, and a rule color is
3862
+ too faint for text. Keep the label at the muted text tone so it meets
3863
+ WCAG AA contrast on the card surface. */
3864
+ .db-shell .squisq-editor-shell .squisq-inline-preview-card-template {
3865
+ color: var(--db-text-muted);
3866
+ }
3867
+
3868
+ /* The extent bar shows a block's reach; at Squisq's 4px it read as a cable
3869
+ running beside the page. Squisq has no width token for it. */
3870
+ .db-shell .squisq-editor-shell .squisq-inline-preview-extent {
3871
+ width: 2px;
3872
+ }
3873
+
3874
+ .db-shell .squisq-editor-shell .squisq-inline-preview-extent--untagged {
3875
+ width: 1px;
3876
+ }
3877
+
3795
3878
  /* ── Squisq dark-theme override ──────────────────────────────── */
3796
3879
  /* Squisq has hardcoded slate-blue surfaces in its dark mode. We re-tone
3797
3880
  them via the DocBlocks dark palette so the editor reads as warm dark
@@ -3956,7 +4039,7 @@ body.db-resizing-sidebar * {
3956
4039
  }
3957
4040
 
3958
4041
  .db-shell .squisq-editor-shell .squisq-media-bin .squisq-media-bin-context-menu {
3959
- background: var(--db-bg);
4042
+ background: var(--db-bg-raised);
3960
4043
  border-color: var(--db-border);
3961
4044
  box-shadow: 0 12px 28px var(--db-shadow);
3962
4045
  }
@@ -4088,38 +4171,15 @@ body.db-resizing-sidebar * {
4088
4171
  border-color: var(--db-border-strong);
4089
4172
  }
4090
4173
 
4091
- /* ── Tooltips (portal): sans-serif + thematic chip ───────────── */
4092
- /* Tooltips render via portal into document.body, OUTSIDE `.db-shell`
4093
- — so the `--db-accent-*` variables (scoped to `.db-shell`) don't
4094
- cascade into them. We reach the portaled element with
4095
- `html:has(.db-shell)` and emit explicit colors per theme; using
4096
- `var(--db-accent-…)` here drops to the squisq fallback (dark slate
4097
- bg + near-white text) because the vars never resolve. */
4174
+ /* ── Tooltips (portal): sans-serif + ink chip ───────────────── */
4175
+ /* Tooltips portal into document.body, outside `.db-shell`; the palette is
4176
+ hoisted to the root, so the tokens resolve there. The chip inverts the
4177
+ chrome: ink on cream in light mode, light ink on espresso in dark. */
4098
4178
  html:has(.db-shell) .squisq-tooltip {
4099
4179
  font-family: var(--db-ui-font);
4100
4180
  box-shadow: 0 2px 8px rgba(15, 30, 20, 0.35);
4101
- /* Default (light mode + system-light): dark espresso chip, cream
4102
- text — an inverted floating chip against the cream UI. */
4103
- background: #3d3220;
4104
- color: #f3eede;
4105
- }
4106
-
4107
- html:has(.db-shell[data-theme='dark']) .squisq-tooltip {
4108
- /* Dark mode: cream chip, dark text — an inverted floating chip
4109
- against the espresso UI. Contrast ratio ~12:1 between
4110
- `#e6dcc0` and `#1f1a10`. */
4111
- background: #e6dcc0;
4112
- color: #1f1a10;
4113
- }
4114
-
4115
- @media (prefers-color-scheme: dark) {
4116
- /* Shell defaults to system theme when `data-theme` is unset —
4117
- mirror the dark-mode override so the tooltip stays readable
4118
- without an explicit user choice. */
4119
- html:has(.db-shell:not([data-theme='light'])) .squisq-tooltip {
4120
- background: #e6dcc0;
4121
- color: #1f1a10;
4122
- }
4181
+ background: var(--db-text);
4182
+ color: var(--db-bg-subtle);
4123
4183
  }
4124
4184
 
4125
4185
  /* ── Template picker accents (dark): indigo → thematic green ─── */
@@ -4139,64 +4199,69 @@ html:has(.db-shell[data-theme='dark']) .squisq-tooltip {
4139
4199
 
4140
4200
  /* The template gallery and file-tree context menu render into document.body
4141
4201
  via createPortal, so they live outside `.db-shell`. Hoist the same
4142
- brown/canvas tokens onto the html element (gated by the resolved shell
4202
+ palette tokens onto the html element (gated by the resolved shell
4143
4203
  theme) so every portaled surface keeps the DocBlocks palette. */
4144
4204
  html:has(.db-shell[data-theme='dark']) {
4145
4205
  --db-bg: #1a1812;
4146
4206
  --db-bg-subtle: #262219;
4147
4207
  --db-bg-hover: #3a3528;
4148
- --db-border: #4d4636;
4149
- --db-border-strong: #6b6448;
4150
- --db-text: #e8e2d0;
4208
+ --db-border: #342e27;
4209
+ --db-border-strong: #4a4238;
4210
+ --db-text: #ece6d8;
4151
4211
  --db-text-secondary: #d4ccb0;
4152
- --db-text-muted: #a89a7c;
4212
+ --db-text-muted: #a39885;
4153
4213
  --db-danger: #f87171;
4154
4214
  --db-danger-bg: #1c1917;
4155
4215
  --db-text-on-danger: #1c1917;
4156
4216
  --db-shadow: rgba(0, 0, 0, 0.4);
4157
- --db-accent: #c8b48f;
4158
- --db-accent-hover: #dec79d;
4217
+ --db-accent: #e0835a;
4218
+ --db-accent-hover: #eb9a76;
4159
4219
  --db-text-on-accent: #1a1812;
4160
- --db-accent-soft-15: rgba(200, 180, 143, 0.18);
4161
- --db-accent-soft-25: rgba(200, 180, 143, 0.28);
4162
- --db-accent-tint-strong: #3a382e;
4163
- --db-accent-deep: #e6dcc0;
4220
+ --db-accent-soft-15: rgba(224, 131, 90, 0.18);
4221
+ --db-accent-soft-25: rgba(224, 131, 90, 0.28);
4222
+ --db-accent-tint-strong: #533725;
4223
+ --db-accent-deep: #f0c2aa;
4164
4224
  --db-gutter-bg: #16110b;
4225
+ --db-bg-raised: color-mix(in srgb, var(--db-bg-subtle), var(--db-bg-hover) 40%);
4165
4226
  }
4166
4227
 
4167
4228
  html:has(.db-shell[data-theme='light']) {
4168
- --db-bg: #ffffff;
4229
+ --db-bg: #fffdf9;
4169
4230
  --db-bg-subtle: #f3eede;
4170
4231
  --db-bg-hover: #e9e2cb;
4171
- --db-border: #d6cdb0;
4172
- --db-border-strong: #b5a985;
4173
- --db-text: #2a2419;
4232
+ --db-border: #ddd5c3;
4233
+ --db-border-strong: #c7bca3;
4234
+ --db-text: #231f18;
4174
4235
  --db-text-secondary: #3d3528;
4175
- --db-text-muted: #6b614a;
4236
+ --db-text-muted: #6b6252;
4176
4237
  --db-danger: #b22b1b;
4177
4238
  --db-danger-bg: #fdf0ee;
4178
4239
  --db-text-on-danger: #ffffff;
4179
4240
  --db-shadow: rgba(40, 30, 15, 0.12);
4180
- --db-accent: #7d6948;
4181
- --db-accent-hover: #5e4f37;
4182
- --db-text-on-accent: #ffffff;
4183
- --db-accent-soft-15: rgba(125, 105, 72, 0.15);
4184
- --db-accent-soft-25: rgba(125, 105, 72, 0.25);
4185
- --db-accent-tint-strong: #d8d0b5;
4186
- --db-accent-deep: #3d3220;
4241
+ --db-accent: #a0461f;
4242
+ --db-accent-hover: #8a3a1a;
4243
+ --db-text-on-accent: #fffdf9;
4244
+ --db-accent-soft-15: rgba(160, 70, 31, 0.15);
4245
+ --db-accent-soft-25: rgba(160, 70, 31, 0.25);
4246
+ --db-accent-tint-strong: #e8d2be;
4247
+ --db-accent-deep: #7a3418;
4187
4248
  --db-gutter-bg: #efe8d4;
4188
4249
  }
4189
4250
 
4190
- /* Accent variants keep Brown as the untouched default while recoloring the
4251
+ /* Accent variants keep Rust as the untouched default while recoloring the
4191
4252
  full chrome palette for either appearance. The same tokens are hoisted to
4192
4253
  `html` so Squisq portals and file-tree menus inherit the active variant. */
4193
- .db-shell[data-theme='light']:not([data-accent='brown']),
4194
- html:has(.db-shell[data-theme='light']:not([data-accent='brown'])) {
4254
+ .db-shell[data-theme='light']:not([data-accent='rust']),
4255
+ html:has(.db-shell[data-theme='light']:not([data-accent='rust'])) {
4195
4256
  --db-accent-soft-08: rgb(var(--db-accent-rgb) / 8%);
4196
4257
  --db-accent-soft-10: rgb(var(--db-accent-rgb) / 10%);
4197
4258
  --db-accent-soft-12: rgb(var(--db-accent-rgb) / 12%);
4198
4259
  --db-accent-soft-15: rgb(var(--db-accent-rgb) / 15%);
4199
4260
  --db-accent-soft-25: rgb(var(--db-accent-rgb) / 25%);
4261
+ --db-text-on-selected: var(--db-text);
4262
+ --db-selected-rule: var(--db-accent);
4263
+ --db-bg: #ffffff;
4264
+ --db-editor-canvas: #ffffff;
4200
4265
  --db-gallery-backdrop: rgba(30, 30, 30, 0.24);
4201
4266
  --db-gallery-panel-bg: var(--db-bg);
4202
4267
  --db-gallery-raised-bg: var(--db-bg);
@@ -4205,13 +4270,14 @@ html:has(.db-shell[data-theme='light']:not([data-accent='brown'])) {
4205
4270
  --db-gallery-placeholder: var(--db-text-muted);
4206
4271
  }
4207
4272
 
4208
- .db-shell[data-theme='dark']:not([data-accent='brown']),
4209
- html:has(.db-shell[data-theme='dark']:not([data-accent='brown'])) {
4273
+ .db-shell[data-theme='dark']:not([data-accent='rust']),
4274
+ html:has(.db-shell[data-theme='dark']:not([data-accent='rust'])) {
4210
4275
  --db-accent-soft-08: rgb(var(--db-accent-rgb) / 8%);
4211
4276
  --db-accent-soft-10: rgb(var(--db-accent-rgb) / 10%);
4212
4277
  --db-accent-soft-12: rgb(var(--db-accent-rgb) / 12%);
4213
4278
  --db-accent-soft-15: rgb(var(--db-accent-rgb) / 18%);
4214
4279
  --db-accent-soft-25: rgb(var(--db-accent-rgb) / 28%);
4280
+ --db-selected-rule: var(--db-accent);
4215
4281
  --db-gallery-backdrop: rgba(0, 0, 0, 0.58);
4216
4282
  --db-gallery-panel-bg: var(--db-bg);
4217
4283
  --db-gallery-header-bg: var(--db-editor-canvas);
@@ -4225,8 +4291,8 @@ html:has(.db-shell[data-theme='dark']:not([data-accent='brown'])) {
4225
4291
  html:has(.db-shell[data-theme='light'][data-accent='green']) {
4226
4292
  --db-bg-subtle: #edf4ef;
4227
4293
  --db-bg-hover: #dfece3;
4228
- --db-bg-selected: #4f715d;
4229
- --db-bg-selected-hover: #3d5949;
4294
+ --db-bg-selected: #cfe0d3;
4295
+ --db-bg-selected-hover: #c2d6c7;
4230
4296
  --db-border: #c6d8cb;
4231
4297
  --db-border-strong: #98b3a1;
4232
4298
  --db-text: #202a23;
@@ -4274,8 +4340,8 @@ html:has(.db-shell[data-theme='dark'][data-accent='green']) {
4274
4340
  html:has(.db-shell[data-theme='light'][data-accent='blue']) {
4275
4341
  --db-bg-subtle: #eef2f7;
4276
4342
  --db-bg-hover: #e1e8f0;
4277
- --db-bg-selected: #526f91;
4278
- --db-bg-selected-hover: #3c5675;
4343
+ --db-bg-selected: #d0dbe7;
4344
+ --db-bg-selected-hover: #c3d0de;
4279
4345
  --db-border: #c7d1de;
4280
4346
  --db-border-strong: #99aabd;
4281
4347
  --db-text: #202733;
@@ -4323,8 +4389,8 @@ html:has(.db-shell[data-theme='dark'][data-accent='blue']) {
4323
4389
  html:has(.db-shell[data-theme='light'][data-accent='purple']) {
4324
4390
  --db-bg-subtle: #f3eff6;
4325
4391
  --db-bg-hover: #e9e1ef;
4326
- --db-bg-selected: #735b8c;
4327
- --db-bg-selected-hover: #59436f;
4392
+ --db-bg-selected: #ddd0e4;
4393
+ --db-bg-selected-hover: #d2c3db;
4328
4394
  --db-border: #d5c8dd;
4329
4395
  --db-border-strong: #b19cbe;
4330
4396
  --db-text: #29222e;
@@ -4372,8 +4438,8 @@ html:has(.db-shell[data-theme='dark'][data-accent='purple']) {
4372
4438
  html:has(.db-shell[data-theme='light'][data-accent='maroon']) {
4373
4439
  --db-bg-subtle: #f7eff2;
4374
4440
  --db-bg-hover: #eedfe5;
4375
- --db-bg-selected: #805365;
4376
- --db-bg-selected-hover: #643d4d;
4441
+ --db-bg-selected: #e6d0d8;
4442
+ --db-bg-selected-hover: #dcc3cd;
4377
4443
  --db-border: #dec8d0;
4378
4444
  --db-border-strong: #bd9ba8;
4379
4445
  --db-text: #2f2227;
@@ -4421,8 +4487,8 @@ html:has(.db-shell[data-theme='dark'][data-accent='maroon']) {
4421
4487
  html:has(.db-shell[data-theme='light'][data-accent='orange']) {
4422
4488
  --db-bg-subtle: #f8f1e9;
4423
4489
  --db-bg-hover: #f0e4d6;
4424
- --db-bg-selected: #8a5a32;
4425
- --db-bg-selected-hover: #6d4323;
4490
+ --db-bg-selected: #ead8c5;
4491
+ --db-bg-selected-hover: #e1cbb4;
4426
4492
  --db-border: #e0cfbc;
4427
4493
  --db-border-strong: #c2a282;
4428
4494
  --db-text: #30271f;
@@ -4470,8 +4536,8 @@ html:has(.db-shell[data-theme='dark'][data-accent='orange']) {
4470
4536
  html:has(.db-shell[data-theme='light'][data-accent='gray']) {
4471
4537
  --db-bg-subtle: #f2f2f2;
4472
4538
  --db-bg-hover: #e6e6e6;
4473
- --db-bg-selected: #676767;
4474
- --db-bg-selected-hover: #505050;
4539
+ --db-bg-selected: #d8d8d8;
4540
+ --db-bg-selected-hover: #cdcdcd;
4475
4541
  --db-border: #d1d1d1;
4476
4542
  --db-border-strong: #a8a8a8;
4477
4543
  --db-text: #252525;
@@ -4520,7 +4586,7 @@ html:has(.db-shell[data-theme='dark'][data-accent='gray']) {
4520
4586
  above so its surface, states, icons, and text follow every DocBlocks theme
4521
4587
  and accent instead of falling back to Squisq's standalone blue/slate UI. */
4522
4588
  html:has(.db-shell) .squisq-use-mode-menu {
4523
- background: var(--db-bg);
4589
+ background: var(--db-bg-raised);
4524
4590
  border-color: var(--db-border);
4525
4591
  box-shadow:
4526
4592
  0 12px 32px var(--db-shadow),
@@ -4631,7 +4697,7 @@ html:has(.db-shell)
4631
4697
  same menu surfaces as the rest of the shell. The selector also covers the
4632
4698
  nested Mermaid and code-snippet menus, which share this portal class. */
4633
4699
  html:has(.db-shell) .squisq-insert-menu {
4634
- background: var(--db-bg);
4700
+ background: var(--db-bg-raised);
4635
4701
  border-color: var(--db-border);
4636
4702
  color: var(--db-text-secondary);
4637
4703
  box-shadow: 0 4px 12px var(--db-shadow);
@@ -4654,12 +4720,12 @@ html:has(.db-shell) .squisq-insert-menu .squisq-insert-menu-header--separated {
4654
4720
  border-top-color: var(--db-border);
4655
4721
  }
4656
4722
 
4657
- html:has(.db-shell[data-theme='light']:not([data-accent='brown'])) .squisq-tooltip {
4723
+ html:has(.db-shell[data-theme='light']:not([data-accent='rust'])) .squisq-tooltip {
4658
4724
  background: var(--db-accent-deep);
4659
4725
  color: var(--db-bg-subtle);
4660
4726
  }
4661
4727
 
4662
- html:has(.db-shell[data-theme='dark']:not([data-accent='brown'])) .squisq-tooltip {
4728
+ html:has(.db-shell[data-theme='dark']:not([data-accent='rust'])) .squisq-tooltip {
4663
4729
  background: var(--db-accent-deep);
4664
4730
  color: var(--db-bg);
4665
4731
  }
@@ -4720,7 +4786,7 @@ html:has(.db-shell[data-theme='dark'])
4720
4786
 
4721
4787
  html:has(.db-shell[data-theme='light'])
4722
4788
  .squisq-template-gallery-dialog[data-theme='light']:has([data-squisq-template-gallery-portal]) {
4723
- --squisq-template-gallery-backdrop: var(--db-gallery-backdrop, rgba(42, 36, 25, 0.24));
4789
+ --squisq-template-gallery-backdrop: var(--db-gallery-backdrop, rgba(35, 31, 24, 0.24));
4724
4790
  --squisq-template-gallery-panel-bg: var(--db-gallery-panel-bg, #fffdf7);
4725
4791
  --squisq-template-gallery-panel-border: var(--db-border);
4726
4792
  --squisq-template-gallery-header-bg: var(--db-bg-subtle);
@@ -5283,13 +5349,13 @@ html:has(.db-shell[data-theme='dark'])
5283
5349
  }
5284
5350
 
5285
5351
  .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] .squisq-toolbar-view-tabs {
5286
- background: var(--db-gutter-bg);
5352
+ background: var(--db-bg-subtle);
5287
5353
  border-right-color: var(--db-border);
5288
5354
  }
5289
5355
 
5290
5356
  .db-shell[data-theme='light'] .squisq-editor-shell[data-theme='light'] .squisq-status-bar {
5291
5357
  --squisq-text-muted: var(--db-text-secondary);
5292
- background: var(--db-accent-tint-strong);
5358
+ background: var(--db-bg-subtle);
5293
5359
  border-top-color: var(--db-border-strong);
5294
5360
  }
5295
5361
 
@@ -5330,48 +5396,49 @@ html:has(.db-shell[data-theme='dark'])
5330
5396
  border-left: 1px solid var(--db-border);
5331
5397
  }
5332
5398
 
5333
- /* Toolbar overflow menu. Squisq intentionally ships a neutral slate
5399
+ /* Toolbar overflow menu. Squisq portals it onto <body> (2.12+), outside the
5400
+ shell, so these rules reach it through `html:has(.db-shell)` like the
5401
+ Insert and Use mode menus. Squisq intentionally ships a neutral slate
5334
5402
  palette; inside DocBlocks this popover should use the same surfaces,
5335
5403
  borders, text, and interaction colors as our other shell menus. The
5336
5404
  contextual template/transition controls need explicit treatment too,
5337
5405
  since they bring their own Squisq surfaces into the popover. */
5338
- .db-shell .squisq-editor-shell .squisq-toolbar-overflow-menu {
5339
- background: var(--db-bg);
5406
+ html:has(.db-shell) .squisq-toolbar-overflow-menu {
5407
+ background: var(--db-bg-raised);
5340
5408
  border-color: var(--db-border);
5341
5409
  box-shadow: 0 4px 12px var(--db-shadow);
5342
5410
  }
5343
5411
 
5344
- .db-shell .squisq-editor-shell .squisq-toolbar-overflow-menu--up {
5412
+ html:has(.db-shell) .squisq-toolbar-overflow-menu--up {
5345
5413
  box-shadow: 0 -4px 12px var(--db-shadow);
5346
5414
  }
5347
5415
 
5348
- .db-shell .squisq-editor-shell .squisq-toolbar-overflow-item {
5416
+ html:has(.db-shell) .squisq-toolbar-overflow-item {
5349
5417
  color: var(--db-text-secondary);
5350
5418
  }
5351
5419
 
5352
- .db-shell .squisq-editor-shell .squisq-toolbar-overflow-item:hover {
5420
+ html:has(.db-shell) .squisq-toolbar-overflow-item:hover {
5353
5421
  background: var(--db-bg-hover);
5354
5422
  }
5355
5423
 
5356
- .db-shell .squisq-editor-shell .squisq-toolbar-overflow-heading {
5424
+ html:has(.db-shell) .squisq-toolbar-overflow-heading {
5357
5425
  color: var(--db-text-muted);
5358
5426
  }
5359
5427
 
5360
- .db-shell .squisq-editor-shell .squisq-toolbar-overflow-menu > .squisq-toolbar-separator {
5428
+ html:has(.db-shell) .squisq-toolbar-overflow-menu > .squisq-toolbar-separator {
5361
5429
  background: var(--db-border);
5362
5430
  }
5363
5431
 
5364
- .db-shell .squisq-editor-shell .squisq-toolbar-overflow-item--danger {
5432
+ html:has(.db-shell) .squisq-toolbar-overflow-item--danger {
5365
5433
  color: var(--db-danger);
5366
5434
  }
5367
5435
 
5368
- .db-shell .squisq-editor-shell .squisq-toolbar-overflow-item--danger:hover {
5436
+ html:has(.db-shell) .squisq-toolbar-overflow-item--danger:hover {
5369
5437
  background: var(--db-danger-bg);
5370
5438
  color: var(--db-danger);
5371
5439
  }
5372
5440
 
5373
- .db-shell
5374
- .squisq-editor-shell
5441
+ html:has(.db-shell)
5375
5442
  .squisq-toolbar-overflow-menu
5376
5443
  :is(.squisq-template-picker-trigger, .squisq-transition-picker-trigger) {
5377
5444
  background: var(--db-bg-subtle);
@@ -5379,16 +5446,14 @@ html:has(.db-shell[data-theme='dark'])
5379
5446
  color: var(--db-text-secondary);
5380
5447
  }
5381
5448
 
5382
- .db-shell
5383
- .squisq-editor-shell
5449
+ html:has(.db-shell)
5384
5450
  .squisq-toolbar-overflow-menu
5385
5451
  :is(.squisq-template-picker-trigger, .squisq-transition-picker-trigger):hover {
5386
5452
  background: var(--db-bg-hover);
5387
5453
  border-color: var(--db-border-strong);
5388
5454
  }
5389
5455
 
5390
- .db-shell
5391
- .squisq-editor-shell
5456
+ html:has(.db-shell)
5392
5457
  .squisq-toolbar-overflow-menu
5393
5458
  :is(.squisq-template-picker-trigger--open, .squisq-transition-picker-trigger--open) {
5394
5459
  background: var(--db-bg-hover);
@@ -5396,66 +5461,64 @@ html:has(.db-shell[data-theme='dark'])
5396
5461
  outline-color: var(--db-accent-soft-25);
5397
5462
  }
5398
5463
 
5399
- .db-shell
5400
- .squisq-editor-shell
5464
+ html:has(.db-shell)
5401
5465
  .squisq-toolbar-overflow-menu
5402
5466
  :is(.squisq-template-picker-trigger-label, .squisq-transition-picker-trigger-label),
5403
- .db-shell
5404
- .squisq-editor-shell
5467
+ html:has(.db-shell)
5405
5468
  .squisq-toolbar-overflow-menu
5406
5469
  :is(.squisq-template-picker-trigger-caret, .squisq-transition-picker-trigger svg) {
5407
5470
  color: var(--db-text-muted);
5408
5471
  }
5409
5472
 
5410
- .db-shell
5411
- .squisq-editor-shell
5473
+ html:has(.db-shell)
5412
5474
  .squisq-toolbar-overflow-menu
5413
5475
  :is(.squisq-template-picker-trigger-value, .squisq-transition-picker-trigger-value) {
5414
5476
  color: var(--db-text-secondary);
5415
5477
  }
5416
5478
 
5417
- .db-shell .squisq-editor-shell .squisq-toolbar-overflow-menu .squisq-template-picker-trigger-thumb {
5479
+ html:has(.db-shell) .squisq-toolbar-overflow-menu .squisq-template-picker-trigger-thumb {
5418
5480
  background: var(--db-bg);
5419
5481
  border-color: var(--db-border);
5420
5482
  }
5421
5483
 
5422
- /* View menu. Squisq's dark appearance otherwise replaces its generic
5423
- variables with a fixed slate-blue palette. Keep the popover and its
5424
- controls on the same host palette as the DocBlocks app and overflow
5425
- menus, including the native radio/checkbox selection color. */
5426
- .db-shell .squisq-editor-shell .squisq-view-menu-popover {
5427
- background: var(--db-bg);
5484
+ /* View menu — portaled onto <body> like the overflow menu, so reached
5485
+ through `html:has(.db-shell)`. Squisq's dark appearance otherwise
5486
+ replaces its generic variables with a fixed slate-blue palette. Keep the
5487
+ popover and its controls on the same host palette as the DocBlocks app
5488
+ and overflow menus, including the native radio/checkbox selection color. */
5489
+ html:has(.db-shell) .squisq-view-menu-popover {
5490
+ background: var(--db-bg-raised);
5428
5491
  border-color: var(--db-border);
5429
5492
  box-shadow: 0 4px 12px var(--db-shadow);
5430
5493
  color: var(--db-text-secondary);
5431
5494
  }
5432
5495
 
5433
- .db-shell .squisq-editor-shell .squisq-view-menu-row:hover,
5434
- .db-shell .squisq-editor-shell .squisq-view-menu-radio-row:hover {
5496
+ html:has(.db-shell) .squisq-view-menu-row:hover,
5497
+ html:has(.db-shell) .squisq-view-menu-radio-row:hover {
5435
5498
  background: var(--db-bg-hover);
5436
5499
  }
5437
5500
 
5438
- .db-shell .squisq-editor-shell .squisq-view-menu-row--select:hover,
5439
- .db-shell .squisq-editor-shell .squisq-view-menu-row--radios:hover {
5501
+ html:has(.db-shell) .squisq-view-menu-row--select:hover,
5502
+ html:has(.db-shell) .squisq-view-menu-row--radios:hover {
5440
5503
  background: transparent;
5441
5504
  }
5442
5505
 
5443
- .db-shell .squisq-editor-shell .squisq-view-menu-row--select .squisq-view-menu-label,
5444
- .db-shell .squisq-editor-shell .squisq-view-menu-row--radios > .squisq-view-menu-label {
5506
+ html:has(.db-shell) .squisq-view-menu-row--select .squisq-view-menu-label,
5507
+ html:has(.db-shell) .squisq-view-menu-row--radios > .squisq-view-menu-label {
5445
5508
  color: var(--db-text-muted);
5446
5509
  }
5447
5510
 
5448
- .db-shell .squisq-editor-shell .squisq-view-menu-select {
5511
+ html:has(.db-shell) .squisq-view-menu-select {
5449
5512
  background: var(--db-bg-subtle);
5450
5513
  border-color: var(--db-border);
5451
5514
  color: var(--db-text-secondary);
5452
5515
  }
5453
5516
 
5454
- .db-shell .squisq-editor-shell .squisq-view-menu-separator {
5517
+ html:has(.db-shell) .squisq-view-menu-separator {
5455
5518
  background: var(--db-border);
5456
5519
  }
5457
5520
 
5458
- .db-shell .squisq-editor-shell :is(.squisq-view-menu-checkbox, .squisq-view-menu-radio) {
5521
+ html:has(.db-shell) :is(.squisq-view-menu-checkbox, .squisq-view-menu-radio) {
5459
5522
  accent-color: var(--db-accent);
5460
5523
  }
5461
5524
 
@@ -5539,7 +5602,7 @@ html:has(.db-shell[data-theme='dark'])
5539
5602
  }
5540
5603
 
5541
5604
  .db-shell[data-theme='dark'] .squisq-version-history-popover {
5542
- background: var(--db-bg);
5605
+ background: var(--db-bg-raised);
5543
5606
  border-color: var(--db-border);
5544
5607
  color: var(--db-text);
5545
5608
  }
@@ -5562,62 +5625,149 @@ html:has(.db-shell[data-theme='dark'])
5562
5625
  already autosaved on every keystroke; this just confirms it
5563
5626
  so muscle-memory savers feel at ease. */
5564
5627
 
5565
- /* ── Welcome gateway ─────────────────────────────────────────── */
5566
- /* One-time first-run callout floated over the welcome doc's Play
5567
- view. Names the mode the user landed in and offers a one-click
5568
- path into the editor. Dismissed forever via localStorage. */
5628
+ /* ── Welcome screen ─────────────────────────────────────────── */
5629
+ /* First visit on a two-pane layout: covers the editor area -- the welcome
5630
+ document mounts, inert, beneath it -- with what DocBlocks is and two
5631
+ choices. Dismissed for good via localStorage. Phones keep their card in
5632
+ the file pane (`.db-mobile-first-run`). The class names predate this
5633
+ screen; they were a toast over a slideshow. */
5634
+
5635
+ .db-shell-editor-content {
5636
+ display: contents;
5637
+ }
5569
5638
 
5570
5639
  .db-welcome-gateway {
5571
5640
  position: absolute;
5572
- bottom: 56px;
5573
- left: 50%;
5574
- transform: translateX(-50%);
5641
+ inset: 0;
5575
5642
  z-index: 60;
5576
5643
  display: flex;
5577
5644
  align-items: center;
5578
- gap: 12px;
5579
- max-width: min(640px, calc(100% - 32px));
5580
- padding: 10px 10px 10px 16px;
5581
- background: var(--db-bg);
5582
- border: 1px solid var(--db-border-strong);
5583
- border-radius: 10px;
5584
- box-shadow: 0 10px 32px var(--db-shadow);
5645
+ justify-content: center;
5646
+ overflow-y: auto;
5647
+ padding: calc(var(--db-safe-top) + 40px) 40px 40px;
5648
+ background:
5649
+ radial-gradient(circle at 88% 8%, var(--db-accent-soft-12), transparent 42%), var(--db-bg);
5585
5650
  color: var(--db-text);
5586
- font-size: 13px;
5587
- line-height: 1.45;
5588
- animation: db-welcome-gateway-in 0.4s ease-out;
5651
+ container-type: inline-size;
5589
5652
  }
5590
5653
 
5591
- .db-welcome-gateway-cta {
5592
- flex-shrink: 0;
5593
- padding: 6px 14px;
5594
- font-size: 13px;
5654
+ .db-welcome-gateway-body {
5655
+ display: grid;
5656
+ width: min(1040px, 100%);
5657
+ margin: auto 0;
5658
+ gap: 36px;
5659
+ align-items: center;
5660
+ }
5661
+
5662
+ @container (min-width: 980px) {
5663
+ .db-welcome-gateway-body {
5664
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
5665
+ gap: 56px;
5666
+ }
5667
+ }
5668
+
5669
+ .db-welcome-gateway-eyebrow {
5670
+ margin: 0 0 12px;
5671
+ color: var(--db-accent);
5672
+ font-size: 12px;
5673
+ font-weight: 700;
5674
+ letter-spacing: 0.1em;
5675
+ text-transform: uppercase;
5676
+ }
5677
+
5678
+ .db-welcome-gateway h1 {
5679
+ margin: 0;
5680
+ color: var(--db-text);
5681
+ font-family: 'PT Serif', Georgia, 'Times New Roman', serif;
5682
+ font-size: clamp(30px, 4.4cqi, 46px);
5683
+ font-weight: 700;
5684
+ line-height: 1.1;
5685
+ letter-spacing: -0.01em;
5686
+ }
5687
+
5688
+ .db-welcome-gateway-copy > p:not(.db-welcome-gateway-eyebrow) {
5689
+ max-width: 34em;
5690
+ margin: 16px 0 0;
5691
+ color: var(--db-text-secondary);
5692
+ font-size: 16px;
5693
+ line-height: 1.6;
5694
+ }
5695
+
5696
+ .db-welcome-gateway-copy > .db-welcome-gateway-note {
5697
+ margin-top: 8px;
5698
+ color: var(--db-text-muted);
5699
+ font-size: 14px;
5700
+ }
5701
+
5702
+ .db-welcome-gateway-actions {
5703
+ display: flex;
5704
+ flex-wrap: wrap;
5705
+ gap: 10px;
5706
+ margin-top: 28px;
5707
+ }
5708
+
5709
+ .db-welcome-gateway-actions button,
5710
+ .db-welcome-gateway-actions a {
5711
+ min-height: 44px;
5712
+ padding: 10px 20px;
5713
+ border: 1px solid var(--db-border-strong);
5714
+ border-radius: 8px;
5715
+ background: var(--db-bg);
5716
+ color: var(--db-text);
5717
+ font: inherit;
5718
+ font-size: 15px;
5595
5719
  font-weight: 600;
5720
+ cursor: pointer;
5721
+ }
5722
+
5723
+ /* The apps link wears the button treatment; this centers its label the way a
5724
+ button's is and drops the underline. */
5725
+ .db-welcome-gateway-actions a {
5726
+ box-sizing: border-box;
5727
+ display: inline-flex;
5728
+ align-items: center;
5729
+ text-decoration: none;
5730
+ }
5731
+
5732
+ .db-welcome-gateway-actions button:hover,
5733
+ .db-welcome-gateway-actions a:hover {
5734
+ border-color: var(--db-accent);
5735
+ background: var(--db-bg-hover);
5736
+ }
5737
+
5738
+ .db-welcome-gateway-actions .db-welcome-gateway-primary {
5739
+ border-color: var(--db-accent);
5596
5740
  background: var(--db-accent);
5597
5741
  color: var(--db-text-on-accent);
5598
- border: none;
5599
- border-radius: 6px;
5600
- cursor: pointer;
5601
- white-space: nowrap;
5602
5742
  }
5603
5743
 
5604
- .db-welcome-gateway-cta:hover {
5744
+ .db-welcome-gateway-actions .db-welcome-gateway-primary:hover {
5745
+ border-color: var(--db-accent-hover);
5605
5746
  background: var(--db-accent-hover);
5606
5747
  }
5607
5748
 
5749
+ .db-welcome-gateway-actions button:focus-visible,
5750
+ .db-welcome-gateway-actions a:focus-visible,
5751
+ .db-welcome-gateway-dismiss:focus-visible {
5752
+ outline: 2px solid var(--db-focus);
5753
+ outline-offset: 2px;
5754
+ }
5755
+
5608
5756
  .db-welcome-gateway-dismiss {
5609
- flex-shrink: 0;
5757
+ position: absolute;
5758
+ top: calc(var(--db-safe-top) + 12px);
5759
+ right: 12px;
5610
5760
  display: inline-flex;
5611
5761
  align-items: center;
5612
5762
  justify-content: center;
5613
- width: 26px;
5614
- height: 26px;
5615
- font-size: 16px;
5616
- line-height: 1;
5763
+ width: 32px;
5764
+ height: 32px;
5765
+ border: none;
5766
+ border-radius: 8px;
5617
5767
  background: transparent;
5618
5768
  color: var(--db-text-muted);
5619
- border: none;
5620
- border-radius: 6px;
5769
+ font-size: 20px;
5770
+ line-height: 1;
5621
5771
  cursor: pointer;
5622
5772
  }
5623
5773
 
@@ -5626,20 +5776,247 @@ html:has(.db-shell[data-theme='dark'])
5626
5776
  color: var(--db-text);
5627
5777
  }
5628
5778
 
5629
- @keyframes db-welcome-gateway-in {
5630
- from {
5631
- transform: translate(-50%, 8px);
5632
- }
5633
- to {
5634
- transform: translate(-50%, 0);
5635
- }
5779
+ /* One Markdown file becoming a PDF page, a slide and a video frame on a 9 s
5780
+ loop. The frames share one stage and take turns; each label lights with
5781
+ its frame. The page and slide colors are fixed: they depict output, which
5782
+ looks the same whatever theme the app is in. */
5783
+ .db-welcome-loop {
5784
+ display: grid;
5785
+ grid-template-columns: minmax(0, 0.95fr) auto minmax(0, 1.1fr);
5786
+ align-items: center;
5787
+ gap: 14px 16px;
5636
5788
  }
5637
5789
 
5638
- .db-save-toast {
5639
- position: fixed;
5640
- bottom: 32px;
5641
- left: 50%;
5642
- transform: translateX(-50%);
5790
+ .db-welcome-loop-source {
5791
+ padding: 14px 16px;
5792
+ border: 1px solid var(--db-border-strong);
5793
+ border-radius: 10px;
5794
+ background: var(--db-bg-subtle);
5795
+ box-shadow: 0 10px 28px var(--db-shadow);
5796
+ }
5797
+
5798
+ .db-welcome-loop-file {
5799
+ display: block;
5800
+ margin-bottom: 10px;
5801
+ color: var(--db-text-muted);
5802
+ font: 600 11px/1 var(--db-meta-font);
5803
+ letter-spacing: 0.04em;
5804
+ }
5805
+
5806
+ .db-welcome-loop-source code {
5807
+ display: block;
5808
+ overflow: hidden;
5809
+ color: var(--db-text-secondary);
5810
+ font: 12px/1.65 var(--db-meta-font);
5811
+ white-space: pre-wrap;
5812
+ overflow-wrap: anywhere;
5813
+ }
5814
+
5815
+ .db-welcome-loop-mark {
5816
+ color: var(--db-accent);
5817
+ }
5818
+
5819
+ .db-welcome-loop-arrow {
5820
+ color: var(--db-accent);
5821
+ font-size: 24px;
5822
+ animation: db-welcome-loop-nudge 3s ease-in-out infinite;
5823
+ }
5824
+
5825
+ .db-welcome-loop-stage {
5826
+ position: relative;
5827
+ aspect-ratio: 4 / 3;
5828
+ }
5829
+
5830
+ .db-welcome-loop-frame {
5831
+ position: absolute;
5832
+ inset: 0;
5833
+ display: flex;
5834
+ flex-direction: column;
5835
+ gap: 6px;
5836
+ margin: auto;
5837
+ padding: 18px;
5838
+ overflow: hidden;
5839
+ border-radius: 8px;
5840
+ box-shadow: 0 14px 34px var(--db-shadow);
5841
+ font-family: 'PT Serif', Georgia, 'Times New Roman', serif;
5842
+ opacity: 0;
5843
+ animation: db-welcome-loop-frame 9s ease-in-out infinite both;
5844
+ }
5845
+
5846
+ .db-welcome-loop-frame strong {
5847
+ font-size: 17px;
5848
+ line-height: 1.2;
5849
+ }
5850
+
5851
+ .db-welcome-loop-frame span {
5852
+ font-size: 11.5px;
5853
+ line-height: 1.4;
5854
+ }
5855
+
5856
+ .db-welcome-loop-frame em {
5857
+ margin-top: 4px;
5858
+ font-size: 13px;
5859
+ font-style: normal;
5860
+ font-weight: 700;
5861
+ }
5862
+
5863
+ .db-welcome-loop-frame--page {
5864
+ width: 74%;
5865
+ border: 1px solid #e3dccb;
5866
+ background: #fffdf8;
5867
+ color: #2b241c;
5868
+ }
5869
+
5870
+ .db-welcome-loop-frame--slide,
5871
+ .db-welcome-loop-frame--video {
5872
+ height: 75%;
5873
+ justify-content: center;
5874
+ background: radial-gradient(circle at 30% 20%, #5a3322, #24170f 72%);
5875
+ color: #f6ecdc;
5876
+ }
5877
+
5878
+ .db-welcome-loop-frame--slide {
5879
+ align-items: center;
5880
+ text-align: center;
5881
+ animation-delay: 3s;
5882
+ }
5883
+
5884
+ .db-welcome-loop-frame--slide strong {
5885
+ font-size: 21px;
5886
+ }
5887
+
5888
+ .db-welcome-loop-frame--video {
5889
+ justify-content: flex-start;
5890
+ animation-delay: 6s;
5891
+ }
5892
+
5893
+ .db-welcome-loop-play {
5894
+ position: absolute;
5895
+ bottom: 11px;
5896
+ left: 14px;
5897
+ font-size: 10px;
5898
+ font-style: normal;
5899
+ }
5900
+
5901
+ .db-welcome-loop-progress {
5902
+ position: absolute;
5903
+ right: 14px;
5904
+ bottom: 15px;
5905
+ left: 32px;
5906
+ height: 3px;
5907
+ border-radius: 2px;
5908
+ background: rgba(246, 236, 220, 0.25);
5909
+ }
5910
+
5911
+ .db-welcome-loop-progress::after {
5912
+ position: absolute;
5913
+ inset: 0;
5914
+ width: 0;
5915
+ border-radius: inherit;
5916
+ background: #e7a36d;
5917
+ content: '';
5918
+ animation: db-welcome-loop-progress 9s linear infinite both;
5919
+ animation-delay: 6s;
5920
+ }
5921
+
5922
+ .db-welcome-loop-labels {
5923
+ display: flex;
5924
+ grid-column: 3;
5925
+ justify-content: center;
5926
+ gap: 20px;
5927
+ margin: 0;
5928
+ padding: 0;
5929
+ color: var(--db-text-muted);
5930
+ font: 600 11px/1 var(--db-meta-font);
5931
+ letter-spacing: 0.08em;
5932
+ list-style: none;
5933
+ text-transform: uppercase;
5934
+ }
5935
+
5936
+ .db-welcome-loop-labels li {
5937
+ animation: db-welcome-loop-label 9s ease-in-out infinite both;
5938
+ }
5939
+
5940
+ .db-welcome-loop-labels li:nth-child(2) {
5941
+ animation-delay: 3s;
5942
+ }
5943
+
5944
+ .db-welcome-loop-labels li:nth-child(3) {
5945
+ animation-delay: 6s;
5946
+ }
5947
+
5948
+ @keyframes db-welcome-loop-frame {
5949
+ 0% {
5950
+ opacity: 0;
5951
+ transform: translateY(8px) scale(0.98);
5952
+ }
5953
+ 4%,
5954
+ 28% {
5955
+ opacity: 1;
5956
+ transform: none;
5957
+ }
5958
+ 32%,
5959
+ 100% {
5960
+ opacity: 0;
5961
+ transform: translateY(-6px) scale(0.99);
5962
+ }
5963
+ }
5964
+
5965
+ @keyframes db-welcome-loop-label {
5966
+ 0%,
5967
+ 32%,
5968
+ 100% {
5969
+ color: var(--db-text-muted);
5970
+ }
5971
+ 4%,
5972
+ 28% {
5973
+ color: var(--db-accent);
5974
+ }
5975
+ }
5976
+
5977
+ @keyframes db-welcome-loop-progress {
5978
+ 0% {
5979
+ width: 0;
5980
+ }
5981
+ 33%,
5982
+ 100% {
5983
+ width: 100%;
5984
+ }
5985
+ }
5986
+
5987
+ @keyframes db-welcome-loop-nudge {
5988
+ 0%,
5989
+ 100% {
5990
+ transform: translateX(0);
5991
+ }
5992
+ 50% {
5993
+ transform: translateX(4px);
5994
+ }
5995
+ }
5996
+
5997
+ @media (prefers-reduced-motion: reduce) {
5998
+ /* Without motion, hold on the page: the labels still name all three. */
5999
+ .db-welcome-loop-arrow,
6000
+ .db-welcome-loop-labels li {
6001
+ animation: none;
6002
+ }
6003
+
6004
+ .db-welcome-loop-frame--page {
6005
+ opacity: 1;
6006
+ animation: none;
6007
+ }
6008
+
6009
+ .db-welcome-loop-frame--slide,
6010
+ .db-welcome-loop-frame--video {
6011
+ display: none;
6012
+ }
6013
+ }
6014
+
6015
+ .db-save-toast {
6016
+ position: fixed;
6017
+ bottom: 32px;
6018
+ left: 50%;
6019
+ transform: translateX(-50%);
5643
6020
  z-index: 200;
5644
6021
  padding: 8px 16px;
5645
6022
  font-size: 13px;
@@ -6172,6 +6549,8 @@ html:has(.db-shell[data-theme='dark'])
6172
6549
 
6173
6550
  .db-text-from-narration button:not(.db-dialog-close),
6174
6551
  .db-ai-draft-dialog .db-dialog-footer button,
6552
+ .db-ai-study-dialog .db-dialog-footer button,
6553
+ .db-ai-study-saved button,
6175
6554
  .db-ai-draft-start button,
6176
6555
  .db-ai-review-panel button {
6177
6556
  min-height: var(--db-target-min);
@@ -6186,6 +6565,7 @@ html:has(.db-shell[data-theme='dark'])
6186
6565
 
6187
6566
  .db-text-from-narration .db-dialog-footer button:last-child,
6188
6567
  .db-ai-draft-dialog .db-dialog-footer button:last-child,
6568
+ .db-ai-study-dialog .db-dialog-footer button:last-child,
6189
6569
  .db-ai-draft-start button,
6190
6570
  .db-ai-review-finding-actions button:last-child,
6191
6571
  .db-ai-review-actions button {
@@ -6196,6 +6576,8 @@ html:has(.db-shell[data-theme='dark'])
6196
6576
 
6197
6577
  .db-text-from-narration button:not(.db-dialog-close):hover:not(:disabled),
6198
6578
  .db-ai-draft-dialog .db-dialog-footer button:hover:not(:disabled),
6579
+ .db-ai-study-dialog .db-dialog-footer button:hover:not(:disabled),
6580
+ .db-ai-study-saved button:hover,
6199
6581
  .db-ai-draft-start button:hover,
6200
6582
  .db-ai-review-panel button:hover:not(:disabled) {
6201
6583
  border-color: var(--db-accent-hover);
@@ -6206,6 +6588,8 @@ html:has(.db-shell[data-theme='dark'])
6206
6588
  .db-text-from-narration button:focus-visible,
6207
6589
  .db-text-from-narration textarea:focus-visible,
6208
6590
  .db-ai-draft-dialog .db-dialog-footer button:focus-visible,
6591
+ .db-ai-study-dialog .db-dialog-footer button:focus-visible,
6592
+ .db-ai-study-saved button:focus-visible,
6209
6593
  .db-ai-draft-start button:focus-visible,
6210
6594
  .db-ai-review-panel button:focus-visible {
6211
6595
  outline: 2px solid var(--db-focus);
@@ -6214,6 +6598,7 @@ html:has(.db-shell[data-theme='dark'])
6214
6598
 
6215
6599
  .db-text-from-narration button:disabled,
6216
6600
  .db-ai-draft-dialog .db-dialog-footer button:disabled,
6601
+ .db-ai-study-dialog .db-dialog-footer button:disabled,
6217
6602
  .db-ai-review-panel button:disabled {
6218
6603
  opacity: 0.5;
6219
6604
  cursor: default;
@@ -6229,7 +6614,7 @@ html:has(.db-shell[data-theme='dark'])
6229
6614
  box-sizing: border-box;
6230
6615
  overflow-y: auto;
6231
6616
  border-left: 1px solid var(--db-border-strong);
6232
- background: var(--db-bg);
6617
+ background: var(--db-bg-raised);
6233
6618
  color: var(--db-text-secondary);
6234
6619
  font: 13px/1.45 var(--db-ui-font);
6235
6620
  }
@@ -6252,7 +6637,7 @@ html:has(.db-shell[data-theme='dark'])
6252
6637
  gap: 12px;
6253
6638
  padding: 14px 14px 10px;
6254
6639
  border-bottom: 1px solid var(--db-border);
6255
- background: var(--db-bg);
6640
+ background: var(--db-bg-raised);
6256
6641
  }
6257
6642
 
6258
6643
  .db-ai-review-header h2 {
@@ -6468,6 +6853,133 @@ html:has(.db-shell[data-theme='dark'])
6468
6853
  cursor: pointer;
6469
6854
  }
6470
6855
 
6856
+ /* Report AI output: the flag beside each AI disclaimer and its dialog. */
6857
+ .db-ai-report-button {
6858
+ white-space: nowrap;
6859
+ }
6860
+
6861
+ .db-ai-report-intro {
6862
+ margin: 0 0 14px;
6863
+ color: var(--db-text-secondary);
6864
+ font-size: 13px;
6865
+ line-height: 1.5;
6866
+ }
6867
+
6868
+ .db-ai-report-dialog .db-settings-fieldset {
6869
+ margin-bottom: 14px;
6870
+ }
6871
+
6872
+ /* Study aids: Summarize document, Create quiz, Create flashcards. */
6873
+ .db-ai-study-dialog .db-dialog-header,
6874
+ .db-ai-study-dialog .db-dialog-footer {
6875
+ flex-shrink: 0;
6876
+ }
6877
+
6878
+ .db-ai-study-dialog .db-ai-study-footer {
6879
+ flex-direction: column;
6880
+ align-items: stretch;
6881
+ }
6882
+
6883
+ .db-ai-study-start,
6884
+ .db-ai-study-result,
6885
+ .db-ai-study-running {
6886
+ display: flex;
6887
+ flex-direction: column;
6888
+ gap: 10px;
6889
+ }
6890
+
6891
+ .db-ai-study-start p,
6892
+ .db-ai-study-result p,
6893
+ .db-ai-study-running p {
6894
+ margin: 0;
6895
+ }
6896
+
6897
+ /* In the full-height deck dialog the result fills the body, and the deck
6898
+ takes whatever the notes and disclaimer leave. */
6899
+ .db-ai-study-result {
6900
+ flex: 1 1 auto;
6901
+ min-height: 0;
6902
+ }
6903
+
6904
+ .db-ai-study-intro,
6905
+ .db-ai-study-stage,
6906
+ .db-ai-study-saved-title {
6907
+ color: var(--db-text);
6908
+ font-size: 13px;
6909
+ line-height: 1.5;
6910
+ }
6911
+
6912
+ .db-ai-study-stage,
6913
+ .db-ai-study-saved-title {
6914
+ font-weight: 600;
6915
+ }
6916
+
6917
+ .db-ai-study-saved {
6918
+ display: flex;
6919
+ flex-wrap: wrap;
6920
+ align-items: center;
6921
+ justify-content: space-between;
6922
+ gap: 10px 12px;
6923
+ padding: 10px 12px;
6924
+ border: 1px solid var(--db-border);
6925
+ border-radius: 6px;
6926
+ background: var(--db-bg-subtle);
6927
+ }
6928
+
6929
+ .db-ai-study-saved-text {
6930
+ display: grid;
6931
+ gap: 2px;
6932
+ min-width: 0;
6933
+ }
6934
+
6935
+ .db-ai-study-stale {
6936
+ color: var(--db-accent-deep);
6937
+ font-size: 12px;
6938
+ }
6939
+
6940
+ .db-ai-study-summary,
6941
+ .db-ai-study-deck {
6942
+ border: 1px solid var(--db-border);
6943
+ border-radius: 6px;
6944
+ background: var(--db-bg-subtle);
6945
+ }
6946
+
6947
+ .db-ai-study-summary {
6948
+ max-height: min(52dvh, 460px);
6949
+ overflow: auto;
6950
+ }
6951
+
6952
+ /* Squisq's compact deck fills the pane it is given and scrolls its own card,
6953
+ so the frame takes the height the dialog has left and hands all of it
6954
+ over. The minimum is what the deck's toolbar and a few card lines need;
6955
+ the body scrolls instead only when a short window cannot fit even that. */
6956
+ .db-ai-study-deck {
6957
+ display: flex;
6958
+ flex-direction: column;
6959
+ flex: 1 1 0;
6960
+ min-height: min(280px, 50dvh);
6961
+ overflow: hidden;
6962
+ }
6963
+
6964
+ .db-ai-study-deck > .squisq-flashcards {
6965
+ flex: 1 1 auto;
6966
+ height: auto;
6967
+ min-height: 0;
6968
+ }
6969
+
6970
+ /* The deck dialog spends its height on the deck. */
6971
+ .db-ai-study-dialog.db-dialog--full .db-ai-study-body {
6972
+ padding-block: 12px;
6973
+ }
6974
+
6975
+ .db-ai-study-meta {
6976
+ display: flex;
6977
+ flex-wrap: wrap;
6978
+ align-items: baseline;
6979
+ gap: 4px 12px;
6980
+ font-size: 12px;
6981
+ }
6982
+
6471
6983
  @media (prefers-reduced-motion: reduce) {
6472
6984
  .db-ai-spinner {
6473
6985
  animation: none;
@@ -6675,7 +7187,7 @@ html:has(.db-shell[data-theme='dark'])
6675
7187
  left: 8px;
6676
7188
  right: 8px;
6677
7189
  z-index: 100;
6678
- background: var(--db-bg);
7190
+ background: var(--db-bg-raised);
6679
7191
  border: 1px solid var(--db-border);
6680
7192
  border-radius: 6px;
6681
7193
  box-shadow: 0 4px 12px var(--db-shadow);
@@ -6884,6 +7396,91 @@ button.db-git-file-row:hover {
6884
7396
  margin: 10px 0;
6885
7397
  }
6886
7398
 
7399
+ .db-new-document-hint {
7400
+ grid-column: 2;
7401
+ margin: -4px 0 0;
7402
+ color: var(--db-text-muted);
7403
+ font-size: 12px;
7404
+ line-height: 1.4;
7405
+ }
7406
+
7407
+ /* ── Keyboard shortcut sheet ─────────────────────────────────── */
7408
+
7409
+ /* Two columns of sections on a desktop screen, so the sheet reads at a
7410
+ glance instead of scrolling; one column on narrow windows. */
7411
+ .db-dialog.db-shortcuts-dialog {
7412
+ width: 780px;
7413
+ max-height: min(calc(100dvh - 32px), 780px);
7414
+ }
7415
+
7416
+ .db-shortcuts {
7417
+ display: grid;
7418
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
7419
+ gap: 18px 32px;
7420
+ align-items: start;
7421
+ }
7422
+
7423
+ .db-shortcuts:focus-visible {
7424
+ outline: 2px solid var(--db-focus);
7425
+ outline-offset: 4px;
7426
+ }
7427
+
7428
+ .db-shortcuts-heading {
7429
+ margin: 0 0 6px;
7430
+ color: var(--db-text);
7431
+ font-size: 13px;
7432
+ font-weight: 600;
7433
+ }
7434
+
7435
+ .db-shortcuts-list {
7436
+ margin: 0;
7437
+ }
7438
+
7439
+ .db-shortcuts-row {
7440
+ display: flex;
7441
+ align-items: baseline;
7442
+ justify-content: space-between;
7443
+ gap: 12px;
7444
+ padding: 4px 0;
7445
+ border-bottom: 1px solid var(--db-border);
7446
+ }
7447
+
7448
+ .db-shortcuts-action {
7449
+ color: var(--db-text-secondary);
7450
+ font-size: 13px;
7451
+ }
7452
+
7453
+ .db-shortcuts-keys {
7454
+ display: flex;
7455
+ flex-wrap: wrap;
7456
+ align-items: baseline;
7457
+ justify-content: flex-end;
7458
+ gap: 4px;
7459
+ margin: 0;
7460
+ white-space: nowrap;
7461
+ }
7462
+
7463
+ .db-shortcuts-or {
7464
+ color: var(--db-text-muted);
7465
+ font-size: 12px;
7466
+ }
7467
+
7468
+ .db-shortcuts-chord kbd {
7469
+ display: inline-block;
7470
+ min-width: 1.6em;
7471
+ margin-left: 2px;
7472
+ padding: 1px 5px;
7473
+ border: 1px solid var(--db-border-strong);
7474
+ border-bottom-width: 2px;
7475
+ border-radius: 4px;
7476
+ background: var(--db-bg-subtle);
7477
+ color: var(--db-text);
7478
+ font: inherit;
7479
+ font-size: 12px;
7480
+ line-height: 1.4;
7481
+ text-align: center;
7482
+ }
7483
+
6887
7484
  .db-git-form-error,
6888
7485
  .db-export-error {
6889
7486
  margin: 8px 0 0;
@@ -7046,7 +7643,6 @@ button.db-git-file-row:hover {
7046
7643
  transition: none;
7047
7644
  }
7048
7645
 
7049
- .db-welcome-gateway,
7050
7646
  .db-save-toast {
7051
7647
  animation: none;
7052
7648
  }
@@ -7249,10 +7845,12 @@ button.db-git-file-row:hover {
7249
7845
  -webkit-app-region: no-drag;
7250
7846
  }
7251
7847
 
7252
- /* Folder and empty states do not render Squisq's toolbar. Preserve a top
7253
- drag strip in those states and keep folder content below it. */
7848
+ /* Folder and empty states do not render Squisq's toolbar, and the first-run
7849
+ welcome screen covers it. Preserve a top drag strip in those states and
7850
+ keep folder content below it. */
7254
7851
  .db-shell .db-shell-empty::before,
7255
- .db-shell .db-folder-view::before {
7852
+ .db-shell .db-folder-view::before,
7853
+ .db-shell .db-welcome-gateway::before {
7256
7854
  content: '';
7257
7855
  position: absolute;
7258
7856
  top: 0;
@@ -7267,6 +7865,11 @@ button.db-git-file-row:hover {
7267
7865
  box-sizing: border-box;
7268
7866
  padding-top: calc(24px + var(--db-wco-titlebar-height));
7269
7867
  }
7868
+
7869
+ /* Clear the caption buttons at the top right. */
7870
+ .db-shell .db-welcome-gateway-dismiss {
7871
+ top: calc(var(--db-wco-titlebar-height) + 8px);
7872
+ }
7270
7873
  }
7271
7874
 
7272
7875
  /* Transcript review shares the shell's dialog and theme tokens. */
@@ -7419,6 +8022,42 @@ button.db-git-file-row:hover {
7419
8022
  color: var(--db-text-muted);
7420
8023
  overflow-wrap: anywhere;
7421
8024
  }
8025
+ .db-presentation-beat-tags {
8026
+ display: flex;
8027
+ flex-wrap: wrap;
8028
+ gap: 6px;
8029
+ max-width: 100%;
8030
+ }
8031
+ /* Marks the slide a request is open for, then every slide with AI wording. */
8032
+ .db-presentation-beats small.db-presentation-beat-ai {
8033
+ display: inline-flex;
8034
+ align-items: center;
8035
+ gap: 5px;
8036
+ background: var(--db-accent-soft-12);
8037
+ color: var(--db-accent-deep);
8038
+ }
8039
+ .db-presentation-beat-ai .db-ai-spinner {
8040
+ width: 10px;
8041
+ height: 10px;
8042
+ flex-basis: 10px;
8043
+ }
8044
+ /* While slides are being suggested, this takes the Suggest button's place in
8045
+ the footer, with Stop beside it, so progress sits where the action started. */
8046
+ .db-presentation-progress {
8047
+ display: inline-flex;
8048
+ align-items: center;
8049
+ flex-wrap: wrap;
8050
+ gap: 8px;
8051
+ min-width: 0;
8052
+ min-height: var(--db-target-min);
8053
+ color: var(--db-text-secondary);
8054
+ font: 600 12px/1.2 var(--db-ui-font);
8055
+ }
8056
+ .db-presentation-progress progress {
8057
+ width: 120px;
8058
+ height: 6px;
8059
+ accent-color: var(--db-accent);
8060
+ }
7422
8061
  .db-presentation label.db-presentation-toggle {
7423
8062
  display: flex;
7424
8063
  flex-direction: row;