@vscode/markdown-editor 0.0.2-14 → 0.0.2-140

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 (79) hide show
  1. package/README.md +663 -0
  2. package/dist/commands.d.ts +67 -0
  3. package/dist/commands.js +185 -0
  4. package/dist/commands.js.map +1 -0
  5. package/dist/config-BGeaJqWk.js +286 -0
  6. package/dist/config-BGeaJqWk.js.map +1 -0
  7. package/dist/config.d.ts +10 -0
  8. package/dist/config.js +6 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/index.d.ts +1615 -270
  11. package/dist/index.js +7845 -3291
  12. package/dist/index.js.map +1 -1
  13. package/dist/markdown-editor.css +1 -1
  14. package/dist/scrolling-C4GW1cCQ.js +391 -0
  15. package/dist/scrolling-C4GW1cCQ.js.map +1 -0
  16. package/dist/web-editors.d.ts +357 -0
  17. package/dist/web-editors.js +7597 -0
  18. package/dist/web-editors.js.map +1 -0
  19. package/package.json +60 -20
  20. package/src/contrib/comments/commentInput.css +38 -80
  21. package/src/contrib/comments/commentWidget.css +60 -0
  22. package/src/contrib/find/find.css +347 -0
  23. package/src/contrib/rename/rename.css +73 -0
  24. package/src/contrib/suggest/suggest.css +109 -0
  25. package/src/view/editor.css +1702 -111
  26. package/src/view/themes/default.css +21 -4
  27. package/src/view/themes/github.css +25 -13
  28. package/src/view/themes/vscode-default.css +98 -23
  29. package/src/view/themes/vscode-github.css +84 -15
  30. package/dist/_observables/assert.d.ts +0 -2
  31. package/dist/_observables/deps.d.ts +0 -28
  32. package/dist/_observables/disposables.d.ts +0 -19
  33. package/dist/_observables/equals.d.ts +0 -32
  34. package/dist/_observables/index.d.ts +0 -2
  35. package/dist/_observables/observableInternal/base.d.ts +0 -172
  36. package/dist/_observables/observableInternal/changeTracker.d.ts +0 -44
  37. package/dist/_observables/observableInternal/commonFacade/cancellation.d.ts +0 -24
  38. package/dist/_observables/observableInternal/commonFacade/deps.d.ts +0 -24
  39. package/dist/_observables/observableInternal/debugLocation.d.ts +0 -21
  40. package/dist/_observables/observableInternal/debugName.d.ts +0 -33
  41. package/dist/_observables/observableInternal/experimental/deferUnobserve.d.ts +0 -16
  42. package/dist/_observables/observableInternal/experimental/reducer.d.ts +0 -37
  43. package/dist/_observables/observableInternal/experimental/utils.d.ts +0 -15
  44. package/dist/_observables/observableInternal/index.d.ts +0 -25
  45. package/dist/_observables/observableInternal/logging/consoleObservableLogger.d.ts +0 -40
  46. package/dist/_observables/observableInternal/logging/debugGetDependencyGraph.d.ts +0 -4
  47. package/dist/_observables/observableInternal/logging/debugger/debuggerRpc.d.ts +0 -4
  48. package/dist/_observables/observableInternal/logging/debugger/devToolsLogger.d.ts +0 -43
  49. package/dist/_observables/observableInternal/logging/debugger/rpc.d.ts +0 -41
  50. package/dist/_observables/observableInternal/logging/debugger/utils.d.ts +0 -13
  51. package/dist/_observables/observableInternal/logging/logging.d.ts +0 -30
  52. package/dist/_observables/observableInternal/map.d.ts +0 -18
  53. package/dist/_observables/observableInternal/observables/baseObservable.d.ts +0 -58
  54. package/dist/_observables/observableInternal/observables/constObservable.d.ts +0 -5
  55. package/dist/_observables/observableInternal/observables/derived.d.ts +0 -46
  56. package/dist/_observables/observableInternal/observables/derivedImpl.d.ts +0 -83
  57. package/dist/_observables/observableInternal/observables/lazyObservableValue.d.ts +0 -27
  58. package/dist/_observables/observableInternal/observables/observableFromEvent.d.ts +0 -37
  59. package/dist/_observables/observableInternal/observables/observableSignal.d.ts +0 -11
  60. package/dist/_observables/observableInternal/observables/observableSignalFromEvent.d.ts +0 -5
  61. package/dist/_observables/observableInternal/observables/observableValue.d.ts +0 -37
  62. package/dist/_observables/observableInternal/observables/observableValueOpts.d.ts +0 -8
  63. package/dist/_observables/observableInternal/reactions/autorun.d.ts +0 -56
  64. package/dist/_observables/observableInternal/reactions/autorunImpl.d.ts +0 -53
  65. package/dist/_observables/observableInternal/set.d.ts +0 -17
  66. package/dist/_observables/observableInternal/transaction.d.ts +0 -27
  67. package/dist/_observables/observableInternal/utils/promise.d.ts +0 -75
  68. package/dist/_observables/observableInternal/utils/runOnChange.d.ts +0 -7
  69. package/dist/_observables/observableInternal/utils/utils.d.ts +0 -43
  70. package/dist/_observables/observableInternal/utils/utilsCancellation.d.ts +0 -10
  71. package/dist/_observables/observableInternal/utils/valueWithChangeEvent.d.ts +0 -10
  72. package/dist/_observables/utils.d.ts +0 -15
  73. package/dist/observables.d.ts +0 -4
  74. package/dist/observables.js +0 -439
  75. package/dist/observables.js.map +0 -1
  76. package/dist/runOnChange-C00UIwqQ.js +0 -1538
  77. package/dist/runOnChange-C00UIwqQ.js.map +0 -1
  78. package/src/contrib/comments/comments.css +0 -129
  79. package/src/contrib/commentsVscode/vscodeCommentWidgetV2.css +0 -166
@@ -1,3 +1,6 @@
1
+ @import '@vscode/codicons/dist/codicon.css';
2
+ @import '../contrib/find/find.css';
3
+
1
4
  /*
2
5
  * Base editor styles — ABSOLUTE MINIMUM.
3
6
  *
@@ -22,11 +25,152 @@
22
25
  */
23
26
 
24
27
  .md-editor {
28
+ --md-marker-font-family: 'Cascadia Code', 'Fira Code', monospace;
29
+ --md-marker-font-scale: 0.85;
30
+ --md-readonly-toggle-width: 58px;
31
+ --md-readonly-toggle-height: 32px;
32
+ --md-readonly-toggle-inset: 8px;
33
+ display: flow-root;
34
+ min-height: 100%;
25
35
  outline: none;
26
36
  /* The editor paints its own cursor (`.md-cursor`); hide the native caret. */
27
37
  caret-color: transparent;
28
38
  }
29
39
 
40
+ .md-iframe-surface {
41
+ position: absolute;
42
+ pointer-events: none;
43
+ outline: 1px solid transparent;
44
+ border-radius: 4px;
45
+ transition: outline-color 0.2s ease-in-out;
46
+ }
47
+
48
+ :is(.md-iframe-surface:hover, .md-iframe-surface:focus-within, [data-md-iframe-hover=true] .md-iframe-surface)
49
+ > .md-iframe-toolbar:not([hidden]) {
50
+ opacity: 1;
51
+ }
52
+
53
+ .md-iframe-surface:hover,
54
+ .md-iframe-surface:focus-within,
55
+ [data-md-iframe-hover=true] .md-iframe-surface {
56
+ outline-color: var(--md-iframe-border, #e5e5e5);
57
+ }
58
+
59
+ .md-iframe-toolbar,
60
+ .md-iframe-resize-handle {
61
+ position: absolute;
62
+ box-sizing: border-box;
63
+ pointer-events: auto;
64
+ background: var(--md-iframe-background, #fff);
65
+ color: var(--md-iframe-foreground, #616161);
66
+ }
67
+
68
+ .md-iframe-toolbar:not([hidden]) {
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: flex-end;
72
+ gap: 2px;
73
+ padding: 2px 4px;
74
+ border: 1px solid var(--md-iframe-border, #e5e5e5);
75
+ border-radius: 6px;
76
+ width: max-content;
77
+ transform: translateX(-100%);
78
+ opacity: 0;
79
+ transition: opacity 0.2s ease-in-out;
80
+ }
81
+
82
+ .md-iframe-toolbar:has(.md-code-block-copy-feedback),
83
+ .md-iframe-toolbar.md-iframe-toolbar-full-view {
84
+ opacity: 1;
85
+ }
86
+
87
+ .md-iframe-toolbar > .md-code-block-actions {
88
+ position: static;
89
+ height: auto;
90
+ margin: 0;
91
+ padding: 0;
92
+ opacity: 1;
93
+ order: 1;
94
+ }
95
+
96
+ .md-iframe-toolbar .md-code-block-copy-status:not(:empty) {
97
+ position: absolute;
98
+ top: 100%;
99
+ right: 0;
100
+ margin-top: 4px;
101
+ white-space: nowrap;
102
+ }
103
+
104
+ @media (hover: none) {
105
+ .md-iframe-toolbar:not([hidden]) {
106
+ opacity: 1;
107
+ }
108
+ }
109
+
110
+ @media (prefers-reduced-motion: reduce) {
111
+ .md-iframe-surface,
112
+ .md-iframe-toolbar:not([hidden]) {
113
+ transition: none;
114
+ }
115
+ }
116
+
117
+ .md-iframe-toolbar button,
118
+ .md-iframe-toolbar .md-code-block-copy {
119
+ background: transparent;
120
+ color: inherit;
121
+ border: none;
122
+ border-radius: 3px;
123
+ width: 22px;
124
+ height: 22px;
125
+ padding: 3px;
126
+ cursor: pointer;
127
+ }
128
+
129
+ .md-iframe-toolbar button:not([hidden]) {
130
+ display: grid;
131
+ place-items: center;
132
+ }
133
+
134
+ .md-iframe-toolbar button:hover,
135
+ .md-iframe-toolbar button[aria-pressed=true] {
136
+ background: var(--md-iframe-hover-background, rgba(128, 128, 128, 0.12));
137
+ }
138
+
139
+ .md-iframe-toolbar button:focus-visible,
140
+ .md-iframe-resize-handle:focus-visible {
141
+ outline: 1px solid var(--md-iframe-focus-border, #007acc);
142
+ outline-offset: -1px;
143
+ }
144
+
145
+ .md-iframe-resize-handle {
146
+ cursor: ns-resize;
147
+ touch-action: none;
148
+ border-radius: 0 0 4px 4px;
149
+ }
150
+
151
+ .md-iframe-resize-handle::after {
152
+ content: '';
153
+ display: block;
154
+ width: 32px;
155
+ height: 2px;
156
+ margin: 2px auto;
157
+ border-radius: 1px;
158
+ background: currentColor;
159
+ opacity: 0.35;
160
+ }
161
+
162
+ .md-editor-a11y-status {
163
+ position: absolute;
164
+ width: 1px;
165
+ height: 1px;
166
+ padding: 0;
167
+ margin: -1px;
168
+ overflow: hidden;
169
+ clip: rect(0, 0, 0, 0);
170
+ white-space: nowrap;
171
+ border: 0;
172
+ }
173
+
30
174
  /*
31
175
  * The transient empty paragraph — the blank line conjured by pressing Enter at
32
176
  * the end of a paragraph (see `PendingParagraph` in the model). It is not part
@@ -42,20 +186,66 @@
42
186
  * overlays, which position themselves relative to this box, so it is the
43
187
  * positioning context. In limited-width mode the editor sets an inline
44
188
  * `max-width` here and the auto inline margins center it within the full-width
45
- * `.md-editor`.
189
+ * `.md-editor`. The block-start padding keeps every document clear of the top
190
+ * edge, independent of the first block's theme margins.
46
191
  */
47
192
  .md-editor-content {
193
+ --md-editor-min-inline-padding: 8px;
194
+ --md-editor-content-inline-start-padding: var(--md-editor-min-inline-padding);
195
+ --md-editor-content-inline-end-padding: var(--md-editor-content-inline-start-padding);
48
196
  position: relative;
197
+ display: flow-root;
49
198
  margin-inline: auto;
50
- padding: 0 48px;
199
+ padding-block: 32px 0;
200
+ padding-inline: var(--md-editor-content-inline-start-padding) var(--md-editor-content-inline-end-padding);
201
+ }
202
+
203
+ .md-editor-medium-margins > .md-editor-content {
204
+ --md-editor-content-inline-start-padding: max(var(--md-editor-min-inline-padding), 48px);
205
+ }
206
+
207
+ .md-editor-content:has(> .md-document > .md-heading) {
208
+ --md-editor-min-inline-padding: 2em;
209
+ }
210
+
211
+ .md-editor-content>.md-document :is(.md-heading, .md-paragraph) {
212
+ overflow-wrap: anywhere;
213
+ }
214
+
215
+ .md-editor .md-document > :first-child,
216
+ .md-editor .md-blockquote > :nth-child(1 of .md-block) {
217
+ margin-block-start: 0;
51
218
  }
52
219
 
53
- .md-block-active {
220
+ :where(.md-editor:not(.md-no-active-block-highlight)) .md-block-active {
54
221
  background: var(--md-block-active-background, #f8f8f8);
55
222
  border-radius: 4px;
56
223
  box-shadow: 0 0 0 8px var(--md-block-active-background, #f8f8f8);
57
224
  }
58
225
 
226
+ /*
227
+ * The whole-empty-document case. Markdown has no empty-paragraph node, so a
228
+ * document with no content parses to a single empty paragraph (see
229
+ * `_ensureBlocks` in the parser) which renders as a childless `<p>` of zero
230
+ * height. Give it one line's height so the editor presents an intentional,
231
+ * clickable empty editing surface — and so typing the first character causes no
232
+ * layout shift (a filled line is also one `lh` tall).
233
+ */
234
+ .md-paragraph:empty {
235
+ min-height: 1lh;
236
+ }
237
+
238
+ /*
239
+ * ...and never paint the active-block card over that zero-content line: with no
240
+ * text to size it, the card's background + 8px box-shadow glow would show up as
241
+ * a stray gray bar. The two extra classes outrank the base `.md-block-active`
242
+ * rule above in every theme (themes only remap `--md-block-active-background`).
243
+ */
244
+ .md-paragraph:empty.md-block-active {
245
+ background: transparent;
246
+ box-shadow: none;
247
+ }
248
+
59
249
  /*
60
250
  * Cursor mirrors the same open affordance as the underline below: the anchor's
61
251
  * pointer cursor appears exactly when a click would open the link. An inactive
@@ -87,6 +277,560 @@
87
277
  text-decoration: none;
88
278
  }
89
279
 
280
+ .md-rich-link {
281
+ display: inline-flex;
282
+ align-items: baseline;
283
+ max-width: min(100%, var(--md-rich-link-line-width, 52rem));
284
+ box-sizing: border-box;
285
+ gap: 0.24em;
286
+ padding: 1px 0.3em;
287
+ border: 1px solid color-mix(in srgb, var(--vscode-textLink-foreground, #0969da) 24%, transparent);
288
+ border-radius: 0.3em;
289
+ background: var(--vscode-button-secondaryBackground, #f3f3f3);
290
+ color: inherit;
291
+ font-size: 1em;
292
+ line-height: 1.25;
293
+ text-decoration: none;
294
+ vertical-align: baseline;
295
+ white-space: nowrap;
296
+ cursor: pointer;
297
+ --md-rich-link-success-color: var(--vscode-charts-green, #1f883d);
298
+ }
299
+
300
+ .md-rich-link:hover {
301
+ border-color: var(--vscode-focusBorder, color-mix(in srgb, currentColor 42%, transparent));
302
+ background: var(--vscode-button-secondaryHoverBackground, #e5e5e5);
303
+ text-decoration: none;
304
+ }
305
+
306
+ .md-rich-link:focus-visible {
307
+ outline: 1px solid var(--vscode-focusBorder, currentColor);
308
+ outline-offset: 1px;
309
+ }
310
+
311
+ .md-rich-link-icon {
312
+ flex: none;
313
+ align-self: center;
314
+ font-size: 0.92em;
315
+ color: color-mix(in srgb, var(--vscode-textLink-foreground, #0969da) 78%, currentColor);
316
+ }
317
+
318
+ .md-rich-link-label,
319
+ .md-rich-link-title,
320
+ .md-rich-link-detail {
321
+ overflow: hidden;
322
+ text-overflow: ellipsis;
323
+ }
324
+
325
+ .md-rich-link-label,
326
+ .md-rich-link-title {
327
+ flex: 0 1 auto;
328
+ min-width: 0;
329
+ color: var(--vscode-textLink-foreground, currentColor);
330
+ font-weight: 600;
331
+ }
332
+
333
+ .md-rich-link-title {
334
+ max-width: var(--md-rich-link-title-width, 200px);
335
+ }
336
+
337
+ .md-rich-link-label {
338
+ max-width: var(--md-rich-link-title-width, none);
339
+ }
340
+
341
+ .md-rich-link[data-md-rich-link-kind='session'] :is(.md-rich-link-label, .md-rich-link-title) {
342
+ max-width: var(--md-rich-link-title-width, 150px);
343
+ }
344
+
345
+ .md-rich-link-line-end {
346
+ --md-rich-link-title-width: none;
347
+ }
348
+
349
+ .md-rich-link-label[hidden],
350
+ .md-rich-link-title[hidden],
351
+ .md-rich-link-reference[hidden] {
352
+ display: none;
353
+ }
354
+
355
+ .md-rich-link-reference {
356
+ flex: none;
357
+ color: var(--vscode-descriptionForeground, color-mix(in srgb, currentColor 72%, transparent));
358
+ font-size: 0.92em;
359
+ }
360
+
361
+ .md-rich-link-detail {
362
+ flex: 1 1 auto;
363
+ min-width: 1.5em;
364
+ color: var(--vscode-descriptionForeground, color-mix(in srgb, currentColor 72%, transparent));
365
+ font-size: 0.92em;
366
+ }
367
+
368
+ .md-rich-link-detail::before {
369
+ content: '·';
370
+ margin-right: 0.28em;
371
+ }
372
+
373
+ .md-rich-link-status {
374
+ flex: none;
375
+ display: inline-flex;
376
+ align-self: center;
377
+ align-items: center;
378
+ gap: 0.22em;
379
+ margin-left: 0.04em;
380
+ color: var(--vscode-descriptionForeground, currentColor);
381
+ font-size: 0.86em;
382
+ font-weight: 600;
383
+ line-height: 1;
384
+ }
385
+
386
+ .md-rich-link-detail[hidden],
387
+ .md-rich-link-changes[hidden],
388
+ .md-rich-link-status[hidden] {
389
+ display: none;
390
+ }
391
+
392
+ .md-rich-link-changes {
393
+ flex: none;
394
+ display: inline-flex;
395
+ align-self: center;
396
+ gap: 0.28em;
397
+ font-size: 0.86em;
398
+ font-weight: 600;
399
+ line-height: 1;
400
+ }
401
+
402
+ .md-rich-link-changes::before,
403
+ .md-rich-link:not(
404
+ [data-md-rich-link-kind='issue'],
405
+ [data-md-rich-link-kind='pullRequest'],
406
+ [data-md-rich-link-kind='session']
407
+ ) .md-rich-link-primary-status::before {
408
+ content: '·';
409
+ color: var(--vscode-descriptionForeground, currentColor);
410
+ font-weight: 400;
411
+ }
412
+
413
+ .md-rich-link-insertions {
414
+ color: var(--vscode-charts-green, #1f883d);
415
+ }
416
+
417
+ .md-rich-link-deletions {
418
+ color: var(--vscode-charts-red, #cf222e);
419
+ }
420
+
421
+ .md-rich-link-status-icon {
422
+ flex: none;
423
+ align-self: center;
424
+ font-size: 1em;
425
+ }
426
+
427
+ .md-rich-link:is(
428
+ [data-md-rich-link-status='open'],
429
+ [data-md-rich-link-status='closed'],
430
+ [data-md-rich-link-status='merged'],
431
+ [data-md-rich-link-status='draft'],
432
+ [data-md-rich-link-status='notPlanned']
433
+ ) .md-rich-link-primary-status {
434
+ color: var(--md-rich-link-state-color);
435
+ }
436
+
437
+ .md-rich-link-secondary-status {
438
+ margin-left: 0.06em;
439
+ }
440
+
441
+ .md-rich-link-secondary-status::before {
442
+ content: '·';
443
+ margin-right: 0.08em;
444
+ color: var(--vscode-descriptionForeground, currentColor);
445
+ font-weight: 400;
446
+ }
447
+
448
+ .md-rich-link:is(
449
+ [data-md-rich-link-status='open'],
450
+ [data-md-rich-link-status='closed'],
451
+ [data-md-rich-link-status='merged'],
452
+ [data-md-rich-link-status='draft'],
453
+ [data-md-rich-link-status='notPlanned']
454
+ ) .md-rich-link-primary-status {
455
+ align-self: baseline;
456
+ padding: 0;
457
+ border: 0;
458
+ border-radius: 0;
459
+ background: transparent;
460
+ font-size: 1em;
461
+ line-height: inherit;
462
+ }
463
+
464
+ .md-rich-link[data-md-rich-link-status='success'] .md-rich-link-primary-status {
465
+ color: var(--vscode-charts-green, #1f883d);
466
+ }
467
+
468
+ .md-rich-link[data-md-rich-link-secondary-status='success'] .md-rich-link-secondary-status {
469
+ color: var(--md-rich-link-success-color);
470
+ }
471
+
472
+ .md-rich-link[data-md-rich-link-status='warning'] .md-rich-link-primary-status,
473
+ .md-rich-link[data-md-rich-link-secondary-status='warning'] .md-rich-link-secondary-status {
474
+ color: var(--vscode-editorWarning-foreground, #bf8700);
475
+ }
476
+
477
+ .md-rich-link[data-md-rich-link-status='error'] .md-rich-link-primary-status,
478
+ .md-rich-link[data-md-rich-link-secondary-status='error'] .md-rich-link-secondary-status {
479
+ color: var(--vscode-errorForeground, #cf222e);
480
+ }
481
+
482
+ .md-rich-link[data-md-rich-link-status='pending'] .md-rich-link-primary-status,
483
+ .md-rich-link[data-md-rich-link-secondary-status='pending'] .md-rich-link-secondary-status {
484
+ color: var(--vscode-editorWarning-foreground, #bf8700);
485
+ }
486
+
487
+ .md-rich-link[data-md-rich-link-kind='issue'] .md-rich-link-primary-status .md-rich-link-status-label,
488
+ .md-rich-link[data-md-rich-link-kind='pullRequest'] :is(
489
+ .md-rich-link-primary-status,
490
+ .md-rich-link-secondary-status
491
+ ) .md-rich-link-status-label {
492
+ display: none;
493
+ }
494
+
495
+ .md-rich-link[data-md-rich-link-status='open'] {
496
+ --md-rich-link-state-color: var(--vscode-charts-green, #1f883d);
497
+ }
498
+
499
+ .md-rich-link[data-md-rich-link-kind='issue'][data-md-rich-link-status='closed'],
500
+ .md-rich-link[data-md-rich-link-status='merged'] {
501
+ --md-rich-link-state-color: var(--vscode-charts-purple, #8250df);
502
+ }
503
+
504
+ .md-rich-link[data-md-rich-link-kind='pullRequest'][data-md-rich-link-status='closed'] {
505
+ --md-rich-link-state-color: var(--vscode-charts-red, #cf222e);
506
+ }
507
+
508
+ .md-rich-link[data-md-rich-link-status='draft'],
509
+ .md-rich-link[data-md-rich-link-status='notPlanned'] {
510
+ --md-rich-link-state-color: var(--vscode-descriptionForeground, #656d76);
511
+ }
512
+
513
+ .md-rich-link[data-md-rich-link-kind='pullRequest'][data-md-rich-link-secondary-status='error'] .md-rich-link-secondary-status {
514
+ color: var(--vscode-charts-red, var(--vscode-errorForeground, #cf222e));
515
+ }
516
+
517
+ .md-rich-link:is(
518
+ [data-md-rich-link-kind='issue'],
519
+ [data-md-rich-link-kind='pullRequest']
520
+ ) {
521
+ align-items: center;
522
+ gap: 4px;
523
+ padding: 1px 6px;
524
+ border-color: var(--vscode-button-secondaryBorder, var(--vscode-button-border, transparent));
525
+ border-radius: 4px;
526
+ background: var(--vscode-button-secondaryBackground, #f3f3f3);
527
+ color: var(--vscode-button-secondaryForeground, #242424);
528
+ font-size: 1em;
529
+ line-height: 1.25;
530
+ vertical-align: -0.5px;
531
+ }
532
+
533
+ .md-rich-link:is(
534
+ [data-md-rich-link-kind='issue'],
535
+ [data-md-rich-link-kind='pullRequest']
536
+ ):hover {
537
+ border-color: var(--vscode-button-secondaryBorder, var(--vscode-button-border, transparent));
538
+ background: var(--vscode-button-secondaryHoverBackground, #e5e5e5);
539
+ color: var(--vscode-button-secondaryForeground, #242424);
540
+ }
541
+
542
+ .md-rich-link:is(
543
+ [data-md-rich-link-kind='issue'],
544
+ [data-md-rich-link-kind='pullRequest']
545
+ ) .md-rich-link-reference {
546
+ display: none;
547
+ }
548
+
549
+ .md-rich-link:is(
550
+ [data-md-rich-link-kind='issue'],
551
+ [data-md-rich-link-kind='pullRequest']
552
+ ) :is(
553
+ .md-rich-link-label,
554
+ .md-rich-link-title,
555
+ .md-rich-link-primary-status,
556
+ .md-rich-link-secondary-status
557
+ ) {
558
+ align-self: center;
559
+ font-size: inherit;
560
+ line-height: inherit;
561
+ }
562
+
563
+ .md-rich-link:is(
564
+ [data-md-rich-link-kind='issue'],
565
+ [data-md-rich-link-kind='pullRequest']
566
+ ) :is(.md-rich-link-label, .md-rich-link-title) {
567
+ position: relative;
568
+ top: 0.25px;
569
+ max-width: var(--md-rich-link-title-width, 200px);
570
+ color: inherit;
571
+ font-weight: 400;
572
+ }
573
+
574
+ .md-rich-link:is(
575
+ [data-md-rich-link-kind='issue'],
576
+ [data-md-rich-link-kind='pullRequest']
577
+ ) .md-rich-link-status {
578
+ align-items: center;
579
+ height: 1.25em;
580
+ }
581
+
582
+ .md-rich-link:is(
583
+ [data-md-rich-link-kind='issue'],
584
+ [data-md-rich-link-kind='pullRequest']
585
+ ) .md-rich-link-status-icon {
586
+ display: inline-flex;
587
+ align-items: center;
588
+ justify-content: center;
589
+ width: 12px;
590
+ height: 12px;
591
+ font-size: 12px;
592
+ line-height: 12px;
593
+ }
594
+
595
+ .md-rich-link:is(
596
+ [data-md-rich-link-kind='issue'],
597
+ [data-md-rich-link-kind='pullRequest']
598
+ ) .md-rich-link-secondary-status::before {
599
+ align-self: center;
600
+ line-height: inherit;
601
+ }
602
+
603
+ .md-rich-link[data-md-rich-link-kind='session'] {
604
+ align-items: center;
605
+ gap: 4px;
606
+ padding: 1px 6px;
607
+ border-color: var(--vscode-chat-requestBorder, var(--vscode-input-border, color-mix(in srgb, currentColor 24%, transparent)));
608
+ border-radius: 4px;
609
+ background: var(--vscode-button-secondaryBackground, #f3f3f3);
610
+ color: var(--vscode-descriptionForeground, #656d76);
611
+ font-size: 1em;
612
+ font-weight: var(--vscode-agents-fontWeight-regular, 400);
613
+ line-height: 1.25;
614
+ vertical-align: baseline;
615
+ }
616
+
617
+ .md-rich-link[data-md-rich-link-kind='session']:hover {
618
+ border-color: var(--vscode-chat-requestBorder, var(--vscode-input-border, color-mix(in srgb, currentColor 24%, transparent)));
619
+ background: var(--vscode-toolbar-hoverBackground, color-mix(in srgb, currentColor 8%, transparent));
620
+ }
621
+
622
+ .md-rich-link[data-md-rich-link-kind='session'] :is(.md-rich-link-label, .md-rich-link-title) {
623
+ color: inherit;
624
+ font-weight: 400;
625
+ }
626
+
627
+ .md-rich-link[data-md-rich-link-kind='session'] .md-rich-link-primary-status {
628
+ align-self: center;
629
+ align-items: center;
630
+ width: 12px;
631
+ height: 12px;
632
+ margin: 0;
633
+ padding: 0;
634
+ border: 0;
635
+ border-radius: 0;
636
+ background: transparent;
637
+ font-size: 1em;
638
+ line-height: inherit;
639
+ }
640
+
641
+ .md-rich-link[data-md-rich-link-kind='session'] .md-rich-link-primary-status .md-rich-link-status-label {
642
+ display: none;
643
+ }
644
+
645
+ .md-rich-link[data-md-rich-link-kind='session'] .md-rich-link-status-icon:not(.monaco-pixel-spinner, [hidden]) {
646
+ display: inline-flex;
647
+ align-items: center;
648
+ justify-content: center;
649
+ width: 12px;
650
+ height: 12px;
651
+ font-size: 12px;
652
+ line-height: 12px;
653
+ }
654
+
655
+ .md-rich-link .md-rich-link-status-icon[hidden] {
656
+ display: none;
657
+ }
658
+
659
+ .md-rich-link[data-md-rich-link-kind='session'][data-md-rich-link-status='neutral'] .md-rich-link-primary-status,
660
+ .md-rich-link[data-md-rich-link-kind='session'][data-md-rich-link-status='success'] .md-rich-link-primary-status,
661
+ .md-rich-link[data-md-rich-link-kind='session'][data-md-rich-link-status='pending'] .md-rich-link-primary-status {
662
+ color: var(--vscode-descriptionForeground, #656d76);
663
+ }
664
+
665
+ .md-rich-link .monaco-pixel-spinner {
666
+ display: inline-grid;
667
+ grid-template-columns: repeat(2, 2px);
668
+ grid-template-rows: repeat(3, 2px);
669
+ column-gap: 2px;
670
+ row-gap: 2px;
671
+ place-content: center;
672
+ width: 16px;
673
+ height: 16px;
674
+ color: currentColor;
675
+ contain: layout style size paint;
676
+ isolation: isolate;
677
+ pointer-events: none;
678
+ transform: translateZ(0);
679
+ }
680
+
681
+ .md-rich-link[data-md-rich-link-kind='session'] .monaco-pixel-spinner {
682
+ width: 12px;
683
+ height: 12px;
684
+ }
685
+
686
+ .md-rich-link .monaco-pixel-spinner-dot {
687
+ display: block;
688
+ width: 2px;
689
+ height: 2px;
690
+ border-radius: 50%;
691
+ background-color: currentColor;
692
+ opacity: 0;
693
+ transform: translateY(-4px);
694
+ animation: monaco-pixel-spinner-dot-cycle 1820ms steps(6, jump-none) infinite;
695
+ }
696
+
697
+ .md-rich-link .monaco-pixel-spinner-dot:nth-child(1) {
698
+ animation-delay: 520ms;
699
+ }
700
+
701
+ .md-rich-link .monaco-pixel-spinner-dot:nth-child(2) {
702
+ animation-delay: 650ms;
703
+ }
704
+
705
+ .md-rich-link .monaco-pixel-spinner-dot:nth-child(3) {
706
+ animation-delay: 260ms;
707
+ }
708
+
709
+ .md-rich-link .monaco-pixel-spinner-dot:nth-child(4) {
710
+ animation-delay: 390ms;
711
+ }
712
+
713
+ .md-rich-link .monaco-pixel-spinner-dot:nth-child(5) {
714
+ animation-name: monaco-pixel-spinner-dot-cycle-long;
715
+ }
716
+
717
+ .md-rich-link .monaco-pixel-spinner-dot:nth-child(6) {
718
+ animation-name: monaco-pixel-spinner-dot-cycle-short;
719
+ animation-delay: 130ms;
720
+ }
721
+
722
+ .md-rich-link .monaco-pixel-spinner-ring .monaco-pixel-spinner-dot {
723
+ opacity: 0.25;
724
+ transform: none;
725
+ animation: monaco-pixel-spinner-ring-pulse 1200ms steps(4, jump-none) infinite;
726
+ }
727
+
728
+ .md-rich-link .monaco-pixel-spinner-ring .monaco-pixel-spinner-dot:nth-child(1) {
729
+ animation-delay: 0ms;
730
+ }
731
+
732
+ .md-rich-link .monaco-pixel-spinner-ring .monaco-pixel-spinner-dot:nth-child(2) {
733
+ animation-delay: 200ms;
734
+ }
735
+
736
+ .md-rich-link .monaco-pixel-spinner-ring .monaco-pixel-spinner-dot:nth-child(3) {
737
+ animation-delay: 1000ms;
738
+ }
739
+
740
+ .md-rich-link .monaco-pixel-spinner-ring .monaco-pixel-spinner-dot:nth-child(4) {
741
+ animation-delay: 400ms;
742
+ }
743
+
744
+ .md-rich-link .monaco-pixel-spinner-ring .monaco-pixel-spinner-dot:nth-child(5) {
745
+ animation-delay: 800ms;
746
+ }
747
+
748
+ .md-rich-link .monaco-pixel-spinner-ring .monaco-pixel-spinner-dot:nth-child(6) {
749
+ animation-delay: 600ms;
750
+ }
751
+
752
+ @keyframes monaco-pixel-spinner-dot-cycle {
753
+ 0% {
754
+ opacity: 0;
755
+ transform: translateY(-4px);
756
+ }
757
+ 9.34%, 57.14% {
758
+ opacity: 1;
759
+ transform: translateY(0);
760
+ }
761
+ 66.48%, 100% {
762
+ opacity: 0;
763
+ transform: translateY(7px);
764
+ }
765
+ }
766
+
767
+ @keyframes monaco-pixel-spinner-dot-cycle-long {
768
+ 0% {
769
+ opacity: 0;
770
+ transform: translateY(-4px);
771
+ }
772
+ 9.34%, 64.29% {
773
+ opacity: 1;
774
+ transform: translateY(0);
775
+ }
776
+ 73.63%, 100% {
777
+ opacity: 0;
778
+ transform: translateY(7px);
779
+ }
780
+ }
781
+
782
+ @keyframes monaco-pixel-spinner-dot-cycle-short {
783
+ 0% {
784
+ opacity: 0;
785
+ transform: translateY(-4px);
786
+ }
787
+ 9.34%, 50% {
788
+ opacity: 1;
789
+ transform: translateY(0);
790
+ }
791
+ 59.34%, 100% {
792
+ opacity: 0;
793
+ transform: translateY(7px);
794
+ }
795
+ }
796
+
797
+ @keyframes monaco-pixel-spinner-ring-pulse {
798
+ 0%, 100% {
799
+ opacity: 0.25;
800
+ transform: none;
801
+ }
802
+ 16.67% {
803
+ opacity: 1;
804
+ transform: none;
805
+ }
806
+ }
807
+
808
+ @media (prefers-reduced-motion: reduce) {
809
+ .md-rich-link .monaco-pixel-spinner-dot {
810
+ animation: none;
811
+ opacity: 1;
812
+ transform: translateY(0);
813
+ }
814
+ }
815
+
816
+ .md-rich-link[data-md-rich-link-kind='session'][data-md-rich-link-status='warning'] .md-rich-link-primary-status {
817
+ color: var(--vscode-list-warningForeground, #855f00);
818
+ }
819
+
820
+ .md-rich-link[data-md-rich-link-kind='session'][data-md-rich-link-status='warning'] {
821
+ border-color: var(--vscode-list-warningForeground, #855f00);
822
+ background-color: color-mix(in srgb, var(--vscode-list-warningForeground, #855f00) 12%, transparent);
823
+ color: var(--vscode-list-warningForeground, #855f00);
824
+ }
825
+
826
+ .md-rich-link[data-md-rich-link-kind='session'][data-md-rich-link-status='error'] .md-rich-link-primary-status {
827
+ color: var(--vscode-errorForeground, #cf222e);
828
+ }
829
+
830
+ .md-rich-link-unavailable {
831
+ border-style: dashed;
832
+ }
833
+
90
834
  .md-fence-spacer {
91
835
  visibility: hidden;
92
836
  font-family: 'Cascadia Code', 'Fira Code', monospace;
@@ -95,8 +839,8 @@
95
839
 
96
840
  .md-marker {
97
841
  color: #999;
98
- font-family: 'Cascadia Code', 'Fira Code', monospace;
99
- font-size: 0.85em;
842
+ font-family: var(--md-marker-font-family);
843
+ font-size: calc(1em * var(--md-marker-font-scale));
100
844
  display: inline;
101
845
  overflow: hidden;
102
846
  max-width: 100px;
@@ -122,6 +866,88 @@
122
866
  white-space: pre-wrap;
123
867
  }
124
868
 
869
+ .md-video-wrapper {
870
+ max-width: 100%;
871
+ }
872
+
873
+ .md-video {
874
+ display: block;
875
+ max-width: 100%;
876
+ max-height: 100%;
877
+ }
878
+
879
+ .md-editor:not(.md-readonly) .md-video:not([controls]) {
880
+ cursor: text;
881
+ }
882
+
883
+ .md-video-source {
884
+ overflow-wrap: anywhere;
885
+ white-space: pre-wrap;
886
+ }
887
+
888
+ /*
889
+ * An unhandled block: a construct the parser does not model (setext heading,
890
+ * an extension token). Its raw source is shown verbatim,
891
+ * styled like a code block but visibly flagged as "not understood" by a dashed
892
+ * warning border, so the content is preserved and editable rather than silently
893
+ * dropped.
894
+ *
895
+ * The wrapper is the non-scrolling box (border + block spacing); the inner
896
+ * `.md-unhandled-scroll` <pre> is the horizontal scroller.
897
+ */
898
+ .md-unhandled-block {
899
+ margin: 0.5em 0;
900
+ border: 1px dashed #d0a000;
901
+ border-radius: 4px;
902
+ }
903
+
904
+ /*
905
+ * Inner scroller. Beats the per-theme `.md-theme-* .md-code-block` box rules
906
+ * (same class count) via the extra `pre` type selector: no margin/border of its
907
+ * own (those live on the wrapper).
908
+ */
909
+ pre.md-unhandled-scroll.md-code-block {
910
+ margin: 0;
911
+ border: 0;
912
+ border-radius: 4px;
913
+ }
914
+
915
+ /*
916
+ * Complete block HTML comments are authoring metadata, not unsupported-syntax
917
+ * warnings. Keep them source-identifiable but quiet while reading, and reveal
918
+ * their exact whitespace when the block becomes active.
919
+ */
920
+ .md-html-comment {
921
+ margin: 0.125em 0 0.25em;
922
+ padding: 0.125em 0;
923
+ overflow: hidden;
924
+ color: var(--md-html-comment-foreground, #6e7378);
925
+ font-family: var(--md-html-comment-font-family, 'Cascadia Code', 'Fira Code', monospace);
926
+ font-size: 0.85em;
927
+ line-height: 1.5;
928
+ text-overflow: ellipsis;
929
+ white-space: nowrap;
930
+ transition: color 80ms ease-out;
931
+ }
932
+
933
+ .md-html-comment:not(.md-html-comment-source):hover {
934
+ color: var(--md-html-comment-hover-foreground, #45494e);
935
+ }
936
+
937
+ .md-html-comment-source {
938
+ overflow: visible;
939
+ text-overflow: clip;
940
+ white-space: pre-wrap;
941
+ }
942
+
943
+ .md-html-comment-syntax {
944
+ opacity: 0.6;
945
+ }
946
+
947
+ .md-html-comment-source .md-html-comment-syntax {
948
+ opacity: 1;
949
+ }
950
+
125
951
  /*
126
952
  * Visible whitespace indicators, shown only in the active/source view. The real
127
953
  * whitespace character stays in the DOM (so source ↔ DOM mapping and selection
@@ -155,7 +981,7 @@
155
981
  left: 0;
156
982
  right: 0;
157
983
  text-align: center;
158
- color: #b0b0b0;
984
+ color: var(--md-whitespace-foreground, #b0b0b0);
159
985
  pointer-events: none;
160
986
  }
161
987
 
@@ -169,7 +995,7 @@
169
995
 
170
996
  .md-ws-newline::before {
171
997
  content: '↵';
172
- color: #b0b0b0;
998
+ color: var(--md-whitespace-foreground, #b0b0b0);
173
999
  pointer-events: none;
174
1000
  }
175
1001
 
@@ -221,39 +1047,162 @@
221
1047
  }
222
1048
 
223
1049
  /*
224
- * Glue (table cell pipes, the task `[x] ` source, source padding) keeps its
225
- * inline footprint when hidden so column widths and the checkbox gutter stay
226
- * identical between active and inactive states.
1050
+ * A soft ending followed by an explicit blockquote continuation marker renders
1051
+ * a real line break in both views. Its source newline is still mapped and is
1052
+ * revealed while editing, but contributes no hidden width in rendered mode.
1053
+ */
1054
+ .md-blockquote-linebreak-source-hidden {
1055
+ display: none;
1056
+ }
1057
+
1058
+ /*
1059
+ * Structural quote prefixes between child blocks can be owned by a source gap
1060
+ * instead of an inline continuation marker. Keep the exact gap for active
1061
+ * editing, but remove it entirely from inactive layout and hit testing.
1062
+ */
1063
+ .md-glue-blockQuoteSourceGap.md-glue-hidden {
1064
+ display: none;
1065
+ }
1066
+
1067
+ /* A fallback-font newline glyph must not increase the source line's height. */
1068
+ .md-glue-blockQuoteSourceGap > .md-ws-newline-glyph {
1069
+ line-height: 0;
1070
+ }
1071
+
1072
+ /*
1073
+ * Glue normally keeps its inline footprint when hidden so source padding and
1074
+ * widget gutters stay identical between active and inactive states. Hidden
1075
+ * table-cell glue is the exception below: leaving it in inline flow lets its
1076
+ * invisible spaces wrap around long cell content.
227
1077
  */
228
1078
  .md-glue-hidden {
229
1079
  display: inline;
230
1080
  visibility: hidden;
231
1081
  }
232
1082
 
1083
+ /*
1084
+ * Inactive table pipes stay in the DOM/source tree, but leave layout and
1085
+ * hit-testing entirely. Keeping an invisible rect either in the content flow or
1086
+ * over the cell padding can create phantom lines or steal clicks from visible
1087
+ * text. Hidden source offsets therefore collapse to the neighboring semantic
1088
+ * seam, matching other display-none markers. Visible pipes retain the per-theme
1089
+ * active/source layout.
1090
+ */
1091
+ .md-table td>.md-glue-tableCellGlue.md-glue-hidden {
1092
+ display: none;
1093
+ }
1094
+
1095
+ /*
1096
+ * Active table: take each cell's TRAILING structural glue (the source space
1097
+ * after the cell text, and — via the per-theme `right: 0` rule — the last
1098
+ * column's closing `|`) out of the cell's inline flow. Left in flow, that glue
1099
+ * wraps below long cell content (the same wrapping the hidden-glue note above
1100
+ * describes), which makes the cell two lines tall: the browser's default
1101
+ * `vertical-align: middle` then re-centres the other cells' single-line content
1102
+ * in Y, their runs merge into one oversized VisualLine, and the caret — sized
1103
+ * directly from that line box — grows far past the line height while the
1104
+ * visible pipes drift apart row-to-row. Positioning the trailing glue
1105
+ * absolutely removes it from wrapping flow while keeping its real client rects
1106
+ * at the static (content-line) position, so caret placement, hit-testing,
1107
+ * source mapping and injectivity are unchanged. `top`/`bottom: auto` keep it on
1108
+ * that content line rather than the cell's top edge. This mirrors the inactive
1109
+ * `display: none` above; the leading `| ` glue deliberately stays in flow (a
1110
+ * relative glyph shift, per theme) so first-text X is preserved.
1111
+ *
1112
+ * `:not(:first-child)` restricts this to a genuine trailing glue: a non-empty
1113
+ * cell emits leading + trailing glue, but an EMPTY cell parses to a single glue
1114
+ * node that is simultaneously first and last child. That lone node is the
1115
+ * cell's leading pipe, so it must stay in flow like every other leading pipe;
1116
+ * excluding it keeps empty cells identical to their previous (base) behaviour.
1117
+ */
1118
+ .md-table.md-block-active td {
1119
+ position: relative;
1120
+ }
1121
+
1122
+ .md-table.md-block-active td>.md-glue-tableCellGlue:last-child:not(:first-child) {
1123
+ position: absolute;
1124
+ top: auto;
1125
+ bottom: auto;
1126
+ }
1127
+
233
1128
  /*
234
1129
  * Inter-block glue: the run of blank lines between two top-level blocks. It is
235
1130
  * mounted as the last inline child of the block that precedes it, so it sits at
236
1131
  * the end of that block's last line rather than on its own lines between the
237
1132
  * blocks. When a neighbouring block is active it is revealed: each blank-line
238
- * newline shows a real `↵` glyph character (`.md-ws-newline-glyph`) while the
239
- * trailing line-terminator `\n` collapses (`white-space: normal`) so the run
240
- * adds no line break and no height — active and inactive therefore have the
241
- * same height. When hidden it collapses to nothing.
1133
+ * newline shows a real `↵` glyph character (`.md-ws-newline-glyph`) so each
1134
+ * source offset remains distinct. The glyphs stay on the preceding source line
1135
+ * rather than introducing line breaks. When hidden the run collapses to nothing.
242
1136
  */
243
- .md-glue-blockGap {
1137
+ .md-glue-blockGap,
1138
+ .md-glue-blockQuoteSourceGap {
244
1139
  white-space: normal;
245
1140
  }
246
1141
 
247
1142
  /*
248
1143
  * The structural block break between two top-level blocks. Like `.md-glue-blockGap`
249
- * its trailing line-terminator `\n` collapses (`white-space: normal`) so the run
250
- * adds no height; its leading newline is painted as the blue break glyph
1144
+ * its newlines stay inline so the run adds no height; its leading newline is painted as the blue break glyph
251
1145
  * (`.md-ws-blockbreak-glyph`).
252
1146
  */
253
1147
  .md-glue-blockBreak {
254
1148
  white-space: normal;
255
1149
  }
256
1150
 
1151
+ .md-source-editing :is(.md-paragraph, .md-heading, .md-empty-block, td),
1152
+ .md-source-editing :is(.md-text, .md-marker) {
1153
+ white-space: pre-wrap;
1154
+ }
1155
+
1156
+ .md-editor.md-source-editing .md-block,
1157
+ .md-editor.md-source-editing .md-list > li {
1158
+ margin-block: 0;
1159
+ }
1160
+
1161
+ .md-source-editing .md-empty-block {
1162
+ min-height: 1lh;
1163
+ }
1164
+
1165
+ .md-source-editing .md-list > .md-empty-block {
1166
+ list-style: none;
1167
+ counter-increment: list-item 0;
1168
+ margin-inline-start: calc(-1 * var(--md-list-indent-step, 2em));
1169
+ }
1170
+
1171
+ .md-source-editing .md-list > li > .md-empty-block {
1172
+ padding-inline-start: calc(var(--md-list-label-reserve) + var(--md-list-source-padding));
1173
+ }
1174
+
1175
+ .md-source-editing .md-glue-emptyLine {
1176
+ white-space: pre-wrap;
1177
+ visibility: visible;
1178
+ }
1179
+
1180
+ .md-source-editing .md-glue-blockTerminator {
1181
+ display: none;
1182
+ }
1183
+
1184
+ .md-source-editing .md-glue-lineSuffix {
1185
+ white-space: pre-wrap;
1186
+ visibility: visible;
1187
+ }
1188
+
1189
+ .md-source-editing .md-ws-newline::before {
1190
+ content: none;
1191
+ }
1192
+
1193
+ .md-source-editing :is(.md-ws-space, .md-ws-tab) {
1194
+ white-space: inherit;
1195
+ }
1196
+
1197
+ /* These source holders already have a <br> supplying their line ending. */
1198
+ .md-source-block :is(.md-hardbreak-src, .md-blockquote-linebreak-source) {
1199
+ white-space: normal;
1200
+ }
1201
+
1202
+ .md-source-block .md-blockquote-linebreak-source .md-ws-newline::before {
1203
+ content: none;
1204
+ }
1205
+
257
1206
  /*
258
1207
  * The task-list checkbox marker (`[x]`/`[ ]`) is special: instead of being
259
1208
  * removed from layout when hidden, it keeps its inline width (visibility
@@ -266,15 +1215,6 @@
266
1215
  visibility: hidden;
267
1216
  }
268
1217
 
269
- /*
270
- * Table cell-glue pipes (`| `) keep their inline footprint when hidden so the
271
- * column widths stay identical active and inactive.
272
- */
273
- .md-marker-tableCellGlue.md-marker-hidden {
274
- display: inline;
275
- visibility: hidden;
276
- }
277
-
278
1218
  /*
279
1219
  * The code-block fences (```lang / ```) each sit on their own source line. When
280
1220
  * hidden they keep their vertical footprint (visibility hidden, not display
@@ -309,6 +1249,69 @@
309
1249
  height: 16px;
310
1250
  }
311
1251
 
1252
+ /*
1253
+ * A wide table scrolls horizontally inside its wrapper (the block box) instead
1254
+ * of overflowing the page and scrolling the editor's fixed left gutter away.
1255
+ * The wrapper is the scroll viewport the selection/caret clipping measures (see
1256
+ * `BlockViewNode.scrollElement` / `blockViewportClip`); the inner `<table>`
1257
+ * keeps `width: auto` (theme-defined) so it sizes to its content and overflows.
1258
+ *
1259
+ * `width: fit-content` keeps the wrapper hugging the table's intrinsic width, so
1260
+ * a narrow table — and the active-block glow redirected onto the wrapper below —
1261
+ * stays as wide as the table (unchanged from before this wrapper existed).
1262
+ * `max-width: 100%` caps it at the content column, past which the table
1263
+ * overflows and scrolls locally. This is the standard responsive-table pattern
1264
+ * (cf. GitHub's own `width: max-content; max-width: 100%`).
1265
+ */
1266
+ .md-table-wrapper {
1267
+ overflow-x: auto;
1268
+ width: fit-content;
1269
+ max-width: 100%;
1270
+ }
1271
+
1272
+ .md-table:has(> .md-glue-blockGap) {
1273
+ position: relative;
1274
+ }
1275
+
1276
+ /* Table trivia must not generate an anonymous row when source is revealed. */
1277
+ .md-table > .md-glue-blockGap {
1278
+ position: absolute;
1279
+ left: 100%;
1280
+ bottom: 0.3em;
1281
+ }
1282
+
1283
+ .md-editor:not(.md-source-editing) .md-paragraph:has(> .md-glue-indent:first-child) {
1284
+ position: relative;
1285
+ }
1286
+
1287
+ .md-editor:not(.md-source-editing) .md-paragraph > .md-glue-indent:first-child {
1288
+ position: absolute;
1289
+ right: 100%;
1290
+ top: 0;
1291
+ }
1292
+
1293
+ /*
1294
+ * The active-block highlight is an *outset* glow (`box-shadow: 0 0 0 8px`).
1295
+ * Making the wrapper a scroll box (`overflow-x: auto`, which also forces
1296
+ * `overflow-y: auto`) clips descendant paint to its padding box, so the glow on
1297
+ * the inner active `<table>` would be cut off (the table has no horizontal
1298
+ * margin to give the shadow room). Render the generic active chrome on the
1299
+ * wrapper instead — a scroll box's own shadow is never clipped by its own
1300
+ * overflow, exactly like a code block carries the glow on its own scroller —
1301
+ * and drop it from the table, which keeps `md-block-active` purely for the
1302
+ * per-theme source-pipe styling.
1303
+ */
1304
+ :where(.md-editor:not(.md-no-active-block-highlight)) .md-table-wrapper:has(> .md-table.md-block-active) {
1305
+ background: var(--md-block-active-background, #f8f8f8);
1306
+ border-radius: 4px;
1307
+ box-shadow: 0 0 0 8px var(--md-block-active-background, #f8f8f8);
1308
+ }
1309
+
1310
+ .md-table.md-block-active {
1311
+ background: none;
1312
+ box-shadow: none;
1313
+ }
1314
+
312
1315
  .md-selection-layer {
313
1316
  position: absolute;
314
1317
  top: 0;
@@ -374,6 +1377,7 @@
374
1377
  /* Source markers occupy the gutter so toggling them never shifts content. */
375
1378
  .md-heading {
376
1379
  position: relative;
1380
+ min-height: 1lh;
377
1381
  }
378
1382
 
379
1383
  .md-heading>.md-marker:first-child {
@@ -390,7 +1394,7 @@
390
1394
  display: inline-flex;
391
1395
  align-items: center;
392
1396
  justify-content: flex-end;
393
- transform: scale(0.85);
1397
+ transform: scale(var(--md-heading-marker-scale, 0.85));
394
1398
  transform-origin: right center;
395
1399
  }
396
1400
 
@@ -403,6 +1407,18 @@
403
1407
  display: none;
404
1408
  }
405
1409
 
1410
+ /* Nested heading prefixes must not overlap their enclosing quote/list gutter. */
1411
+ .md-source-editing :is(.md-blockquote, .md-list) .md-heading > .md-marker:first-child {
1412
+ position: static;
1413
+ display: inline;
1414
+ font-size: calc(1em * var(--md-marker-font-scale));
1415
+ transform: none;
1416
+ }
1417
+
1418
+ .md-source-editing :is(.md-blockquote, .md-list) .md-heading > .md-marker-hidden:first-child {
1419
+ display: none;
1420
+ }
1421
+
406
1422
  /*
407
1423
  * Block-quote prefixes (`> `, one per quoted source line) are real
408
1424
  * `blockQuoteMarker` markers, siblings of the quote's child blocks. Each hangs
@@ -422,21 +1438,146 @@
422
1438
  position: relative;
423
1439
  }
424
1440
 
425
- .md-blockquote>.md-marker-blockQuoteMarker {
1441
+ .md-blockquote>.md-marker-blockQuoteMarker,
1442
+ .md-source-editing li > .md-glue-blockQuotePrefix {
426
1443
  position: absolute;
427
- right: calc(100% - var(--md-blockquote-pad, 0px));
1444
+ right: calc(100% - var(--md-blockquote-pad, 0px) - 1ch);
428
1445
  top: auto;
1446
+ /*
1447
+ * Reserve the optional-space column so adding it cannot move the `>` glyph,
1448
+ * then shift and scale every active quote marker consistently to leave a
1449
+ * virtual gap before body text without consuming source width. These tuned
1450
+ * properties are shared by ordinary and marker-only quote lines.
1451
+ */
1452
+ --md-blockquote-marker-shift: -0.18ch;
1453
+ --md-blockquote-marker-scale: 0.9;
1454
+ display: inline-flex;
1455
+ min-width: 2ch;
1456
+ font-size: inherit;
1457
+ line-height: inherit;
1458
+ height: 1lh;
1459
+ align-items: center;
1460
+ text-align: left;
429
1461
  white-space: pre;
1462
+ transform: translateX(var(--md-blockquote-marker-shift)) scale(var(--md-blockquote-marker-scale));
1463
+ transform-origin: left center;
1464
+ }
1465
+
1466
+ .md-source-editing li > .md-glue-blockQuotePrefix {
1467
+ right: calc(100% + var(--md-list-indent-step, 2em) - 1ch);
1468
+ }
1469
+
1470
+ /* Inactive: gone entirely (the gutter is empty, the text stays put). */
1471
+ .md-blockquote>.md-marker-blockQuoteMarker.md-marker-hidden {
1472
+ display: none;
1473
+ }
1474
+
1475
+ /* Collapsed block-gap newlines still need one flow box per marker-only line. */
1476
+ .md-blockquote-line-anchor {
1477
+ display: block;
1478
+ }
1479
+
1480
+ /* A trailing marker-only source line follows the preceding quoted line directly. */
1481
+ .md-blockquote-marker-only-line>.md-paragraph:last-of-type {
1482
+ margin-bottom: 0;
1483
+ }
1484
+
1485
+ /* Code/math blocks scroll horizontally; their look is theme-defined. */
1486
+ .md-code-block {
1487
+ overflow-x: auto;
1488
+ }
1489
+
1490
+ .md-block.md-code-block.md-embedded-code-editor {
1491
+ background: transparent;
1492
+ padding: 0;
1493
+ }
1494
+
1495
+ /* Keep actions out of the horizontal scroller and sticky within a long block. */
1496
+ .md-code-block-container {
1497
+ display: flow-root;
1498
+ position: relative;
1499
+ min-width: 0;
1500
+ }
1501
+
1502
+ .md-code-block-container > .md-code-block {
1503
+ box-sizing: border-box;
1504
+ min-height: 36px;
1505
+ }
1506
+
1507
+ .md-code-block-actions {
1508
+ position: sticky;
1509
+ top: 0;
1510
+ z-index: 2;
1511
+ display: flex;
1512
+ align-items: center;
1513
+ justify-content: flex-end;
1514
+ gap: 6px;
1515
+ box-sizing: border-box;
1516
+ height: 32px;
1517
+ margin-bottom: -32px;
1518
+ padding: 4px 4px 0;
1519
+ opacity: 0;
1520
+ pointer-events: none;
1521
+ user-select: none;
1522
+ }
1523
+
1524
+ .md-code-block-container:hover>.md-code-block-actions,
1525
+ .md-code-block-container:hover>.md-embedded-code-editor>.md-code-block-actions,
1526
+ .md-code-block-actions:focus-within,
1527
+ .md-code-block-actions.md-code-block-copy-feedback {
1528
+ opacity: 1;
1529
+ }
1530
+
1531
+ .md-code-block-copy {
1532
+ display: inline-flex;
1533
+ align-items: center;
1534
+ justify-content: center;
1535
+ flex: none;
1536
+ width: 28px;
1537
+ height: 28px;
1538
+ padding: 4px;
1539
+ border: 1px solid var(--md-readonly-border, #b8b8b8);
1540
+ border-radius: 4px;
1541
+ background: var(--md-readonly-background, #f3f3f3);
1542
+ color: var(--md-readonly-foreground, #444444);
1543
+ cursor: pointer;
1544
+ pointer-events: auto;
1545
+ }
1546
+
1547
+ .md-code-block-copy:hover {
1548
+ background: var(--md-readonly-background-hover, #e9e9e9);
1549
+ }
1550
+
1551
+ .md-code-block-copy:focus-visible {
1552
+ outline: 2px solid var(--md-readonly-accent, #4c8bf5);
1553
+ outline-offset: 1px;
1554
+ }
1555
+
1556
+ .md-code-block-copy-status:not(:empty) {
1557
+ padding: 2px 6px;
1558
+ border-radius: 4px;
1559
+ background: var(--md-readonly-background, #f3f3f3);
1560
+ color: var(--md-readonly-foreground, #444444);
1561
+ font: 12px/1.4 sans-serif;
1562
+ }
1563
+
1564
+ @media (hover: none) {
1565
+ .md-code-block-actions {
1566
+ opacity: 1;
1567
+ }
430
1568
  }
431
1569
 
432
- /* Inactive: gone entirely (the gutter is empty, the text stays put). */
433
- .md-blockquote>.md-marker-blockQuoteMarker.md-marker-hidden {
434
- display: none;
435
- }
1570
+ @media (forced-colors: active) {
1571
+ .md-code-block-copy,
1572
+ .md-code-block-copy-status:not(:empty) {
1573
+ background: ButtonFace;
1574
+ color: ButtonText;
1575
+ border-color: ButtonText;
1576
+ }
436
1577
 
437
- /* Code/math blocks scroll horizontally; their look is theme-defined. */
438
- .md-code-block {
439
- overflow-x: auto;
1578
+ .md-code-block-copy:focus-visible {
1579
+ outline-color: Highlight;
1580
+ }
440
1581
  }
441
1582
 
442
1583
  .md-math-block {
@@ -447,7 +1588,8 @@
447
1588
  margin: 0;
448
1589
  }
449
1590
 
450
- .md-list li>.md-block {
1591
+ .md-list li>.md-block,
1592
+ .md-list li>.md-code-block-container>.md-code-block {
451
1593
  margin: 0;
452
1594
  }
453
1595
 
@@ -460,25 +1602,97 @@
460
1602
  position: relative;
461
1603
  }
462
1604
 
1605
+ .md-list > li {
1606
+ min-height: 1lh;
1607
+ position: relative;
1608
+ }
1609
+
463
1610
  /*
464
1611
  * The list marker is pulled into the gutter by markerKind (not `:first-child`),
465
1612
  * because a nested item may carry its source indentation as a leading glue
466
1613
  * before the marker. Gutter-positioning keeps the marker out of the inline
467
1614
  * flow so toggling it never shifts the item's text horizontally.
468
1615
  *
469
- * `line-height: inherit` makes the marker share the item's line box (its own
470
- * `.md-marker` rule shrinks it to `line-height: 1`, which floats the glyph to
471
- * the top of the taller text line); matching the line box vertically centres
472
- * the `-` with the rendered text.
1616
+ * The source box follows the first body line; the native reading marker is
1617
+ * never replaced or resized. Source symbols share the body's font baseline,
1618
+ * not a font-dependent optical centre of the painted asterisk.
473
1619
  */
474
1620
  .md-list-item-active>.md-marker-listItemMarker {
475
1621
  position: absolute;
476
1622
  right: 100%;
477
1623
  top: 0;
1624
+ }
1625
+
1626
+ .md-list-item-active>.md-marker-listItemMarker,
1627
+ .md-list-item-active>.md-list-gutter>.md-marker-listItemMarker,
1628
+ .md-source-editing .md-list-gutter > .md-marker-listItemMarker {
478
1629
  line-height: inherit;
1630
+ height: calc(1lh / var(--md-marker-font-scale));
1631
+ display: inline-flex;
1632
+ align-items: center;
1633
+ justify-content: flex-end;
1634
+ white-space: pre;
1635
+ }
1636
+
1637
+ /*
1638
+ * `display: inline-flex` above outranks the plain `.md-marker-hidden`
1639
+ * (`display: none`), so — exactly as for headings — re-hide the marker here for
1640
+ * the states that ask for it, otherwise the bullet could never be hidden.
1641
+ */
1642
+ .md-list-item-active>.md-marker-listItemMarker.md-marker-hidden,
1643
+ .md-list-item-active>.md-list-gutter>.md-marker-listItemMarker.md-marker-hidden {
1644
+ display: none;
1645
+ }
1646
+
1647
+ /* An unfinished marker still uses the gutter of its completed "marker + space" prefix. */
1648
+ .md-list-item-incomplete > .md-marker-listItemMarker::after,
1649
+ .md-list-item-incomplete > .md-list-gutter > .md-marker-listItemMarker::after {
1650
+ content: ' ';
479
1651
  white-space: pre;
480
1652
  }
481
1653
 
1654
+ .md-list-item-incomplete .md-marker-listItemMarker > .md-list-item-line-anchor {
1655
+ font-size: calc(1em / var(--md-marker-font-scale));
1656
+ }
1657
+
1658
+ .md-marker-listItemMarker:has(> .md-list-marker-symbol) {
1659
+ font-family: inherit;
1660
+ --md-marker-font-scale: 1;
1661
+ }
1662
+
1663
+ .md-list-marker-symbol {
1664
+ display: inline-block;
1665
+ flex: 0 0 1em;
1666
+ width: 1em;
1667
+ text-align: center;
1668
+ }
1669
+
1670
+ .md-marker-listItemMarker:has(> .md-list-marker-symbol) > :is(.md-ws-space, .md-ws-tab),
1671
+ .md-source-editing .md-list-continuation-separator {
1672
+ font-family: var(--md-marker-font-family);
1673
+ word-spacing: calc(0.5em - 1ch + var(--md-list-marker-reserve) / var(--md-list-marker-spaces));
1674
+ tab-size: calc(0.5em + var(--md-list-marker-reserve) / var(--md-list-marker-spaces));
1675
+ }
1676
+
1677
+ .md-list-item-incomplete > .md-marker-listItemMarker:has(> .md-list-marker-symbol)::after,
1678
+ .md-list-item-incomplete > .md-list-gutter > .md-marker-listItemMarker:has(> .md-list-marker-symbol)::after {
1679
+ width: 0.5em;
1680
+ }
1681
+
1682
+ /*
1683
+ * An inactive ordered item uses the browser's native `::marker`. Match its
1684
+ * typography when revealing the source marker so switching the active item
1685
+ * does not change the number's width or horizontal position: an ordered marker
1686
+ * opts out of the muted size step entirely, which also makes the `1lh`
1687
+ * compensation above a no-op for it.
1688
+ */
1689
+ ol.md-list>.md-list-item-active>.md-marker-listItemMarker,
1690
+ ol.md-list>.md-list-item-active>.md-list-gutter>.md-marker-listItemMarker,
1691
+ .md-source-editing ol.md-list > li > .md-list-gutter > .md-marker-listItemMarker {
1692
+ font-family: inherit;
1693
+ --md-marker-font-scale: 1;
1694
+ }
1695
+
482
1696
  /*
483
1697
  * A nested item's source indentation precedes its bullet (`␣␣- text`). The
484
1698
  * indent glue and the bullet are mounted together in this gutter span, which is
@@ -507,8 +1721,66 @@
507
1721
  justify-content: space-between;
508
1722
  }
509
1723
 
1724
+ .md-source-editing .md-list-gutter {
1725
+ top: 0;
1726
+ height: 1lh;
1727
+ align-items: center;
1728
+ }
1729
+
1730
+ .md-source-editing .md-list-gutter > .md-glue-indent,
1731
+ .md-source-editing .md-list-continuation-indent {
1732
+ --md-source-indent-width: calc(var(--md-list-source-indent) * var(--md-list-indent-step, 2em));
1733
+ --md-source-space-width: calc(var(--md-source-indent-width) / var(--md-indent-length));
1734
+ flex-basis: var(--md-source-indent-width);
1735
+ display: block;
1736
+ font-family: var(--md-marker-font-family);
1737
+ /* Stretch the source character itself so DOM ranges and selections fill the cell too. */
1738
+ word-spacing: calc(var(--md-source-space-width) - 1ch);
1739
+ tab-size: var(--md-source-space-width);
1740
+ }
1741
+
1742
+ .md-source-editing .md-task-list-item > .md-list-gutter > .md-glue-indent {
1743
+ --md-source-indent-width: calc(var(--md-list-source-indent) * var(--md-list-indent-step, 2em) / 2);
1744
+ }
1745
+
1746
+ .md-source-editing .md-list-continuation-prefix {
1747
+ font-family: var(--md-marker-font-family);
1748
+ white-space: pre;
1749
+ }
1750
+
1751
+ .md-source-editing .md-list-continuation-prefix > span {
1752
+ display: inline;
1753
+ }
1754
+
1755
+ .md-source-editing .md-list-continuation-symbol {
1756
+ word-spacing: calc(1em - 1ch);
1757
+ }
1758
+
1759
+ .md-source-editing .md-list-continuation-outside {
1760
+ margin-inline-start: calc((var(--md-list-level) - var(--md-list-source-indent)) * var(--md-list-indent-step, 2em) - 1.5em - var(--md-list-marker-reserve));
1761
+ }
1762
+
1763
+ .md-source-editing .md-list-gutter > .md-marker-listItemMarker.md-marker-hidden {
1764
+ display: inline-flex;
1765
+ visibility: hidden;
1766
+ }
1767
+
510
1768
  .md-list-gutter>.md-marker-listItemMarker {
511
1769
  flex: 0 0 auto;
1770
+ white-space: pre;
1771
+ }
1772
+
1773
+ /*
1774
+ * A nested item's gutter stays one body line tall. The marker has the same
1775
+ * compensated line box as a top-level marker, including when it hosts the
1776
+ * incomplete item's zero-source caret anchor.
1777
+ *
1778
+ * The gutter and source symbol carry body typography, so their baselines stay
1779
+ * aligned without measuring fonts or changing native reading markers.
1780
+ */
1781
+ .md-list-item-active>.md-list-gutter {
1782
+ height: 1lh;
1783
+ align-items: center;
512
1784
  }
513
1785
 
514
1786
 
@@ -523,6 +1795,20 @@
523
1795
  white-space: pre;
524
1796
  }
525
1797
 
1798
+ /*
1799
+ * A continuation-line indent inside a paragraph is source-only padding. When
1800
+ * inactive, the preceding soft-break newline already collapses to the single
1801
+ * rendered space Markdown requires; retaining the hidden indent would add the
1802
+ * tab/space run's width on top of it.
1803
+ */
1804
+ .md-paragraph>.md-glue-indent.md-glue-hidden {
1805
+ display: none;
1806
+ }
1807
+
1808
+ .md-source-editing .md-paragraph>.md-glue-indent.md-glue-hidden {
1809
+ display: inline;
1810
+ }
1811
+
526
1812
  /*
527
1813
  * A loose list item's later block (its second paragraph etc.) owns the source
528
1814
  * continuation indent that precedes it as its `leadingTrivia`. Like a nested
@@ -532,12 +1818,14 @@
532
1818
  * active (the footprint is identical in both states, so the text never shifts).
533
1819
  */
534
1820
  .md-list li>.md-block,
535
- .md-task-list-item>.md-block {
1821
+ .md-task-list-item>.md-block,
1822
+ .md-list li>.md-code-block-container>.md-code-block {
536
1823
  position: relative;
537
1824
  }
538
1825
 
539
1826
  .md-list li>.md-block>.md-glue-indent:first-child,
540
- .md-task-list-item>.md-block>.md-glue-indent:first-child {
1827
+ .md-task-list-item>.md-block>.md-glue-indent:first-child,
1828
+ .md-list li>.md-code-block-container>.md-code-block>.md-glue-indent:first-child {
541
1829
  position: absolute;
542
1830
  right: 100%;
543
1831
  top: 0;
@@ -546,34 +1834,148 @@
546
1834
  .md-task-list-item {
547
1835
  list-style: none;
548
1836
  position: relative;
549
- /*
550
- * Width of the checkbox / `[x]` source column. Single-sourced so the marker
551
- * reservation on the first paragraph and the left indent of any following
552
- * block (loose task items) stay in lockstep — keeping every block's text in
553
- * one vertical column under the marker.
554
- */
555
- --md-task-marker-width: 1.75em;
556
1837
  }
557
1838
 
558
- /*
559
- * Reserve the marker column after the `[x]`/`[ ]` source marker (the first glue
560
- * in a task item's paragraph) so the rendered checkbox widget overlaid on it has
561
- * a comfortable gap before the text. The fixed width applies in both active and
562
- * inactive states, so the first text character does not drift horizontally when
563
- * markers toggle (see the compare fixture's `checkMarkedTextX` assertion).
564
- */
565
- .md-task-list-item .md-paragraph>.md-glue:first-child {
1839
+ .md-list > li {
1840
+ --md-list-label-reserve: 0em;
1841
+ --md-list-marker-reserve: var(--md-list-label-reserve);
1842
+ --md-list-source-padding: 0em;
1843
+ }
1844
+
1845
+ .md-list > .md-list-item-active {
1846
+ --md-list-source-padding: calc((var(--md-list-marker-spaces) - 1) * 0.5em);
1847
+ }
1848
+
1849
+ .md-list > .md-task-list-item {
1850
+ --md-list-marker-reserve: 0em;
1851
+ }
1852
+
1853
+ .md-list-with-task-items > li:not(.md-empty-block) {
1854
+ --md-list-label-reserve: 0.5em;
1855
+ }
1856
+
1857
+ .md-editor .md-list > li > .md-paragraph {
1858
+ padding-inline-start: calc(var(--md-list-label-reserve) + var(--md-list-source-padding));
1859
+ }
1860
+
1861
+ .md-editor .md-list > li > .md-list-item-line-anchor {
1862
+ margin-inline-start: calc(var(--md-list-label-reserve) + var(--md-list-source-padding));
1863
+ }
1864
+
1865
+ .md-editor .md-list > li > .md-marker-listItemMarker {
1866
+ right: calc(100% - (var(--md-list-label-reserve) + var(--md-list-source-padding)) / var(--md-marker-font-scale));
1867
+ }
1868
+
1869
+ .md-editor .md-list-gutter {
1870
+ right: calc(100% - var(--md-list-label-reserve) - var(--md-list-source-padding));
1871
+ }
1872
+
1873
+ .md-source-editing .md-marker-listItemMarker {
1874
+ word-spacing: calc(var(--md-list-marker-reserve) / var(--md-marker-font-scale) / var(--md-list-marker-spaces));
1875
+ }
1876
+
1877
+ /* Keep the mandatory separator's native width; each extra source space adds a body-sized half-em cell. */
1878
+ .md-source-editing .md-marker-listItemMarker > :is(.md-ws-space, .md-ws-tab) ~ :is(.md-ws-space, .md-ws-tab) {
1879
+ font-family: var(--md-marker-font-family);
1880
+ word-spacing: calc((0.5em + var(--md-list-marker-reserve) / var(--md-list-marker-spaces)) / var(--md-marker-font-scale) - 1ch);
1881
+ tab-size: calc((0.5em + var(--md-list-marker-reserve) / var(--md-list-marker-spaces)) / var(--md-marker-font-scale));
1882
+ }
1883
+
1884
+ .md-task-separator {
1885
+ position: absolute;
1886
+ left: calc(var(--md-list-source-padding) - 1em + 1.5ch * var(--md-marker-font-scale));
1887
+ top: 0;
1888
+ font-family: var(--md-marker-font-family);
1889
+ white-space: pre;
1890
+ word-spacing: calc((1.5em - 1.5ch * var(--md-marker-font-scale)) / var(--md-separator-length) - 1ch);
1891
+ tab-size: calc((1.5em - 1.5ch * var(--md-marker-font-scale)) / var(--md-separator-length));
1892
+ }
1893
+
1894
+ .md-task-list-item>.md-paragraph>.md-glue-taskListCheck {
1895
+ position: absolute;
1896
+ top: 0;
1897
+ font-family: var(--md-marker-font-family);
1898
+ font-size: calc(1em * var(--md-marker-font-scale));
1899
+ left: calc((var(--md-list-source-padding) - 1em) / var(--md-marker-font-scale) - 1.5ch);
1900
+ width: 3ch;
1901
+ }
1902
+
1903
+ .md-source-editing .md-task-list-item > .md-paragraph > .md-glue-taskListCheck {
1904
+ position: static;
566
1905
  display: inline-block;
567
- width: var(--md-task-marker-width);
1906
+ margin-inline-start: calc((-1em - var(--md-list-label-reserve)) / var(--md-marker-font-scale) - 1.5ch);
568
1907
  }
569
1908
 
570
- /*
571
- * Following blocks in a loose task item (the second paragraph etc.) carry no
572
- * marker glue, so indent them by the marker column to line their text up under
573
- * the first paragraph's text rather than under the checkbox.
574
- */
575
- .md-task-list-item>.md-block+.md-block {
576
- padding-left: var(--md-task-marker-width);
1909
+ .md-source-editing .md-task-separator {
1910
+ position: static;
1911
+ }
1912
+
1913
+ .md-source-editing .md-list-continuation-source {
1914
+ display: none;
1915
+ white-space: pre;
1916
+ }
1917
+
1918
+ .md-source-editing .md-block-active .md-list-continuation-source {
1919
+ display: inline;
1920
+ }
1921
+
1922
+ .md-source-editing .md-list-continuation-source.md-list-continuation-leading {
1923
+ display: inline;
1924
+ position: absolute;
1925
+ right: calc(100% - var(--md-list-label-reserve) - var(--md-list-source-padding));
1926
+ top: auto;
1927
+ }
1928
+
1929
+ .md-source-editing .md-list .md-code-block-container:has(> .md-code-list-source) {
1930
+ display: block;
1931
+ --md-list-prefix-width: calc(var(--md-list-source-indent) * var(--md-list-indent-step, 2em) + 1em + var(--md-list-marker-spaces) * 0.5em + var(--md-list-label-reserve));
1932
+ margin-inline-start: calc(var(--md-list-label-reserve) + var(--md-list-source-padding) - var(--md-list-prefix-width));
1933
+ }
1934
+
1935
+ .md-source-editing .md-list .md-code-list-source {
1936
+ position: relative;
1937
+ font-size: inherit;
1938
+ border-inline-start-width: 0;
1939
+ padding-inline-start: var(--md-list-prefix-width);
1940
+ }
1941
+
1942
+ .md-source-editing .md-list li > .md-code-block-container > .md-code-list-source > .md-list-continuation-prefix:first-child {
1943
+ right: calc(100% - var(--md-list-prefix-width));
1944
+ top: auto;
1945
+ }
1946
+
1947
+ .md-code-source-line {
1948
+ position: relative;
1949
+ }
1950
+
1951
+ .md-code-source-line > .md-list-continuation-prefix {
1952
+ position: absolute;
1953
+ right: 100%;
1954
+ }
1955
+
1956
+ .md-editor .md-task-list-item > .md-list-gutter {
1957
+ right: calc(100% - var(--md-list-source-padding));
1958
+ }
1959
+
1960
+ .md-task-list-item > .md-list-gutter::after {
1961
+ content: '';
1962
+ font-family: var(--md-marker-font-family);
1963
+ font-size: calc(1em * var(--md-marker-font-scale));
1964
+ flex: 0 0 calc(1em / var(--md-marker-font-scale) + 1.5ch);
1965
+ }
1966
+
1967
+ .md-task-list-item > .md-block + .md-block:not(.md-list) {
1968
+ padding-left: calc(var(--md-list-label-reserve) + var(--md-list-source-padding));
1969
+ }
1970
+
1971
+ .md-task-list-item > .md-list {
1972
+ padding-left: var(--md-list-indent-step, 2em);
1973
+ }
1974
+
1975
+ .md-task-list-item > .md-checkbox {
1976
+ font: inherit;
1977
+ left: calc(var(--md-list-source-padding) - 1em - 8px);
1978
+ top: calc((1lh - 16px) / 2);
577
1979
  }
578
1980
 
579
1981
  .md-checkbox {
@@ -588,6 +1990,7 @@
588
1990
  position: absolute;
589
1991
  left: 0;
590
1992
  top: 0.25em;
1993
+ z-index: 1;
591
1994
  cursor: pointer;
592
1995
  transition: background-color 0.15s ease, border-color 0.15s ease;
593
1996
  }
@@ -600,8 +2003,8 @@
600
2003
  .md-checkbox:checked::after {
601
2004
  content: '';
602
2005
  position: absolute;
603
- left: 3px;
604
- top: 0px;
2006
+ left: 2.5px;
2007
+ top: -1px;
605
2008
  width: 5px;
606
2009
  height: 9px;
607
2010
  border: solid white;
@@ -613,6 +2016,39 @@
613
2016
  border-color: #888;
614
2017
  }
615
2018
 
2019
+ /*
2020
+ * The rotating "broken rounded-square" progress ring for an inactive task item
2021
+ * whose text begins with the hidden `:running:` marker (see
2022
+ * `ListItemViewData.isRunning`). Rendered as a conic-gradient ring — masked so
2023
+ * only the ring (not its center) paints — with a transparent gap that spins,
2024
+ * reading as a segmented spinner rather than a checked/unchecked box.
2025
+ */
2026
+ .md-checkbox-running,
2027
+ .md-checkbox-running:checked {
2028
+ padding: 2px;
2029
+ border: 0;
2030
+ border-radius: 4px;
2031
+ background: conic-gradient(
2032
+ transparent 0deg 42deg,
2033
+ #bbb 62deg 360deg
2034
+ );
2035
+ -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
2036
+ -webkit-mask-composite: xor;
2037
+ mask-composite: exclude;
2038
+ animation: md-checkbox-spin 0.8s linear infinite;
2039
+ opacity: 1;
2040
+ }
2041
+
2042
+ @keyframes md-checkbox-spin {
2043
+ to {
2044
+ transform: rotate(360deg);
2045
+ }
2046
+ }
2047
+
2048
+ .md-checkbox-running:hover {
2049
+ border-color: transparent;
2050
+ }
2051
+
616
2052
  .md-checkbox:checked:hover {
617
2053
  background-color: #3a73d4;
618
2054
  border-color: #3a73d4;
@@ -623,14 +2059,66 @@
623
2059
  opacity: 0.6;
624
2060
  }
625
2061
 
2062
+ .md-checkbox-running:disabled {
2063
+ opacity: 1;
2064
+ }
2065
+
2066
+ @media (prefers-reduced-motion: reduce) {
2067
+ .md-checkbox-running {
2068
+ animation: none !important;
2069
+ }
2070
+ }
2071
+
2072
+ /*
2073
+ * The `:running:` marker hidden from an inactive task item's rendered text
2074
+ * (see `TextViewData.hiddenPrefixLength`). It stays real, selectable source —
2075
+ * only visually hidden, per "Hidden markers remain real source" — so it takes
2076
+ * no layout space in either state.
2077
+ */
2078
+ .md-runner-marker {
2079
+ display: none;
2080
+ }
2081
+
626
2082
  .md-cursor {
627
2083
  position: absolute;
628
2084
  width: 2px;
629
2085
  background: var(--md-cursor-background, #000);
630
2086
  pointer-events: none;
2087
+ }
2088
+
2089
+ /*
2090
+ * The painted caret is only shown while the editor is genuinely focused — focus
2091
+ * rests inside it and its window is focused, mirrored onto the root as
2092
+ * `.md-focused`. When unfocused, hide the caret element but keep its layout box
2093
+ * (so caret geometry, selection and comment anchoring are unchanged) and stop
2094
+ * the blink. Adding the animation on focus restarts it from 0% (a solid caret).
2095
+ */
2096
+ .md-editor:not(.md-focused) .md-cursor {
2097
+ visibility: hidden;
2098
+ }
2099
+
2100
+ .md-editor.md-focused .md-cursor {
631
2101
  animation: md-cursor-blink 1s step-end infinite;
632
2102
  }
633
2103
 
2104
+ /*
2105
+ * Read-only mode retains the logical caret for selection and comment anchoring.
2106
+ * Hide only its painted element so unlocking can restore it in place.
2107
+ */
2108
+ .md-editor.md-readonly .md-cursor {
2109
+ visibility: hidden;
2110
+ }
2111
+
2112
+ .md-editor.md-readonly-editing-attempt {
2113
+ animation: md-readonly-editing-attempt 300ms ease-out;
2114
+ }
2115
+
2116
+ @keyframes md-readonly-editing-attempt {
2117
+ 50% {
2118
+ box-shadow: inset 0 0 0 2px var(--md-readonly-shine-glow, rgba(255, 255, 255, 0.58));
2119
+ }
2120
+ }
2121
+
634
2122
  @keyframes md-cursor-blink {
635
2123
 
636
2124
  0%,
@@ -646,15 +2134,15 @@
646
2134
  /*
647
2135
  * Edit / read-only lock toggle.
648
2136
  *
649
- * The host is a zero-height sticky strip pinned to the top of the scroll
650
- * viewport, so the lock stays in the top-right corner as the document scrolls.
651
- * Being height-0 it never participates in the document's vertical flow. Colors
652
- * use local `--md-readonly-*` custom properties with literal fallbacks so this
653
- * base file stays theme-agnostic (themes may override them).
2137
+ * The sticky overlay never changes text flow or the symmetric content margins.
2138
+ * Narrow margins let the control overlap content rather than reserving a rail.
2139
+ * Colors use local `--md-readonly-*` custom
2140
+ * properties with literal fallbacks so this base file stays theme-agnostic
2141
+ * (themes may override them).
654
2142
  */
655
2143
  .md-readonly-toggle-host {
656
2144
  position: sticky;
657
- top: 0;
2145
+ top: var(--md-readonly-toggle-inset);
658
2146
  height: 0;
659
2147
  z-index: 10;
660
2148
  pointer-events: none;
@@ -662,28 +2150,78 @@
662
2150
 
663
2151
  .md-readonly-toggle {
664
2152
  position: absolute;
665
- top: 8px;
666
- right: 8px;
2153
+ top: 4px;
2154
+ right: var(--md-readonly-toggle-inset);
667
2155
  pointer-events: auto;
668
- display: inline-flex;
2156
+ display: inline-grid;
2157
+ grid-template-columns: repeat(3, 24px);
669
2158
  align-items: center;
670
- gap: 5px;
671
- height: 26px;
672
- padding: 0 10px;
673
- border-radius: 13px;
674
- border: 1px solid var(--md-readonly-border, #d4d4d4);
675
- background: var(--md-readonly-background, #ffffff);
676
- color: var(--md-readonly-foreground, #444);
677
- font: 600 11px/1 system-ui, -apple-system, 'Segoe UI', sans-serif;
678
- letter-spacing: 0.02em;
2159
+ justify-items: center;
2160
+ gap: 2px;
2161
+ box-sizing: border-box;
2162
+ width: var(--md-readonly-toggle-width);
2163
+ height: var(--md-readonly-toggle-height);
2164
+ padding: 3px;
2165
+ overflow: hidden;
2166
+ direction: ltr;
2167
+ appearance: none;
2168
+ border-radius: 999px;
2169
+ border: 1px solid var(--md-readonly-border, #b8b8b8);
2170
+ background: var(--md-readonly-background, #f3f3f3);
2171
+ color: var(--md-readonly-foreground, #444444);
2172
+ font-size: 16px;
2173
+ line-height: 1;
679
2174
  cursor: pointer;
680
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
681
- transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
2175
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08);
2176
+ transition: background-color 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
2177
+ }
2178
+
2179
+ .md-readonly-toggle::after {
2180
+ content: '';
2181
+ position: absolute;
2182
+ z-index: 2;
2183
+ top: -8px;
2184
+ bottom: -8px;
2185
+ left: -30px;
2186
+ width: 24px;
2187
+ background: linear-gradient(90deg,
2188
+ transparent,
2189
+ var(--md-readonly-shine-edge, rgba(255, 255, 255, 0.16)) 24%,
2190
+ var(--md-readonly-shine, #ffffff) 50%,
2191
+ var(--md-readonly-shine-edge, rgba(255, 255, 255, 0.16)) 76%,
2192
+ transparent);
2193
+ box-shadow: 0 0 8px 2px var(--md-readonly-shine-glow, rgba(255, 255, 255, 0.58));
2194
+ opacity: 0;
2195
+ pointer-events: none;
2196
+ transform: skewX(-20deg);
2197
+ }
2198
+
2199
+ .md-readonly-toggle.md-readonly-toggle-shine::after {
2200
+ animation: md-readonly-toggle-shine 2s linear;
2201
+ will-change: transform, opacity;
2202
+ }
2203
+
2204
+ @keyframes md-readonly-toggle-shine {
2205
+ 0% {
2206
+ opacity: 0;
2207
+ transform: translateX(0) skewX(-20deg);
2208
+ }
2209
+
2210
+ 12%,
2211
+ 88% {
2212
+ opacity: 1;
2213
+ }
2214
+
2215
+ 100% {
2216
+ opacity: 0;
2217
+ transform: translateX(122px) skewX(-20deg);
2218
+ }
682
2219
  }
683
2220
 
684
2221
  .md-readonly-toggle:hover {
685
- border-color: var(--md-readonly-border-hover, #b8b8b8);
686
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.16);
2222
+ border-color: var(--md-readonly-border-hover, #8d8d8d);
2223
+ background: var(--md-readonly-background-hover, #e9e9e9);
2224
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 6px 16px rgba(0, 0, 0, 0.1);
687
2225
  }
688
2226
 
689
2227
  .md-readonly-toggle:focus-visible {
@@ -691,36 +2229,89 @@
691
2229
  outline-offset: 1px;
692
2230
  }
693
2231
 
694
- .md-readonly-toggle .md-readonly-toggle-icon {
695
- display: inline-flex;
696
- align-items: center;
2232
+ .md-readonly-toggle .md-readonly-toggle-indicator {
2233
+ position: absolute;
2234
+ top: 50%;
2235
+ left: 3px;
2236
+ width: 24px;
2237
+ height: 24px;
2238
+ border-radius: 50%;
2239
+ background: var(--md-readonly-accent, #4c8bf5);
2240
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.25);
2241
+ transform: translate(26px, -50%);
2242
+ transition: background-color 0.12s ease, transform 0.16s ease;
697
2243
  }
698
2244
 
699
- .md-readonly-toggle .md-readonly-toggle-label {
700
- white-space: nowrap;
2245
+ .md-readonly-toggle .md-readonly-toggle-icon {
2246
+ position: relative;
2247
+ z-index: 1;
2248
+ display: block;
2249
+ width: 16px;
2250
+ height: 16px;
2251
+ color: var(--md-readonly-foreground, #444444);
2252
+ opacity: 0.62;
2253
+ pointer-events: none;
2254
+ transition: color 0.12s ease, opacity 0.12s ease;
701
2255
  }
702
2256
 
703
- /* Show the open padlock while editing, the closed one while locked. */
704
- .md-readonly-toggle .md-readonly-toggle-icon-locked {
705
- display: none;
2257
+ .md-readonly-toggle:not(.md-readonly-toggle-locked) .md-readonly-toggle-icon-editing,
2258
+ .md-readonly-toggle.md-readonly-toggle-locked .md-readonly-toggle-icon-locked {
2259
+ color: var(--md-readonly-accent-foreground, #ffffff);
2260
+ opacity: 1;
706
2261
  }
707
2262
 
708
- .md-readonly-toggle.md-readonly-toggle-locked .md-readonly-toggle-icon-unlocked {
709
- display: none;
2263
+ .md-readonly-toggle.md-readonly-toggle-locked .md-readonly-toggle-indicator {
2264
+ transform: translate(0, -50%);
710
2265
  }
711
2266
 
712
- .md-readonly-toggle.md-readonly-toggle-locked .md-readonly-toggle-icon-locked {
713
- display: inline-flex;
714
- }
2267
+ @media (prefers-reduced-motion: reduce) {
715
2268
 
716
- /* Locked (read-only) state: filled accent so the engaged lock reads clearly. */
717
- .md-readonly-toggle.md-readonly-toggle-locked {
718
- border-color: var(--md-readonly-accent, #4c8bf5);
719
- background: var(--md-readonly-accent, #4c8bf5);
720
- color: var(--md-readonly-accent-foreground, #ffffff);
2269
+ .md-editor.md-readonly-editing-attempt,
2270
+ .md-readonly-toggle,
2271
+ .md-readonly-toggle .md-readonly-toggle-indicator,
2272
+ .md-readonly-toggle .md-readonly-toggle-icon,
2273
+ .md-readonly-toggle.md-readonly-toggle-shine::after {
2274
+ animation: none;
2275
+ transition: none;
2276
+ }
721
2277
  }
722
2278
 
723
- .md-readonly-toggle.md-readonly-toggle-locked:hover {
724
- border-color: var(--md-readonly-accent-hover, #3a73d4);
725
- background: var(--md-readonly-accent-hover, #3a73d4);
2279
+ @media (forced-colors: active) {
2280
+ .md-readonly-toggle {
2281
+ forced-color-adjust: none;
2282
+ border-color: ButtonText;
2283
+ background: ButtonFace;
2284
+ color: ButtonText;
2285
+ box-shadow: none;
2286
+ }
2287
+
2288
+ .md-readonly-toggle::after {
2289
+ display: none;
2290
+ }
2291
+
2292
+ .md-readonly-toggle:hover {
2293
+ border-color: Highlight;
2294
+ background: ButtonFace;
2295
+ box-shadow: none;
2296
+ }
2297
+
2298
+ .md-readonly-toggle:focus-visible {
2299
+ outline-color: Highlight;
2300
+ }
2301
+
2302
+ .md-readonly-toggle .md-readonly-toggle-indicator {
2303
+ background: Highlight;
2304
+ box-shadow: none;
2305
+ }
2306
+
2307
+ .md-readonly-toggle .md-readonly-toggle-icon {
2308
+ color: ButtonText;
2309
+ opacity: 1;
2310
+ }
2311
+
2312
+ .md-readonly-toggle:not(.md-readonly-toggle-locked):not(.md-readonly-toggle-source) .md-readonly-toggle-icon-editing,
2313
+ .md-readonly-toggle.md-readonly-toggle-source .md-readonly-toggle-icon-source,
2314
+ .md-readonly-toggle.md-readonly-toggle-locked .md-readonly-toggle-icon-locked {
2315
+ color: HighlightText;
2316
+ }
726
2317
  }