stilo-editor 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -2
  3. package/dist/characters--8h5uTeF.js +854 -0
  4. package/dist/content.css +398 -0
  5. package/dist/core/drop.d.ts +6 -0
  6. package/dist/core/editor.d.ts +120 -0
  7. package/dist/core/errors.d.ts +6 -0
  8. package/dist/core/events.d.ts +19 -0
  9. package/dist/core/extension-manager.d.ts +57 -0
  10. package/dist/core/extension.d.ts +48 -0
  11. package/dist/core/helpers/active.d.ts +33 -0
  12. package/dist/core/helpers/block-style.d.ts +25 -0
  13. package/dist/core/helpers/input-rules.d.ts +28 -0
  14. package/dist/core/helpers/lists.d.ts +20 -0
  15. package/dist/core/helpers/marks.d.ts +52 -0
  16. package/dist/core/helpers/nodes.d.ts +26 -0
  17. package/dist/core/helpers/parse-rules.d.ts +8 -0
  18. package/dist/core/helpers/word-count.d.ts +14 -0
  19. package/dist/core/html/css.d.ts +106 -0
  20. package/dist/core/html/parse.d.ts +7 -0
  21. package/dist/core/html/paste/base-styles.d.ts +7 -0
  22. package/dist/core/html/paste/google-docs.d.ts +7 -0
  23. package/dist/core/html/paste/index.d.ts +9 -0
  24. package/dist/core/html/paste/table-widths.d.ts +7 -0
  25. package/dist/core/html/paste/word.d.ts +8 -0
  26. package/dist/core/html/sanitize.d.ts +49 -0
  27. package/dist/core/html/serialize.d.ts +31 -0
  28. package/dist/core/types.d.ts +107 -0
  29. package/dist/extensions/blockquote/index.d.ts +15 -0
  30. package/dist/extensions/bold/index.d.ts +17 -0
  31. package/dist/extensions/bullet-list/index.d.ts +9 -0
  32. package/dist/extensions/clear-formatting/index.d.ts +12 -0
  33. package/dist/extensions/code/index.d.ts +15 -0
  34. package/dist/extensions/code-block/index.d.ts +24 -0
  35. package/dist/extensions/default-extensions/index.d.ts +57 -0
  36. package/dist/extensions/document/index.d.ts +17 -0
  37. package/dist/extensions/drop-cursor/index.d.ts +15 -0
  38. package/dist/extensions/gap-cursor/index.d.ts +6 -0
  39. package/dist/extensions/hard-break/index.d.ts +11 -0
  40. package/dist/extensions/heading/index.d.ts +25 -0
  41. package/dist/extensions/highlight/index.d.ts +24 -0
  42. package/dist/extensions/history/index.d.ts +21 -0
  43. package/dist/extensions/horizontal-rule/index.d.ts +11 -0
  44. package/dist/extensions/image/image-view.d.ts +27 -0
  45. package/dist/extensions/image/index.d.ts +29 -0
  46. package/dist/extensions/index.d.ts +36 -0
  47. package/dist/extensions/italic/index.d.ts +16 -0
  48. package/dist/extensions/line-height/index.d.ts +18 -0
  49. package/dist/extensions/link/index.d.ts +23 -0
  50. package/dist/extensions/list-item/index.d.ts +16 -0
  51. package/dist/extensions/move-block/index.d.ts +17 -0
  52. package/dist/extensions/ordered-list/index.d.ts +12 -0
  53. package/dist/extensions/paragraph/index.d.ts +14 -0
  54. package/dist/extensions/placeholder/index.d.ts +13 -0
  55. package/dist/extensions/search/index.d.ts +55 -0
  56. package/dist/extensions/strike/index.d.ts +16 -0
  57. package/dist/extensions/subscript/index.d.ts +16 -0
  58. package/dist/extensions/superscript/index.d.ts +17 -0
  59. package/dist/extensions/table/index.d.ts +70 -0
  60. package/dist/extensions/task-item/index.d.ts +24 -0
  61. package/dist/extensions/task-item/task-item-view.d.ts +24 -0
  62. package/dist/extensions/task-list/index.d.ts +11 -0
  63. package/dist/extensions/text/index.d.ts +12 -0
  64. package/dist/extensions/text-align/index.d.ts +18 -0
  65. package/dist/extensions/text-case/index.d.ts +14 -0
  66. package/dist/extensions/text-style/font-size.d.ts +21 -0
  67. package/dist/extensions/text-style/index.d.ts +30 -0
  68. package/dist/extensions/underline/index.d.ts +15 -0
  69. package/dist/index.d.ts +14 -0
  70. package/dist/index.js +1 -0
  71. package/dist/src-CV6pgfTS.js +2662 -0
  72. package/dist/style.css +1395 -0
  73. package/dist/ui/components/character-picker.d.ts +22 -0
  74. package/dist/ui/components/characters.d.ts +10 -0
  75. package/dist/ui/components/color-button.d.ts +23 -0
  76. package/dist/ui/components/dropdown.d.ts +34 -0
  77. package/dist/ui/components/find-bar.d.ts +24 -0
  78. package/dist/ui/components/font-size-input.d.ts +21 -0
  79. package/dist/ui/components/icon-menu.d.ts +20 -0
  80. package/dist/ui/components/icon.d.ts +3 -0
  81. package/dist/ui/components/link-bubble.d.ts +19 -0
  82. package/dist/ui/components/link-popover.d.ts +20 -0
  83. package/dist/ui/components/popover.d.ts +27 -0
  84. package/dist/ui/components/shortcut.d.ts +11 -0
  85. package/dist/ui/components/status-bar.d.ts +19 -0
  86. package/dist/ui/components/table-actions.d.ts +25 -0
  87. package/dist/ui/components/table-handles.d.ts +16 -0
  88. package/dist/ui/components/table-menu.d.ts +21 -0
  89. package/dist/ui/i18n/en.d.ts +3 -0
  90. package/dist/ui/i18n/it.d.ts +3 -0
  91. package/dist/ui/i18n/types.d.ts +4 -0
  92. package/dist/ui/index.d.ts +23 -0
  93. package/dist/ui/toolbar/fonts.d.ts +8 -0
  94. package/dist/ui/toolbar/items.d.ts +33 -0
  95. package/dist/ui/toolbar/palette.d.ts +6 -0
  96. package/dist/ui/toolbar/toolbar.d.ts +28 -0
  97. package/dist/ui/toolbar/types.d.ts +150 -0
  98. package/dist/ui.css +996 -0
  99. package/dist/ui.js +2350 -0
  100. package/package.json +96 -4
package/dist/style.css ADDED
@@ -0,0 +1,1395 @@
1
+ /* Stilo content styles: ProseMirror base CSS and defaults for the editable content. */
2
+
3
+ /*
4
+ * prosemirror-view/style/prosemirror.css and prosemirror-gapcursor/style/gapcursor.css.
5
+ * Copyright (C) 2015-2017 by Marijn Haverbeke and others, MIT license. Adapted to the lint
6
+ * rules: no `white-space: pre-wrap` fallback before `break-spaces`, and the separator image
7
+ * rule gains specificity instead of `!important`.
8
+ */
9
+ .ProseMirror {
10
+ position: relative;
11
+ }
12
+
13
+ .ProseMirror {
14
+ word-wrap: break-word;
15
+ white-space: break-spaces;
16
+ -webkit-font-variant-ligatures: none;
17
+ font-variant-ligatures: none;
18
+ font-feature-settings: "liga" 0; /* the above doesn't seem to work in Edge */
19
+ }
20
+
21
+ .ProseMirror pre {
22
+ white-space: pre-wrap;
23
+ }
24
+
25
+ .ProseMirror li {
26
+ position: relative;
27
+ }
28
+
29
+ .ProseMirror-hideselection *::selection {
30
+ background: transparent;
31
+ }
32
+ .ProseMirror-hideselection *::-moz-selection {
33
+ background: transparent;
34
+ }
35
+ .ProseMirror-hideselection {
36
+ caret-color: transparent;
37
+ }
38
+
39
+ /* See https://code.haverbeke.berlin/prosemirror/prosemirror/issues/1421#issuecomment-1759320191 */
40
+ .ProseMirror [draggable][contenteditable="false"] {
41
+ user-select: text;
42
+ }
43
+
44
+ .ProseMirror-selectednode {
45
+ outline: 2px solid #8cf;
46
+ }
47
+
48
+ /* Make sure li selections wrap around markers */
49
+
50
+ li.ProseMirror-selectednode {
51
+ outline: none;
52
+ }
53
+
54
+ li.ProseMirror-selectednode:after {
55
+ content: "";
56
+ position: absolute;
57
+ left: -32px;
58
+ right: -2px;
59
+ top: -2px;
60
+ bottom: -2px;
61
+ border: 2px solid #8cf;
62
+ pointer-events: none;
63
+ }
64
+
65
+ /* Protect against generic img rules */
66
+
67
+ .ProseMirror img.ProseMirror-separator {
68
+ display: inline;
69
+ border: none;
70
+ margin: 0;
71
+ }
72
+
73
+ .ProseMirror-gapcursor {
74
+ display: none;
75
+ pointer-events: none;
76
+ position: absolute;
77
+ }
78
+
79
+ .ProseMirror-gapcursor:after {
80
+ content: "";
81
+ display: block;
82
+ position: absolute;
83
+ top: -2px;
84
+ width: 20px;
85
+ border-top: 1px solid black;
86
+ animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;
87
+ }
88
+
89
+ @keyframes ProseMirror-cursor-blink {
90
+ to {
91
+ visibility: hidden;
92
+ }
93
+ }
94
+
95
+ .ProseMirror-focused .ProseMirror-gapcursor {
96
+ display: block;
97
+ }
98
+
99
+ /*
100
+ * prosemirror-tables/style/tables.css. Copyright (C) 2015-2016 by Marijn Haverbeke and others,
101
+ * MIT license. Adapted: one `cursor` value, the colors from the Stilo custom properties.
102
+ */
103
+ .ProseMirror .tableWrapper {
104
+ overflow-x: auto;
105
+ }
106
+
107
+ .ProseMirror table {
108
+ border-collapse: collapse;
109
+ table-layout: fixed;
110
+ width: 100%;
111
+ overflow: hidden;
112
+ }
113
+
114
+ .ProseMirror td,
115
+ .ProseMirror th {
116
+ vertical-align: top;
117
+ box-sizing: border-box;
118
+ position: relative;
119
+ }
120
+
121
+ .ProseMirror td:not([data-colwidth]):not(.column-resize-dragging),
122
+ .ProseMirror th:not([data-colwidth]):not(.column-resize-dragging) {
123
+ min-width: var(--default-cell-min-width);
124
+ }
125
+
126
+ .ProseMirror .column-resize-handle {
127
+ position: absolute;
128
+ right: -2px;
129
+ top: 0;
130
+ bottom: 0;
131
+ width: 4px;
132
+ z-index: 20;
133
+ background-color: var(--stilo-color-focus, #0969da);
134
+ pointer-events: none;
135
+ }
136
+
137
+ .ProseMirror.resize-cursor {
138
+ cursor: col-resize;
139
+ }
140
+
141
+ .ProseMirror .selectedCell:after {
142
+ z-index: 2;
143
+ position: absolute;
144
+ content: "";
145
+ left: 0;
146
+ right: 0;
147
+ top: 0;
148
+ bottom: 0;
149
+ background: var(--stilo-color-selected-cell, rgb(9 105 218 / 0.12));
150
+ pointer-events: none;
151
+ }
152
+
153
+ /* Stilo content defaults */
154
+
155
+ /* Lists: list items hold paragraphs, which must not add their own margins. */
156
+ .stilo-content ul,
157
+ .stilo-content ol {
158
+ margin: 0.5em 0;
159
+ padding-left: 1.75em;
160
+ }
161
+
162
+ .stilo-content li > p,
163
+ .stilo-content li > ul,
164
+ .stilo-content li > ol,
165
+ .stilo-content .stilo-task-item__content > p,
166
+ .stilo-content .stilo-task-item__content > ul,
167
+ .stilo-content .stilo-task-item__content > ol {
168
+ margin: 0;
169
+ }
170
+
171
+ /* Task lists: a checkbox in place of the bullet, done items struck through. In the editor the
172
+ item is a flex row: its <input> checkbox, then the content (ProseMirror needs a container that
173
+ holds only the content). Content shown elsewhere under the class stilo-content gets a box drawn
174
+ from data-checked instead. Either way the box is centered on the first line, not on the whole
175
+ item, which may hold more paragraphs and sub-lists. */
176
+ .stilo-content ul[data-type="taskList"] {
177
+ list-style: none;
178
+ }
179
+
180
+ .stilo-content.ProseMirror ul[data-type="taskList"] {
181
+ padding-left: 0.25em;
182
+ }
183
+
184
+ .stilo-content.ProseMirror ul[data-type="taskList"] > li {
185
+ display: flex;
186
+ gap: 0.5em;
187
+ }
188
+
189
+ .stilo-task-item__content {
190
+ flex: 1;
191
+ min-width: 0;
192
+ }
193
+
194
+ /* Form controls have their own font: inherit it, so that em and lh are those of the text. */
195
+ .stilo-task-item__checkbox {
196
+ flex: none;
197
+ width: 1em;
198
+ height: 1em;
199
+ margin: calc(0.5lh - 0.5em) 0 0;
200
+ font-size: inherit;
201
+ line-height: inherit;
202
+ accent-color: var(--stilo-color-focus, #0969da);
203
+ cursor: pointer;
204
+ }
205
+
206
+ .stilo-content:not(.ProseMirror) ul[data-type="taskList"] > li {
207
+ position: relative;
208
+ }
209
+
210
+ .stilo-content:not(.ProseMirror) ul[data-type="taskList"] > li::before {
211
+ content: "";
212
+ display: flex;
213
+ position: absolute;
214
+ top: calc(0.5lh - 0.5em);
215
+ left: -1.5em;
216
+ box-sizing: border-box;
217
+ width: 1em;
218
+ height: 1em;
219
+ align-items: center;
220
+ justify-content: center;
221
+ border: 1px solid var(--stilo-color-muted, #59636e);
222
+ border-radius: 0.2em;
223
+ color: #ffffff;
224
+ }
225
+
226
+ .stilo-content:not(.ProseMirror) ul[data-type="taskList"] > li[data-checked="true"]::before {
227
+ content: "\2713";
228
+ border-color: var(--stilo-color-focus, #0969da);
229
+ background: var(--stilo-color-focus, #0969da);
230
+ }
231
+
232
+ .stilo-content [data-checked="true"] > .stilo-task-item__content > p:first-child,
233
+ .stilo-content:not(.ProseMirror) [data-checked="true"] > p:first-child,
234
+ .stilo-content:not(.ProseMirror) [data-checked="true"]:not(:has(> p)) {
235
+ color: var(--stilo-color-muted, #59636e);
236
+ text-decoration: line-through;
237
+ }
238
+
239
+ .stilo-content blockquote {
240
+ margin: 0.5em 0;
241
+ padding-left: 1em;
242
+ border-left: 3px solid var(--stilo-color-border, #d1d9e0);
243
+ color: var(--stilo-color-muted, #59636e);
244
+ }
245
+
246
+ .stilo-content hr {
247
+ margin: 1em 0;
248
+ border: none;
249
+ border-top: 1px solid var(--stilo-color-border, #d1d9e0);
250
+ }
251
+
252
+ .stilo-content code {
253
+ padding: 0.1em 0.3em;
254
+ border-radius: 0.25em;
255
+ background: var(--stilo-color-hover, #eef1f4);
256
+ font-family: ui-monospace, monospace;
257
+ font-size: 0.9em;
258
+ }
259
+
260
+ /* Code block: the <code> inside it drops the inline code box. */
261
+ .stilo-content pre {
262
+ margin: 0.5em 0;
263
+ padding: 0.75em 1em;
264
+ border-radius: 0.375em;
265
+ background: var(--stilo-color-hover, #eef1f4);
266
+ font-family: ui-monospace, monospace;
267
+ font-size: 0.9em;
268
+ line-height: 1.5;
269
+ }
270
+
271
+ .stilo-content pre code {
272
+ padding: 0;
273
+ border-radius: 0;
274
+ background: none;
275
+ font-size: inherit;
276
+ }
277
+
278
+ /* Tables: a cell holds blocks, whose outer margins would pad the cell twice. */
279
+ .stilo-content .tableWrapper {
280
+ margin: 1em 0;
281
+ }
282
+
283
+ .stilo-content td,
284
+ .stilo-content th {
285
+ padding: 6px 8px;
286
+ border: 1px solid var(--stilo-color-border, #d1d9e0);
287
+ }
288
+
289
+ .stilo-content th {
290
+ background: var(--stilo-color-table-header, #f6f8fa);
291
+ font-weight: 600;
292
+ text-align: start;
293
+ }
294
+
295
+ .stilo-content td > :first-child,
296
+ .stilo-content th > :first-child {
297
+ margin-top: 0;
298
+ }
299
+
300
+ /* The resize handle shown on hover is the last child of its cell: the block before it is the last
301
+ block, otherwise its margin would come back and the table grow under the mouse. */
302
+ .stilo-content td > :last-child,
303
+ .stilo-content th > :last-child,
304
+ .stilo-content td > :has(+ .column-resize-handle:last-child),
305
+ .stilo-content th > :has(+ .column-resize-handle:last-child) {
306
+ margin-bottom: 0;
307
+ }
308
+
309
+ /* Images: never wider than the content; with width and height they keep their ratio. */
310
+ .stilo-content img {
311
+ max-width: 100%;
312
+ height: auto;
313
+ }
314
+
315
+ /* Image in the editor: two side handles, inside the image (a top-level block clips what
316
+ overflows it, see "Large documents" below), shown while the image is selected. Only a selected
317
+ image is positioned: a positioned element paints over the caret placed right after it. */
318
+ .stilo-image {
319
+ display: inline-block;
320
+ max-width: 100%;
321
+ }
322
+
323
+ .stilo-image.ProseMirror-selectednode {
324
+ position: relative;
325
+ }
326
+
327
+ .stilo-image img {
328
+ display: block;
329
+ }
330
+
331
+ .stilo-image__handle {
332
+ display: none;
333
+ position: absolute;
334
+ top: 50%;
335
+ width: 6px;
336
+ height: min(48px, 50%);
337
+ min-height: 16px;
338
+ transform: translateY(-50%);
339
+ border: 1px solid #ffffff;
340
+ border-radius: 3px;
341
+ background: var(--stilo-color-text, #1f2328);
342
+ opacity: 0.7;
343
+ cursor: ew-resize;
344
+ touch-action: none;
345
+ }
346
+
347
+ .stilo-image__handle--left {
348
+ left: 6px;
349
+ }
350
+
351
+ .stilo-image__handle--right {
352
+ right: 6px;
353
+ }
354
+
355
+ .stilo-content[contenteditable="true"] .stilo-image.ProseMirror-selectednode .stilo-image__handle {
356
+ display: block;
357
+ }
358
+
359
+ .stilo-image__handle:hover {
360
+ opacity: 1;
361
+ }
362
+
363
+ /* Placeholder: shown only while the content is editable. */
364
+ .stilo-content[contenteditable="true"] .stilo-placeholder::before {
365
+ content: attr(data-placeholder);
366
+ float: left;
367
+ height: 0;
368
+ color: var(--stilo-color-muted, #59636e);
369
+ pointer-events: none;
370
+ }
371
+
372
+ /*
373
+ * Large documents (ADR 0003): the browser skips style, layout and paint of the top-level blocks
374
+ * outside the viewport. Real typing in 10k paragraphs went from 144 ms to 24 ms per key (median,
375
+ * Chromium). A skipped block is 3em tall until it has been rendered once.
376
+ */
377
+ .stilo-content > * {
378
+ content-visibility: auto;
379
+ contain-intrinsic-size: auto 3em;
380
+ }
381
+
382
+ /* Containment stops margins from collapsing through a block: trim them inside a blockquote. */
383
+ .stilo-content blockquote > :first-child {
384
+ margin-top: 0;
385
+ }
386
+
387
+ .stilo-content blockquote > :last-child {
388
+ margin-bottom: 0;
389
+ }
390
+
391
+ /* Find and replace (T-043): the matches and the selected one */
392
+ .stilo-search-match {
393
+ background: var(--stilo-color-search-match, #fff1a8);
394
+ }
395
+
396
+ .stilo-search-match--current {
397
+ background: var(--stilo-color-search-current, #ffb347);
398
+ }
399
+
400
+ /* Stilo default UI styles. */
401
+
402
+ /*
403
+ * Default values of the custom properties (docs/UI.md §7). `:where()` has no specificity, so any
404
+ * rule of the host page that sets them wins, whatever the order of the stylesheets.
405
+ */
406
+ :where(:root) {
407
+ --stilo-font-family: system-ui, sans-serif;
408
+ --stilo-font-size: 14px;
409
+
410
+ --stilo-color-text: #1f2328;
411
+ --stilo-color-muted: #59636e;
412
+ --stilo-color-bg: #ffffff;
413
+ --stilo-color-toolbar-bg: #f9fbfd;
414
+ --stilo-color-border: #d1d9e0;
415
+ --stilo-color-separator: #e4e8ec;
416
+ --stilo-color-hover: #eef1f4;
417
+ --stilo-color-hover-group: #f5f7f9;
418
+ --stilo-color-active: #dde4ee;
419
+ --stilo-color-focus: #0969da;
420
+ --stilo-color-error: #d1242f;
421
+
422
+ --stilo-radius: 6px;
423
+
424
+ --stilo-toolbar-padding-x: 2px;
425
+ --stilo-toolbar-padding-y: 4px;
426
+ --stilo-toolbar-gap: 2px;
427
+ --stilo-toolbar-group-gap: 4px;
428
+ --stilo-toolbar-separator-height: 18px;
429
+ --stilo-toolbar-sticky-top: 0;
430
+ --stilo-toolbar-shadow: 0 2px 6px rgb(0 0 0 / 0.08);
431
+ --stilo-z-toolbar: 1001;
432
+
433
+ --stilo-button-size: 30px;
434
+ --stilo-icon-size: 18px;
435
+
436
+ --stilo-popover-shadow: 0 8px 24px rgb(0 0 0 / 0.12);
437
+ --stilo-z-popover: 1000;
438
+
439
+ --stilo-menu-h1-size: 1.5em;
440
+ --stilo-menu-h2-size: 1.3em;
441
+ --stilo-menu-h3-size: 1.15em;
442
+ --stilo-menu-h4-size: 1em;
443
+ --stilo-menu-h5-size: 1em;
444
+ --stilo-menu-h6-size: 1em;
445
+ }
446
+
447
+ /* Toolbar */
448
+ .stilo-toolbar {
449
+ display: flex;
450
+ flex-wrap: wrap;
451
+ gap: var(--stilo-toolbar-group-gap);
452
+ padding: var(--stilo-toolbar-padding-y) var(--stilo-toolbar-padding-x);
453
+ background: var(--stilo-color-toolbar-bg);
454
+ }
455
+
456
+ /*
457
+ * The toolbar and its sticky container have a background: their top corners follow the element
458
+ * that holds them, so that a rounded editor box keeps its corners (no `overflow` on the host,
459
+ * which would cut the popovers).
460
+ */
461
+ .stilo-toolbar-host,
462
+ .stilo-toolbar {
463
+ border-top-left-radius: inherit;
464
+ border-top-right-radius: inherit;
465
+ }
466
+
467
+ /* Sticky toolbar container (option `sticky`) */
468
+ .stilo-toolbar-host {
469
+ position: sticky;
470
+ top: var(--stilo-toolbar-sticky-top);
471
+ z-index: var(--stilo-z-toolbar);
472
+ background: var(--stilo-color-bg);
473
+ container-type: scroll-state;
474
+ }
475
+
476
+ /*
477
+ * A shadow while the toolbar is stuck at the top of the scrolling page. Pure CSS: browsers
478
+ * without scroll-state container queries ignore it and show the toolbar without shadow.
479
+ */
480
+ @container scroll-state(stuck: top) {
481
+ .stilo-toolbar {
482
+ box-shadow: var(--stilo-toolbar-shadow);
483
+ }
484
+ }
485
+
486
+ /* Group */
487
+ .stilo-toolbar__group {
488
+ display: flex;
489
+ gap: var(--stilo-toolbar-gap);
490
+ }
491
+
492
+ /* Separator: a short line, vertically centered, before every group after the first */
493
+ .stilo-toolbar__group:not(:first-child) {
494
+ position: relative;
495
+ padding-left: var(--stilo-toolbar-group-gap);
496
+ }
497
+
498
+ .stilo-toolbar__group:not(:first-child)::before {
499
+ content: "";
500
+ position: absolute;
501
+ top: 50%;
502
+ left: 0;
503
+ width: 1px;
504
+ height: var(--stilo-toolbar-separator-height);
505
+ background: var(--stilo-color-separator);
506
+ transform: translateY(-50%);
507
+ }
508
+
509
+ /* Button */
510
+ .stilo-toolbar__button {
511
+ display: flex;
512
+ align-items: center;
513
+ justify-content: center;
514
+ width: var(--stilo-button-size);
515
+ min-width: var(--stilo-button-size);
516
+ height: var(--stilo-button-size);
517
+ border: none;
518
+ border-radius: var(--stilo-radius);
519
+ background: transparent;
520
+ color: var(--stilo-color-text);
521
+ cursor: pointer;
522
+ font-family: var(--stilo-font-family);
523
+ font-size: var(--stilo-font-size);
524
+ padding: 0;
525
+ margin: 0;
526
+ transition: background-color 0.15s;
527
+ }
528
+
529
+ .stilo-toolbar__button:hover {
530
+ background: var(--stilo-color-hover);
531
+ }
532
+
533
+ .stilo-toolbar__button:focus-visible {
534
+ outline: 2px solid var(--stilo-color-focus);
535
+ outline-offset: 2px;
536
+ }
537
+
538
+ .stilo-toolbar__button.stilo-toolbar__button--active {
539
+ background: var(--stilo-color-active);
540
+ }
541
+
542
+ /* The find button while its bar is open (T-043) */
543
+ .stilo-toolbar__button[data-item="find"][aria-expanded="true"] {
544
+ background: var(--stilo-color-active);
545
+ }
546
+
547
+ .stilo-toolbar__button[aria-disabled="true"] {
548
+ opacity: 0.4;
549
+ cursor: default;
550
+ }
551
+
552
+ .stilo-toolbar__button[aria-disabled="true"]:hover {
553
+ background: transparent;
554
+ }
555
+
556
+ /* Icon */
557
+ .stilo-icon {
558
+ width: var(--stilo-icon-size);
559
+ height: var(--stilo-icon-size);
560
+ color: var(--stilo-color-text);
561
+ }
562
+
563
+ /* Popover */
564
+ .stilo-popover-host {
565
+ position: relative;
566
+ }
567
+
568
+ .stilo-popover {
569
+ position: absolute;
570
+ top: 0;
571
+ left: 0;
572
+ width: max-content;
573
+ background: var(--stilo-color-bg);
574
+ border: 1px solid var(--stilo-color-border);
575
+ border-radius: var(--stilo-radius);
576
+ box-shadow: var(--stilo-popover-shadow);
577
+ z-index: var(--stilo-z-popover);
578
+ padding: 4px;
579
+ }
580
+
581
+ /* A component class with its own `display` must not show a closed popover. */
582
+ .stilo-popover[hidden] {
583
+ display: none;
584
+ }
585
+
586
+ /* Dropdown */
587
+ .stilo-dropdown__trigger {
588
+ width: auto;
589
+ min-width: 120px;
590
+ justify-content: space-between;
591
+ gap: 6px;
592
+ padding: 0 8px;
593
+ }
594
+
595
+ .stilo-dropdown__trigger[data-item="fontFamily"] {
596
+ width: 120px;
597
+ }
598
+
599
+ /* A long value is truncated, the chevron keeps its size */
600
+ .stilo-dropdown__trigger .stilo-icon {
601
+ flex-shrink: 0;
602
+ }
603
+
604
+ .stilo-dropdown__value {
605
+ overflow: hidden;
606
+ text-overflow: ellipsis;
607
+ white-space: nowrap;
608
+ font-weight: 600;
609
+ }
610
+
611
+ .stilo-dropdown__menu {
612
+ min-width: 160px;
613
+ }
614
+
615
+ .stilo-dropdown__option {
616
+ display: flex;
617
+ align-items: center;
618
+ gap: 8px;
619
+ padding: 6px 8px;
620
+ border-radius: var(--stilo-radius);
621
+ cursor: pointer;
622
+ font-family: var(--stilo-font-family);
623
+ font-size: var(--stilo-font-size);
624
+ color: var(--stilo-color-text);
625
+ }
626
+
627
+ .stilo-dropdown__option:hover,
628
+ .stilo-dropdown__option:focus-visible {
629
+ background: var(--stilo-color-hover);
630
+ }
631
+
632
+ .stilo-dropdown__option:focus-visible {
633
+ outline: 2px solid var(--stilo-color-focus);
634
+ outline-offset: -2px;
635
+ }
636
+
637
+ .stilo-dropdown__option[aria-checked="true"] {
638
+ background: var(--stilo-color-active);
639
+ }
640
+
641
+ .stilo-dropdown__option[aria-disabled="true"] {
642
+ opacity: 0.4;
643
+ cursor: default;
644
+ }
645
+
646
+ .stilo-dropdown__option[aria-disabled="true"]:hover {
647
+ background: transparent;
648
+ }
649
+
650
+ .stilo-dropdown__label {
651
+ flex: 1;
652
+ }
653
+
654
+ .stilo-dropdown__shortcut {
655
+ font-size: 0.85em;
656
+ color: var(--stilo-color-muted);
657
+ }
658
+
659
+ /* Heading preview */
660
+ .stilo-dropdown__option--h1 .stilo-dropdown__label {
661
+ font-size: var(--stilo-menu-h1-size);
662
+ font-weight: 600;
663
+ }
664
+
665
+ .stilo-dropdown__option--h2 .stilo-dropdown__label {
666
+ font-size: var(--stilo-menu-h2-size);
667
+ font-weight: 600;
668
+ }
669
+
670
+ .stilo-dropdown__option--h3 .stilo-dropdown__label {
671
+ font-size: var(--stilo-menu-h3-size);
672
+ font-weight: 600;
673
+ }
674
+
675
+ .stilo-dropdown__option--h4 .stilo-dropdown__label {
676
+ font-size: var(--stilo-menu-h4-size);
677
+ font-weight: 600;
678
+ }
679
+
680
+ .stilo-dropdown__option--h5 .stilo-dropdown__label {
681
+ font-size: var(--stilo-menu-h5-size);
682
+ font-weight: 600;
683
+ }
684
+
685
+ .stilo-dropdown__option--h6 .stilo-dropdown__label {
686
+ font-size: var(--stilo-menu-h6-size);
687
+ font-weight: 600;
688
+ }
689
+
690
+ /* Font size control: − field + */
691
+ .stilo-font-size {
692
+ display: inline-flex;
693
+ align-items: center;
694
+ gap: var(--stilo-toolbar-gap);
695
+ }
696
+
697
+ .stilo-font-size__input {
698
+ box-sizing: border-box;
699
+ width: 2.5em;
700
+ height: calc(var(--stilo-button-size) - 4px);
701
+ padding: 0 4px;
702
+ border: 1px solid var(--stilo-color-border);
703
+ border-radius: var(--stilo-radius);
704
+ background: var(--stilo-color-bg);
705
+ color: var(--stilo-color-text);
706
+ font-family: var(--stilo-font-family);
707
+ font-size: var(--stilo-font-size);
708
+ text-align: center;
709
+ font-weight: 600;
710
+ }
711
+
712
+ .stilo-font-size__input:focus-visible {
713
+ outline: 2px solid var(--stilo-color-focus);
714
+ outline-offset: -1px;
715
+ }
716
+
717
+ .stilo-font-size__input[aria-invalid="true"] {
718
+ border-color: var(--stilo-color-error);
719
+ }
720
+
721
+ .stilo-font-size__input[aria-disabled="true"] {
722
+ opacity: 0.4;
723
+ }
724
+
725
+ .stilo-font-size__list {
726
+ min-width: 4.5em;
727
+ max-height: 280px;
728
+ overflow-y: auto;
729
+ }
730
+
731
+ .stilo-font-size__option {
732
+ padding: 4px 12px;
733
+ border-radius: var(--stilo-radius);
734
+ cursor: pointer;
735
+ font-family: var(--stilo-font-family);
736
+ font-size: var(--stilo-font-size);
737
+ color: var(--stilo-color-text);
738
+ text-align: center;
739
+ }
740
+
741
+ .stilo-font-size__option:hover,
742
+ .stilo-font-size__option--active {
743
+ background: var(--stilo-color-hover);
744
+ }
745
+
746
+ .stilo-font-size__option[aria-selected="true"] {
747
+ background: var(--stilo-color-active);
748
+ }
749
+
750
+ /* Icon menu (text alignment): the options in a row. An icon dropdown (line spacing) has the same
751
+ trigger. */
752
+ .stilo-icon-menu__trigger,
753
+ .stilo-dropdown__trigger--icon {
754
+ width: auto;
755
+ min-width: var(--stilo-button-size);
756
+ gap: 2px;
757
+ padding: 0 4px;
758
+ }
759
+
760
+ .stilo-icon-menu {
761
+ display: flex;
762
+ gap: var(--stilo-toolbar-gap);
763
+ }
764
+
765
+ .stilo-icon-menu__trigger .stilo-icon:last-child,
766
+ .stilo-dropdown__trigger--icon .stilo-icon:last-child {
767
+ width: 12px;
768
+ height: 12px;
769
+ }
770
+
771
+ /* Link popover */
772
+ .stilo-link-popover__form {
773
+ display: flex;
774
+ flex-wrap: wrap;
775
+ align-items: center;
776
+ gap: 8px;
777
+ width: 320px;
778
+ padding: 4px;
779
+ font-family: var(--stilo-font-family);
780
+ font-size: var(--stilo-font-size);
781
+ color: var(--stilo-color-text);
782
+ }
783
+
784
+ .stilo-link-popover__url {
785
+ flex: 1 1 100%;
786
+ box-sizing: border-box;
787
+ padding: 6px 8px;
788
+ border: 1px solid var(--stilo-color-border);
789
+ border-radius: var(--stilo-radius);
790
+ background: var(--stilo-color-bg);
791
+ color: inherit;
792
+ font: inherit;
793
+ }
794
+
795
+ .stilo-link-popover__url:focus-visible {
796
+ outline: 2px solid var(--stilo-color-focus);
797
+ outline-offset: -1px;
798
+ }
799
+
800
+ .stilo-link-popover__url[aria-invalid="true"] {
801
+ border-color: var(--stilo-color-error);
802
+ }
803
+
804
+ .stilo-link-popover__new-tab {
805
+ display: flex;
806
+ flex: 1;
807
+ align-items: center;
808
+ gap: 6px;
809
+ cursor: pointer;
810
+ }
811
+
812
+ .stilo-link-popover__actions {
813
+ display: flex;
814
+ gap: 4px;
815
+ }
816
+
817
+ .stilo-link-popover__button {
818
+ padding: 4px 10px;
819
+ border: 1px solid var(--stilo-color-border);
820
+ border-radius: var(--stilo-radius);
821
+ background: var(--stilo-color-bg);
822
+ color: inherit;
823
+ cursor: pointer;
824
+ font: inherit;
825
+ }
826
+
827
+ .stilo-link-popover__button:hover {
828
+ background: var(--stilo-color-hover);
829
+ }
830
+
831
+ .stilo-link-popover__button:focus-visible {
832
+ outline: 2px solid var(--stilo-color-focus);
833
+ outline-offset: 1px;
834
+ }
835
+
836
+ .stilo-link-popover__button--primary,
837
+ .stilo-link-popover__button--primary:hover {
838
+ border-color: var(--stilo-color-focus);
839
+ background: var(--stilo-color-focus);
840
+ color: #ffffff;
841
+ }
842
+
843
+ /* Link bubble: small and unobtrusive */
844
+ .stilo-link-bubble {
845
+ display: flex;
846
+ gap: 1px;
847
+ padding: 2px;
848
+ }
849
+
850
+ .stilo-link-bubble__button {
851
+ display: flex;
852
+ align-items: center;
853
+ justify-content: center;
854
+ width: 24px;
855
+ height: 24px;
856
+ padding: 0;
857
+ border: none;
858
+ border-radius: var(--stilo-radius);
859
+ background: transparent;
860
+ color: var(--stilo-color-text);
861
+ cursor: pointer;
862
+ }
863
+
864
+ .stilo-link-bubble__button:hover {
865
+ background: var(--stilo-color-hover);
866
+ }
867
+
868
+ .stilo-link-bubble__button .stilo-icon {
869
+ width: 16px;
870
+ height: 16px;
871
+ }
872
+
873
+ /* Character picker: 10 columns (COLUMNS in character-picker.ts) */
874
+ .stilo-char-picker {
875
+ display: flex;
876
+ flex-direction: column;
877
+ gap: 4px;
878
+ font-family: var(--stilo-font-family);
879
+ font-size: var(--stilo-font-size);
880
+ color: var(--stilo-color-text);
881
+ }
882
+
883
+ .stilo-char-picker__search {
884
+ padding: 6px 8px;
885
+ border: 1px solid var(--stilo-color-border);
886
+ border-radius: var(--stilo-radius);
887
+ font: inherit;
888
+ }
889
+
890
+ .stilo-char-picker__search:focus-visible,
891
+ .stilo-char-picker__tab:focus-visible,
892
+ .stilo-char-picker__char:focus-visible {
893
+ outline: 2px solid var(--stilo-color-focus);
894
+ outline-offset: -2px;
895
+ }
896
+
897
+ .stilo-char-picker__tabs {
898
+ display: flex;
899
+ gap: 4px;
900
+ border-bottom: 1px solid var(--stilo-color-border);
901
+ }
902
+
903
+ .stilo-char-picker__tabs[hidden] {
904
+ display: none;
905
+ }
906
+
907
+ .stilo-char-picker__tab {
908
+ padding: 6px 10px;
909
+ border: none;
910
+ border-bottom: 2px solid transparent;
911
+ background: transparent;
912
+ color: var(--stilo-color-muted);
913
+ font: inherit;
914
+ cursor: pointer;
915
+ }
916
+
917
+ .stilo-char-picker__tab[aria-selected="true"] {
918
+ border-bottom-color: var(--stilo-color-focus);
919
+ color: var(--stilo-color-text);
920
+ }
921
+
922
+ .stilo-char-picker__panel {
923
+ max-height: 280px;
924
+ overflow-y: auto;
925
+ }
926
+
927
+ .stilo-char-picker__heading {
928
+ margin: 8px 0 4px;
929
+ color: var(--stilo-color-muted);
930
+ font-size: 0.85em;
931
+ }
932
+
933
+ .stilo-char-picker__grid {
934
+ display: grid;
935
+ grid-template-columns: repeat(10, 32px);
936
+ gap: 2px;
937
+ }
938
+
939
+ .stilo-char-picker__char {
940
+ width: 32px;
941
+ height: 32px;
942
+ padding: 0;
943
+ border: none;
944
+ border-radius: var(--stilo-radius);
945
+ background: transparent;
946
+ color: inherit;
947
+ font-size: 18px;
948
+ line-height: 1;
949
+ cursor: pointer;
950
+ }
951
+
952
+ .stilo-char-picker__char:hover {
953
+ background: var(--stilo-color-hover);
954
+ }
955
+
956
+ .stilo-char-picker__empty {
957
+ margin: 8px 0;
958
+ color: var(--stilo-color-muted);
959
+ }
960
+
961
+ /* Table menu (T-045): insert grid of 10 columns (GRID_COLUMNS in table-menu.ts), operations */
962
+ .stilo-table-menu {
963
+ font-family: var(--stilo-font-family);
964
+ font-size: var(--stilo-font-size);
965
+ color: var(--stilo-color-text);
966
+ }
967
+
968
+ .stilo-table-menu__picker {
969
+ display: flex;
970
+ flex-direction: column;
971
+ gap: 6px;
972
+ padding: 4px;
973
+ }
974
+
975
+ .stilo-table-menu__picker[hidden],
976
+ .stilo-table-menu__actions[hidden] {
977
+ display: none;
978
+ }
979
+
980
+ .stilo-table-menu__grid {
981
+ display: grid;
982
+ grid-template-columns: repeat(10, 18px);
983
+ gap: 3px;
984
+ }
985
+
986
+ .stilo-table-menu__cell {
987
+ width: 18px;
988
+ height: 18px;
989
+ padding: 0;
990
+ border: 1px solid var(--stilo-color-border);
991
+ border-radius: 3px;
992
+ background: var(--stilo-color-bg);
993
+ cursor: pointer;
994
+ }
995
+
996
+ .stilo-table-menu__cell--active {
997
+ border-color: var(--stilo-color-focus);
998
+ background: var(--stilo-color-active);
999
+ }
1000
+
1001
+ .stilo-table-menu__cell:focus-visible {
1002
+ outline: 2px solid var(--stilo-color-focus);
1003
+ outline-offset: 1px;
1004
+ }
1005
+
1006
+ .stilo-table-menu__size {
1007
+ text-align: center;
1008
+ color: var(--stilo-color-muted);
1009
+ }
1010
+
1011
+ .stilo-table-menu__header {
1012
+ display: flex;
1013
+ align-items: center;
1014
+ gap: 6px;
1015
+ cursor: pointer;
1016
+ }
1017
+
1018
+ .stilo-table-menu__actions {
1019
+ min-width: 200px;
1020
+ }
1021
+
1022
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked] {
1023
+ background: transparent;
1024
+ }
1025
+
1026
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked]:hover,
1027
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked]:focus-visible {
1028
+ background: var(--stilo-color-hover);
1029
+ }
1030
+
1031
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked]::after {
1032
+ content: "✓";
1033
+ margin-left: auto;
1034
+ visibility: hidden;
1035
+ }
1036
+
1037
+ .stilo-table-menu__actions .stilo-dropdown__option[aria-checked="true"]::after {
1038
+ visibility: visible;
1039
+ }
1040
+
1041
+ /* Table handles (T-049): row, column and corner, over the editor */
1042
+ .stilo-table-handle {
1043
+ position: absolute;
1044
+ top: 0;
1045
+ left: 0;
1046
+ z-index: var(--stilo-z-popover);
1047
+ display: flex;
1048
+ align-items: center;
1049
+ justify-content: center;
1050
+ width: 18px;
1051
+ height: 18px;
1052
+ padding: 0;
1053
+ border: 1px solid var(--stilo-color-border);
1054
+ border-radius: var(--stilo-radius);
1055
+ background: var(--stilo-color-bg);
1056
+ color: var(--stilo-color-muted);
1057
+ cursor: pointer;
1058
+ }
1059
+
1060
+ .stilo-table-handle[hidden] {
1061
+ display: none;
1062
+ }
1063
+
1064
+ .stilo-table-handle:hover,
1065
+ .stilo-table-handle[aria-expanded="true"] {
1066
+ border-color: var(--stilo-color-focus);
1067
+ color: var(--stilo-color-focus);
1068
+ }
1069
+
1070
+ .stilo-table-handle .stilo-icon {
1071
+ width: 14px;
1072
+ height: 14px;
1073
+ }
1074
+
1075
+ .stilo-table-handle-menu {
1076
+ font-family: var(--stilo-font-family);
1077
+ font-size: var(--stilo-font-size);
1078
+ color: var(--stilo-color-text);
1079
+ }
1080
+
1081
+ .stilo-table-menu__separator {
1082
+ height: 1px;
1083
+ margin: 4px 0;
1084
+ background: var(--stilo-color-separator);
1085
+ }
1086
+
1087
+ /* Color split button (T-026): the main part shows the last used color under its icon */
1088
+ .stilo-split {
1089
+ display: flex;
1090
+ }
1091
+
1092
+ /* Group hover: hovering one part lightly highlights both; the hovered part stays darker */
1093
+ .stilo-split:hover
1094
+ .stilo-toolbar__button:not(.stilo-toolbar__button--active, [aria-disabled="true"]) {
1095
+ background: var(--stilo-color-hover-group);
1096
+ }
1097
+
1098
+ .stilo-split
1099
+ .stilo-toolbar__button:not(.stilo-toolbar__button--active, [aria-disabled="true"]):hover {
1100
+ background: var(--stilo-color-hover);
1101
+ }
1102
+
1103
+ .stilo-toolbar__button.stilo-split__main {
1104
+ flex-direction: column;
1105
+ gap: 1px;
1106
+ border-top-right-radius: 0;
1107
+ border-bottom-right-radius: 0;
1108
+ }
1109
+
1110
+ .stilo-split__main .stilo-icon {
1111
+ width: 16px;
1112
+ height: 16px;
1113
+ }
1114
+
1115
+ .stilo-split__color {
1116
+ width: 16px;
1117
+ height: 4px;
1118
+ border-radius: 1px;
1119
+ box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.15);
1120
+ }
1121
+
1122
+ .stilo-toolbar__button.stilo-split__arrow {
1123
+ width: 20px;
1124
+ min-width: 20px;
1125
+ border-top-left-radius: 0;
1126
+ border-bottom-left-radius: 0;
1127
+ }
1128
+
1129
+ .stilo-split__arrow .stilo-icon {
1130
+ width: 12px;
1131
+ height: 12px;
1132
+ }
1133
+
1134
+ /* Color picker: 8 columns (COLUMNS in color-button.ts) */
1135
+ .stilo-color-picker {
1136
+ display: flex;
1137
+ flex-direction: column;
1138
+ gap: 6px;
1139
+ padding: 4px;
1140
+ font-family: var(--stilo-font-family);
1141
+ font-size: var(--stilo-font-size);
1142
+ color: var(--stilo-color-text);
1143
+ }
1144
+
1145
+ .stilo-color-picker__actions {
1146
+ display: flex;
1147
+ align-items: center;
1148
+ gap: 6px;
1149
+ }
1150
+
1151
+ .stilo-color-picker__none,
1152
+ .stilo-color-picker__default {
1153
+ flex: 1;
1154
+ padding: 4px 8px;
1155
+ border: none;
1156
+ border-radius: var(--stilo-radius);
1157
+ background: transparent;
1158
+ color: inherit;
1159
+ font: inherit;
1160
+ text-align: center;
1161
+ cursor: pointer;
1162
+ }
1163
+
1164
+ .stilo-color-picker__none:hover,
1165
+ .stilo-color-picker__default:hover {
1166
+ background: var(--stilo-color-hover);
1167
+ }
1168
+
1169
+ .stilo-color-picker__default[aria-pressed="true"] {
1170
+ background: var(--stilo-color-active);
1171
+ }
1172
+
1173
+ .stilo-color-picker__default mark {
1174
+ padding: 0 4px;
1175
+ border-radius: 2px;
1176
+ }
1177
+
1178
+ .stilo-color-picker__separator {
1179
+ width: 1px;
1180
+ height: 18px;
1181
+ background: var(--stilo-color-separator);
1182
+ }
1183
+
1184
+ .stilo-color-picker__grid {
1185
+ display: grid;
1186
+ grid-template-columns: repeat(8, 22px);
1187
+ gap: 4px;
1188
+ }
1189
+
1190
+ .stilo-color-picker__swatch {
1191
+ width: 22px;
1192
+ height: 22px;
1193
+ padding: 0;
1194
+ border: none;
1195
+ border-radius: 4px;
1196
+ box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.15);
1197
+ cursor: pointer;
1198
+ }
1199
+
1200
+ .stilo-color-picker__swatch:hover {
1201
+ transform: scale(1.15);
1202
+ }
1203
+
1204
+ .stilo-color-picker__swatch[aria-pressed="true"] {
1205
+ outline: 2px solid var(--stilo-color-text);
1206
+ outline-offset: 1px;
1207
+ }
1208
+
1209
+ .stilo-color-picker__none:focus-visible,
1210
+ .stilo-color-picker__default:focus-visible,
1211
+ .stilo-color-picker__swatch:focus-visible,
1212
+ .stilo-color-picker__value:focus-visible,
1213
+ .stilo-color-picker__native:focus-visible,
1214
+ .stilo-color-picker__apply:focus-visible {
1215
+ outline: 2px solid var(--stilo-color-focus);
1216
+ outline-offset: 1px;
1217
+ }
1218
+
1219
+ .stilo-color-picker__custom {
1220
+ display: flex;
1221
+ gap: 4px;
1222
+ align-items: center;
1223
+ margin: 0;
1224
+ }
1225
+
1226
+ .stilo-color-picker__native {
1227
+ width: 32px;
1228
+ height: 28px;
1229
+ padding: 0;
1230
+ border: 1px solid var(--stilo-color-border);
1231
+ border-radius: var(--stilo-radius);
1232
+ background: var(--stilo-color-bg);
1233
+ cursor: pointer;
1234
+ }
1235
+
1236
+ .stilo-color-picker__value {
1237
+ flex: 1;
1238
+ min-width: 0;
1239
+ padding: 4px 8px;
1240
+ border: 1px solid var(--stilo-color-border);
1241
+ border-radius: var(--stilo-radius);
1242
+ font: inherit;
1243
+ }
1244
+
1245
+ .stilo-color-picker__value[aria-invalid="true"] {
1246
+ border-color: var(--stilo-color-error);
1247
+ }
1248
+
1249
+ .stilo-color-picker__apply {
1250
+ padding: 4px 10px;
1251
+ border: 1px solid var(--stilo-color-focus);
1252
+ border-radius: var(--stilo-radius);
1253
+ background: var(--stilo-color-focus);
1254
+ color: #ffffff;
1255
+ font: inherit;
1256
+ cursor: pointer;
1257
+ }
1258
+
1259
+ /*
1260
+ * Find bar (T-043): a floating panel at the top right, just under the toolbar, over the content
1261
+ * (the content does not move). It lives in the toolbar container, so it stays at the top with a
1262
+ * sticky toolbar; without `sticky` the container is made a positioned ancestor.
1263
+ */
1264
+ .stilo-find-bar-host:not(.stilo-toolbar-host) {
1265
+ position: relative;
1266
+ }
1267
+
1268
+ .stilo-find-bar {
1269
+ position: absolute;
1270
+ top: calc(100% + 4px);
1271
+ right: 8px;
1272
+ /* Under the popovers of the toolbar (character picker, colors, menus), which open over it. */
1273
+ z-index: calc(var(--stilo-z-popover) - 1);
1274
+ box-sizing: border-box;
1275
+ display: flex;
1276
+ flex-direction: column;
1277
+ gap: 4px;
1278
+ max-width: calc(100% - 16px);
1279
+ padding: 6px 8px;
1280
+ border: 1px solid var(--stilo-color-border);
1281
+ border-radius: var(--stilo-radius);
1282
+ background: var(--stilo-color-bg);
1283
+ box-shadow: var(--stilo-popover-shadow);
1284
+ color: var(--stilo-color-text);
1285
+ font-family: var(--stilo-font-family);
1286
+ font-size: var(--stilo-font-size);
1287
+ transition:
1288
+ opacity 0.15s ease,
1289
+ transform 0.15s ease,
1290
+ display 0.15s allow-discrete;
1291
+ }
1292
+
1293
+ /* Slides in from above; browsers without @starting-style show it at once. */
1294
+ @starting-style {
1295
+ .stilo-find-bar {
1296
+ opacity: 0;
1297
+ transform: translateY(-6px);
1298
+ }
1299
+ }
1300
+
1301
+ @media (prefers-reduced-motion: reduce) {
1302
+ .stilo-find-bar {
1303
+ transition: none;
1304
+ }
1305
+ }
1306
+
1307
+ .stilo-find-bar__row {
1308
+ display: flex;
1309
+ align-items: center;
1310
+ gap: 4px;
1311
+ }
1312
+
1313
+ .stilo-find-bar[hidden] {
1314
+ display: none;
1315
+ opacity: 0;
1316
+ transform: translateY(-6px);
1317
+ }
1318
+
1319
+ .stilo-find-bar__row[hidden] {
1320
+ display: none;
1321
+ }
1322
+
1323
+ .stilo-find-bar__input {
1324
+ box-sizing: border-box;
1325
+ width: 200px;
1326
+ min-width: 0;
1327
+ flex: 1 1 auto;
1328
+ padding: 4px 8px;
1329
+ border: 1px solid var(--stilo-color-border);
1330
+ border-radius: var(--stilo-radius);
1331
+ background: var(--stilo-color-bg);
1332
+ color: inherit;
1333
+ font: inherit;
1334
+ }
1335
+
1336
+ .stilo-find-bar__input:focus-visible {
1337
+ outline: 2px solid var(--stilo-color-focus);
1338
+ outline-offset: -1px;
1339
+ }
1340
+
1341
+ .stilo-find-bar__count {
1342
+ min-width: 7em;
1343
+ color: var(--stilo-color-muted);
1344
+ font-size: 0.9em;
1345
+ white-space: nowrap;
1346
+ }
1347
+
1348
+ .stilo-find-bar__button {
1349
+ display: flex;
1350
+ align-items: center;
1351
+ justify-content: center;
1352
+ min-width: 28px;
1353
+ height: 28px;
1354
+ padding: 0;
1355
+ border: none;
1356
+ border-radius: var(--stilo-radius);
1357
+ background: transparent;
1358
+ color: inherit;
1359
+ cursor: pointer;
1360
+ font: inherit;
1361
+ }
1362
+
1363
+ .stilo-find-bar__button:hover {
1364
+ background: var(--stilo-color-hover);
1365
+ }
1366
+
1367
+ .stilo-find-bar__button:focus-visible {
1368
+ outline: 2px solid var(--stilo-color-focus);
1369
+ outline-offset: 1px;
1370
+ }
1371
+
1372
+ .stilo-find-bar__toggle[aria-pressed="true"] {
1373
+ background: var(--stilo-color-active);
1374
+ }
1375
+
1376
+ .stilo-find-bar__button--text {
1377
+ padding: 0 10px;
1378
+ white-space: nowrap;
1379
+ border: 1px solid var(--stilo-color-border);
1380
+ background: var(--stilo-color-bg);
1381
+ }
1382
+
1383
+ /* Status bar (T-043): word and character count under the editor */
1384
+ .stilo-status-bar {
1385
+ display: flex;
1386
+ gap: 16px;
1387
+ padding: 4px 12px;
1388
+ border-top: 1px solid var(--stilo-color-separator);
1389
+ border-bottom-left-radius: inherit;
1390
+ border-bottom-right-radius: inherit;
1391
+ background: var(--stilo-color-toolbar-bg);
1392
+ color: var(--stilo-color-muted);
1393
+ font-family: var(--stilo-font-family);
1394
+ font-size: 12px;
1395
+ }