mossmd 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/LICENSE +21 -0
- package/README.md +336 -0
- package/dist/collab/index.d.ts +14 -0
- package/dist/collab/index.d.ts.map +1 -0
- package/dist/collab/index.js +6 -0
- package/dist/collab/index.js.map +1 -0
- package/dist/core/code-languages.d.ts +3 -0
- package/dist/core/code-languages.d.ts.map +1 -0
- package/dist/core/code-languages.js +130 -0
- package/dist/core/code-languages.js.map +1 -0
- package/dist/core/decoration-utils.d.ts +4 -0
- package/dist/core/decoration-utils.d.ts.map +1 -0
- package/dist/core/decoration-utils.js +25 -0
- package/dist/core/decoration-utils.js.map +1 -0
- package/dist/core/edit-helpers.d.ts +13 -0
- package/dist/core/edit-helpers.d.ts.map +1 -0
- package/dist/core/edit-helpers.js +318 -0
- package/dist/core/edit-helpers.js.map +1 -0
- package/dist/core/icons.d.ts +16 -0
- package/dist/core/icons.d.ts.map +1 -0
- package/dist/core/icons.js +86 -0
- package/dist/core/icons.js.map +1 -0
- package/dist/core/inline-preview.d.ts +32 -0
- package/dist/core/inline-preview.d.ts.map +1 -0
- package/dist/core/inline-preview.js +925 -0
- package/dist/core/inline-preview.js.map +1 -0
- package/dist/core/list-editing.d.ts +10 -0
- package/dist/core/list-editing.d.ts.map +1 -0
- package/dist/core/list-editing.js +244 -0
- package/dist/core/list-editing.js.map +1 -0
- package/dist/core/list-model.d.ts +40 -0
- package/dist/core/list-model.d.ts.map +1 -0
- package/dist/core/list-model.js +114 -0
- package/dist/core/list-model.js.map +1 -0
- package/dist/core/list-navigation.d.ts +3 -0
- package/dist/core/list-navigation.d.ts.map +1 -0
- package/dist/core/list-navigation.js +234 -0
- package/dist/core/list-navigation.js.map +1 -0
- package/dist/core/markdown-context.d.ts +3 -0
- package/dist/core/markdown-context.d.ts.map +1 -0
- package/dist/core/markdown-context.js +10 -0
- package/dist/core/markdown-context.js.map +1 -0
- package/dist/core/preview-activity.d.ts +18 -0
- package/dist/core/preview-activity.d.ts.map +1 -0
- package/dist/core/preview-activity.js +199 -0
- package/dist/core/preview-activity.js.map +1 -0
- package/dist/core/preview-widgets.d.ts +65 -0
- package/dist/core/preview-widgets.d.ts.map +1 -0
- package/dist/core/preview-widgets.js +359 -0
- package/dist/core/preview-widgets.js.map +1 -0
- package/dist/core/read-only.d.ts +26 -0
- package/dist/core/read-only.d.ts.map +1 -0
- package/dist/core/read-only.js +49 -0
- package/dist/core/read-only.js.map +1 -0
- package/dist/core/tree-progress.d.ts +29 -0
- package/dist/core/tree-progress.d.ts.map +1 -0
- package/dist/core/tree-progress.js +143 -0
- package/dist/core/tree-progress.js.map +1 -0
- package/dist/editor.d.ts +219 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +551 -0
- package/dist/editor.js.map +1 -0
- package/dist/features/callout/index.d.ts +9 -0
- package/dist/features/callout/index.d.ts.map +1 -0
- package/dist/features/callout/index.js +223 -0
- package/dist/features/callout/index.js.map +1 -0
- package/dist/features/file-blocks/index.d.ts +12 -0
- package/dist/features/file-blocks/index.d.ts.map +1 -0
- package/dist/features/file-blocks/index.js +397 -0
- package/dist/features/file-blocks/index.js.map +1 -0
- package/dist/features/image/index.d.ts +28 -0
- package/dist/features/image/index.d.ts.map +1 -0
- package/dist/features/image/index.js +699 -0
- package/dist/features/image/index.js.map +1 -0
- package/dist/features/index.d.ts +17 -0
- package/dist/features/index.d.ts.map +1 -0
- package/dist/features/index.js +9 -0
- package/dist/features/index.js.map +1 -0
- package/dist/features/search/index.d.ts +4 -0
- package/dist/features/search/index.d.ts.map +1 -0
- package/dist/features/search/index.js +131 -0
- package/dist/features/search/index.js.map +1 -0
- package/dist/features/slash-commands/index.d.ts +52 -0
- package/dist/features/slash-commands/index.d.ts.map +1 -0
- package/dist/features/slash-commands/index.js +422 -0
- package/dist/features/slash-commands/index.js.map +1 -0
- package/dist/features/table/index.d.ts +44 -0
- package/dist/features/table/index.d.ts.map +1 -0
- package/dist/features/table/index.js +1262 -0
- package/dist/features/table/index.js.map +1 -0
- package/dist/features/upload/index.d.ts +80 -0
- package/dist/features/upload/index.d.ts.map +1 -0
- package/dist/features/upload/index.js +790 -0
- package/dist/features/upload/index.js.map +1 -0
- package/dist/features/wiki-links/index.d.ts +27 -0
- package/dist/features/wiki-links/index.d.ts.map +1 -0
- package/dist/features/wiki-links/index.js +577 -0
- package/dist/features/wiki-links/index.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/styles/content.css +247 -0
- package/dist/styles/inline-preview.css +2116 -0
- package/dist/styles/tokens.css +234 -0
- package/dist/syntax/highlight.d.ts +10 -0
- package/dist/syntax/highlight.d.ts.map +1 -0
- package/dist/syntax/highlight.js +75 -0
- package/dist/syntax/highlight.js.map +1 -0
- package/dist/syntax/index.d.ts +16 -0
- package/dist/syntax/index.d.ts.map +1 -0
- package/dist/syntax/index.js +29 -0
- package/dist/syntax/index.js.map +1 -0
- package/dist/theme/index.d.ts +6 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +204 -0
- package/dist/theme/index.js.map +1 -0
- package/package.json +237 -0
|
@@ -0,0 +1,2116 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @mossmd — inline live-preview styles.
|
|
3
|
+
*
|
|
4
|
+
* Every rule below sets font-size / weight / decoration purely by CSS
|
|
5
|
+
* class, and does NOT depend on cursor state. Line heights therefore
|
|
6
|
+
* stay constant whether the line is "active" (syntax tokens visible)
|
|
7
|
+
* or "inactive" (tokens hidden by the inline-preview extension's
|
|
8
|
+
* replace-decorations) — that's what eliminates the layout-shift
|
|
9
|
+
* problem from widget-replacement approaches.
|
|
10
|
+
*
|
|
11
|
+
* Vertical-rhythm rules use `padding` on .cm-line, not `margin`. CM6
|
|
12
|
+
* measures each line's bounding-box height for virtualization;
|
|
13
|
+
* padding is inside the box (measured), margin is outside (not
|
|
14
|
+
* measured), so only padding yields the reader's spacing without
|
|
15
|
+
* confusing CM6.
|
|
16
|
+
*
|
|
17
|
+
* Theming contract: every color / font / size token below reads from
|
|
18
|
+
* a `--moss-*` custom property with an inline fallback. The
|
|
19
|
+
* defaults target a dark background; override the prefixed vars on
|
|
20
|
+
* any ancestor of the editor to theme it for your app.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
@import './tokens.css';
|
|
24
|
+
|
|
25
|
+
.cm-moss-icon {
|
|
26
|
+
display: block;
|
|
27
|
+
flex: 0 0 auto;
|
|
28
|
+
max-width: 100%;
|
|
29
|
+
max-height: 100%;
|
|
30
|
+
overflow: visible;
|
|
31
|
+
color: inherit;
|
|
32
|
+
stroke: currentColor;
|
|
33
|
+
pointer-events: none;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Root container — fills its parent so the CM6 scroller can take over
|
|
37
|
+
* scrolling behavior. Previously relied on Tailwind `h-full w-full`
|
|
38
|
+
* applied in the React layer, which only worked for consumers who had
|
|
39
|
+
* Tailwind configured. Baking the sizing into the package means
|
|
40
|
+
* dropping the editor into any height-bounded parent just works. */
|
|
41
|
+
.moss-cm-editor {
|
|
42
|
+
position: relative;
|
|
43
|
+
height: 100%;
|
|
44
|
+
width: 100%;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Content container — constrain to a comfortable reading width. This
|
|
48
|
+
* is where the prose feel mostly comes from: line length in the
|
|
49
|
+
* 60–75ch range is what lets the eye sweep naturally. The full editor
|
|
50
|
+
* frame can still be wide (for search UI, sidebars, etc.) — only the
|
|
51
|
+
* text column is narrowed. */
|
|
52
|
+
.moss-cm-editor .cm-content {
|
|
53
|
+
max-width: var(--moss-measure, 70ch);
|
|
54
|
+
margin-inline: auto;
|
|
55
|
+
padding-inline: 0.5rem;
|
|
56
|
+
font-family: var(--moss-font, system-ui, -apple-system, BlinkMacSystemFont, sans-serif);
|
|
57
|
+
font-size: var(--moss-body-size, 1.0625rem);
|
|
58
|
+
line-height: var(--moss-body-leading, 1.7);
|
|
59
|
+
color: var(--moss-fg, #dcddde);
|
|
60
|
+
text-wrap: pretty;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.cm-line.cm-moss-empty-line {
|
|
64
|
+
font-size: var(--moss-body-size, 1.0625rem);
|
|
65
|
+
line-height: 1.25;
|
|
66
|
+
min-height: calc(var(--moss-body-size, 1.0625rem) * var(--moss-body-leading, 1.7));
|
|
67
|
+
padding-top: max(0px, calc(var(--moss-body-size, 1.0625rem) * (var(--moss-body-leading, 1.7) - 1.25) / 2));
|
|
68
|
+
padding-bottom: max(0px, calc(var(--moss-body-size, 1.0625rem) * (var(--moss-body-leading, 1.7) - 1.25) / 2));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Heading lines. Padding-top (not margin-top) creates the rhythm so
|
|
72
|
+
* CM6's line-height measurement stays correct.
|
|
73
|
+
*
|
|
74
|
+
* These values are intentionally small (≤ 0.2em). Prior values
|
|
75
|
+
* (0.4em–0.7em) produced a tall visual strip above the heading's
|
|
76
|
+
* text that belongs to the heading's hit-box but looks identical to
|
|
77
|
+
* the empty separator line above it. Users would click the visual
|
|
78
|
+
* "blank space above the heading" and land on the heading by
|
|
79
|
+
* surprise. The empty markdown line before a heading (which almost
|
|
80
|
+
* every real doc has) supplies the rest of the rhythm naturally. */
|
|
81
|
+
.cm-line.cm-moss-h1 {
|
|
82
|
+
font-size: 1.35em;
|
|
83
|
+
font-weight: 700;
|
|
84
|
+
line-height: 1.3;
|
|
85
|
+
letter-spacing: -0.015em;
|
|
86
|
+
padding-top: 0.15em;
|
|
87
|
+
padding-bottom: 0.1em;
|
|
88
|
+
color: var(--moss-fg, #dcddde);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.cm-line.cm-moss-h2 {
|
|
92
|
+
font-size: 1.2em;
|
|
93
|
+
font-weight: 700;
|
|
94
|
+
line-height: 1.35;
|
|
95
|
+
padding-top: 0.15em;
|
|
96
|
+
padding-bottom: 0.1em;
|
|
97
|
+
color: var(--moss-fg, #dcddde);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.cm-line.cm-moss-h3 {
|
|
101
|
+
font-size: 1.1em;
|
|
102
|
+
font-weight: 600;
|
|
103
|
+
line-height: 1.4;
|
|
104
|
+
padding-top: 0.12em;
|
|
105
|
+
color: var(--moss-fg, #dcddde);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.cm-line.cm-moss-h4 {
|
|
109
|
+
font-size: 1em;
|
|
110
|
+
font-weight: 600;
|
|
111
|
+
padding-top: 0.1em;
|
|
112
|
+
color: var(--moss-fg, #dcddde);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.cm-line.cm-moss-h5 {
|
|
116
|
+
font-size: 0.95em;
|
|
117
|
+
font-weight: 600;
|
|
118
|
+
padding-top: 0.08em;
|
|
119
|
+
color: var(--moss-fg, #dcddde);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.cm-line.cm-moss-h6 {
|
|
123
|
+
font-size: 0.9em;
|
|
124
|
+
font-weight: 600;
|
|
125
|
+
letter-spacing: 0.03em;
|
|
126
|
+
text-transform: uppercase;
|
|
127
|
+
padding-top: 0.08em;
|
|
128
|
+
color: var(--moss-fg-muted, #888);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* Blockquote lines — each line in the quote gets a left rail. Putting
|
|
132
|
+
* the rail on every line means the visual continues for multi-line
|
|
133
|
+
* quotes even though each line is an independent DOM element. */
|
|
134
|
+
.cm-line.cm-moss-blockquote {
|
|
135
|
+
padding-left: 1rem;
|
|
136
|
+
border-left: 3px solid var(--moss-accent-soft, color-mix(in srgb, #7c3aed 72%, white 28%));
|
|
137
|
+
color: var(--moss-fg-muted, #888);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.cm-line.cm-moss-callout {
|
|
141
|
+
--moss-callout-accent: var(--moss-accent-bright, #a78bfa);
|
|
142
|
+
--moss-callout-bg: color-mix(in srgb, var(--moss-callout-accent) 10%, transparent 90%);
|
|
143
|
+
--moss-callout-border: color-mix(in srgb, var(--moss-callout-accent) 72%, var(--moss-border, #3d3d3d) 28%);
|
|
144
|
+
background: var(--moss-callout-bg);
|
|
145
|
+
border-left-color: var(--moss-callout-border);
|
|
146
|
+
color: var(--moss-fg, #dcddde);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.cm-line.cm-moss-callout-first {
|
|
150
|
+
border-top-right-radius: var(--moss-radius, 6px);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.cm-line.cm-moss-callout-last {
|
|
154
|
+
border-bottom-right-radius: var(--moss-radius, 6px);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.cm-line.cm-moss-callout-note,
|
|
158
|
+
.cm-moss-callout-label-note {
|
|
159
|
+
--moss-callout-accent: #82aaff;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.cm-line.cm-moss-callout-info,
|
|
163
|
+
.cm-line.cm-moss-callout-todo,
|
|
164
|
+
.cm-moss-callout-label-info,
|
|
165
|
+
.cm-moss-callout-label-todo {
|
|
166
|
+
--moss-callout-accent: #89ddff;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.cm-line.cm-moss-callout-tip,
|
|
170
|
+
.cm-line.cm-moss-callout-success,
|
|
171
|
+
.cm-moss-callout-label-tip,
|
|
172
|
+
.cm-moss-callout-label-success {
|
|
173
|
+
--moss-callout-accent: #c3e88d;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.cm-line.cm-moss-callout-warning,
|
|
177
|
+
.cm-moss-callout-label-warning {
|
|
178
|
+
--moss-callout-accent: #ffcb6b;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.cm-line.cm-moss-callout-important,
|
|
182
|
+
.cm-moss-callout-label-important {
|
|
183
|
+
--moss-callout-accent: #c792ea;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.cm-line.cm-moss-callout-danger,
|
|
187
|
+
.cm-line.cm-moss-callout-failure,
|
|
188
|
+
.cm-line.cm-moss-callout-bug,
|
|
189
|
+
.cm-line.cm-moss-callout-caution,
|
|
190
|
+
.cm-moss-callout-label-danger,
|
|
191
|
+
.cm-moss-callout-label-failure,
|
|
192
|
+
.cm-moss-callout-label-bug,
|
|
193
|
+
.cm-moss-callout-label-caution {
|
|
194
|
+
--moss-callout-accent: #f07178;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.cm-line.cm-moss-callout-question,
|
|
198
|
+
.cm-line.cm-moss-callout-example,
|
|
199
|
+
.cm-line.cm-moss-callout-abstract,
|
|
200
|
+
.cm-moss-callout-label-question,
|
|
201
|
+
.cm-moss-callout-label-example,
|
|
202
|
+
.cm-moss-callout-label-abstract {
|
|
203
|
+
--moss-callout-accent: #c792ea;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.cm-line.cm-moss-callout-quote,
|
|
207
|
+
.cm-moss-callout-label-quote {
|
|
208
|
+
--moss-callout-accent: var(--moss-fg-muted, #888);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.cm-moss-callout-label {
|
|
212
|
+
display: inline-flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
min-height: 1.35em;
|
|
215
|
+
margin-right: 0.45em;
|
|
216
|
+
color: var(--moss-callout-accent, var(--moss-accent-bright, #a78bfa));
|
|
217
|
+
font-size: 0.78em;
|
|
218
|
+
font-weight: 700;
|
|
219
|
+
letter-spacing: 0.02em;
|
|
220
|
+
text-transform: uppercase;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.cm-moss-callout-title {
|
|
224
|
+
font-weight: 650;
|
|
225
|
+
color: var(--moss-fg, #dcddde);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* Fenced-code lines — subtle backdrop plus a left rail so the block
|
|
229
|
+
* reads as a contained unit. The rail is an *inset box-shadow*, not a
|
|
230
|
+
* border, so it adds no width and never perturbs the line-box geometry
|
|
231
|
+
* CM6 measures for virtualization (a real border would shift the
|
|
232
|
+
* padding math between active/inactive states). */
|
|
233
|
+
.cm-line.cm-moss-fenced-code {
|
|
234
|
+
font-family: var(--moss-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
235
|
+
font-size: 0.92em;
|
|
236
|
+
position: relative;
|
|
237
|
+
background-color: color-mix(in srgb, var(--moss-code-bg, #2d2d2d) 86%, transparent 14%);
|
|
238
|
+
background-image:
|
|
239
|
+
radial-gradient(
|
|
240
|
+
circle at 1px 1px,
|
|
241
|
+
color-mix(in srgb, var(--moss-fg-faint, #666) 22%, transparent 78%) 1px,
|
|
242
|
+
transparent 1.1px
|
|
243
|
+
);
|
|
244
|
+
background-size: 14px 14px;
|
|
245
|
+
border-left: 1px solid color-mix(in srgb, var(--moss-border, #3d3d3d) 76%, transparent 24%);
|
|
246
|
+
border-right: 1px solid color-mix(in srgb, var(--moss-border, #3d3d3d) 76%, transparent 24%);
|
|
247
|
+
padding-left: 0.7rem;
|
|
248
|
+
padding-right: 2.4rem;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.cm-line.cm-moss-fenced-code-start {
|
|
252
|
+
border-top: 1px solid color-mix(in srgb, var(--moss-border, #3d3d3d) 76%, transparent 24%);
|
|
253
|
+
border-top-left-radius: var(--moss-radius, 6px);
|
|
254
|
+
border-top-right-radius: var(--moss-radius, 6px);
|
|
255
|
+
padding-top: 0.28rem;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.cm-line.cm-moss-fenced-code-end {
|
|
259
|
+
border-bottom: 1px solid color-mix(in srgb, var(--moss-border, #3d3d3d) 76%, transparent 24%);
|
|
260
|
+
border-bottom-left-radius: var(--moss-radius, 6px);
|
|
261
|
+
border-bottom-right-radius: var(--moss-radius, 6px);
|
|
262
|
+
padding-bottom: 0.28rem;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* `drawSelection()` paints behind content, where the opaque code backdrop
|
|
266
|
+
* would cover it. A selection-only inline decoration mirrors the same token
|
|
267
|
+
* above the block background while leaving syntax-highlighted text on top. */
|
|
268
|
+
.cm-moss-fenced-selection {
|
|
269
|
+
background-color: var(
|
|
270
|
+
--moss-selection-bg,
|
|
271
|
+
color-mix(in srgb, #7c3aed 28%, #1e1e1e 72%)
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.cm-moss-code-copy {
|
|
276
|
+
position: absolute;
|
|
277
|
+
top: 0.15rem;
|
|
278
|
+
inset-inline-end: 0.15rem;
|
|
279
|
+
z-index: 2;
|
|
280
|
+
display: inline-flex;
|
|
281
|
+
align-items: center;
|
|
282
|
+
justify-content: center;
|
|
283
|
+
width: 1.9rem;
|
|
284
|
+
height: 1.9rem;
|
|
285
|
+
padding: 0;
|
|
286
|
+
background: transparent;
|
|
287
|
+
border: 1px solid transparent;
|
|
288
|
+
border-radius: var(--moss-radius, 6px);
|
|
289
|
+
color: var(--moss-fg-muted, #888);
|
|
290
|
+
cursor: pointer;
|
|
291
|
+
opacity: 0.7;
|
|
292
|
+
transition: background-color 0.12s ease, color 0.12s ease, opacity 0.12s ease, border-color 0.12s ease;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.cm-line.cm-moss-fenced-code:hover .cm-moss-code-copy,
|
|
296
|
+
.cm-moss-code-copy:focus-visible {
|
|
297
|
+
opacity: 1;
|
|
298
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
299
|
+
color: var(--moss-fg, #dcddde);
|
|
300
|
+
border-color: var(--moss-border, #3d3d3d);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.cm-moss-code-copy.is-copied {
|
|
304
|
+
opacity: 1;
|
|
305
|
+
background: var(--moss-accent, #7c3aed);
|
|
306
|
+
color: #fff;
|
|
307
|
+
border-color: var(--moss-accent, #7c3aed);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.cm-moss-code-copy svg {
|
|
311
|
+
width: 1rem;
|
|
312
|
+
height: 1rem;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* Inline content marks — applied on the text inside **…**, *…*, `…`,
|
|
316
|
+
* ~~…~~, [text](url). Styling only; no height changes. */
|
|
317
|
+
.cm-moss-strong {
|
|
318
|
+
font-weight: 700;
|
|
319
|
+
color: var(--moss-fg, #dcddde);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.cm-moss-em {
|
|
323
|
+
font-style: italic;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.cm-moss-inline-code {
|
|
327
|
+
font-family: var(--moss-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
328
|
+
font-size: 0.88em;
|
|
329
|
+
color: var(--moss-fg, #dcddde);
|
|
330
|
+
background: var(--moss-code-bg, color-mix(in srgb, #2d2d2d 88%, black 12%));
|
|
331
|
+
border-radius: 0.35rem;
|
|
332
|
+
padding: 0.08em 0.35em;
|
|
333
|
+
word-break: break-word;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.cm-moss-strike {
|
|
337
|
+
text-decoration: line-through;
|
|
338
|
+
color: var(--moss-fg-muted, #888);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.cm-moss-highlight {
|
|
342
|
+
background: color-mix(in srgb, var(--moss-accent-bright, #a78bfa) 20%, transparent 80%);
|
|
343
|
+
border-radius: 0.2em;
|
|
344
|
+
color: var(--moss-fg, #dcddde);
|
|
345
|
+
box-decoration-break: clone;
|
|
346
|
+
-webkit-box-decoration-break: clone;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/* Delimiter characters for emphasis marks we supplemented manually
|
|
350
|
+
* (see `supplementMidTypingEmphasis` in inline-preview.ts). Each
|
|
351
|
+
* class mirrors what an `EmphasisMark` token would pick up through
|
|
352
|
+
* syntax highlighting when lezer does parse the pattern: faint
|
|
353
|
+
* color from `processingInstruction`, plus the parent scope's
|
|
354
|
+
* weight / style / decoration so the delimiter glyph keeps the
|
|
355
|
+
* same metrics whether lezer recognized the emphasis or not.
|
|
356
|
+
* Without the matching weight / style, `**` would visibly change
|
|
357
|
+
* width as the user types through a trailing space. */
|
|
358
|
+
.cm-moss-strong-mark {
|
|
359
|
+
color: var(--moss-fg-faint, #666);
|
|
360
|
+
font-weight: 700;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.cm-moss-em-mark {
|
|
364
|
+
color: var(--moss-fg-faint, #666);
|
|
365
|
+
font-style: italic;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.cm-moss-strike-mark {
|
|
369
|
+
color: var(--moss-fg-faint, #666);
|
|
370
|
+
text-decoration: line-through;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.cm-moss-highlight-mark {
|
|
374
|
+
color: var(--moss-fg-faint, #666);
|
|
375
|
+
background: transparent;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.cm-moss-link {
|
|
379
|
+
color: var(--moss-link, #818cf8);
|
|
380
|
+
text-decoration: underline;
|
|
381
|
+
text-decoration-thickness: 1px;
|
|
382
|
+
text-underline-offset: 0.15em;
|
|
383
|
+
/* No pointer cursor on the link text — the text is editable like
|
|
384
|
+
* any other content. The pointer cursor is scoped to the trailing
|
|
385
|
+
* icon below, which is the actual open-in-new-tab affordance. */
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.cm-moss-link:hover {
|
|
389
|
+
color: var(--moss-link-hover, #a5b4fc);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/* External-link icon. In prose it's a `::after` pseudo-element; inside
|
|
393
|
+
* table cells it's a real `.cm-moss-link-icon` element (a pseudo can't
|
|
394
|
+
* receive a click, so the in-cell icon wouldn't open the link). Both
|
|
395
|
+
* share the masked-SVG visual so the color tracks the link color via
|
|
396
|
+
* `background-color`. */
|
|
397
|
+
.cm-moss-link::after,
|
|
398
|
+
.cm-moss-link-icon {
|
|
399
|
+
display: inline-block;
|
|
400
|
+
width: 0.78em;
|
|
401
|
+
height: 0.78em;
|
|
402
|
+
margin-left: 0.32em;
|
|
403
|
+
vertical-align: -0.02em;
|
|
404
|
+
cursor: pointer;
|
|
405
|
+
background-color: color-mix(in srgb, var(--moss-link, #818cf8) 82%, white 18%);
|
|
406
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg%3E%3Cpath d='M10.0002 5H8.2002C7.08009 5 6.51962 5 6.0918 5.21799C5.71547 5.40973 5.40973 5.71547 5.21799 6.0918C5 6.51962 5 7.08009 5 8.2002V15.8002C5 16.9203 5 17.4801 5.21799 17.9079C5.40973 18.2842 5.71547 18.5905 6.0918 18.7822C6.5192 19 7.07899 19 8.19691 19H15.8031C16.921 19 17.48 19 17.9074 18.7822C18.2837 18.5905 18.5905 18.2839 18.7822 17.9076C19 17.4802 19 16.921 19 15.8031V14M20 9V4M20 4H15M20 4L13 11' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/g%3E%3C/svg%3E");
|
|
407
|
+
mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg%3E%3Cpath d='M10.0002 5H8.2002C7.08009 5 6.51962 5 6.0918 5.21799C5.71547 5.40973 5.40973 5.71547 5.21799 6.0918C5 6.51962 5 7.08009 5 8.2002V15.8002C5 16.9203 5 17.4801 5.21799 17.9079C5.40973 18.2842 5.71547 18.5905 6.0918 18.7822C6.5192 19 7.07899 19 8.19691 19H15.8031C16.921 19 17.48 19 17.9074 18.7822C18.2837 18.5905 18.5905 18.2839 18.7822 17.9076C19 17.4802 19 16.921 19 15.8031V14M20 9V4M20 4H15M20 4L13 11' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/g%3E%3C/svg%3E");
|
|
408
|
+
-webkit-mask-repeat: no-repeat;
|
|
409
|
+
mask-repeat: no-repeat;
|
|
410
|
+
-webkit-mask-size: contain;
|
|
411
|
+
mask-size: contain;
|
|
412
|
+
opacity: 0.9;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.cm-moss-link::after {
|
|
416
|
+
content: "";
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/* The real in-cell icon must be clickable but never selectable / part
|
|
420
|
+
* of caret navigation. */
|
|
421
|
+
.cm-moss-link-icon {
|
|
422
|
+
pointer-events: auto;
|
|
423
|
+
user-select: none;
|
|
424
|
+
-webkit-user-select: none;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* In cells the icon is a real element — suppress the pseudo so the icon
|
|
428
|
+
* doesn't render twice. */
|
|
429
|
+
.cm-moss-table-cell-source .cm-moss-link::after {
|
|
430
|
+
content: none;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.cm-moss-link:hover::after,
|
|
434
|
+
.cm-moss-link-icon:hover {
|
|
435
|
+
background-color: color-mix(in srgb, var(--moss-link-hover, #a5b4fc) 84%, white 16%);
|
|
436
|
+
opacity: 1;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.cm-moss-wiki-link {
|
|
440
|
+
color: var(--moss-link, #818cf8);
|
|
441
|
+
text-decoration: underline;
|
|
442
|
+
text-decoration-thickness: 1px;
|
|
443
|
+
text-underline-offset: 0.15em;
|
|
444
|
+
cursor: pointer;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.cm-moss-wiki-link:hover {
|
|
448
|
+
color: var(--moss-link-hover, #a5b4fc);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.cm-moss-wiki-link-missing,
|
|
452
|
+
.cm-moss-wiki-link-unresolved {
|
|
453
|
+
color: var(--moss-fg-muted, #888);
|
|
454
|
+
text-decoration-style: dotted;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
.cm-moss-wiki-link-loading {
|
|
458
|
+
color: var(--moss-fg-muted, #888);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.cm-line .cm-moss-hr-source,
|
|
462
|
+
.cm-line .cm-moss-hr-source * {
|
|
463
|
+
font-weight: 400;
|
|
464
|
+
font-style: normal;
|
|
465
|
+
text-decoration: none;
|
|
466
|
+
color: inherit;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.cm-moss-hr-widget {
|
|
470
|
+
display: inline-flex;
|
|
471
|
+
align-items: center;
|
|
472
|
+
justify-content: center;
|
|
473
|
+
width: 100%;
|
|
474
|
+
min-height: 1.7em;
|
|
475
|
+
gap: 0.6em;
|
|
476
|
+
vertical-align: middle;
|
|
477
|
+
pointer-events: none;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.cm-moss-hr-segment {
|
|
481
|
+
flex: 1 1 auto;
|
|
482
|
+
min-width: 0;
|
|
483
|
+
border-top: 1px solid var(--moss-border, #3d3d3d);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.cm-moss-hr-widget-wavy .cm-moss-hr-segment {
|
|
487
|
+
border-top: none;
|
|
488
|
+
height: 8px;
|
|
489
|
+
background-color: var(--moss-border, #3d3d3d);
|
|
490
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 8' preserveAspectRatio='none'%3E%3Cpath d='M0 4 C4 0.5 12 0.5 16 4 S28 7.5 32 4' fill='none' stroke='white' stroke-width='1.25' stroke-linecap='round'/%3E%3C/svg%3E");
|
|
491
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 8' preserveAspectRatio='none'%3E%3Cpath d='M0 4 C4 0.5 12 0.5 16 4 S28 7.5 32 4' fill='none' stroke='white' stroke-width='1.25' stroke-linecap='round'/%3E%3C/svg%3E");
|
|
492
|
+
mask-repeat: repeat-x;
|
|
493
|
+
-webkit-mask-repeat: repeat-x;
|
|
494
|
+
mask-position: center;
|
|
495
|
+
-webkit-mask-position: center;
|
|
496
|
+
mask-size: 32px 8px;
|
|
497
|
+
-webkit-mask-size: 32px 8px;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.cm-moss-hr-symbol {
|
|
501
|
+
flex: 0 1 auto;
|
|
502
|
+
min-width: 1.45em;
|
|
503
|
+
max-width: min(12em, calc(100% - 2em));
|
|
504
|
+
color: var(--moss-fg-muted, #888);
|
|
505
|
+
font-size: 0.95em;
|
|
506
|
+
line-height: 1.35;
|
|
507
|
+
text-align: center;
|
|
508
|
+
overflow: hidden;
|
|
509
|
+
text-overflow: ellipsis;
|
|
510
|
+
white-space: nowrap;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/* The source of a standalone image is replaced visually by its block
|
|
514
|
+
* widget. Keep the source line for CM6 position mapping, but remove its
|
|
515
|
+
* line box so it does not read as an empty row above the image. */
|
|
516
|
+
.cm-line.cm-moss-image-source-line {
|
|
517
|
+
height: 0;
|
|
518
|
+
min-height: 0;
|
|
519
|
+
padding-top: 0;
|
|
520
|
+
padding-bottom: 0;
|
|
521
|
+
line-height: 0;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/* Image block widget — rendered below the source line containing
|
|
525
|
+
* the `` markdown. Natural image size up to the editor's
|
|
526
|
+
* content width (`max-width: 100%` of .cm-content, which is the
|
|
527
|
+
* reading-width column). Smaller images render at their own size,
|
|
528
|
+
* left-aligned. Aspect ratio preserved by `height: auto`. */
|
|
529
|
+
.cm-moss-image {
|
|
530
|
+
position: relative;
|
|
531
|
+
display: flex;
|
|
532
|
+
flex-direction: column;
|
|
533
|
+
align-items: center;
|
|
534
|
+
justify-content: center;
|
|
535
|
+
overflow: visible;
|
|
536
|
+
padding: 0.35em 0;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.cm-moss-image-frame {
|
|
540
|
+
position: relative;
|
|
541
|
+
flex: 0 0 auto;
|
|
542
|
+
display: inline-block;
|
|
543
|
+
box-sizing: border-box;
|
|
544
|
+
max-width: 100%;
|
|
545
|
+
line-height: 0;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/* Remote images have no intrinsic height until they finish loading. Keep
|
|
549
|
+
* their widget measurable so inserting an image never creates a blank,
|
|
550
|
+
* zero-height block that shifts the document when the request completes. */
|
|
551
|
+
.cm-moss-image-frame-placeholder {
|
|
552
|
+
width: min(28rem, 100%);
|
|
553
|
+
min-height: 10rem;
|
|
554
|
+
aspect-ratio: 16 / 9;
|
|
555
|
+
border-radius: 0.4em;
|
|
556
|
+
background: var(--moss-bg-surface, rgba(127, 127, 127, 0.08));
|
|
557
|
+
overflow: hidden;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
.cm-moss-image-placeholder {
|
|
561
|
+
position: absolute;
|
|
562
|
+
inset: 0;
|
|
563
|
+
display: grid;
|
|
564
|
+
place-items: center;
|
|
565
|
+
color: var(--moss-fg-muted, #888);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.cm-moss-image-placeholder svg {
|
|
569
|
+
opacity: 0.72;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
.cm-moss-image-frame-placeholder > img {
|
|
573
|
+
opacity: 0;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/* Once a width has been chosen explicitly, keep the image usable while
|
|
577
|
+
* preserving the responsive percentage in the source. The `min()` keeps
|
|
578
|
+
* the frame from overflowing a narrow phone viewport. */
|
|
579
|
+
.cm-moss-image-frame-sized {
|
|
580
|
+
min-width: min(160px, 100%);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
.cm-moss-image img {
|
|
584
|
+
display: block;
|
|
585
|
+
width: auto;
|
|
586
|
+
max-width: 100%;
|
|
587
|
+
height: auto;
|
|
588
|
+
border-radius: 0.4em;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/* The source line is kept at zero height for position mapping. When its
|
|
592
|
+
* entire range is selected through the rendered widget, suppress CM6's
|
|
593
|
+
* caret layer so the caret cannot appear at the line's top-left corner. */
|
|
594
|
+
.moss-cm-editor.moss-cm-image-selection-active .cm-cursorLayer {
|
|
595
|
+
visibility: hidden;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.cm-moss-image.cm-moss-image-selected .cm-moss-image-frame {
|
|
599
|
+
outline: 1px solid color-mix(
|
|
600
|
+
in srgb,
|
|
601
|
+
var(--moss-accent, #7c3aed) 52%,
|
|
602
|
+
var(--moss-border, #3d3d3d) 48%
|
|
603
|
+
);
|
|
604
|
+
outline-offset: 2px;
|
|
605
|
+
border-radius: 0.45em;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/* The edit affordance is overlaid on the image so it never adds a row to
|
|
609
|
+
* the document or changes the block widget's measured height. It appears
|
|
610
|
+
* on hover and keyboard focus, while the image itself remains a quiet
|
|
611
|
+
* reading surface. */
|
|
612
|
+
.cm-moss-image-edit {
|
|
613
|
+
position: absolute;
|
|
614
|
+
top: 0.7em;
|
|
615
|
+
right: 0.7em;
|
|
616
|
+
z-index: 1;
|
|
617
|
+
width: 2em;
|
|
618
|
+
height: 2em;
|
|
619
|
+
display: inline-flex;
|
|
620
|
+
align-items: center;
|
|
621
|
+
justify-content: center;
|
|
622
|
+
padding: 0;
|
|
623
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.45));
|
|
624
|
+
border-radius: 0.35em;
|
|
625
|
+
background: var(--moss-bg-panel, #252525);
|
|
626
|
+
color: var(--moss-fg, #dcddde);
|
|
627
|
+
cursor: pointer;
|
|
628
|
+
opacity: 0;
|
|
629
|
+
transition: opacity 0.12s ease, background-color 0.12s ease;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
.cm-moss-image-frame:hover .cm-moss-image-edit,
|
|
633
|
+
.cm-moss-image-frame:focus-within .cm-moss-image-edit,
|
|
634
|
+
.cm-moss-image-frame:hover .cm-moss-image-preview,
|
|
635
|
+
.cm-moss-image-frame:focus-within .cm-moss-image-preview,
|
|
636
|
+
.cm-moss-image-frame:hover .cm-moss-image-resize,
|
|
637
|
+
.cm-moss-image-frame:focus-within .cm-moss-image-resize {
|
|
638
|
+
opacity: 1;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.cm-moss-image-edit:hover {
|
|
642
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
.cm-moss-image-preview {
|
|
646
|
+
position: absolute;
|
|
647
|
+
top: 0.7em;
|
|
648
|
+
left: 0.7em;
|
|
649
|
+
z-index: 1;
|
|
650
|
+
width: 2em;
|
|
651
|
+
height: 2em;
|
|
652
|
+
display: inline-flex;
|
|
653
|
+
align-items: center;
|
|
654
|
+
justify-content: center;
|
|
655
|
+
padding: 0;
|
|
656
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.45));
|
|
657
|
+
border-radius: 0.35em;
|
|
658
|
+
background: var(--moss-bg-panel, #252525);
|
|
659
|
+
color: var(--moss-fg, #dcddde);
|
|
660
|
+
cursor: pointer;
|
|
661
|
+
opacity: 0;
|
|
662
|
+
transition: opacity 0.12s ease, background-color 0.12s ease;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
.cm-moss-image-preview:hover {
|
|
666
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
.cm-moss-image-resize {
|
|
670
|
+
position: absolute;
|
|
671
|
+
right: 0.55em;
|
|
672
|
+
bottom: 0.55em;
|
|
673
|
+
z-index: 1;
|
|
674
|
+
width: 2em;
|
|
675
|
+
height: 2em;
|
|
676
|
+
display: inline-flex;
|
|
677
|
+
align-items: center;
|
|
678
|
+
justify-content: center;
|
|
679
|
+
padding: 0;
|
|
680
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.45));
|
|
681
|
+
border-radius: 0.35em;
|
|
682
|
+
background: var(--moss-bg-panel, #252525);
|
|
683
|
+
color: var(--moss-fg, #dcddde);
|
|
684
|
+
cursor: nwse-resize;
|
|
685
|
+
opacity: 0;
|
|
686
|
+
touch-action: none;
|
|
687
|
+
transition: opacity 0.12s ease, background-color 0.12s ease;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
.cm-moss-image-resize:hover {
|
|
691
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/* Maximize2 is rotated so its diagonal reads from the image's top-left
|
|
695
|
+
* toward the bottom-right resize handle. */
|
|
696
|
+
.cm-moss-image-resize svg {
|
|
697
|
+
transform: rotate(90deg);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
@media (hover: none), (pointer: coarse) {
|
|
701
|
+
.cm-moss-image-edit,
|
|
702
|
+
.cm-moss-image-preview,
|
|
703
|
+
.cm-moss-image-resize {
|
|
704
|
+
width: 2.75rem;
|
|
705
|
+
height: 2.75rem;
|
|
706
|
+
opacity: 1;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.cm-moss-image-edit:focus-visible,
|
|
711
|
+
.cm-moss-image-preview:focus-visible,
|
|
712
|
+
.cm-moss-image-editor-button:focus-visible,
|
|
713
|
+
.cm-moss-image-editor input:focus-visible {
|
|
714
|
+
outline: 2px solid var(--moss-accent, #7c3aed);
|
|
715
|
+
outline-offset: 2px;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/* This editor floats over the rendered image. Absolute positioning keeps
|
|
719
|
+
* opening it out of the CodeMirror heightmap and document flow. */
|
|
720
|
+
.cm-moss-image-editor {
|
|
721
|
+
position: absolute;
|
|
722
|
+
top: 0.7em;
|
|
723
|
+
right: 0.7em;
|
|
724
|
+
z-index: 2;
|
|
725
|
+
box-sizing: border-box;
|
|
726
|
+
width: min(22rem, calc(100% - 1rem));
|
|
727
|
+
display: grid;
|
|
728
|
+
gap: 0.55em;
|
|
729
|
+
padding: 0.8em;
|
|
730
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.38));
|
|
731
|
+
border-radius: 0.5em;
|
|
732
|
+
background: var(--moss-bg-panel, #252525);
|
|
733
|
+
box-shadow: 0 0.7em 2em rgba(0, 0, 0, 0.28);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
.cm-moss-image-editor-title {
|
|
737
|
+
color: var(--moss-fg, #dcddde);
|
|
738
|
+
font-size: 0.9em;
|
|
739
|
+
font-weight: 650;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.cm-moss-image-editor-field {
|
|
743
|
+
display: grid;
|
|
744
|
+
gap: 0.25em;
|
|
745
|
+
color: var(--moss-fg-muted, #9a9da4);
|
|
746
|
+
font-size: 0.72em;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
.cm-moss-image-editor input {
|
|
750
|
+
box-sizing: border-box;
|
|
751
|
+
width: 100%;
|
|
752
|
+
min-width: 0;
|
|
753
|
+
padding: 0.45em 0.55em;
|
|
754
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.34));
|
|
755
|
+
border-radius: 0.3em;
|
|
756
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
757
|
+
color: var(--moss-fg, #dcddde);
|
|
758
|
+
font: inherit;
|
|
759
|
+
font-size: 1.05em;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
.cm-moss-image-editor-actions {
|
|
763
|
+
display: flex;
|
|
764
|
+
justify-content: flex-end;
|
|
765
|
+
gap: 0.4em;
|
|
766
|
+
padding-top: 0.15em;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
.cm-moss-image-editor-button {
|
|
770
|
+
width: 1.9em;
|
|
771
|
+
height: 1.9em;
|
|
772
|
+
display: inline-flex;
|
|
773
|
+
align-items: center;
|
|
774
|
+
justify-content: center;
|
|
775
|
+
padding: 0;
|
|
776
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.34));
|
|
777
|
+
border-radius: 0.35em;
|
|
778
|
+
background: transparent;
|
|
779
|
+
color: var(--moss-fg-muted, #9a9da4);
|
|
780
|
+
cursor: pointer;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
.cm-moss-image-editor-button:hover {
|
|
784
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
785
|
+
color: var(--moss-fg, #dcddde);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
.cm-moss-image-editor-button.is-primary {
|
|
789
|
+
border-color: var(--moss-accent, #7c3aed);
|
|
790
|
+
background: var(--moss-accent, #7c3aed);
|
|
791
|
+
color: #ffffff;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.cm-moss-image-editor-error {
|
|
795
|
+
min-height: 1.1em;
|
|
796
|
+
color: var(--moss-hl-invalid, #ff5370);
|
|
797
|
+
font-size: 0.72em;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/* The preview is mounted on document.body, outside CodeMirror's scroller,
|
|
801
|
+
* so a large image is never clipped by the editor viewport. */
|
|
802
|
+
.cm-moss-image-preview-backdrop {
|
|
803
|
+
position: fixed;
|
|
804
|
+
inset: 0;
|
|
805
|
+
z-index: 1000;
|
|
806
|
+
box-sizing: border-box;
|
|
807
|
+
display: flex;
|
|
808
|
+
align-items: center;
|
|
809
|
+
justify-content: center;
|
|
810
|
+
padding: 5vh 5vw;
|
|
811
|
+
background: rgba(0, 0, 0, 0.68);
|
|
812
|
+
backdrop-filter: blur(2px);
|
|
813
|
+
-webkit-backdrop-filter: blur(2px);
|
|
814
|
+
cursor: zoom-out;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
.cm-moss-image-preview-dialog {
|
|
818
|
+
position: relative;
|
|
819
|
+
display: flex;
|
|
820
|
+
max-width: 96vw;
|
|
821
|
+
max-height: 90vh;
|
|
822
|
+
flex-direction: column;
|
|
823
|
+
align-items: center;
|
|
824
|
+
gap: 0.65rem;
|
|
825
|
+
cursor: default;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
.cm-moss-image-preview-dialog > img {
|
|
829
|
+
display: block;
|
|
830
|
+
max-width: 90vw;
|
|
831
|
+
max-height: 82vh;
|
|
832
|
+
width: auto;
|
|
833
|
+
height: auto;
|
|
834
|
+
object-fit: contain;
|
|
835
|
+
border-radius: 0.35rem;
|
|
836
|
+
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.45);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
.cm-moss-image-preview-close {
|
|
840
|
+
position: absolute;
|
|
841
|
+
top: 0.6rem;
|
|
842
|
+
right: 0.6rem;
|
|
843
|
+
z-index: 1;
|
|
844
|
+
width: 1.9rem;
|
|
845
|
+
height: 1.9rem;
|
|
846
|
+
display: inline-flex;
|
|
847
|
+
align-items: center;
|
|
848
|
+
justify-content: center;
|
|
849
|
+
padding: 0;
|
|
850
|
+
border: 1px solid color-mix(in srgb, white 32%, transparent);
|
|
851
|
+
border-radius: var(--moss-radius, 6px);
|
|
852
|
+
background: color-mix(in srgb, var(--moss-bg-panel, #252525) 82%, transparent);
|
|
853
|
+
color: var(--moss-fg, #dcddde);
|
|
854
|
+
cursor: pointer;
|
|
855
|
+
opacity: 0.9;
|
|
856
|
+
transition: background-color 0.12s ease, border-color 0.12s ease, opacity 0.12s ease;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
.cm-moss-image-preview-close:hover {
|
|
860
|
+
border-color: color-mix(in srgb, white 52%, transparent);
|
|
861
|
+
background: color-mix(in srgb, var(--moss-bg-surface, #2d2d2d) 92%, transparent);
|
|
862
|
+
opacity: 1;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
.cm-moss-image-preview-caption {
|
|
866
|
+
max-width: min(90vw, 70ch);
|
|
867
|
+
color: rgba(255, 255, 255, 0.85);
|
|
868
|
+
font-size: 0.9rem;
|
|
869
|
+
line-height: 1.4;
|
|
870
|
+
text-align: center;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
.cm-moss-image-preview-close:focus-visible {
|
|
874
|
+
outline: 2px solid var(--moss-accent, #a78bfa);
|
|
875
|
+
outline-offset: 2px;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/* When a caption is present, switch the wrap to a column so the
|
|
879
|
+
* figcaption stacks below the image instead of beside it. */
|
|
880
|
+
.cm-moss-image.cm-moss-image-has-caption {
|
|
881
|
+
flex-direction: column;
|
|
882
|
+
align-items: center;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
.cm-moss-image-caption {
|
|
886
|
+
margin: 0.4em 0 0;
|
|
887
|
+
text-align: center;
|
|
888
|
+
font-size: 0.85em;
|
|
889
|
+
color: var(--moss-fg-muted, #888);
|
|
890
|
+
max-width: 100%;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
/* ------------------------------------------------------------------ */
|
|
894
|
+
/* File link block.
|
|
895
|
+
*
|
|
896
|
+
* Same treatment as image blocks — rendered below a source line that
|
|
897
|
+
* contains a standalone file link `[label](url)`. Layout mirrors the
|
|
898
|
+
* upload-progress widget so the flow "upload widget → file-block
|
|
899
|
+
* widget" looks like a single continuous transition rather than a
|
|
900
|
+
* pop-and-replace. Left: preview (thumb for image URLs, glyph+ext
|
|
901
|
+
* badge for generic files). Right: name + info row. */
|
|
902
|
+
.cm-moss-file-block {
|
|
903
|
+
position: relative;
|
|
904
|
+
display: flex;
|
|
905
|
+
align-items: center;
|
|
906
|
+
gap: 0.85em;
|
|
907
|
+
padding: 0.6em 3.5em 0.6em 0.9em;
|
|
908
|
+
margin: 0.25em 0;
|
|
909
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.22));
|
|
910
|
+
border-radius: 0.55em;
|
|
911
|
+
background: var(--moss-file-block-bg, rgba(127, 127, 127, 0.06));
|
|
912
|
+
transition: background-color 0.12s ease, border-color 0.12s ease;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
.cm-moss-file-block:hover {
|
|
916
|
+
background: var(--moss-file-block-hover-bg, rgba(127, 127, 127, 0.1));
|
|
917
|
+
border-color: var(--moss-border, rgba(127, 127, 127, 0.35));
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
.cm-moss-file-block-preview {
|
|
921
|
+
flex: 0 0 auto;
|
|
922
|
+
width: 4.2em;
|
|
923
|
+
height: 4.2em;
|
|
924
|
+
display: inline-flex;
|
|
925
|
+
align-items: center;
|
|
926
|
+
justify-content: center;
|
|
927
|
+
overflow: hidden;
|
|
928
|
+
border-radius: 0.5em;
|
|
929
|
+
background: var(--moss-file-block-preview-bg, rgba(127, 127, 127, 0.12));
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
.cm-moss-file-block-preview.cm-moss-file-block-preview-image {
|
|
933
|
+
background: transparent;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
.cm-moss-file-block-preview-image img {
|
|
937
|
+
width: 100%;
|
|
938
|
+
height: 100%;
|
|
939
|
+
object-fit: cover;
|
|
940
|
+
display: block;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
.cm-moss-file-block-preview.cm-moss-file-block-preview-file {
|
|
944
|
+
flex-direction: column;
|
|
945
|
+
align-items: center;
|
|
946
|
+
justify-content: center;
|
|
947
|
+
gap: 0.18em;
|
|
948
|
+
color: var(--moss-fg-muted, #9a9da4);
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
.cm-moss-file-block-glyph {
|
|
952
|
+
display: inline-flex;
|
|
953
|
+
align-items: center;
|
|
954
|
+
justify-content: center;
|
|
955
|
+
flex: 1 1 auto;
|
|
956
|
+
min-height: 0;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
.cm-moss-file-block-glyph svg {
|
|
960
|
+
width: 2.6em;
|
|
961
|
+
height: 2.6em;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
.cm-moss-file-block-ext {
|
|
965
|
+
font-size: 0.6em;
|
|
966
|
+
font-weight: 700;
|
|
967
|
+
letter-spacing: 0.05em;
|
|
968
|
+
line-height: 1;
|
|
969
|
+
padding: 0.2em 0.45em;
|
|
970
|
+
border-radius: 0.3em;
|
|
971
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
972
|
+
color: var(--moss-fg, #dcddde);
|
|
973
|
+
text-transform: uppercase;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.cm-moss-file-block-meta {
|
|
977
|
+
flex: 1 1 auto;
|
|
978
|
+
min-width: 0;
|
|
979
|
+
display: flex;
|
|
980
|
+
flex-direction: column;
|
|
981
|
+
gap: 0.15em;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
.cm-moss-file-block-name {
|
|
985
|
+
font-size: 0.95em;
|
|
986
|
+
font-weight: 600;
|
|
987
|
+
color: var(--moss-fg, #dcddde);
|
|
988
|
+
white-space: nowrap;
|
|
989
|
+
overflow: hidden;
|
|
990
|
+
text-overflow: ellipsis;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
.cm-moss-file-block-info {
|
|
994
|
+
font-size: 0.8em;
|
|
995
|
+
color: var(--moss-fg-muted, #888);
|
|
996
|
+
white-space: nowrap;
|
|
997
|
+
overflow: hidden;
|
|
998
|
+
text-overflow: ellipsis;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
/* Keep file actions attached to the card itself. They are absolutely
|
|
1002
|
+
* positioned so they never add width or height to the block widget. */
|
|
1003
|
+
.cm-moss-file-block-actions {
|
|
1004
|
+
position: absolute;
|
|
1005
|
+
top: 50%;
|
|
1006
|
+
right: 0.7em;
|
|
1007
|
+
z-index: 1;
|
|
1008
|
+
display: flex;
|
|
1009
|
+
align-items: center;
|
|
1010
|
+
gap: 0.3em;
|
|
1011
|
+
transform: translateY(-50%);
|
|
1012
|
+
opacity: 0;
|
|
1013
|
+
transition: opacity 0.12s ease;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
.cm-moss-file-block-download,
|
|
1017
|
+
.cm-moss-file-block-delete {
|
|
1018
|
+
width: 2em;
|
|
1019
|
+
height: 2em;
|
|
1020
|
+
display: inline-flex;
|
|
1021
|
+
align-items: center;
|
|
1022
|
+
justify-content: center;
|
|
1023
|
+
padding: 0;
|
|
1024
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.45));
|
|
1025
|
+
border-radius: 0.35em;
|
|
1026
|
+
background: var(--moss-bg-panel, #252525);
|
|
1027
|
+
color: var(--moss-fg, #dcddde);
|
|
1028
|
+
cursor: pointer;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
.cm-moss-file-block:hover .cm-moss-file-block-actions,
|
|
1032
|
+
.cm-moss-file-block:focus-within .cm-moss-file-block-actions {
|
|
1033
|
+
opacity: 1;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
.cm-moss-file-block-download:hover,
|
|
1037
|
+
.cm-moss-file-block-delete:hover {
|
|
1038
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
@media (hover: none), (pointer: coarse) {
|
|
1042
|
+
.cm-moss-file-block-actions {
|
|
1043
|
+
opacity: 1;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
.cm-moss-file-block-download,
|
|
1047
|
+
.cm-moss-file-block-delete {
|
|
1048
|
+
width: 2.75rem;
|
|
1049
|
+
height: 2.75rem;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.cm-moss-file-block-download:focus-visible,
|
|
1054
|
+
.cm-moss-file-block-delete:focus-visible {
|
|
1055
|
+
outline: 2px solid var(--moss-accent, #7c3aed);
|
|
1056
|
+
outline-offset: 2px;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/* The source line remains in the document for position mapping, but its
|
|
1060
|
+
* line box is removed so the rendered file card is the only visible block. */
|
|
1061
|
+
.cm-line.cm-moss-file-block-source-line {
|
|
1062
|
+
height: 0;
|
|
1063
|
+
min-height: 0;
|
|
1064
|
+
padding-top: 0;
|
|
1065
|
+
padding-bottom: 0;
|
|
1066
|
+
line-height: 0;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/* ------------------------------------------------------------------ */
|
|
1070
|
+
/* Upload progress block.
|
|
1071
|
+
*
|
|
1072
|
+
* Rendered by mossUploadBlocks while an upload is in flight. Layout:
|
|
1073
|
+
* preview on the left (image thumb or file icon), body on the right
|
|
1074
|
+
* with filename + size, a progress bar, status text, and (on error)
|
|
1075
|
+
* retry / cancel buttons. Matches the image block's padding so the
|
|
1076
|
+
* transition from "uploading" → final markdown + image widget is
|
|
1077
|
+
* visually smooth.
|
|
1078
|
+
* ------------------------------------------------------------------ */
|
|
1079
|
+
.cm-moss-upload {
|
|
1080
|
+
display: flex;
|
|
1081
|
+
align-items: center;
|
|
1082
|
+
gap: 0.75em;
|
|
1083
|
+
padding: 0.5em 0.75em;
|
|
1084
|
+
margin: 0.2em 0;
|
|
1085
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.18));
|
|
1086
|
+
border-radius: 0.5em;
|
|
1087
|
+
background: var(--moss-upload-bg, rgba(127, 127, 127, 0.06));
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
.cm-moss-upload-preview {
|
|
1091
|
+
flex: 0 0 auto;
|
|
1092
|
+
width: 3.5em;
|
|
1093
|
+
height: 3.5em;
|
|
1094
|
+
display: inline-flex;
|
|
1095
|
+
align-items: center;
|
|
1096
|
+
justify-content: center;
|
|
1097
|
+
overflow: hidden;
|
|
1098
|
+
border-radius: 0.4em;
|
|
1099
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
.cm-moss-upload-preview img {
|
|
1103
|
+
width: 100%;
|
|
1104
|
+
height: 100%;
|
|
1105
|
+
object-fit: cover;
|
|
1106
|
+
display: block;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
.cm-moss-upload-preview.cm-moss-upload-preview-file {
|
|
1110
|
+
flex-direction: column;
|
|
1111
|
+
align-items: center;
|
|
1112
|
+
justify-content: center;
|
|
1113
|
+
gap: 0.18em;
|
|
1114
|
+
color: var(--moss-fg-muted, #9a9da4);
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
.cm-moss-upload-file-glyph {
|
|
1118
|
+
display: inline-flex;
|
|
1119
|
+
align-items: center;
|
|
1120
|
+
justify-content: center;
|
|
1121
|
+
flex: 1 1 auto;
|
|
1122
|
+
min-height: 0;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
.cm-moss-upload-file-glyph svg {
|
|
1126
|
+
width: 2.2em;
|
|
1127
|
+
height: 2.2em;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
.cm-moss-upload-ext {
|
|
1131
|
+
font-size: 0.62em;
|
|
1132
|
+
font-weight: 700;
|
|
1133
|
+
letter-spacing: 0.05em;
|
|
1134
|
+
line-height: 1;
|
|
1135
|
+
padding: 0.18em 0.4em;
|
|
1136
|
+
border-radius: 0.25em;
|
|
1137
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
1138
|
+
color: var(--moss-fg, #dcddde);
|
|
1139
|
+
text-transform: uppercase;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
.cm-moss-upload-body {
|
|
1143
|
+
flex: 1 1 auto;
|
|
1144
|
+
min-width: 0;
|
|
1145
|
+
display: flex;
|
|
1146
|
+
flex-direction: column;
|
|
1147
|
+
gap: 0.3em;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
.cm-moss-upload-meta {
|
|
1151
|
+
font-size: 0.85em;
|
|
1152
|
+
color: var(--moss-fg, #dcddde);
|
|
1153
|
+
white-space: nowrap;
|
|
1154
|
+
overflow: hidden;
|
|
1155
|
+
text-overflow: ellipsis;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
.cm-moss-upload-progress {
|
|
1159
|
+
width: 100%;
|
|
1160
|
+
height: 0.35em;
|
|
1161
|
+
border-radius: 999px;
|
|
1162
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
1163
|
+
overflow: hidden;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
.cm-moss-upload-bar {
|
|
1167
|
+
height: 100%;
|
|
1168
|
+
width: 0%;
|
|
1169
|
+
border-radius: 999px;
|
|
1170
|
+
background: var(--moss-accent, #4facfe);
|
|
1171
|
+
transition: width 0.15s ease;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
.cm-moss-upload-status {
|
|
1175
|
+
font-size: 0.8em;
|
|
1176
|
+
color: var(--moss-fg-muted, #888);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
.cm-moss-upload-status.is-error {
|
|
1180
|
+
color: var(--moss-hl-invalid, #ff5370);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
.cm-moss-upload-actions {
|
|
1184
|
+
display: inline-flex;
|
|
1185
|
+
gap: 0.4em;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
.cm-moss-upload-btn {
|
|
1189
|
+
display: inline-flex;
|
|
1190
|
+
align-items: center;
|
|
1191
|
+
justify-content: center;
|
|
1192
|
+
width: 1.75em;
|
|
1193
|
+
height: 1.75em;
|
|
1194
|
+
padding: 0;
|
|
1195
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.2));
|
|
1196
|
+
border-radius: 0.35em;
|
|
1197
|
+
background: transparent;
|
|
1198
|
+
color: var(--moss-fg-muted, #888);
|
|
1199
|
+
cursor: pointer;
|
|
1200
|
+
transition: background-color 0.12s ease, color 0.12s ease;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
.cm-moss-upload-btn:hover {
|
|
1204
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
1205
|
+
color: var(--moss-fg, #dcddde);
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
.cm-moss-upload-btn svg {
|
|
1209
|
+
width: 1em;
|
|
1210
|
+
height: 1em;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/* ------------------------------------------------------------------ */
|
|
1214
|
+
/* Slash-commands side `+` button + popup tweaks.
|
|
1215
|
+
*
|
|
1216
|
+
* The `+` button is rendered by mossSlashCommands (sideButton: true)
|
|
1217
|
+
* as a non-block widget at line.from when the cursor sits on an empty
|
|
1218
|
+
* line. It is visually pulled into the left gutter without adding a row.
|
|
1219
|
+
*
|
|
1220
|
+
* The autocomplete popup keeps the editor's panel tokens but gets its own
|
|
1221
|
+
* compact menu geometry: content-sized width, comfortable hit rows, and a
|
|
1222
|
+
* little more separation from the document below it.
|
|
1223
|
+
* ------------------------------------------------------------------- */
|
|
1224
|
+
.moss-cm-editor .cm-line {
|
|
1225
|
+
position: relative;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
.cm-moss-side-plus {
|
|
1229
|
+
position: absolute;
|
|
1230
|
+
left: -2.8em;
|
|
1231
|
+
top: 50%;
|
|
1232
|
+
transform: translateY(-50%);
|
|
1233
|
+
width: 1.7em;
|
|
1234
|
+
height: 1.7em;
|
|
1235
|
+
display: inline-flex;
|
|
1236
|
+
align-items: center;
|
|
1237
|
+
justify-content: center;
|
|
1238
|
+
padding: 0;
|
|
1239
|
+
margin: 0;
|
|
1240
|
+
border: 1px solid var(--moss-border, rgba(127, 127, 127, 0.45));
|
|
1241
|
+
border-radius: 6px;
|
|
1242
|
+
background: var(--moss-side-plus-bg, rgba(127, 127, 127, 0.22));
|
|
1243
|
+
color: var(--moss-fg-muted, #b4b8bf);
|
|
1244
|
+
font: inherit;
|
|
1245
|
+
font-size: 1em;
|
|
1246
|
+
line-height: 1;
|
|
1247
|
+
cursor: pointer;
|
|
1248
|
+
user-select: none;
|
|
1249
|
+
opacity: 1;
|
|
1250
|
+
transition: opacity 0.12s ease, background-color 0.12s ease,
|
|
1251
|
+
color 0.12s ease, border-color 0.12s ease;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
.cm-moss-side-plus svg {
|
|
1255
|
+
width: 1em;
|
|
1256
|
+
height: 1em;
|
|
1257
|
+
display: block;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/* Subtle hover: a muted neutral wash + slightly stronger border.
|
|
1261
|
+
* No accent color — keeps the affordance quiet but discoverable. */
|
|
1262
|
+
.cm-moss-side-plus:hover,
|
|
1263
|
+
.cm-moss-side-plus:focus-visible {
|
|
1264
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
1265
|
+
border-color: var(--moss-border, rgba(127, 127, 127, 0.7));
|
|
1266
|
+
color: var(--moss-fg, #dcddde);
|
|
1267
|
+
outline: none;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
.moss-cm-editor .cm-tooltip.cm-tooltip-autocomplete {
|
|
1271
|
+
box-sizing: border-box;
|
|
1272
|
+
width: min(11rem, calc(100vw - 1rem));
|
|
1273
|
+
min-width: 0;
|
|
1274
|
+
max-width: min(16rem, calc(100vw - 1rem));
|
|
1275
|
+
font-family: var(--moss-font, system-ui, sans-serif);
|
|
1276
|
+
font-size: 0.875rem;
|
|
1277
|
+
padding: 0.28rem;
|
|
1278
|
+
border-radius: var(--moss-radius, 6px);
|
|
1279
|
+
box-shadow: 0 0.6rem 1.5rem rgba(0, 0, 0, 0.26);
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
.moss-cm-editor .cm-tooltip.cm-tooltip-autocomplete > ul {
|
|
1283
|
+
min-width: 0;
|
|
1284
|
+
width: 100%;
|
|
1285
|
+
max-height: min(17rem, 40vh);
|
|
1286
|
+
margin: 0;
|
|
1287
|
+
padding: 0;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
.moss-cm-editor .cm-tooltip.cm-tooltip-autocomplete > ul > li {
|
|
1291
|
+
box-sizing: border-box;
|
|
1292
|
+
display: flex;
|
|
1293
|
+
align-items: center;
|
|
1294
|
+
gap: 0.6rem;
|
|
1295
|
+
width: 100%;
|
|
1296
|
+
min-width: 0;
|
|
1297
|
+
min-height: 1.95rem;
|
|
1298
|
+
padding: 0.34rem 0.5rem;
|
|
1299
|
+
border-radius: 0.35rem;
|
|
1300
|
+
line-height: 1.25;
|
|
1301
|
+
transition: background-color 0.12s ease, color 0.12s ease;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
.moss-cm-editor .cm-tooltip.cm-tooltip-autocomplete > ul > li:hover {
|
|
1305
|
+
background: color-mix(
|
|
1306
|
+
in srgb,
|
|
1307
|
+
var(--moss-accent, #7c3aed) 10%,
|
|
1308
|
+
var(--moss-bg-surface, #2d2d2d) 90%
|
|
1309
|
+
);
|
|
1310
|
+
color: var(--moss-fg, #dcddde);
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
.cm-tooltip-autocomplete li[aria-selected] {
|
|
1314
|
+
background: var(
|
|
1315
|
+
--moss-accent-bg,
|
|
1316
|
+
color-mix(in srgb, var(--moss-accent, #7c3aed) 16%, transparent)
|
|
1317
|
+
);
|
|
1318
|
+
color: var(--moss-fg, #dcddde);
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
.cm-tooltip-autocomplete .cm-completionLabel {
|
|
1322
|
+
display: block;
|
|
1323
|
+
min-width: 0;
|
|
1324
|
+
flex: 1 1 auto;
|
|
1325
|
+
overflow: hidden;
|
|
1326
|
+
text-overflow: ellipsis;
|
|
1327
|
+
white-space: nowrap;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
/* "icon + title" layout: drop the secondary detail text and render a
|
|
1331
|
+
* leading icon per command kind. Slash command renderers insert the
|
|
1332
|
+
* actual SVG node; CSS only owns sizing and layout. */
|
|
1333
|
+
.cm-tooltip-autocomplete .cm-completionDetail {
|
|
1334
|
+
display: none;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/* Override CM6's defaults: it sets `opacity: .6` (too faint for our
|
|
1338
|
+
* stroke icons), `box-sizing: content-box` + `padding-right: .6em`
|
|
1339
|
+
* (width/height then exclude padding, so the SVG gets clipped to a
|
|
1340
|
+
* sub-em box and reads as nearly invisible).
|
|
1341
|
+
* Switch to border-box, drop the right padding (we use margin
|
|
1342
|
+
* instead), and pin opacity to 1 so the icon is the visual anchor. */
|
|
1343
|
+
.cm-tooltip-autocomplete .cm-completionIcon {
|
|
1344
|
+
width: 1.15em;
|
|
1345
|
+
min-width: 1.15em;
|
|
1346
|
+
height: 1.15em;
|
|
1347
|
+
flex: 0 0 1.15em;
|
|
1348
|
+
margin-right: 0;
|
|
1349
|
+
padding: 0;
|
|
1350
|
+
vertical-align: middle;
|
|
1351
|
+
display: inline-block;
|
|
1352
|
+
box-sizing: border-box;
|
|
1353
|
+
opacity: 1;
|
|
1354
|
+
background-repeat: no-repeat;
|
|
1355
|
+
background-position: center;
|
|
1356
|
+
background-size: contain;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
.cm-tooltip-autocomplete .cm-completionIcon svg {
|
|
1360
|
+
display: block;
|
|
1361
|
+
width: 100%;
|
|
1362
|
+
height: 100%;
|
|
1363
|
+
stroke: currentColor;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
.cm-tooltip-autocomplete .cm-completionIcon::after {
|
|
1367
|
+
content: none;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
/* Hide the popup's scrollbar without disabling scroll. CM6's list
|
|
1371
|
+
* is a <ul> with its own max-height + overflow:auto. */
|
|
1372
|
+
.cm-tooltip-autocomplete ul,
|
|
1373
|
+
.cm-tooltip-autocomplete .cm-completionList {
|
|
1374
|
+
scrollbar-width: none;
|
|
1375
|
+
-ms-overflow-style: none;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
.cm-tooltip-autocomplete ul::-webkit-scrollbar,
|
|
1379
|
+
.cm-tooltip-autocomplete .cm-completionList::-webkit-scrollbar {
|
|
1380
|
+
display: none;
|
|
1381
|
+
width: 0;
|
|
1382
|
+
height: 0;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
/* Bullet widget — replaces the raw `-` / `*` marker on bullet-list
|
|
1386
|
+
* items. Matches the visual weight of a real list marker while
|
|
1387
|
+
* staying in the muted-secondary color so the item text dominates. */
|
|
1388
|
+
/* Shared marker alcove — forces bullet, task checkbox, and
|
|
1389
|
+
* ordered-list number into the same fixed horizontal width so the
|
|
1390
|
+
* inline-preview line padding / text-indent math is stable across
|
|
1391
|
+
* list kinds. Width here must match LIST_ALCOVE_EM in
|
|
1392
|
+
* inline-preview.ts. Without the fixed width, wrapped-line
|
|
1393
|
+
* indent lands in different places for each kind because the raw
|
|
1394
|
+
* marker widths differ per font. */
|
|
1395
|
+
.cm-moss-list-marker {
|
|
1396
|
+
display: inline-block;
|
|
1397
|
+
width: 0.9em;
|
|
1398
|
+
margin-right: 0.3em;
|
|
1399
|
+
text-align: right;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
/* Active lines keep the source separator space so the caret can map to the
|
|
1403
|
+
* real Markdown position. Let that space provide the separation instead of
|
|
1404
|
+
* adding the alcove margin a second time. */
|
|
1405
|
+
.cm-moss-list-marker-active {
|
|
1406
|
+
margin-right: 0;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
/* Ordered markers keep their real source separator in the DOM on every
|
|
1410
|
+
* line, so their alcove must not add a second separator via margin. */
|
|
1411
|
+
.cm-moss-ordered-marker {
|
|
1412
|
+
margin-right: 0;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
/* List heads stay visually distinct from ordinary prose while the raw
|
|
1416
|
+
* Markdown remains the source of truth. Consumers can tune these tokens
|
|
1417
|
+
* independently without changing the list layout. */
|
|
1418
|
+
.cm-line .cm-moss-ordered-marker,
|
|
1419
|
+
.cm-line .cm-moss-ordered-marker * {
|
|
1420
|
+
color: var(--moss-list-marker, var(--moss-list-ordered, var(--moss-accent-bright, #a78bfa)));
|
|
1421
|
+
font-weight: 600;
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
.cm-moss-unordered-marker {
|
|
1425
|
+
color: var(--moss-list-marker, var(--moss-list-unordered, var(--moss-fg-muted, #888)));
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
/* Bullet-only visual styling on top of the shared alcove. */
|
|
1429
|
+
.cm-moss-bullet {
|
|
1430
|
+
color: var(--moss-fg-muted, #888);
|
|
1431
|
+
font-weight: 700;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
/* GFM task-list checkbox widget — replaces `[ ]` / `[x]` in a task
|
|
1435
|
+
* item. Styled as a small custom circle rather than the platform's
|
|
1436
|
+
* native checkbox so it reads consistently across browsers.
|
|
1437
|
+
* Width+margin still total 1.2em to match ALCOVE_EM in
|
|
1438
|
+
* inline-preview.ts. The trailing space after `[ ]` in the source is
|
|
1439
|
+
* swallowed by the replace decoration. */
|
|
1440
|
+
input.cm-moss-task-checkbox {
|
|
1441
|
+
width: 1.05em;
|
|
1442
|
+
height: 1.05em;
|
|
1443
|
+
margin: 0 0.31em 0 -0.16em;
|
|
1444
|
+
font-size: inherit;
|
|
1445
|
+
vertical-align: 0.1em;
|
|
1446
|
+
appearance: none;
|
|
1447
|
+
-webkit-appearance: none;
|
|
1448
|
+
box-sizing: border-box;
|
|
1449
|
+
border: 1px solid var(--moss-fg-muted, #888);
|
|
1450
|
+
border-radius: 50%;
|
|
1451
|
+
background: transparent;
|
|
1452
|
+
cursor: pointer;
|
|
1453
|
+
position: relative;
|
|
1454
|
+
display: inline-grid;
|
|
1455
|
+
place-content: center;
|
|
1456
|
+
transform: translateY(-0.04em);
|
|
1457
|
+
transition: border-color 140ms ease, box-shadow 140ms ease;
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
input.cm-moss-task-checkbox::after {
|
|
1461
|
+
content: "";
|
|
1462
|
+
width: 0.26em;
|
|
1463
|
+
height: 0.5em;
|
|
1464
|
+
border-right: 0.12em solid #ffffff;
|
|
1465
|
+
border-bottom: 0.12em solid #ffffff;
|
|
1466
|
+
transform: rotate(45deg) translate(-0.03em, -0.04em);
|
|
1467
|
+
opacity: 0;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
input.cm-moss-task-checkbox:checked {
|
|
1471
|
+
background: var(--moss-accent, #7c3aed);
|
|
1472
|
+
border-color: var(--moss-accent, #7c3aed);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
input.cm-moss-task-checkbox:checked::after {
|
|
1476
|
+
opacity: 1;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
input.cm-moss-task-checkbox:hover,
|
|
1480
|
+
.cm-moss-task-status:hover {
|
|
1481
|
+
border-color: var(--moss-accent-bright, var(--moss-accent, #7c3aed));
|
|
1482
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--moss-accent, #7c3aed) 16%, transparent 84%);
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
input.cm-moss-task-checkbox:focus-visible {
|
|
1486
|
+
outline: none;
|
|
1487
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--moss-accent, #7c3aed) 28%, transparent 72%);
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
/* Forced-colors mode removes box shadows, so retain a visible keyboard
|
|
1491
|
+
* focus indicator using system colors instead. */
|
|
1492
|
+
@media (forced-colors: active) {
|
|
1493
|
+
input.cm-moss-task-checkbox:focus-visible {
|
|
1494
|
+
outline: 2px solid Highlight;
|
|
1495
|
+
outline-offset: 2px;
|
|
1496
|
+
box-shadow: none;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/* Custom task statuses use their assigned Lucide icon in the same marker
|
|
1501
|
+
* alcove. A button keeps the status keyboard and pointer accessible without
|
|
1502
|
+
* pretending that every state is a binary checkbox. */
|
|
1503
|
+
.cm-moss-task-status {
|
|
1504
|
+
width: 1.05em;
|
|
1505
|
+
height: 1.05em;
|
|
1506
|
+
margin: 0 0.31em 0 -0.16em;
|
|
1507
|
+
padding: 0;
|
|
1508
|
+
border: 0;
|
|
1509
|
+
background: transparent;
|
|
1510
|
+
box-sizing: border-box;
|
|
1511
|
+
color: var(--moss-fg-muted, #888);
|
|
1512
|
+
cursor: pointer;
|
|
1513
|
+
font: inherit;
|
|
1514
|
+
font-size: 1em;
|
|
1515
|
+
line-height: 1;
|
|
1516
|
+
vertical-align: -0.08em;
|
|
1517
|
+
display: inline-flex;
|
|
1518
|
+
align-items: center;
|
|
1519
|
+
justify-content: center;
|
|
1520
|
+
place-content: center;
|
|
1521
|
+
border-radius: 50%;
|
|
1522
|
+
transition: color 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
.cm-moss-task-status-empty {
|
|
1526
|
+
border: 1px solid var(--moss-fg-muted, #888);
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
.cm-moss-task-status svg {
|
|
1530
|
+
width: 1em;
|
|
1531
|
+
height: 1em;
|
|
1532
|
+
stroke-width: 2.5;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
.cm-moss-task-status:hover {
|
|
1536
|
+
color: var(--moss-accent-bright, var(--moss-accent, #7c3aed));
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
.cm-moss-task-status:focus-visible {
|
|
1540
|
+
outline: 2px solid color-mix(in srgb, var(--moss-accent, #7c3aed) 42%, transparent 58%);
|
|
1541
|
+
outline-offset: 2px;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
/* Whole-line strike for completed task items. */
|
|
1545
|
+
.cm-line.cm-moss-task-done {
|
|
1546
|
+
color: var(--moss-fg-faint, #666);
|
|
1547
|
+
text-decoration: line-through;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
/* WYSIWYG table block widget — emitted by `mossTables()` in
|
|
1551
|
+
* table-widget.ts. The Table node's source range is fully replaced
|
|
1552
|
+
* by this rendered `<table>`; users interact with cells directly
|
|
1553
|
+
* via `contenteditable`, with Tab / Shift-Tab moving focus between
|
|
1554
|
+
* cells and Tab past the last cell appending a new row.
|
|
1555
|
+
*
|
|
1556
|
+
* Horizontal scroll on the wrapper so wide tables (common in
|
|
1557
|
+
* RSS-ingested content) don't squish their cells to unreadable
|
|
1558
|
+
* widths on narrow viewports. The inner `<table>` uses
|
|
1559
|
+
* `width: max-content` + `min-width: 100%` so it fills the reading
|
|
1560
|
+
* column when narrow and grows past it (triggering the scrollbar)
|
|
1561
|
+
* when content needs more room. `overscroll-behavior-x: contain`
|
|
1562
|
+
* keeps a horizontal flick from bubbling up and scrolling the
|
|
1563
|
+
* whole editor sideways. */
|
|
1564
|
+
/* Table wrapper — horizontal scroll contained here so wide
|
|
1565
|
+
* tables don't push the editor's content box wider than the
|
|
1566
|
+
* viewport. Paired with `.cm-content { min-width: 0 }` in the
|
|
1567
|
+
* theme, which is what actually keeps the content box pinned to
|
|
1568
|
+
* parent width (CM6's base theme sets `min-width: max-content`,
|
|
1569
|
+
* which otherwise lets a wide child expand the whole scroller).
|
|
1570
|
+
* Without that pairing no amount of table-level overflow
|
|
1571
|
+
* constraints would hold — the symptom was the editor briefly
|
|
1572
|
+
* going wider than the viewport on mobile when a wide table
|
|
1573
|
+
* entered the rendered viewport. */
|
|
1574
|
+
.cm-moss-table {
|
|
1575
|
+
/* Use padding, not margin, for vertical rhythm around the table.
|
|
1576
|
+
* CM6's heightmap measures block-widget heights via
|
|
1577
|
+
* `getBoundingClientRect`, which EXCLUDES margin but INCLUDES
|
|
1578
|
+
* padding. A `margin: 0.5em 0` here meant the heightmap allocated
|
|
1579
|
+
* less height than the DOM layout flow actually consumed — 1em
|
|
1580
|
+
* (~17px) less on typical font sizes. That drift shifted every
|
|
1581
|
+
* line below the table in CM6's heightmap vs the DOM, so clicks
|
|
1582
|
+
* at a visual Y were routed to the doc line BELOW the one
|
|
1583
|
+
* visually targeted. User-visible symptom: clicking an empty
|
|
1584
|
+
* line above a heading placed the caret on the heading; clicking
|
|
1585
|
+
* text in a task item with the caret on the empty line below
|
|
1586
|
+
* left the caret in place (because the "wrong" line was the same
|
|
1587
|
+
* as the current caret). Padding keeps the bbox honest so CM6's
|
|
1588
|
+
* heightmap matches the DOM. */
|
|
1589
|
+
padding: 0.5em 0;
|
|
1590
|
+
overflow-x: auto;
|
|
1591
|
+
overscroll-behavior-x: contain;
|
|
1592
|
+
-webkit-overflow-scrolling: touch;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
.cm-moss-table table {
|
|
1596
|
+
border-collapse: collapse;
|
|
1597
|
+
width: max-content;
|
|
1598
|
+
min-width: 100%;
|
|
1599
|
+
font-family: var(--moss-font, system-ui, sans-serif);
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
.cm-moss-table th,
|
|
1603
|
+
.cm-moss-table td {
|
|
1604
|
+
position: relative;
|
|
1605
|
+
border: 1px solid var(--moss-border, #3d3d3d);
|
|
1606
|
+
padding: 0.35em 0.6em;
|
|
1607
|
+
text-align: left;
|
|
1608
|
+
vertical-align: top;
|
|
1609
|
+
min-width: 2em;
|
|
1610
|
+
min-height: 1.5em;
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
.cm-moss-table th {
|
|
1614
|
+
font-weight: 700;
|
|
1615
|
+
background: var(--moss-code-bg, color-mix(in srgb, #2d2d2d 88%, black 12%));
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
/* Cells aren't contenteditable themselves; the inner source element
|
|
1619
|
+
* is. Outline the whole cell when focus lands inside so the edit
|
|
1620
|
+
* target reads as "the cell" even though the DOM is split. */
|
|
1621
|
+
.cm-moss-table th:focus-within,
|
|
1622
|
+
.cm-moss-table td:focus-within {
|
|
1623
|
+
outline: 2px solid var(--moss-accent, #7c3aed);
|
|
1624
|
+
outline-offset: -2px;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
/* The action button sits on the upper-right border intersection of the
|
|
1628
|
+
* focused cell. It is absolute so it never changes table sizing or row
|
|
1629
|
+
* height. */
|
|
1630
|
+
.cm-moss-table-menu-trigger {
|
|
1631
|
+
position: absolute;
|
|
1632
|
+
top: -0.7em;
|
|
1633
|
+
right: -0.7em;
|
|
1634
|
+
z-index: 2;
|
|
1635
|
+
width: 1.6em;
|
|
1636
|
+
height: 1.6em;
|
|
1637
|
+
display: inline-flex;
|
|
1638
|
+
align-items: center;
|
|
1639
|
+
justify-content: center;
|
|
1640
|
+
padding: 0;
|
|
1641
|
+
border: 1px solid var(--moss-border, #3d3d3d);
|
|
1642
|
+
border-radius: 0.35em;
|
|
1643
|
+
background: var(--moss-bg-panel, #252525);
|
|
1644
|
+
color: var(--moss-fg-muted, #888);
|
|
1645
|
+
cursor: pointer;
|
|
1646
|
+
opacity: 0;
|
|
1647
|
+
pointer-events: none;
|
|
1648
|
+
transition: opacity 0.12s ease, background-color 0.12s ease,
|
|
1649
|
+
color 0.12s ease, transform 0.12s ease;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
.cm-moss-table th:focus-within .cm-moss-table-menu-trigger,
|
|
1653
|
+
.cm-moss-table td:focus-within .cm-moss-table-menu-trigger {
|
|
1654
|
+
opacity: 1;
|
|
1655
|
+
pointer-events: auto;
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
.cm-moss-table-menu-trigger:hover,
|
|
1659
|
+
.cm-moss-table-menu-trigger:focus-visible {
|
|
1660
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
1661
|
+
color: var(--moss-fg, #dcddde);
|
|
1662
|
+
transform: scale(1.05);
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
.cm-moss-table-menu-trigger:focus-visible {
|
|
1666
|
+
outline: 2px solid var(--moss-accent, #7c3aed);
|
|
1667
|
+
outline-offset: 2px;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
.cm-moss-table-menu-trigger svg {
|
|
1671
|
+
width: 1em;
|
|
1672
|
+
height: 1em;
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
/* The editable source inside a cell — always shows the raw markdown
|
|
1676
|
+
* the user types, whether or not the cell also has a rendered image
|
|
1677
|
+
* preview below. Blank outline because the cell's :focus-within
|
|
1678
|
+
* ring is what signals the active edit target. */
|
|
1679
|
+
.cm-moss-table-cell-source {
|
|
1680
|
+
outline: none;
|
|
1681
|
+
min-height: 1.2em;
|
|
1682
|
+
white-space: pre-wrap;
|
|
1683
|
+
word-break: break-word;
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
/* Inline-mark delimiters (`**`, `__`, `*`, `_`, `~~`, `[`, `]`, `(`, `)`,
|
|
1687
|
+
* URLs) inside table cells. Hidden by default so the reader sees only
|
|
1688
|
+
* the rendered content — bold text without `**`, link text without
|
|
1689
|
+
* brackets or URL. The delimiters remain in the DOM (so textContent
|
|
1690
|
+
* round-trips to the raw markdown on input) but take zero space and
|
|
1691
|
+
* the caret can't navigate into them.
|
|
1692
|
+
*
|
|
1693
|
+
* When the caret enters a mark wrap, JS adds `active` and the
|
|
1694
|
+
* descendant delimiters reveal — so the user can actually edit them.
|
|
1695
|
+
* Nested marks (bold-containing-italic) all reveal together when any
|
|
1696
|
+
* of them contains the caret, because the JS walks ancestors. */
|
|
1697
|
+
.cm-moss-table-cell-source .cm-moss-mark {
|
|
1698
|
+
display: none;
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
.cm-moss-table-cell-source .cm-moss-strong-wrap.active > .cm-moss-mark,
|
|
1702
|
+
.cm-moss-table-cell-source .cm-moss-em-wrap.active > .cm-moss-mark,
|
|
1703
|
+
.cm-moss-table-cell-source .cm-moss-strike-wrap.active > .cm-moss-mark,
|
|
1704
|
+
.cm-moss-table-cell-source .cm-moss-highlight-wrap.active > .cm-moss-mark,
|
|
1705
|
+
.cm-moss-table-cell-source .cm-moss-link-wrap.active > .cm-moss-mark {
|
|
1706
|
+
display: inline;
|
|
1707
|
+
color: var(--moss-fg-faint, #666);
|
|
1708
|
+
font-weight: normal;
|
|
1709
|
+
font-style: normal;
|
|
1710
|
+
text-decoration: none;
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
/* Link URL: monospace hint + size cut so a long URL doesn't dominate
|
|
1714
|
+
* the cell's width once its wrap becomes active. */
|
|
1715
|
+
.cm-moss-table-cell-source .cm-moss-link-wrap.active > .cm-moss-link-url {
|
|
1716
|
+
font-family: var(--moss-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
1717
|
+
font-size: 0.88em;
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
.cm-moss-table-cell-source .cm-moss-highlight {
|
|
1721
|
+
background: color-mix(in srgb, var(--moss-accent-bright, #a78bfa) 20%, transparent 80%);
|
|
1722
|
+
border-radius: 0.18em;
|
|
1723
|
+
color: var(--moss-fg, #dcddde);
|
|
1724
|
+
box-decoration-break: clone;
|
|
1725
|
+
-webkit-box-decoration-break: clone;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
/* Rendered image preview strip below the source text. Mirrors how
|
|
1729
|
+
* block-level images render outside a table: the ``
|
|
1730
|
+
* markdown is the source of truth, but the user sees the image in
|
|
1731
|
+
* the resting state — the raw markdown only appears when the cell
|
|
1732
|
+
* is focused for editing (see :focus-within rule below). */
|
|
1733
|
+
.cm-moss-table-cell-preview {
|
|
1734
|
+
margin-top: 0.35em;
|
|
1735
|
+
display: flex;
|
|
1736
|
+
flex-wrap: wrap;
|
|
1737
|
+
gap: 0.3em;
|
|
1738
|
+
user-select: none;
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
/* Mirror the block-image invariant from outside tables: on an
|
|
1742
|
+
* inactive cell, the raw `` markdown hides and only the
|
|
1743
|
+
* rendered image shows. Focus the cell (click or Tab) to bring the
|
|
1744
|
+
* source back so it can be edited.
|
|
1745
|
+
*
|
|
1746
|
+
* We visually hide the source without `display: none` so it stays in
|
|
1747
|
+
* the DOM and remains focusable — Tab nav calls `source.focus()`
|
|
1748
|
+
* explicitly and would silently fail on a display:none element. The
|
|
1749
|
+
* position:absolute + zero-size pattern keeps the element interactive
|
|
1750
|
+
* while taking no visible space. */
|
|
1751
|
+
.cm-moss-table th[data-has-image]:not(:focus-within) .cm-moss-table-cell-source,
|
|
1752
|
+
.cm-moss-table td[data-has-image]:not(:focus-within) .cm-moss-table-cell-source {
|
|
1753
|
+
position: absolute;
|
|
1754
|
+
width: 1px;
|
|
1755
|
+
height: 1px;
|
|
1756
|
+
overflow: hidden;
|
|
1757
|
+
opacity: 0;
|
|
1758
|
+
pointer-events: none;
|
|
1759
|
+
white-space: nowrap;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
/* Inline images inside table cells. Capped so a tall image doesn't
|
|
1763
|
+
* balloon a single row into half the viewport. Users who want larger
|
|
1764
|
+
* in-cell images can do without for now — we'd need Obsidian's
|
|
1765
|
+
* `[[file|width]]` alias syntax to make it controllable. */
|
|
1766
|
+
.cm-moss-table-cell-image {
|
|
1767
|
+
display: block;
|
|
1768
|
+
max-width: 14em;
|
|
1769
|
+
max-height: 5em;
|
|
1770
|
+
border-radius: 0.2em;
|
|
1771
|
+
cursor: pointer;
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
/* Table actions menu — opened from the focused cell's upper-right trigger.
|
|
1775
|
+
* Mounted on document.body so positioning isn't affected by CM6's overflow
|
|
1776
|
+
* scroll. */
|
|
1777
|
+
.cm-moss-table-menu {
|
|
1778
|
+
position: fixed;
|
|
1779
|
+
z-index: 1000;
|
|
1780
|
+
min-width: 170px;
|
|
1781
|
+
padding: 0.25rem 0;
|
|
1782
|
+
background: var(--moss-bg-panel, #252525);
|
|
1783
|
+
border: 1px solid var(--moss-border, #3d3d3d);
|
|
1784
|
+
border-radius: var(--moss-radius, 6px);
|
|
1785
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
|
1786
|
+
font-family: var(--moss-font, system-ui, sans-serif);
|
|
1787
|
+
font-size: 0.82rem;
|
|
1788
|
+
color: var(--moss-fg, #dcddde);
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
.cm-moss-table-menu-item {
|
|
1792
|
+
display: flex;
|
|
1793
|
+
align-items: center;
|
|
1794
|
+
gap: 0.55rem;
|
|
1795
|
+
box-sizing: border-box;
|
|
1796
|
+
width: 100%;
|
|
1797
|
+
text-align: left;
|
|
1798
|
+
min-height: 2rem;
|
|
1799
|
+
padding: 0.38rem 0.7rem;
|
|
1800
|
+
background: transparent;
|
|
1801
|
+
border: 0;
|
|
1802
|
+
color: inherit;
|
|
1803
|
+
font: inherit;
|
|
1804
|
+
cursor: pointer;
|
|
1805
|
+
transition: background-color 0.12s ease, color 0.12s ease;
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
.cm-moss-table-menu-item:hover,
|
|
1809
|
+
.cm-moss-table-menu-item:focus-visible {
|
|
1810
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
1811
|
+
outline: none;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
.cm-moss-table-menu-item.is-destructive {
|
|
1815
|
+
color: var(--moss-hl-invalid, #ff5370);
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
.cm-moss-table-menu-item.is-destructive:hover,
|
|
1819
|
+
.cm-moss-table-menu-item.is-destructive:focus-visible {
|
|
1820
|
+
background: color-mix(
|
|
1821
|
+
in srgb,
|
|
1822
|
+
var(--moss-hl-invalid, #ff5370) 12%,
|
|
1823
|
+
var(--moss-bg-surface, #2d2d2d) 88%
|
|
1824
|
+
);
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
.cm-moss-table-menu-item-icon {
|
|
1828
|
+
display: inline-flex;
|
|
1829
|
+
flex: 0 0 1rem;
|
|
1830
|
+
align-items: center;
|
|
1831
|
+
justify-content: center;
|
|
1832
|
+
color: var(--moss-fg-muted, #888);
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
.cm-moss-table-menu-item.is-destructive .cm-moss-table-menu-item-icon {
|
|
1836
|
+
color: currentColor;
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
.cm-moss-table-menu-item-icon svg {
|
|
1840
|
+
width: 1rem;
|
|
1841
|
+
height: 1rem;
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
.cm-moss-table-menu-item-label {
|
|
1845
|
+
min-width: 0;
|
|
1846
|
+
overflow: hidden;
|
|
1847
|
+
text-overflow: ellipsis;
|
|
1848
|
+
white-space: nowrap;
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
.cm-moss-table-menu-sep {
|
|
1852
|
+
height: 1px;
|
|
1853
|
+
margin: 0.25rem 0;
|
|
1854
|
+
background: var(--moss-border, #3d3d3d);
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
/* Find-in-document panel — a floating control strip owned by the
|
|
1858
|
+
* search feature. The CM panel only reserves the top/bottom slot;
|
|
1859
|
+
* the visible chrome is split into input and actions pills. */
|
|
1860
|
+
.moss-cm-editor .cm-editor {
|
|
1861
|
+
position: relative;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
.moss-cm-editor .cm-panels:has(.moss-search-panel) {
|
|
1865
|
+
position: absolute;
|
|
1866
|
+
left: 0;
|
|
1867
|
+
right: 0;
|
|
1868
|
+
z-index: 10;
|
|
1869
|
+
background: transparent;
|
|
1870
|
+
border: 0;
|
|
1871
|
+
color: var(--moss-fg, #dcddde);
|
|
1872
|
+
pointer-events: none;
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
.moss-cm-editor .cm-panels-top:has(.moss-search-panel) {
|
|
1876
|
+
top: 0.5rem;
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
.moss-cm-editor .cm-panels-top:has(.moss-search-panel-center) {
|
|
1880
|
+
top: 50%;
|
|
1881
|
+
transform: translateY(-50%);
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
.moss-cm-editor .cm-panels-bottom:has(.moss-search-panel) {
|
|
1885
|
+
bottom: 0.5rem;
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
.cm-panel.moss-search-panel {
|
|
1889
|
+
padding: 0;
|
|
1890
|
+
background: transparent;
|
|
1891
|
+
border: 0;
|
|
1892
|
+
font-family: var(--moss-font, system-ui, sans-serif);
|
|
1893
|
+
color: var(--moss-fg, #dcddde);
|
|
1894
|
+
pointer-events: none;
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
.cm-panel.moss-search-panel-top {
|
|
1898
|
+
border-bottom: 0;
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
.cm-panel.moss-search-panel-bottom {
|
|
1902
|
+
border-top: 0;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
.cm-panel.moss-search-panel-center {
|
|
1906
|
+
border: 0;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
.cm-panel.moss-search-panel form {
|
|
1910
|
+
display: flex;
|
|
1911
|
+
align-items: center;
|
|
1912
|
+
justify-content: center;
|
|
1913
|
+
gap: 0.45rem;
|
|
1914
|
+
box-sizing: border-box;
|
|
1915
|
+
width: fit-content;
|
|
1916
|
+
max-width: min(var(--moss-measure, 70ch), calc(100% - 1rem));
|
|
1917
|
+
margin-inline: auto;
|
|
1918
|
+
padding: 0;
|
|
1919
|
+
background: transparent;
|
|
1920
|
+
border: 0;
|
|
1921
|
+
border-radius: 0;
|
|
1922
|
+
box-shadow: none;
|
|
1923
|
+
backdrop-filter: none;
|
|
1924
|
+
pointer-events: auto;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
.cm-panel.moss-search-panel .cm-moss-search-input-pill,
|
|
1928
|
+
.cm-panel.moss-search-panel .cm-moss-search-actions-pill {
|
|
1929
|
+
display: inline-flex;
|
|
1930
|
+
align-items: center;
|
|
1931
|
+
min-height: 1.85rem;
|
|
1932
|
+
background: color-mix(in srgb, var(--moss-bg-surface, #2d2d2d) 92%, transparent);
|
|
1933
|
+
border: 1px solid color-mix(in srgb, var(--moss-fg, #dcddde) 10%, transparent);
|
|
1934
|
+
border-radius: 999px;
|
|
1935
|
+
box-shadow:
|
|
1936
|
+
0 1px 0 rgba(255, 255, 255, 0.06) inset,
|
|
1937
|
+
0 1px 2px rgba(0, 0, 0, 0.3),
|
|
1938
|
+
0 8px 20px rgba(0, 0, 0, 0.2);
|
|
1939
|
+
backdrop-filter: blur(14px);
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
.cm-panel.moss-search-panel .cm-moss-search-input-pill {
|
|
1943
|
+
gap: 0.35rem;
|
|
1944
|
+
max-width: min(24rem, calc(100vw - 5rem));
|
|
1945
|
+
padding: 0.16rem 0.55rem;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
.cm-panel.moss-search-panel .cm-moss-search-input-pill:focus-within {
|
|
1949
|
+
border-color: color-mix(in srgb, var(--moss-accent, #7c3aed) 42%, transparent);
|
|
1950
|
+
box-shadow:
|
|
1951
|
+
0 1px 0 rgba(255, 255, 255, 0.06) inset,
|
|
1952
|
+
0 0 0 2px color-mix(in srgb, var(--moss-accent, #7c3aed) 20%, transparent),
|
|
1953
|
+
0 8px 20px rgba(0, 0, 0, 0.2);
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
.cm-panel.moss-search-panel .cm-moss-search-actions-pill {
|
|
1957
|
+
gap: 0.1rem;
|
|
1958
|
+
padding: 0.18rem 0.25rem;
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
[data-theme="light"] .cm-panel.moss-search-panel .cm-moss-search-input-pill,
|
|
1962
|
+
[data-theme="light"] .cm-panel.moss-search-panel .cm-moss-search-actions-pill {
|
|
1963
|
+
border-color: color-mix(in srgb, var(--moss-fg, #1a1a1a) 10%, transparent);
|
|
1964
|
+
box-shadow:
|
|
1965
|
+
0 1px 0 rgba(0, 0, 0, 0.03) inset,
|
|
1966
|
+
0 1px 3px rgba(0, 0, 0, 0.06),
|
|
1967
|
+
0 6px 16px rgba(0, 0, 0, 0.08);
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
.cm-panel.cm-search.moss-search-panel input.cm-moss-search-input[type="text"] {
|
|
1971
|
+
appearance: none;
|
|
1972
|
+
flex: 1 1 auto;
|
|
1973
|
+
width: clamp(9rem, 28vw, 17rem);
|
|
1974
|
+
min-width: 6rem;
|
|
1975
|
+
height: 1.35rem;
|
|
1976
|
+
padding: 0;
|
|
1977
|
+
background: transparent;
|
|
1978
|
+
border: 0;
|
|
1979
|
+
border-radius: 0;
|
|
1980
|
+
box-shadow: none;
|
|
1981
|
+
color: inherit;
|
|
1982
|
+
font: inherit;
|
|
1983
|
+
font-size: 0.75rem;
|
|
1984
|
+
outline: none;
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
.cm-panel.cm-search.moss-search-panel input.cm-moss-search-input[type="text"]:focus {
|
|
1988
|
+
background: transparent;
|
|
1989
|
+
border: 0;
|
|
1990
|
+
box-shadow: none;
|
|
1991
|
+
outline: none;
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
.cm-panel.cm-search.moss-search-panel input.cm-moss-search-input[type="text"]::placeholder {
|
|
1995
|
+
color: var(--moss-fg-muted, #888);
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
.cm-panel.moss-search-panel .cm-moss-search-count {
|
|
1999
|
+
flex: 0 0 auto;
|
|
2000
|
+
color: var(--moss-fg-muted, #888);
|
|
2001
|
+
font-size: 0.625rem;
|
|
2002
|
+
white-space: nowrap;
|
|
2003
|
+
min-width: 0;
|
|
2004
|
+
padding-inline: 0.1rem;
|
|
2005
|
+
user-select: none;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
.cm-panel.cm-search.moss-search-panel button.cm-moss-search-btn {
|
|
2009
|
+
appearance: none;
|
|
2010
|
+
flex: 0 0 auto;
|
|
2011
|
+
display: inline-flex;
|
|
2012
|
+
align-items: center;
|
|
2013
|
+
justify-content: center;
|
|
2014
|
+
width: 1.45rem;
|
|
2015
|
+
height: 1.45rem;
|
|
2016
|
+
padding: 0;
|
|
2017
|
+
background: transparent;
|
|
2018
|
+
border: 0;
|
|
2019
|
+
border-radius: 999px;
|
|
2020
|
+
box-shadow: none;
|
|
2021
|
+
color: var(--moss-fg-muted, #888);
|
|
2022
|
+
cursor: pointer;
|
|
2023
|
+
transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
.cm-panel.cm-search.moss-search-panel button.cm-moss-search-btn:hover {
|
|
2027
|
+
background: var(--moss-bg-surface, #2d2d2d);
|
|
2028
|
+
color: var(--moss-fg, #dcddde);
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
.cm-panel.cm-search.moss-search-panel button.cm-moss-search-btn:focus-visible {
|
|
2032
|
+
outline: none;
|
|
2033
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--moss-accent, #7c3aed) 30%, transparent);
|
|
2034
|
+
color: var(--moss-fg, #dcddde);
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
.cm-panel.cm-search.moss-search-panel button.cm-moss-search-btn svg {
|
|
2038
|
+
display: block;
|
|
2039
|
+
width: 1rem;
|
|
2040
|
+
height: 1rem;
|
|
2041
|
+
color: inherit;
|
|
2042
|
+
stroke: currentColor;
|
|
2043
|
+
fill: none;
|
|
2044
|
+
pointer-events: none;
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
.cm-panel.cm-search.moss-search-panel button.cm-moss-search-btn svg * {
|
|
2048
|
+
stroke: currentColor;
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
/* Highlight matches in the document. Active match gets a stronger
|
|
2052
|
+
* fill; other matches share the same tone in a lighter shade. The
|
|
2053
|
+
* background-color custom properties are pre-mixed in src/index.css
|
|
2054
|
+
* to alpha-blend cleanly over whatever theme backdrop is active. */
|
|
2055
|
+
.cm-searchMatch {
|
|
2056
|
+
background: var(--moss-search-bg, rgba(124, 58, 237, 0.28));
|
|
2057
|
+
border-radius: 2px;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
.cm-searchMatch-selected {
|
|
2061
|
+
background: var(--moss-search-bg-active, rgba(124, 58, 237, 0.6));
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
/* Initial reveal highlight — paired with the `initialRevealText` prop
|
|
2065
|
+
* and the `revealText()` imperative method on the editor handle.
|
|
2066
|
+
* Starts at a stronger accent-tinted background, settles to a softer
|
|
2067
|
+
* one, then fades to transparent over ~3.2s so the reader's eye
|
|
2068
|
+
* catches the match on arrival without the highlight lingering.
|
|
2069
|
+
*
|
|
2070
|
+
* Two tokens so consumers can theme either the peak or the settled
|
|
2071
|
+
* state independently of the main search-match colors. */
|
|
2072
|
+
.cm-initialRevealMatch {
|
|
2073
|
+
background: var(
|
|
2074
|
+
--moss-initial-reveal-bg,
|
|
2075
|
+
color-mix(in srgb, var(--moss-accent-soft, #a78bfa) 28%, transparent 72%)
|
|
2076
|
+
);
|
|
2077
|
+
border-radius: 0.2rem;
|
|
2078
|
+
animation: moss-initial-reveal-fade 3.2s ease-out forwards;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
@keyframes moss-initial-reveal-fade {
|
|
2082
|
+
0% {
|
|
2083
|
+
background: var(
|
|
2084
|
+
--moss-initial-reveal-bg-strong,
|
|
2085
|
+
color-mix(in srgb, var(--moss-accent-soft, #a78bfa) 42%, transparent 58%)
|
|
2086
|
+
);
|
|
2087
|
+
}
|
|
2088
|
+
65% {
|
|
2089
|
+
background: var(
|
|
2090
|
+
--moss-initial-reveal-bg,
|
|
2091
|
+
color-mix(in srgb, var(--moss-accent-soft, #a78bfa) 28%, transparent 72%)
|
|
2092
|
+
);
|
|
2093
|
+
}
|
|
2094
|
+
100% {
|
|
2095
|
+
background: transparent;
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
/* Read-only ("reading") mode. The `cm-moss-readonly` class is set on
|
|
2100
|
+
* the editor wrapper by `readOnlyExtension` (src/read-only.ts). In this
|
|
2101
|
+
* mode nothing reveals its source and the whole document is a reading
|
|
2102
|
+
* surface, so interactive affordances change accordingly. */
|
|
2103
|
+
|
|
2104
|
+
/* The entire link is the open target now (not just the trailing icon),
|
|
2105
|
+
* so the text gets the pointer cursor too — for both inline links and
|
|
2106
|
+
* links rendered inside table cells. */
|
|
2107
|
+
.cm-moss-readonly .cm-moss-link,
|
|
2108
|
+
.cm-moss-readonly .cm-moss-wiki-link,
|
|
2109
|
+
.cm-moss-readonly .cm-moss-link-wrap {
|
|
2110
|
+
cursor: pointer;
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
/* Table cells are inert: no caret, no text cursor. */
|
|
2114
|
+
.cm-moss-readonly .cm-moss-table-cell-source {
|
|
2115
|
+
cursor: default;
|
|
2116
|
+
}
|