yamlover 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/bin/yamlover.js +202 -0
- package/dist/server.js +4681 -0
- package/index.html +12 -0
- package/package.json +72 -0
- package/src/client/App.tsx +372 -0
- package/src/client/NodeView.tsx +422 -0
- package/src/client/TaskStrip.tsx +34 -0
- package/src/client/Tree.tsx +97 -0
- package/src/client/api.ts +186 -0
- package/src/client/icons.ts +91 -0
- package/src/client/links.tsx +108 -0
- package/src/client/live.ts +42 -0
- package/src/client/main.tsx +10 -0
- package/src/client/paste-html.ts +228 -0
- package/src/client/paste-links.ts +42 -0
- package/src/client/paths.ts +109 -0
- package/src/client/render.tsx +326 -0
- package/src/client/renderers/annotate.tsx +507 -0
- package/src/client/renderers/asciidoc.tsx +35 -0
- package/src/client/renderers/chapter.tsx +138 -0
- package/src/client/renderers/csv.tsx +233 -0
- package/src/client/renderers/decoded.tsx +72 -0
- package/src/client/renderers/djvu.tsx +97 -0
- package/src/client/renderers/doc.tsx +40 -0
- package/src/client/renderers/docx.tsx +49 -0
- package/src/client/renderers/epub.tsx +147 -0
- package/src/client/renderers/explorer.tsx +209 -0
- package/src/client/renderers/fb2.tsx +149 -0
- package/src/client/renderers/headings.ts +69 -0
- package/src/client/renderers/heic.tsx +23 -0
- package/src/client/renderers/imagemap.tsx +157 -0
- package/src/client/renderers/kml.ts +46 -0
- package/src/client/renderers/latex.tsx +36 -0
- package/src/client/renderers/map.tsx +205 -0
- package/src/client/renderers/marklower.tsx +119 -0
- package/src/client/renderers/markup.tsx +64 -0
- package/src/client/renderers/media.tsx +19 -0
- package/src/client/renderers/panzoom.ts +101 -0
- package/src/client/renderers/pdf.tsx +176 -0
- package/src/client/renderers/plaintext.tsx +120 -0
- package/src/client/renderers/plantuml.tsx +82 -0
- package/src/client/renderers/psd.tsx +25 -0
- package/src/client/renderers/registry.tsx +389 -0
- package/src/client/renderers/rtf.tsx +210 -0
- package/src/client/renderers/spreadsheet.tsx +105 -0
- package/src/client/renderers/tag.tsx +113 -0
- package/src/client/renderers/text.tsx +41 -0
- package/src/client/renderers/tiff.tsx +33 -0
- package/src/client/styles.css +1115 -0
- package/src/client/vendor/README.md +30 -0
- package/src/client/vendor/djvu.js +15535 -0
- package/src/client/vite-env.d.ts +31 -0
- package/src/server/api.ts +147 -0
- package/src/server/engine-api.ts +1442 -0
- package/src/server/gitignore.ts +81 -0
- package/src/server/node-kind.ts +48 -0
- package/src/server/tasks.ts +83 -0
- package/src/server/yamlover.ts +1133 -0
|
@@ -0,0 +1,1115 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--bg: #1e1e2e;
|
|
3
|
+
--bg-alt: #181825;
|
|
4
|
+
--panel: #24273a;
|
|
5
|
+
--line: #363a4f;
|
|
6
|
+
--fg: #cad3f5;
|
|
7
|
+
--dim: #8087a2;
|
|
8
|
+
--accent: #8aadf4;
|
|
9
|
+
--key: #91d7e3;
|
|
10
|
+
--string: #a6da95;
|
|
11
|
+
--number: #f5a97f;
|
|
12
|
+
--bool: #c6a0f6;
|
|
13
|
+
--null: #ed8796;
|
|
14
|
+
--sel: #363a4f;
|
|
15
|
+
--font: ui-monospace, "SF Mono", "JetBrains Mono", "Fira Code", Menlo, Consolas, monospace;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
* {
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
html,
|
|
23
|
+
body,
|
|
24
|
+
#root {
|
|
25
|
+
height: 100%;
|
|
26
|
+
margin: 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
body {
|
|
30
|
+
background: var(--bg);
|
|
31
|
+
color: var(--fg);
|
|
32
|
+
font-family: var(--font);
|
|
33
|
+
/* base reading size — TOC labels, breadcrumb, and rendered prose all inherit it.
|
|
34
|
+
14px sits closer to the larger default size of the PDF/DjVu page renderers. */
|
|
35
|
+
font-size: 14px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.app {
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
height: 100vh;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* --- top bar / breadcrumbs ------------------------------------------------ */
|
|
45
|
+
.topbar {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: 16px;
|
|
49
|
+
padding: 8px 14px;
|
|
50
|
+
background: var(--bg-alt);
|
|
51
|
+
border-bottom: 1px solid var(--line);
|
|
52
|
+
flex: 0 0 auto;
|
|
53
|
+
}
|
|
54
|
+
.crumbs {
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
flex-wrap: wrap;
|
|
58
|
+
min-height: 1.3em; /* keep the bar from collapsing before the head loads */
|
|
59
|
+
}
|
|
60
|
+
.crumb {
|
|
61
|
+
color: var(--fg);
|
|
62
|
+
text-decoration: none;
|
|
63
|
+
}
|
|
64
|
+
.crumb:hover {
|
|
65
|
+
color: var(--accent);
|
|
66
|
+
text-decoration: underline;
|
|
67
|
+
}
|
|
68
|
+
.crumb-sep {
|
|
69
|
+
color: var(--dim);
|
|
70
|
+
margin: 0 6px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* --- long-running server tasks (indexing, hashing, …) ---------------------- */
|
|
74
|
+
.task-strip {
|
|
75
|
+
margin-left: auto; /* park the chips at the topbar's right edge */
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
gap: 12px;
|
|
79
|
+
min-width: 0;
|
|
80
|
+
}
|
|
81
|
+
.task-chip {
|
|
82
|
+
display: inline-flex;
|
|
83
|
+
flex-direction: column;
|
|
84
|
+
gap: 3px;
|
|
85
|
+
max-width: 320px;
|
|
86
|
+
font-size: 12px;
|
|
87
|
+
color: var(--dim);
|
|
88
|
+
}
|
|
89
|
+
.task-chip.error {
|
|
90
|
+
color: var(--null);
|
|
91
|
+
}
|
|
92
|
+
.task-label {
|
|
93
|
+
white-space: nowrap;
|
|
94
|
+
overflow: hidden;
|
|
95
|
+
text-overflow: ellipsis;
|
|
96
|
+
}
|
|
97
|
+
.task-counts {
|
|
98
|
+
color: var(--fg);
|
|
99
|
+
}
|
|
100
|
+
.task-bar {
|
|
101
|
+
display: block;
|
|
102
|
+
height: 3px;
|
|
103
|
+
border-radius: 2px;
|
|
104
|
+
background: var(--line);
|
|
105
|
+
overflow: hidden;
|
|
106
|
+
position: relative;
|
|
107
|
+
}
|
|
108
|
+
.task-bar-fill {
|
|
109
|
+
display: block;
|
|
110
|
+
height: 100%;
|
|
111
|
+
background: var(--accent);
|
|
112
|
+
transition: width 0.2s ease;
|
|
113
|
+
}
|
|
114
|
+
.task-chip.done .task-bar-fill {
|
|
115
|
+
background: var(--string);
|
|
116
|
+
}
|
|
117
|
+
.task-chip.error .task-bar-fill {
|
|
118
|
+
background: var(--null);
|
|
119
|
+
width: 100%;
|
|
120
|
+
}
|
|
121
|
+
.task-bar-fill.indeterminate {
|
|
122
|
+
width: 40%;
|
|
123
|
+
position: absolute;
|
|
124
|
+
animation: task-sweep 1.2s ease-in-out infinite;
|
|
125
|
+
}
|
|
126
|
+
@keyframes task-sweep {
|
|
127
|
+
0% { left: -40%; }
|
|
128
|
+
100% { left: 100%; }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* --- body split ----------------------------------------------------------- */
|
|
132
|
+
.body {
|
|
133
|
+
display: flex;
|
|
134
|
+
flex: 1 1 auto;
|
|
135
|
+
min-height: 0;
|
|
136
|
+
}
|
|
137
|
+
.pane {
|
|
138
|
+
height: 100%;
|
|
139
|
+
overflow: auto; /* LHS and RHS scroll independently */
|
|
140
|
+
}
|
|
141
|
+
.left {
|
|
142
|
+
flex: 0 0 auto;
|
|
143
|
+
background: var(--panel);
|
|
144
|
+
border-right: 1px solid var(--line);
|
|
145
|
+
padding: 8px 0;
|
|
146
|
+
}
|
|
147
|
+
.right {
|
|
148
|
+
flex: 1 1 auto;
|
|
149
|
+
padding: 14px 18px;
|
|
150
|
+
}
|
|
151
|
+
.splitter {
|
|
152
|
+
flex: 0 0 5px;
|
|
153
|
+
cursor: col-resize;
|
|
154
|
+
background: var(--line);
|
|
155
|
+
}
|
|
156
|
+
.splitter:hover {
|
|
157
|
+
background: var(--accent);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* --- tree ----------------------------------------------------------------- */
|
|
161
|
+
.tree-row {
|
|
162
|
+
display: flex;
|
|
163
|
+
align-items: center;
|
|
164
|
+
gap: 4px;
|
|
165
|
+
padding: 1px 8px 1px 0;
|
|
166
|
+
white-space: nowrap;
|
|
167
|
+
}
|
|
168
|
+
.tree-row.selected {
|
|
169
|
+
background: var(--sel);
|
|
170
|
+
}
|
|
171
|
+
.tree-label {
|
|
172
|
+
cursor: pointer;
|
|
173
|
+
}
|
|
174
|
+
.tree-label:hover {
|
|
175
|
+
color: var(--accent);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* type/format icon */
|
|
179
|
+
.icon {
|
|
180
|
+
display: inline-block;
|
|
181
|
+
width: 1.6em;
|
|
182
|
+
text-align: center;
|
|
183
|
+
flex: 0 0 auto;
|
|
184
|
+
font-size: 12px;
|
|
185
|
+
}
|
|
186
|
+
.t-struct {
|
|
187
|
+
color: var(--key);
|
|
188
|
+
}
|
|
189
|
+
.t-str {
|
|
190
|
+
color: var(--string);
|
|
191
|
+
}
|
|
192
|
+
.t-num {
|
|
193
|
+
color: var(--number);
|
|
194
|
+
}
|
|
195
|
+
.t-bool {
|
|
196
|
+
color: var(--bool);
|
|
197
|
+
}
|
|
198
|
+
.t-null {
|
|
199
|
+
color: var(--null);
|
|
200
|
+
}
|
|
201
|
+
.t-bin,
|
|
202
|
+
.t-fmt {
|
|
203
|
+
color: var(--dim);
|
|
204
|
+
}
|
|
205
|
+
/* binary type glyph: the bits "0110" boxed into a little square (the TOC icon and
|
|
206
|
+
the explorer grid render the same mark) */
|
|
207
|
+
.icon.binsq,
|
|
208
|
+
.dirview-icon.binsq {
|
|
209
|
+
width: auto;
|
|
210
|
+
font-family: var(--mono, monospace);
|
|
211
|
+
font-size: 6px;
|
|
212
|
+
font-weight: 700;
|
|
213
|
+
line-height: 1;
|
|
214
|
+
border: 1px solid currentColor;
|
|
215
|
+
border-radius: 2px;
|
|
216
|
+
padding: 2px 2px;
|
|
217
|
+
}
|
|
218
|
+
.dirview-icon.binsq {
|
|
219
|
+
flex: none;
|
|
220
|
+
margin: 0 2px; /* keep the label column roughly aligned with the 22px emoji icons */
|
|
221
|
+
}
|
|
222
|
+
.toggle {
|
|
223
|
+
display: inline-flex;
|
|
224
|
+
align-items: center;
|
|
225
|
+
justify-content: center;
|
|
226
|
+
width: 20px;
|
|
227
|
+
height: 20px;
|
|
228
|
+
background: none;
|
|
229
|
+
border: none;
|
|
230
|
+
color: var(--dim);
|
|
231
|
+
cursor: pointer;
|
|
232
|
+
padding: 0;
|
|
233
|
+
flex: 0 0 auto;
|
|
234
|
+
}
|
|
235
|
+
.toggle .chevron {
|
|
236
|
+
font-size: 20px;
|
|
237
|
+
font-weight: 700;
|
|
238
|
+
line-height: 1;
|
|
239
|
+
transition: transform 0.12s ease;
|
|
240
|
+
}
|
|
241
|
+
.toggle.open .chevron {
|
|
242
|
+
transform: rotate(90deg);
|
|
243
|
+
}
|
|
244
|
+
.toggle.loading {
|
|
245
|
+
opacity: 0.4;
|
|
246
|
+
}
|
|
247
|
+
.toggle:hover {
|
|
248
|
+
color: var(--accent);
|
|
249
|
+
}
|
|
250
|
+
.toggle.leaf {
|
|
251
|
+
cursor: default;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* --- node view ------------------------------------------------------------ */
|
|
255
|
+
.nodehead {
|
|
256
|
+
display: flex;
|
|
257
|
+
align-items: center;
|
|
258
|
+
justify-content: flex-start; /* dock chips + tabs to the LEFT (text is left-aligned) */
|
|
259
|
+
flex-wrap: wrap;
|
|
260
|
+
gap: 8px 12px;
|
|
261
|
+
border-bottom: 1px solid var(--line);
|
|
262
|
+
padding-bottom: 8px;
|
|
263
|
+
margin-bottom: 10px;
|
|
264
|
+
}
|
|
265
|
+
/* separates the type/format chips from the representation tabs in the node bar */
|
|
266
|
+
.bar-sep {
|
|
267
|
+
color: var(--dim);
|
|
268
|
+
opacity: 0.5;
|
|
269
|
+
user-select: none;
|
|
270
|
+
}
|
|
271
|
+
/* the markdown/asciidoc reading-width control, beside its renderer tab; red when invalid */
|
|
272
|
+
.markup-width {
|
|
273
|
+
width: 5ch;
|
|
274
|
+
background: var(--bg-alt);
|
|
275
|
+
color: var(--fg);
|
|
276
|
+
border: 1px solid var(--line);
|
|
277
|
+
border-radius: 4px;
|
|
278
|
+
padding: 2px 4px;
|
|
279
|
+
font: inherit;
|
|
280
|
+
font-family: var(--font);
|
|
281
|
+
font-size: 12px;
|
|
282
|
+
text-align: right;
|
|
283
|
+
}
|
|
284
|
+
.markup-width.invalid {
|
|
285
|
+
border-color: #f38ba8;
|
|
286
|
+
color: #f38ba8;
|
|
287
|
+
}
|
|
288
|
+
.nodemeta {
|
|
289
|
+
display: flex;
|
|
290
|
+
align-items: center;
|
|
291
|
+
gap: 8px;
|
|
292
|
+
flex-wrap: wrap;
|
|
293
|
+
}
|
|
294
|
+
.nodepath {
|
|
295
|
+
color: var(--accent);
|
|
296
|
+
}
|
|
297
|
+
.tag {
|
|
298
|
+
font-size: 11px;
|
|
299
|
+
padding: 1px 7px;
|
|
300
|
+
border: 1px solid var(--line);
|
|
301
|
+
border-radius: 10px;
|
|
302
|
+
color: var(--fg);
|
|
303
|
+
}
|
|
304
|
+
.tag.dim {
|
|
305
|
+
color: var(--dim);
|
|
306
|
+
}
|
|
307
|
+
.nodedesc {
|
|
308
|
+
color: var(--dim);
|
|
309
|
+
margin: 0 0 12px;
|
|
310
|
+
font-style: italic;
|
|
311
|
+
}
|
|
312
|
+
.tabs {
|
|
313
|
+
display: flex;
|
|
314
|
+
gap: 4px;
|
|
315
|
+
}
|
|
316
|
+
.tab {
|
|
317
|
+
background: none;
|
|
318
|
+
border: 1px solid var(--line);
|
|
319
|
+
color: var(--dim);
|
|
320
|
+
padding: 2px 10px;
|
|
321
|
+
border-radius: 4px;
|
|
322
|
+
cursor: pointer;
|
|
323
|
+
font-family: var(--font);
|
|
324
|
+
font-size: 12px;
|
|
325
|
+
}
|
|
326
|
+
.tab.active {
|
|
327
|
+
color: var(--bg);
|
|
328
|
+
background: var(--accent);
|
|
329
|
+
border-color: var(--accent);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/* --- code ----------------------------------------------------------------- */
|
|
333
|
+
.code {
|
|
334
|
+
margin: 0;
|
|
335
|
+
white-space: pre-wrap;
|
|
336
|
+
word-break: break-word;
|
|
337
|
+
line-height: 1.55;
|
|
338
|
+
font-family: var(--font);
|
|
339
|
+
}
|
|
340
|
+
.code.raw {
|
|
341
|
+
color: var(--fg);
|
|
342
|
+
}
|
|
343
|
+
.k {
|
|
344
|
+
color: var(--key);
|
|
345
|
+
}
|
|
346
|
+
.s {
|
|
347
|
+
color: var(--string);
|
|
348
|
+
}
|
|
349
|
+
.n {
|
|
350
|
+
color: var(--number);
|
|
351
|
+
}
|
|
352
|
+
.b {
|
|
353
|
+
color: var(--bool);
|
|
354
|
+
}
|
|
355
|
+
.null {
|
|
356
|
+
color: var(--null);
|
|
357
|
+
}
|
|
358
|
+
.punct {
|
|
359
|
+
color: var(--dim);
|
|
360
|
+
}
|
|
361
|
+
.c {
|
|
362
|
+
color: var(--dim);
|
|
363
|
+
font-style: italic;
|
|
364
|
+
}
|
|
365
|
+
.descend {
|
|
366
|
+
color: var(--accent);
|
|
367
|
+
text-decoration: none;
|
|
368
|
+
border-bottom: 1px dashed var(--accent);
|
|
369
|
+
cursor: pointer;
|
|
370
|
+
}
|
|
371
|
+
.descend:hover {
|
|
372
|
+
background: var(--sel);
|
|
373
|
+
}
|
|
374
|
+
/* an external (off-tree) marklower link — solid underline marks it leaves the app */
|
|
375
|
+
.extlink {
|
|
376
|
+
color: var(--accent);
|
|
377
|
+
text-decoration: underline;
|
|
378
|
+
cursor: pointer;
|
|
379
|
+
}
|
|
380
|
+
.extlink:hover {
|
|
381
|
+
background: var(--sel);
|
|
382
|
+
}
|
|
383
|
+
/* divider between the relations panel and the value, in the data views */
|
|
384
|
+
.reldiv {
|
|
385
|
+
border: none;
|
|
386
|
+
border-top: 1px solid var(--border, var(--dim));
|
|
387
|
+
margin: 8px 0;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* --- chapter renderer (x-yamlover-chapter) -------------------------------- */
|
|
391
|
+
.chapter {
|
|
392
|
+
line-height: 1.65;
|
|
393
|
+
max-width: 70ch;
|
|
394
|
+
}
|
|
395
|
+
.chapter-title {
|
|
396
|
+
font-size: 22px;
|
|
397
|
+
font-weight: 700;
|
|
398
|
+
margin: 0 0 4px;
|
|
399
|
+
color: var(--fg);
|
|
400
|
+
}
|
|
401
|
+
.chapter-subtitle {
|
|
402
|
+
margin: 0 0 18px;
|
|
403
|
+
color: var(--dim);
|
|
404
|
+
font-style: italic;
|
|
405
|
+
}
|
|
406
|
+
.chapter-prose {
|
|
407
|
+
margin: 0 0 14px;
|
|
408
|
+
white-space: pre-wrap;
|
|
409
|
+
word-break: break-word;
|
|
410
|
+
}
|
|
411
|
+
.chapter-link {
|
|
412
|
+
font-size: 15px;
|
|
413
|
+
font-weight: 600;
|
|
414
|
+
margin: 18px 0 8px;
|
|
415
|
+
}
|
|
416
|
+
.chapter-link a {
|
|
417
|
+
border-bottom-width: 0;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/* a numbered chunk: an index gutter (linking to the chunk's own node) + body.
|
|
421
|
+
Align the index to the top, not the baseline: a replaced element (image /
|
|
422
|
+
diagram) has its baseline at its *bottom* edge, which would drop the index
|
|
423
|
+
below the object — flex-start keeps it at the body's top-left for prose and
|
|
424
|
+
media alike. */
|
|
425
|
+
.chunk {
|
|
426
|
+
display: flex;
|
|
427
|
+
gap: 12px;
|
|
428
|
+
align-items: flex-start;
|
|
429
|
+
scroll-margin-top: 12px; /* a chunk targeted via #/chunks[n] isn't flush to the top */
|
|
430
|
+
}
|
|
431
|
+
a.chunk-index {
|
|
432
|
+
text-decoration: none;
|
|
433
|
+
}
|
|
434
|
+
.chunk-index {
|
|
435
|
+
flex: 0 0 auto;
|
|
436
|
+
min-width: 2.2em; /* fits the § prefix + a digit, keeps the gutter right-aligned */
|
|
437
|
+
text-align: right;
|
|
438
|
+
font-variant-numeric: tabular-nums;
|
|
439
|
+
font-size: 12px;
|
|
440
|
+
color: var(--dim);
|
|
441
|
+
user-select: none;
|
|
442
|
+
border-bottom-width: 0;
|
|
443
|
+
}
|
|
444
|
+
a.chunk-index:hover {
|
|
445
|
+
color: var(--accent);
|
|
446
|
+
}
|
|
447
|
+
.chunk-body {
|
|
448
|
+
flex: 1 1 auto;
|
|
449
|
+
min-width: 0;
|
|
450
|
+
}
|
|
451
|
+
/* an image / diagram chunk sits flush with its index: drop the standalone-view
|
|
452
|
+
top padding so the object's top-left corner meets the gutter (the index) */
|
|
453
|
+
.chunk-body .filemedia {
|
|
454
|
+
padding-top: 0;
|
|
455
|
+
}
|
|
456
|
+
/* full-page media reused inline as a chunk: cap the heights that otherwise fill
|
|
457
|
+
the viewport (the standalone html iframe / pdf page), so a chapter body stays
|
|
458
|
+
readable when it interleaves an HTML or PDF chunk */
|
|
459
|
+
.chunk-body .filehtml {
|
|
460
|
+
height: 340px;
|
|
461
|
+
}
|
|
462
|
+
.chunk-body .filepdf {
|
|
463
|
+
height: auto; /* a chapter-embedded pdf is capped, not the full-viewport frame */
|
|
464
|
+
max-height: 460px;
|
|
465
|
+
overflow: auto;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.error {
|
|
469
|
+
color: var(--null);
|
|
470
|
+
padding: 12px;
|
|
471
|
+
}
|
|
472
|
+
.loading {
|
|
473
|
+
color: var(--dim);
|
|
474
|
+
padding: 12px;
|
|
475
|
+
}
|
|
476
|
+
/* a full-window hint shown while dragging file(s) over the page (drop = upload). pointer-events:
|
|
477
|
+
none so the drag/drop events still reach the document listeners underneath. */
|
|
478
|
+
.drop-overlay {
|
|
479
|
+
position: fixed;
|
|
480
|
+
inset: 0;
|
|
481
|
+
z-index: 2000;
|
|
482
|
+
display: flex;
|
|
483
|
+
align-items: center;
|
|
484
|
+
justify-content: center;
|
|
485
|
+
pointer-events: none;
|
|
486
|
+
background: rgba(24, 24, 37, 0.55);
|
|
487
|
+
border: 3px dashed var(--accent);
|
|
488
|
+
color: var(--fg);
|
|
489
|
+
font-size: 18px;
|
|
490
|
+
letter-spacing: 0.02em;
|
|
491
|
+
}
|
|
492
|
+
/* transient paste/upload status, pinned to the corner of the right pane */
|
|
493
|
+
.paste-toast {
|
|
494
|
+
position: fixed;
|
|
495
|
+
bottom: 16px;
|
|
496
|
+
right: 16px;
|
|
497
|
+
z-index: 1000;
|
|
498
|
+
padding: 8px 14px;
|
|
499
|
+
background: var(--panel);
|
|
500
|
+
color: var(--fg);
|
|
501
|
+
border: 1px solid var(--accent);
|
|
502
|
+
border-radius: 6px;
|
|
503
|
+
font-size: 13px;
|
|
504
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/* ---- file renderers: image / html / pdf / djvu / markup ------------------ */
|
|
508
|
+
.filemedia {
|
|
509
|
+
padding: 12px 0;
|
|
510
|
+
overflow: auto;
|
|
511
|
+
max-width: 900px; /* don't span the whole pane (001) */
|
|
512
|
+
}
|
|
513
|
+
/* PDF / DjVu are a stable scroll VIEWPORT (like the Leaflet map), so ctrl/alt-wheel zoom enlarges
|
|
514
|
+
the pages and they scroll in BOTH axes within the frame — never clipped to a fixed-width column. */
|
|
515
|
+
.filepdf,
|
|
516
|
+
.filedjvu {
|
|
517
|
+
padding: 12px;
|
|
518
|
+
overflow: auto;
|
|
519
|
+
height: calc(100vh - 160px);
|
|
520
|
+
min-height: 360px;
|
|
521
|
+
}
|
|
522
|
+
.fileimage {
|
|
523
|
+
/* keep the image's own aspect ratio — never stretch (007) */
|
|
524
|
+
max-width: 100%;
|
|
525
|
+
max-height: 80vh;
|
|
526
|
+
width: auto;
|
|
527
|
+
height: auto;
|
|
528
|
+
object-fit: contain;
|
|
529
|
+
display: block;
|
|
530
|
+
margin: 0 0 12px; /* left-aligned, like every other resource (004) */
|
|
531
|
+
background: #fff;
|
|
532
|
+
}
|
|
533
|
+
/* a PlantUML diagram is an SVG on a white card, padded so it doesn't crowd the edges */
|
|
534
|
+
.fileimage.plantuml {
|
|
535
|
+
max-height: none; /* let a tall diagram grow; the pane scrolls */
|
|
536
|
+
padding: 12px;
|
|
537
|
+
border: 1px solid var(--border, #313244);
|
|
538
|
+
border-radius: 6px;
|
|
539
|
+
}
|
|
540
|
+
.filehtml {
|
|
541
|
+
width: 100%;
|
|
542
|
+
height: calc(100vh - 120px);
|
|
543
|
+
border: 1px solid var(--border, #313244);
|
|
544
|
+
background: #fff;
|
|
545
|
+
}
|
|
546
|
+
.filepdf .react-pdf__Page,
|
|
547
|
+
.djvu-page {
|
|
548
|
+
margin: 0 0 12px; /* left-aligned (004) */
|
|
549
|
+
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.4);
|
|
550
|
+
}
|
|
551
|
+
/* a decoded DjVu page — width is driven inline by the zoom factor (ctrl/alt-wheel) */
|
|
552
|
+
.djvu-page {
|
|
553
|
+
display: block;
|
|
554
|
+
max-width: none;
|
|
555
|
+
background: #fff;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/* rendered Markdown / AsciiDoc body */
|
|
559
|
+
.markup {
|
|
560
|
+
line-height: 1.55;
|
|
561
|
+
word-break: break-word;
|
|
562
|
+
max-width: 72ch; /* a readable measure — don't run the full pane width (001) */
|
|
563
|
+
padding-left: 1.6rem; /* a gutter to hold the per-heading `§` anchors (like a chunk's) */
|
|
564
|
+
}
|
|
565
|
+
.markup :first-child {
|
|
566
|
+
margin-top: 0;
|
|
567
|
+
}
|
|
568
|
+
.markup h1,
|
|
569
|
+
.markup h2,
|
|
570
|
+
.markup h3 {
|
|
571
|
+
color: var(--fg);
|
|
572
|
+
margin: 18px 0 8px;
|
|
573
|
+
}
|
|
574
|
+
/* a heading targeted via #slug isn't flush to the top (mirrors .chunk); relative
|
|
575
|
+
so its `§` anchor can sit in the left gutter (like a chunk's index) */
|
|
576
|
+
.markup :is(h1, h2, h3, h4, h5, h6) {
|
|
577
|
+
position: relative;
|
|
578
|
+
scroll-margin-top: 12px;
|
|
579
|
+
}
|
|
580
|
+
.markup a {
|
|
581
|
+
color: var(--accent);
|
|
582
|
+
}
|
|
583
|
+
/* the per-heading `§` fragment anchor: a marker right-aligned in the left gutter,
|
|
584
|
+
matching a chapter chunk's §N index (same 12px size and `--dim` colour, accent on
|
|
585
|
+
hover). A fixed rem offset (not em) so every heading level lines up in the same
|
|
586
|
+
gutter instead of scaling with its font size. */
|
|
587
|
+
.markup .header-anchor {
|
|
588
|
+
position: absolute;
|
|
589
|
+
left: -1.6rem;
|
|
590
|
+
width: 1.6rem;
|
|
591
|
+
box-sizing: border-box;
|
|
592
|
+
padding-right: 0.45rem; /* the gap before the heading text */
|
|
593
|
+
text-align: right;
|
|
594
|
+
font-size: 12px; /* a constant size, not the heading's, so all gutters match (= .chunk-index) */
|
|
595
|
+
font-weight: normal;
|
|
596
|
+
line-height: inherit;
|
|
597
|
+
color: var(--dim);
|
|
598
|
+
text-decoration: none;
|
|
599
|
+
user-select: none;
|
|
600
|
+
}
|
|
601
|
+
.markup :is(h1, h2, h3, h4, h5, h6):hover .header-anchor,
|
|
602
|
+
.markup .header-anchor:hover {
|
|
603
|
+
color: var(--accent);
|
|
604
|
+
}
|
|
605
|
+
.markup code {
|
|
606
|
+
font-family: var(--mono, monospace);
|
|
607
|
+
background: var(--bg-alt);
|
|
608
|
+
padding: 1px 4px;
|
|
609
|
+
border-radius: 3px;
|
|
610
|
+
}
|
|
611
|
+
.markup pre {
|
|
612
|
+
background: var(--bg-alt);
|
|
613
|
+
padding: 10px;
|
|
614
|
+
border-radius: 4px;
|
|
615
|
+
overflow: auto;
|
|
616
|
+
}
|
|
617
|
+
.markup pre code {
|
|
618
|
+
background: none;
|
|
619
|
+
padding: 0;
|
|
620
|
+
}
|
|
621
|
+
.markup img {
|
|
622
|
+
max-width: 100%;
|
|
623
|
+
}
|
|
624
|
+
.markup blockquote {
|
|
625
|
+
border-left: 3px solid var(--border, #313244);
|
|
626
|
+
margin: 10px 0;
|
|
627
|
+
padding-left: 12px;
|
|
628
|
+
color: var(--dim);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/* ---- csv / tsv table renderer -------------------------------------------- */
|
|
632
|
+
/* the CSV parsing controls (separator + header), inline in the node bar beside the
|
|
633
|
+
renderer tab — like the markdown/asciidoc width input */
|
|
634
|
+
.csv-toolbar {
|
|
635
|
+
display: inline-flex;
|
|
636
|
+
gap: 12px;
|
|
637
|
+
align-items: center;
|
|
638
|
+
color: var(--dim);
|
|
639
|
+
font-size: 12px;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/* plain text, shown verbatim (no markup, no re-flow) */
|
|
643
|
+
.plaintext {
|
|
644
|
+
margin: 0;
|
|
645
|
+
white-space: pre-wrap;
|
|
646
|
+
word-break: break-word;
|
|
647
|
+
font-family: var(--font);
|
|
648
|
+
font-size: 13px;
|
|
649
|
+
line-height: 1.55;
|
|
650
|
+
color: var(--fg);
|
|
651
|
+
}
|
|
652
|
+
/* a node-bar selector beside a renderer's tab (plaintext encoding, explorer view) */
|
|
653
|
+
.enc-control {
|
|
654
|
+
display: inline-flex;
|
|
655
|
+
align-items: center;
|
|
656
|
+
gap: 4px;
|
|
657
|
+
color: var(--dim);
|
|
658
|
+
font-size: 12px;
|
|
659
|
+
}
|
|
660
|
+
.enc-control select {
|
|
661
|
+
background: var(--bg-alt);
|
|
662
|
+
color: var(--fg);
|
|
663
|
+
border: 1px solid var(--border, #313244);
|
|
664
|
+
border-radius: 4px;
|
|
665
|
+
padding: 2px 4px;
|
|
666
|
+
font: inherit;
|
|
667
|
+
font-family: var(--font);
|
|
668
|
+
}
|
|
669
|
+
.csv-toolbar label {
|
|
670
|
+
display: inline-flex;
|
|
671
|
+
align-items: center;
|
|
672
|
+
gap: 4px;
|
|
673
|
+
}
|
|
674
|
+
.csv-toolbar select {
|
|
675
|
+
background: var(--bg-alt);
|
|
676
|
+
color: var(--fg);
|
|
677
|
+
border: 1px solid var(--border, #313244);
|
|
678
|
+
border-radius: 4px;
|
|
679
|
+
padding: 2px 4px;
|
|
680
|
+
font: inherit;
|
|
681
|
+
font-family: var(--font);
|
|
682
|
+
}
|
|
683
|
+
.csv-scroll {
|
|
684
|
+
overflow: auto;
|
|
685
|
+
max-width: 100%;
|
|
686
|
+
}
|
|
687
|
+
.csv-table {
|
|
688
|
+
border-collapse: collapse;
|
|
689
|
+
font-size: 13px;
|
|
690
|
+
}
|
|
691
|
+
.csv-table th,
|
|
692
|
+
.csv-table td {
|
|
693
|
+
border: 1px solid var(--border, #313244);
|
|
694
|
+
padding: 3px 8px;
|
|
695
|
+
text-align: left;
|
|
696
|
+
vertical-align: top;
|
|
697
|
+
white-space: pre-wrap;
|
|
698
|
+
}
|
|
699
|
+
.csv-table thead th {
|
|
700
|
+
position: sticky;
|
|
701
|
+
top: 0;
|
|
702
|
+
background: var(--bg-alt);
|
|
703
|
+
color: var(--fg);
|
|
704
|
+
font-weight: 600;
|
|
705
|
+
}
|
|
706
|
+
.csv-table tbody tr:nth-child(even) {
|
|
707
|
+
background: rgba(255, 255, 255, 0.025); /* faint zebra striping */
|
|
708
|
+
}
|
|
709
|
+
.csv-empty {
|
|
710
|
+
color: var(--dim);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/* ---- spreadsheet (xls/xlsx) sheet tabs ----------------------------------- */
|
|
714
|
+
.sheet-tabs {
|
|
715
|
+
display: flex;
|
|
716
|
+
flex-wrap: wrap;
|
|
717
|
+
gap: 4px;
|
|
718
|
+
margin: 4px 0 12px;
|
|
719
|
+
}
|
|
720
|
+
.sheet-tab {
|
|
721
|
+
background: var(--bg-alt);
|
|
722
|
+
color: var(--dim);
|
|
723
|
+
border: 1px solid var(--border, #313244);
|
|
724
|
+
border-radius: 4px;
|
|
725
|
+
padding: 2px 10px;
|
|
726
|
+
font: inherit;
|
|
727
|
+
font-family: var(--font);
|
|
728
|
+
font-size: 12px;
|
|
729
|
+
cursor: pointer;
|
|
730
|
+
}
|
|
731
|
+
.sheet-tab.active {
|
|
732
|
+
color: var(--fg);
|
|
733
|
+
border-color: var(--accent);
|
|
734
|
+
}
|
|
735
|
+
.sheet-tab:hover {
|
|
736
|
+
color: var(--fg);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/* ---- kml / kmz map renderer (Leaflet) ------------------------------------ */
|
|
740
|
+
.filemap {
|
|
741
|
+
width: 100%;
|
|
742
|
+
height: calc(100vh - 160px);
|
|
743
|
+
min-height: 360px;
|
|
744
|
+
border: 1px solid var(--border, #313244);
|
|
745
|
+
border-radius: 6px;
|
|
746
|
+
}
|
|
747
|
+
/* a map embedded inline as a chapter chunk: cap the height so the page stays readable */
|
|
748
|
+
.chunk-body .filemap.chunk-map {
|
|
749
|
+
height: 380px;
|
|
750
|
+
}
|
|
751
|
+
/* annotations: the per-material action bar + the inline highlight mark */
|
|
752
|
+
.annotate-bar {
|
|
753
|
+
display: flex;
|
|
754
|
+
align-items: center;
|
|
755
|
+
gap: 10px;
|
|
756
|
+
margin-bottom: 10px;
|
|
757
|
+
}
|
|
758
|
+
.annotate-count {
|
|
759
|
+
color: var(--dim);
|
|
760
|
+
font-size: 12px;
|
|
761
|
+
}
|
|
762
|
+
/* the floating menu raised by a text selection: a color palette + copy + cancel */
|
|
763
|
+
.annotate-menu {
|
|
764
|
+
position: fixed;
|
|
765
|
+
z-index: 1000; /* above Leaflet panes (≤700) so it floats over an image/map selection */
|
|
766
|
+
display: flex;
|
|
767
|
+
flex-wrap: wrap; /* swatches+tools on the first row; recents and the tag-path input wrap below */
|
|
768
|
+
align-items: center;
|
|
769
|
+
gap: 6px;
|
|
770
|
+
padding: 5px 7px;
|
|
771
|
+
max-width: 280px;
|
|
772
|
+
background: var(--bg-alt);
|
|
773
|
+
border: 1px solid var(--line);
|
|
774
|
+
border-radius: 6px;
|
|
775
|
+
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
|
|
776
|
+
}
|
|
777
|
+
.annotate-palette {
|
|
778
|
+
display: flex;
|
|
779
|
+
gap: 4px;
|
|
780
|
+
}
|
|
781
|
+
.annotate-swatch {
|
|
782
|
+
width: 18px;
|
|
783
|
+
height: 18px;
|
|
784
|
+
padding: 0;
|
|
785
|
+
border-radius: 50%;
|
|
786
|
+
border: 1px solid rgba(0, 0, 0, 0.3);
|
|
787
|
+
cursor: pointer;
|
|
788
|
+
}
|
|
789
|
+
.annotate-swatch.sel {
|
|
790
|
+
outline: 2px solid var(--fg); /* the pre-selected / last-used color */
|
|
791
|
+
outline-offset: 1px;
|
|
792
|
+
}
|
|
793
|
+
.annotate-tool {
|
|
794
|
+
display: inline-flex;
|
|
795
|
+
align-items: center;
|
|
796
|
+
justify-content: center;
|
|
797
|
+
min-width: 26px;
|
|
798
|
+
height: 24px;
|
|
799
|
+
background: var(--bg);
|
|
800
|
+
border: 1px solid var(--line);
|
|
801
|
+
color: var(--fg);
|
|
802
|
+
font: inherit;
|
|
803
|
+
font-size: 15px;
|
|
804
|
+
line-height: 1;
|
|
805
|
+
padding: 0 6px;
|
|
806
|
+
border-radius: 5px;
|
|
807
|
+
cursor: pointer;
|
|
808
|
+
}
|
|
809
|
+
.annotate-tool:hover {
|
|
810
|
+
border-color: var(--dim);
|
|
811
|
+
}
|
|
812
|
+
/* the explicit ✓ confirm (commit) and 🗑 discard/delete — clearly distinct, accent-tinted */
|
|
813
|
+
.annotate-tool.ok {
|
|
814
|
+
color: #a6e3a1;
|
|
815
|
+
border-color: rgba(166, 227, 161, 0.5);
|
|
816
|
+
}
|
|
817
|
+
.annotate-tool.ok:hover {
|
|
818
|
+
background: rgba(166, 227, 161, 0.18);
|
|
819
|
+
border-color: #a6e3a1;
|
|
820
|
+
}
|
|
821
|
+
.annotate-tool.danger {
|
|
822
|
+
color: #f38ba8;
|
|
823
|
+
border-color: rgba(243, 139, 168, 0.5);
|
|
824
|
+
}
|
|
825
|
+
.annotate-tool.danger:hover {
|
|
826
|
+
background: rgba(243, 139, 168, 0.18);
|
|
827
|
+
border-color: #f38ba8;
|
|
828
|
+
}
|
|
829
|
+
/* the recently applied NAMED tags — a row of small badges below the swatches */
|
|
830
|
+
.annotate-recents {
|
|
831
|
+
flex-basis: 100%;
|
|
832
|
+
display: flex;
|
|
833
|
+
flex-wrap: wrap;
|
|
834
|
+
gap: 4px;
|
|
835
|
+
}
|
|
836
|
+
.annotate-recents .tagtag {
|
|
837
|
+
border: 0;
|
|
838
|
+
font: inherit;
|
|
839
|
+
font-size: 11px;
|
|
840
|
+
cursor: pointer;
|
|
841
|
+
}
|
|
842
|
+
/* the assigned / pre-selected tag, framed EXACTLY like the selected color swatch: a ring with a
|
|
843
|
+
gap (the swatch's outline-offset). The ring cannot live on .tagtag itself: filter is applied
|
|
844
|
+
BEFORE clip-path on the same element, so the luggage-tag clip would cut it away. On the
|
|
845
|
+
unclipped WRAPPER the child is clipped first; then a first round of hard offset drop-shadows
|
|
846
|
+
in the MENU BACKGROUND color grows the silhouette by 1px (the gap), and a second round in
|
|
847
|
+
the foreground color rings that — gap + ring, both following the actual tag shape. */
|
|
848
|
+
.annotate-recents .tagframe {
|
|
849
|
+
display: inline-flex;
|
|
850
|
+
}
|
|
851
|
+
.annotate-recents .tagframe.sel {
|
|
852
|
+
filter:
|
|
853
|
+
drop-shadow(1px 0 0 var(--bg-alt))
|
|
854
|
+
drop-shadow(-1px 0 0 var(--bg-alt))
|
|
855
|
+
drop-shadow(0 1px 0 var(--bg-alt))
|
|
856
|
+
drop-shadow(0 -1px 0 var(--bg-alt))
|
|
857
|
+
drop-shadow(1.5px 0 0 var(--fg))
|
|
858
|
+
drop-shadow(-1.5px 0 0 var(--fg))
|
|
859
|
+
drop-shadow(0 1.5px 0 var(--fg))
|
|
860
|
+
drop-shadow(0 -1.5px 0 var(--fg));
|
|
861
|
+
}
|
|
862
|
+
/* apply ANY tag by its node path (Enter commits) */
|
|
863
|
+
.annotate-taginput {
|
|
864
|
+
flex-basis: 100%;
|
|
865
|
+
min-width: 0;
|
|
866
|
+
padding: 3px 6px;
|
|
867
|
+
background: var(--bg);
|
|
868
|
+
border: 1px solid var(--line);
|
|
869
|
+
border-radius: 5px;
|
|
870
|
+
color: var(--fg);
|
|
871
|
+
font: inherit;
|
|
872
|
+
font-size: 12px;
|
|
873
|
+
}
|
|
874
|
+
.annotate-taginput:focus {
|
|
875
|
+
outline: none;
|
|
876
|
+
border-color: var(--dim);
|
|
877
|
+
}
|
|
878
|
+
/* a region annotation drawn over a PDF page (the image overlay uses a Leaflet rectangle) */
|
|
879
|
+
.pdf-page {
|
|
880
|
+
position: relative;
|
|
881
|
+
}
|
|
882
|
+
/* a far-from-viewport page not yet mounted (windowed rendering) — keeps the scroll height */
|
|
883
|
+
.pdf-placeholder {
|
|
884
|
+
background: #fff;
|
|
885
|
+
opacity: 0.06;
|
|
886
|
+
}
|
|
887
|
+
.pdf-region {
|
|
888
|
+
position: absolute;
|
|
889
|
+
box-sizing: border-box;
|
|
890
|
+
border: 2px solid #f9e2af;
|
|
891
|
+
background: rgba(249, 226, 175, 0.18);
|
|
892
|
+
pointer-events: none; /* the live preview must not block selecting text under it */
|
|
893
|
+
}
|
|
894
|
+
.pdf-region.editable {
|
|
895
|
+
pointer-events: auto; /* a saved region is clickable → the edit menu */
|
|
896
|
+
cursor: pointer;
|
|
897
|
+
}
|
|
898
|
+
mark.yo-annotation {
|
|
899
|
+
/* background-color + border-bottom-color are set inline from the annotation's selector.color
|
|
900
|
+
(fallbacks here for marks saved before colors existed) */
|
|
901
|
+
background-color: rgba(249, 226, 175, 0.30); /* a soft highlight; the note rides in the title tooltip */
|
|
902
|
+
color: inherit;
|
|
903
|
+
border-bottom: 2px solid #f9e2af;
|
|
904
|
+
border-radius: 2px;
|
|
905
|
+
cursor: help;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/* the pan/zoom image viewer reuses the map container; its backdrop is the page background, so a
|
|
909
|
+
picture panned/zoomed past the edges sits on the same canvas as the rest of the page. The
|
|
910
|
+
compound `.leaflet-container` selector overrides Leaflet's own default gray (#ddd) backdrop. */
|
|
911
|
+
.fileimagemap,
|
|
912
|
+
.fileimagemap.leaflet-container {
|
|
913
|
+
background: var(--bg);
|
|
914
|
+
}
|
|
915
|
+
/* a view where plain-drag SELECTS (image/map full view): the crosshair signals "drag to annotate";
|
|
916
|
+
hold ctrl/alt to pan. The live rubber-band + saved region rectangles carry their highlight color
|
|
917
|
+
inline (Leaflet path options); a saved region shows a help cursor for its note tooltip. */
|
|
918
|
+
.yo-selectable.leaflet-container {
|
|
919
|
+
cursor: crosshair;
|
|
920
|
+
}
|
|
921
|
+
.leaflet-interactive.yo-region {
|
|
922
|
+
cursor: pointer; /* click a region → the edit menu (recolor / delete) */
|
|
923
|
+
}
|
|
924
|
+
/* Leaflet popups carry the feature's (often HTML) KML description */
|
|
925
|
+
.map-popup-desc {
|
|
926
|
+
margin-top: 4px;
|
|
927
|
+
max-height: 200px;
|
|
928
|
+
overflow: auto;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/* ---- legacy .doc download fallback --------------------------------------- */
|
|
932
|
+
.office-fallback {
|
|
933
|
+
max-width: 60ch;
|
|
934
|
+
line-height: 1.55;
|
|
935
|
+
color: var(--fg);
|
|
936
|
+
}
|
|
937
|
+
.office-fallback a.descend {
|
|
938
|
+
color: var(--accent);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/* ---- fb2 ebook renderer -------------------------------------------------- */
|
|
942
|
+
.fb2-body {
|
|
943
|
+
font-family: var(--mono, monospace);
|
|
944
|
+
}
|
|
945
|
+
.fb2-cover {
|
|
946
|
+
max-width: 320px;
|
|
947
|
+
max-height: 60vh;
|
|
948
|
+
display: block;
|
|
949
|
+
margin: 0 0 18px;
|
|
950
|
+
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
|
|
951
|
+
}
|
|
952
|
+
.fb2-body .fb2-title {
|
|
953
|
+
font-size: 17px;
|
|
954
|
+
font-weight: 700;
|
|
955
|
+
color: var(--fg);
|
|
956
|
+
margin: 22px 0 10px;
|
|
957
|
+
}
|
|
958
|
+
.fb2-body .fb2-subtitle {
|
|
959
|
+
font-weight: 600;
|
|
960
|
+
margin: 14px 0 8px;
|
|
961
|
+
}
|
|
962
|
+
.fb2-body .fb2-cite {
|
|
963
|
+
font-style: italic;
|
|
964
|
+
}
|
|
965
|
+
.fb2-body .fb2-poem {
|
|
966
|
+
margin: 12px 0;
|
|
967
|
+
padding-left: 16px;
|
|
968
|
+
font-style: italic;
|
|
969
|
+
}
|
|
970
|
+
.fb2-body .fb2-stanza {
|
|
971
|
+
margin: 8px 0;
|
|
972
|
+
}
|
|
973
|
+
.fb2-body .fb2-text-author {
|
|
974
|
+
text-align: right;
|
|
975
|
+
color: var(--dim);
|
|
976
|
+
font-style: italic;
|
|
977
|
+
}
|
|
978
|
+
.fb2-body .fb2-img {
|
|
979
|
+
max-width: 100%;
|
|
980
|
+
display: block;
|
|
981
|
+
margin: 12px 0;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/* ---- epub ebook renderer ------------------------------------------------- */
|
|
985
|
+
.epub-body img {
|
|
986
|
+
max-width: 100%;
|
|
987
|
+
height: auto;
|
|
988
|
+
}
|
|
989
|
+
.epub-body .epub-doc + .epub-doc {
|
|
990
|
+
margin-top: 24px;
|
|
991
|
+
padding-top: 24px;
|
|
992
|
+
border-top: 1px solid var(--line);
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/* ---- explorer renderer: a file-manager icon grid of a node's members, uplinks
|
|
996
|
+
(the `..` parent and upstream `*`/`~` sources) leading it. Also the tag page
|
|
997
|
+
(the materials filed under the tag, its description in the header). ---- */
|
|
998
|
+
.dirhead {
|
|
999
|
+
padding: 14px 8px 0;
|
|
1000
|
+
}
|
|
1001
|
+
.dirview {
|
|
1002
|
+
display: flex;
|
|
1003
|
+
flex-wrap: wrap;
|
|
1004
|
+
align-content: flex-start;
|
|
1005
|
+
gap: 6px;
|
|
1006
|
+
padding: 12px 8px;
|
|
1007
|
+
}
|
|
1008
|
+
.dirview-item {
|
|
1009
|
+
display: flex;
|
|
1010
|
+
align-items: center;
|
|
1011
|
+
gap: 8px;
|
|
1012
|
+
width: 210px;
|
|
1013
|
+
padding: 5px 8px;
|
|
1014
|
+
border-radius: 6px;
|
|
1015
|
+
color: var(--fg);
|
|
1016
|
+
text-decoration: none;
|
|
1017
|
+
border-bottom: 0; /* override the global link underline */
|
|
1018
|
+
cursor: pointer;
|
|
1019
|
+
}
|
|
1020
|
+
.dirview-item:hover {
|
|
1021
|
+
background: var(--panel);
|
|
1022
|
+
}
|
|
1023
|
+
.dirview-icon {
|
|
1024
|
+
flex: none;
|
|
1025
|
+
width: 22px;
|
|
1026
|
+
text-align: center;
|
|
1027
|
+
}
|
|
1028
|
+
.dirview-label {
|
|
1029
|
+
white-space: nowrap;
|
|
1030
|
+
overflow: hidden;
|
|
1031
|
+
text-overflow: ellipsis;
|
|
1032
|
+
font-size: 13px;
|
|
1033
|
+
}
|
|
1034
|
+
.dirview-label .val {
|
|
1035
|
+
color: var(--dim);
|
|
1036
|
+
}
|
|
1037
|
+
/* an uplink (a relation: `..`, an upstream ref/tag) — the way OUT, drawn apart */
|
|
1038
|
+
.dirview-up {
|
|
1039
|
+
border: 1px dashed var(--line);
|
|
1040
|
+
color: var(--dim);
|
|
1041
|
+
}
|
|
1042
|
+
.dirview-up:hover {
|
|
1043
|
+
border-color: var(--accent);
|
|
1044
|
+
}
|
|
1045
|
+
.dirview-empty {
|
|
1046
|
+
color: var(--dim);
|
|
1047
|
+
font-style: italic;
|
|
1048
|
+
}
|
|
1049
|
+
/* large icons (the default view): tiles, the icon above a centered label */
|
|
1050
|
+
.dirview.dirview-lg {
|
|
1051
|
+
gap: 10px;
|
|
1052
|
+
}
|
|
1053
|
+
.dirview-lg .dirview-item {
|
|
1054
|
+
flex-direction: column;
|
|
1055
|
+
justify-content: flex-start;
|
|
1056
|
+
width: 120px;
|
|
1057
|
+
padding: 10px 6px 8px;
|
|
1058
|
+
gap: 7px;
|
|
1059
|
+
text-align: center;
|
|
1060
|
+
}
|
|
1061
|
+
.dirview-lg .dirview-icon {
|
|
1062
|
+
width: auto;
|
|
1063
|
+
font-size: 36px;
|
|
1064
|
+
line-height: 1;
|
|
1065
|
+
}
|
|
1066
|
+
.dirview-lg .dirview-icon.binsq {
|
|
1067
|
+
font-size: 11px;
|
|
1068
|
+
padding: 6px 5px;
|
|
1069
|
+
margin: 9px 0; /* keep tile icon rows level with the 36px glyphs */
|
|
1070
|
+
}
|
|
1071
|
+
.dirview-lg .dirview-label {
|
|
1072
|
+
max-width: 100%;
|
|
1073
|
+
white-space: normal;
|
|
1074
|
+
overflow-wrap: anywhere;
|
|
1075
|
+
display: -webkit-box;
|
|
1076
|
+
-webkit-line-clamp: 2; /* a long name wraps to two lines, then ellipsizes */
|
|
1077
|
+
-webkit-box-orient: vertical;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/* tag references shown in a node's header bar: a colored luggage-tag shape — one
|
|
1081
|
+
end rectangular, the other a triangular point with a punched hole. The color is
|
|
1082
|
+
a stable hash of the tag name (see tagColor). */
|
|
1083
|
+
.tagtag {
|
|
1084
|
+
position: relative;
|
|
1085
|
+
display: inline-block;
|
|
1086
|
+
color: #fff;
|
|
1087
|
+
font-size: 11px;
|
|
1088
|
+
line-height: 1.45;
|
|
1089
|
+
padding: 1px 9px 1px 17px; /* extra left clears the point + hole */
|
|
1090
|
+
text-decoration: none;
|
|
1091
|
+
border-bottom: 0; /* override the global link underline */
|
|
1092
|
+
cursor: pointer;
|
|
1093
|
+
white-space: nowrap;
|
|
1094
|
+
clip-path: polygon(11px 0, 100% 0, 100% 100%, 11px 100%, 0 50%);
|
|
1095
|
+
}
|
|
1096
|
+
.tagtag::before {
|
|
1097
|
+
content: "";
|
|
1098
|
+
position: absolute;
|
|
1099
|
+
left: 4px;
|
|
1100
|
+
top: 50%;
|
|
1101
|
+
width: 4px;
|
|
1102
|
+
height: 4px;
|
|
1103
|
+
margin-top: -2px;
|
|
1104
|
+
border-radius: 50%;
|
|
1105
|
+
background: var(--bg); /* the bar behind shows through — a punched hole */
|
|
1106
|
+
}
|
|
1107
|
+
.tagtag:hover {
|
|
1108
|
+
filter: brightness(1.18);
|
|
1109
|
+
}
|
|
1110
|
+
.tagdesc {
|
|
1111
|
+
text-align: left;
|
|
1112
|
+
color: var(--dim);
|
|
1113
|
+
font-style: italic;
|
|
1114
|
+
margin: 8px 0 0;
|
|
1115
|
+
}
|