orz-markdown 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -0
  3. package/dist/index.d.ts +18 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +159 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/plugins/attrs.d.ts +3 -0
  8. package/dist/plugins/attrs.d.ts.map +1 -0
  9. package/dist/plugins/attrs.js +60 -0
  10. package/dist/plugins/attrs.js.map +1 -0
  11. package/dist/plugins/emoji.d.ts +2 -0
  12. package/dist/plugins/emoji.d.ts.map +1 -0
  13. package/dist/plugins/emoji.js +51 -0
  14. package/dist/plugins/emoji.js.map +1 -0
  15. package/dist/plugins/markdown-include.d.ts +3 -0
  16. package/dist/plugins/markdown-include.d.ts.map +1 -0
  17. package/dist/plugins/markdown-include.js +44 -0
  18. package/dist/plugins/markdown-include.js.map +1 -0
  19. package/dist/plugins/mermaid.d.ts +2 -0
  20. package/dist/plugins/mermaid.d.ts.map +1 -0
  21. package/dist/plugins/mermaid.js +18 -0
  22. package/dist/plugins/mermaid.js.map +1 -0
  23. package/dist/plugins/nyml.d.ts +2 -0
  24. package/dist/plugins/nyml.d.ts.map +1 -0
  25. package/dist/plugins/nyml.js +21 -0
  26. package/dist/plugins/nyml.js.map +1 -0
  27. package/dist/plugins/nyml_parser.d.ts +32 -0
  28. package/dist/plugins/nyml_parser.d.ts.map +1 -0
  29. package/dist/plugins/nyml_parser.js +236 -0
  30. package/dist/plugins/nyml_parser.js.map +1 -0
  31. package/dist/plugins/qrcode.d.ts +2 -0
  32. package/dist/plugins/qrcode.d.ts.map +1 -0
  33. package/dist/plugins/qrcode.js +21 -0
  34. package/dist/plugins/qrcode.js.map +1 -0
  35. package/dist/plugins/smiles.d.ts +2 -0
  36. package/dist/plugins/smiles.d.ts.map +1 -0
  37. package/dist/plugins/smiles.js +19 -0
  38. package/dist/plugins/smiles.js.map +1 -0
  39. package/dist/plugins/space.d.ts +2 -0
  40. package/dist/plugins/space.d.ts.map +1 -0
  41. package/dist/plugins/space.js +15 -0
  42. package/dist/plugins/space.js.map +1 -0
  43. package/dist/plugins/span.d.ts +3 -0
  44. package/dist/plugins/span.d.ts.map +1 -0
  45. package/dist/plugins/span.js +18 -0
  46. package/dist/plugins/span.js.map +1 -0
  47. package/dist/plugins/test.d.ts +2 -0
  48. package/dist/plugins/test.d.ts.map +1 -0
  49. package/dist/plugins/test.js +14 -0
  50. package/dist/plugins/test.js.map +1 -0
  51. package/dist/plugins/toc.d.ts +3 -0
  52. package/dist/plugins/toc.d.ts.map +1 -0
  53. package/dist/plugins/toc.js +62 -0
  54. package/dist/plugins/toc.js.map +1 -0
  55. package/dist/plugins/yaml.d.ts +2 -0
  56. package/dist/plugins/yaml.d.ts.map +1 -0
  57. package/dist/plugins/yaml.js +12 -0
  58. package/dist/plugins/yaml.js.map +1 -0
  59. package/dist/plugins/youtube.d.ts +2 -0
  60. package/dist/plugins/youtube.d.ts.map +1 -0
  61. package/dist/plugins/youtube.js +19 -0
  62. package/dist/plugins/youtube.js.map +1 -0
  63. package/dist/prepare-sources.d.ts +10 -0
  64. package/dist/prepare-sources.d.ts.map +1 -0
  65. package/dist/prepare-sources.js +31 -0
  66. package/dist/prepare-sources.js.map +1 -0
  67. package/dist/registry.d.ts +10 -0
  68. package/dist/registry.d.ts.map +1 -0
  69. package/dist/registry.js +24 -0
  70. package/dist/registry.js.map +1 -0
  71. package/dist/rules/block-dispatcher.d.ts +9 -0
  72. package/dist/rules/block-dispatcher.d.ts.map +1 -0
  73. package/dist/rules/block-dispatcher.js +108 -0
  74. package/dist/rules/block-dispatcher.js.map +1 -0
  75. package/dist/rules/inline-dispatcher.d.ts +9 -0
  76. package/dist/rules/inline-dispatcher.d.ts.map +1 -0
  77. package/dist/rules/inline-dispatcher.js +62 -0
  78. package/dist/rules/inline-dispatcher.js.map +1 -0
  79. package/dist/runtime.d.ts +3 -0
  80. package/dist/runtime.d.ts.map +1 -0
  81. package/dist/runtime.js +128 -0
  82. package/dist/runtime.js.map +1 -0
  83. package/package.json +70 -0
  84. package/themes/beige-decent-1.css +559 -0
  85. package/themes/beige-decent-2.css +578 -0
  86. package/themes/common.css +178 -0
  87. package/themes/dark-elegant-1.css +729 -0
  88. package/themes/dark-elegant-2.css +1376 -0
  89. package/themes/light-academic-1.css +541 -0
  90. package/themes/light-academic-2.css +462 -0
  91. package/themes/light-neat-1.css +1244 -0
  92. package/themes/light-neat-2.css +1185 -0
  93. package/themes/light-playful-1.css +493 -0
  94. package/themes/light-playful-2.css +494 -0
@@ -0,0 +1,729 @@
1
+ /* ==========================================================================
2
+ Dark Elegant Theme — markdown-it-customize
3
+ Google Fonts: Cinzel (headings) · Source Serif 4 (body) · JetBrains Mono (code)
4
+ ========================================================================== */
5
+
6
+ @import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;600;700&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,600;0,8..60,700;1,8..60,400&family=JetBrains+Mono:wght@400;500&display=swap');
7
+ @import './common.css';
8
+
9
+ /* --------------------------------------------------------------------------
10
+ Design Tokens
11
+ -------------------------------------------------------------------------- */
12
+ :root {
13
+ /* Palette */
14
+ --bg: #0d0f18;
15
+ --bg-surface: #13161f;
16
+ --bg-elevated: #1c1f2e;
17
+ --bg-input: #252836;
18
+ --border: #2e3248;
19
+ --border-subtle: #1e2130;
20
+
21
+ --text-primary: #e4e8f0;
22
+ --text-secondary:#9aa3b8;
23
+ --text-muted: #60677d;
24
+ --text-heading: #f0f4fc;
25
+ --text-heading-2: #c7d7ff;
26
+ --text-heading-3: #a9c1f0;
27
+ --text-heading-5: #8eaede;
28
+
29
+ --accent: #5f8cff; /* blue-violet */
30
+ --accent-dim: #3f5fa8;
31
+ --accent-glow: rgba(95, 140, 255, 0.15);
32
+
33
+ --link: #82b4ff;
34
+ --link-visited: #a9c2ff;
35
+
36
+ /* Code */
37
+ --code-bg: #1a1d2e;
38
+ --code-text: #cdd6f4;
39
+ --code-border: #313554;
40
+
41
+ /* Semantic colours */
42
+ --success-bg: #0d2318; --success-border:#1a5e35; --success-text: #4ade80;
43
+ --info-bg: #071c30; --info-border: #1a4f7a; --info-text: #60a5fa;
44
+ --warning-bg: #231a07; --warning-border:#7a560d; --warning-text: #fbbf24;
45
+ --danger-bg: #230d0d; --danger-border: #7a1a1a; --danger-text: #f87171;
46
+
47
+ /* Inline span colours */
48
+ --span-red: #f87171;
49
+ --span-yellow: #fbbf24;
50
+ --span-green: #4ade80;
51
+ --span-blue: #60a5fa;
52
+
53
+ /* Typography scale */
54
+ --base-size: 1rem;
55
+ --line-height: 1.75;
56
+ --fs-base: var(--base-size); /* 16px default */
57
+ --fs-sm: 0.875rem;
58
+ --fs-xs: 0.8rem;
59
+ --fs-lg: 1.125rem;
60
+ --fs-xl: 1.25rem;
61
+ --lh-text: var(--line-height);
62
+ --lh-tight: 1.3;
63
+
64
+ /* Spacing */
65
+ --gap: 1.5rem;
66
+ --gap-sm:0.75rem;
67
+ --gap-xs:0.375rem;
68
+
69
+ /* Radii */
70
+ --radius: 8px;
71
+ --radius-sm: 4px;
72
+ --radius-lg: 12px;
73
+
74
+ /* Transitions */
75
+ --t: 0.2s ease;
76
+
77
+ /* Markdown body container toggles */
78
+ --markdown-body-max-width: 860px;
79
+ --markdown-body-padding: clamp(1.5rem, 5vw, 3.5rem);
80
+ --markdown-body-border: 1px solid var(--border-subtle);
81
+ --markdown-body-radius: var(--radius-lg);
82
+ --markdown-body-shadow: none;
83
+ }
84
+
85
+ /* --------------------------------------------------------------------------
86
+ Reset & Base
87
+ -------------------------------------------------------------------------- */
88
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
89
+
90
+ html {
91
+ font-size: var(--base-size);
92
+ scroll-behavior: smooth;
93
+ -webkit-text-size-adjust: 100%;
94
+ }
95
+
96
+ body {
97
+ background: var(--bg);
98
+ color: var(--text-primary);
99
+ font-family: 'Source Serif 4', Georgia, 'Noto Serif SC', 'Noto Serif TC', serif;
100
+ font-weight: 400;
101
+ line-height: var(--lh-text);
102
+ min-height: 100vh;
103
+ padding: 2rem 1rem;
104
+ }
105
+
106
+ /* --------------------------------------------------------------------------
107
+ Scrollbars (WebKit)
108
+ -------------------------------------------------------------------------- */
109
+ ::-webkit-scrollbar { width: 8px; height: 8px; }
110
+ ::-webkit-scrollbar-track { background: var(--bg-surface); }
111
+ ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
112
+ ::-webkit-scrollbar-thumb:hover { background: var(--accent-dim); }
113
+
114
+ /* --------------------------------------------------------------------------
115
+ Article wrapper
116
+ -------------------------------------------------------------------------- */
117
+ .markdown-body {
118
+ display: flow-root;
119
+ max-width: var(--markdown-body-max-width);
120
+ margin: 0 auto;
121
+ background: var(--bg-surface);
122
+ border: var(--markdown-body-border);
123
+ border-radius: var(--markdown-body-radius);
124
+ box-shadow: var(--markdown-body-shadow);
125
+ padding: var(--markdown-body-padding);
126
+ }
127
+
128
+ /* --------------------------------------------------------------------------
129
+ Headings
130
+ -------------------------------------------------------------------------- */
131
+ h1, h2, h3, h4, h5, h6 {
132
+ clear: both;
133
+ font-family: 'Cinzel', Georgia, 'Noto Serif SC', 'Noto Serif TC', serif;
134
+ color: var(--text-heading);
135
+ line-height: var(--lh-tight);
136
+ font-weight: 700;
137
+ margin-top: 2.25em;
138
+ margin-bottom: 0.6em;
139
+ scroll-margin-top: 4rem;
140
+ }
141
+ h1:first-child, h2:first-child { margin-top: 0; }
142
+
143
+ h1 {
144
+ font-size: clamp(1.75rem, 4vw, 2.5rem);
145
+ text-align: center;
146
+ letter-spacing: 0.1em;
147
+ text-transform: uppercase;
148
+ padding: 0.4em 1em;
149
+ border-top: 1px solid var(--border);
150
+ border-bottom: 1px solid var(--border);
151
+ }
152
+ h2 {
153
+ font-size: clamp(1.4rem, 3vw, 1.875rem);
154
+ color: var(--text-heading-2);
155
+ border-bottom: 1px solid var(--accent-dim);
156
+ padding-bottom: 0.3em;
157
+ }
158
+ h3 {
159
+ font-size: 1.375rem;
160
+ color: var(--text-heading-3);
161
+ padding-left: 1.4em;
162
+ position: relative;
163
+ }
164
+ h3::before {
165
+ content: '';
166
+ position: absolute;
167
+ left: 0;
168
+ top: 0.55em;
169
+ width: 0.55em;
170
+ height: 0.55em;
171
+ border-radius: 999px;
172
+ background: var(--accent);
173
+ }
174
+ h4 { font-size: 1.125rem; font-weight: 600; color: var(--accent); }
175
+ h5 { font-size: 1rem; font-weight: 600; color: var(--text-heading-5); }
176
+ h6 { font-size: 0.9rem; font-weight: 600; color: var(--text-secondary); }
177
+
178
+ /* Anchor links from markdown-it-anchor */
179
+ .header-anchor {
180
+ float: left;
181
+ margin-left: -1.25em;
182
+ padding-right: 0.25em;
183
+ opacity: 0;
184
+ color: var(--accent);
185
+ text-decoration: none;
186
+ font-family: 'Source Serif 4', 'Noto Sans SC', 'Noto Sans TC', sans-serif;
187
+ font-size: 0.75em;
188
+ transition: opacity var(--t);
189
+ }
190
+ h1:hover .header-anchor,
191
+ h2:hover .header-anchor,
192
+ h3:hover .header-anchor,
193
+ h4:hover .header-anchor { opacity: 0.6; }
194
+
195
+ /* --------------------------------------------------------------------------
196
+ Paragraphs & Spacing
197
+ -------------------------------------------------------------------------- */
198
+ p { margin-bottom: var(--gap); }
199
+ p:last-child { margin-bottom: 0; }
200
+
201
+ /* --------------------------------------------------------------------------
202
+ Links
203
+ -------------------------------------------------------------------------- */
204
+ a {
205
+ color: var(--link);
206
+ text-decoration: underline;
207
+ text-decoration-color: rgba(130, 180, 255, 0.35);
208
+ text-underline-offset: 3px;
209
+ transition: color var(--t), text-decoration-color var(--t);
210
+ }
211
+ a:hover { color: #aecfff; text-decoration-color: rgba(174, 207, 255, 0.7); }
212
+ a:visited { color: var(--link-visited); }
213
+
214
+ /* --------------------------------------------------------------------------
215
+ Emphasis
216
+ -------------------------------------------------------------------------- */
217
+ strong { font-weight: 600; color: var(--text-heading); }
218
+ em { font-style: italic; }
219
+ s, del { text-decoration: line-through; color: var(--text-muted); }
220
+ mark { background: rgba(251, 191, 36, 0.25); color: #fde68a; border-radius: 2px; padding: 0 2px; }
221
+ ins { text-decoration: underline; text-decoration-style: dashed; color: var(--span-green); }
222
+ sub, sup { font-size: 0.75em; }
223
+
224
+ /* --------------------------------------------------------------------------
225
+ Inline Code
226
+ -------------------------------------------------------------------------- */
227
+ code {
228
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
229
+ font-size: 0.875em;
230
+ background: var(--code-bg);
231
+ color: #9bc7ff;
232
+ border: 1px solid var(--code-border);
233
+ border-radius: var(--radius-sm);
234
+ padding: 0.15em 0.45em;
235
+ }
236
+
237
+ /* --------------------------------------------------------------------------
238
+ Code Blocks
239
+ -------------------------------------------------------------------------- */
240
+ pre {
241
+ background: var(--code-bg);
242
+ border: 1px solid var(--code-border);
243
+ border-radius: var(--radius);
244
+ padding: 1.25rem 1.5rem;
245
+ overflow-x: auto;
246
+ margin-bottom: var(--gap);
247
+ position: relative;
248
+ }
249
+ pre code {
250
+ background: none;
251
+ border: none;
252
+ padding: 0;
253
+ font-size: var(--fs-sm);
254
+ color: var(--code-text);
255
+ line-height: 1.6;
256
+ }
257
+
258
+ /* --------------------------------------------------------------------------
259
+ Blockquotes
260
+ -------------------------------------------------------------------------- */
261
+ blockquote {
262
+ margin: var(--gap) 0;
263
+ padding: 0.85rem 1.35rem;
264
+ background: rgba(95, 140, 255, 0.06);
265
+ border: 1px solid var(--border);
266
+ border-radius: var(--radius);
267
+ color: var(--text-secondary);
268
+ font-style: italic;
269
+ position: relative;
270
+ }
271
+ blockquote > blockquote { border-left-color: var(--accent-dim); margin-top: 0.75rem; }
272
+ blockquote p:last-child { margin-bottom: 0; }
273
+
274
+ /* --------------------------------------------------------------------------
275
+ Lists
276
+ -------------------------------------------------------------------------- */
277
+ ul, ol {
278
+ padding-left: 1.75em;
279
+ margin-bottom: var(--gap);
280
+ }
281
+ li {
282
+ margin-bottom: 0.35em;
283
+ line-height: var(--lh-text);
284
+ }
285
+ li > ul, li > ol { margin-top: 0.35em; margin-bottom: 0; }
286
+ ul { list-style-type: none; }
287
+ ul li::before {
288
+ content: '›';
289
+ color: var(--accent);
290
+ display: inline-block;
291
+ width: 1em;
292
+ margin-left: -1em;
293
+ font-weight: 600;
294
+ }
295
+
296
+ /* Task lists (markdown-it-task-lists) */
297
+ .task-list-item { list-style: none; padding-left: 0; }
298
+ .task-list-item::before { display: none; }
299
+ .task-list-item input[type="checkbox"] {
300
+ appearance: none;
301
+ -webkit-appearance: none;
302
+ width: 1.1em;
303
+ height: 1.1em;
304
+ border: 2px solid var(--border);
305
+ border-radius: 3px;
306
+ background: var(--bg-input);
307
+ vertical-align: baseline;
308
+ margin-right: 0.5em;
309
+ cursor: default;
310
+ position: relative;
311
+ display: inline-block;
312
+ transition: border-color var(--t), background var(--t);
313
+ }
314
+ .task-list-item input[type="checkbox"]:checked {
315
+ background: var(--accent);
316
+ border-color: var(--accent);
317
+ }
318
+ .task-list-item input[type="checkbox"]:checked::after {
319
+ content: '';
320
+ position: absolute;
321
+ left: 3px; top: 0;
322
+ width: 5px; height: 9px;
323
+ border: 2px solid #fff;
324
+ border-top: none; border-left: none;
325
+ transform: rotate(45deg);
326
+ }
327
+
328
+ /* --------------------------------------------------------------------------
329
+ Tables
330
+ -------------------------------------------------------------------------- */
331
+ .markdown-body > table, .markdown-body td table {
332
+ width: max-content;
333
+ max-width: 100%;
334
+ }
335
+ table {
336
+ border-collapse: collapse;
337
+ margin-bottom: var(--gap);
338
+ font-size: var(--fs-sm);
339
+ }
340
+ thead tr { background: var(--bg-elevated); }
341
+ thead th {
342
+ font-family: 'Source Serif 4', 'Noto Sans SC', 'Noto Sans TC', sans-serif;
343
+ font-weight: 600;
344
+ font-size: var(--fs-xs);
345
+ text-transform: uppercase;
346
+ letter-spacing: 0.06em;
347
+ color: var(--text-secondary);
348
+ padding: 0.65rem 1rem;
349
+ border-bottom: 2px solid var(--border);
350
+ text-align: left;
351
+ white-space: nowrap;
352
+ }
353
+ td {
354
+ padding: 0.65rem 1rem;
355
+ border-bottom: 1px solid var(--border-subtle);
356
+ vertical-align: baseline;
357
+ }
358
+ tbody tr:last-child td { border-bottom: none; }
359
+ tbody tr:hover { background: rgba(255,255,255,0.02); }
360
+
361
+ /* --------------------------------------------------------------------------
362
+ Horizontal Rule
363
+ -------------------------------------------------------------------------- */
364
+ hr {
365
+ border: none;
366
+ height: 1px;
367
+ background: linear-gradient(90deg, transparent, var(--border), transparent);
368
+ margin: 2.5rem 0;
369
+ }
370
+
371
+ /* --------------------------------------------------------------------------
372
+ Images
373
+ -------------------------------------------------------------------------- */
374
+ img {
375
+ border-radius: var(--radius);
376
+ margin: var(--gap) auto;
377
+ }
378
+ p > img { margin: 0; display: inline; }
379
+
380
+ /* --------------------------------------------------------------------------
381
+ Footnotes (markdown-it-footnote)
382
+ -------------------------------------------------------------------------- */
383
+ .footnotes-sep { margin: 2rem 0 1rem; }
384
+ .footnotes {
385
+ font-size: var(--fs-sm);
386
+ color: var(--text-secondary);
387
+ border-top: 1px solid var(--border-subtle);
388
+ padding-top: 1rem;
389
+ }
390
+ .footnotes ol { counter-reset: none; }
391
+ .footnote-ref a, .footnote-backref {
392
+ color: var(--accent);
393
+ text-decoration: none;
394
+ font-size: 0.8em;
395
+ vertical-align: super;
396
+ }
397
+
398
+ /* --------------------------------------------------------------------------
399
+ KaTeX overrides
400
+ -------------------------------------------------------------------------- */
401
+ .katex { font-size: 1.1em; }
402
+ .katex-display {
403
+ overflow-x: auto;
404
+ overflow-y: hidden;
405
+ padding: 0.5rem 0;
406
+ margin: var(--gap) 0;
407
+ }
408
+ .katex-error {
409
+ background: var(--danger-bg);
410
+ color: var(--danger-text);
411
+ border: 1px solid var(--danger-border);
412
+ border-radius: var(--radius-sm);
413
+ padding: 0.15em 0.4em;
414
+ font-family: 'JetBrains Mono', monospace;
415
+ font-size: var(--fs-sm);
416
+ }
417
+
418
+ /* --------------------------------------------------------------------------
419
+ Containers — Semantic colour boxes
420
+ -------------------------------------------------------------------------- */
421
+ .success, .info, .warning, .danger {
422
+ border: 1px solid;
423
+ border-radius: var(--radius);
424
+ padding: 1rem 1.25rem;
425
+ margin: var(--gap) 0;
426
+ }
427
+ .success { background: var(--success-bg); border-color: var(--success-border); }
428
+ .info { background: var(--info-bg); border-color: var(--info-border); }
429
+ .warning { background: var(--warning-bg); border-color: var(--warning-border); }
430
+ .danger { background: var(--danger-bg); border-color: var(--danger-border); }
431
+
432
+ .success > p:first-child > strong:first-child,
433
+ .success > p:first-child > b:first-child { color: var(--success-text); }
434
+ .info > p:first-child > strong:first-child,
435
+ .info > p:first-child > b:first-child { color: var(--info-text); }
436
+ .warning > p:first-child > strong:first-child,
437
+ .warning > p:first-child > b:first-child { color: var(--warning-text); }
438
+ .danger > p:first-child > strong:first-child,
439
+ .danger > p:first-child > b:first-child { color: var(--danger-text); }
440
+
441
+ /* Nested containers */
442
+ .success .warning, .info .warning, .warning .warning, .danger .warning {
443
+ margin: var(--gap-sm) 0 0;
444
+ }
445
+
446
+ /* --------------------------------------------------------------------------
447
+ Containers — Layout (left / right / center)
448
+ -------------------------------------------------------------------------- */
449
+ .left { float: left; margin: 0 var(--gap) var(--gap) 0; max-width: 45%; }
450
+ .right { text-align: right; margin: 0 0 var(--gap); }
451
+ .center {
452
+ text-align: center;
453
+ margin: var(--gap) auto;
454
+ }
455
+
456
+ /* --------------------------------------------------------------------------
457
+ Container — Spoiler (uses <details> rendered by custom container renderer)
458
+ -------------------------------------------------------------------------- */
459
+ details.spoil {
460
+ border: 1px solid var(--border);
461
+ border-radius: var(--radius);
462
+ background: var(--bg-elevated);
463
+ margin: var(--gap) 0;
464
+ overflow: hidden;
465
+ }
466
+ details.spoil > summary {
467
+ cursor: pointer;
468
+ padding: 0.75rem 1.25rem;
469
+ font-weight: 500;
470
+ color: var(--text-secondary);
471
+ user-select: none;
472
+ list-style: none;
473
+ display: flex;
474
+ align-items: center;
475
+ gap: 0.5rem;
476
+ transition: background var(--t), color var(--t);
477
+ }
478
+ details.spoil > summary::-webkit-details-marker { display: none; }
479
+ details.spoil > summary::before {
480
+ content: '▶';
481
+ font-size: 0.65em;
482
+ transition: transform var(--t);
483
+ display: inline-block;
484
+ color: var(--accent);
485
+ }
486
+ details.spoil[open] > summary::before { transform: rotate(90deg); }
487
+ details.spoil > summary:hover { background: var(--bg-input); color: var(--text-primary); }
488
+ details.spoil[open] > summary {
489
+ border-bottom: 1px solid var(--border-subtle);
490
+ color: var(--text-primary);
491
+ }
492
+ details.spoil > :not(summary) {
493
+ padding: 1rem 1.25rem;
494
+ }
495
+ details.spoil > p:last-child,
496
+ details.spoil > *:last-child { padding-bottom: 1.25rem; }
497
+
498
+ /* --------------------------------------------------------------------------
499
+ Container — Tabs
500
+ -------------------------------------------------------------------------- */
501
+ .tabs {
502
+ border: 1px solid var(--border);
503
+ border-radius: var(--radius);
504
+ overflow: hidden;
505
+ margin: var(--gap) 0;
506
+ }
507
+
508
+ /* Tab bar — populated by JavaScript */
509
+ .tabs-bar {
510
+ display: flex;
511
+ background: var(--bg-elevated);
512
+ border-bottom: 1px solid var(--border);
513
+ overflow-x: auto;
514
+ scrollbar-width: none;
515
+ }
516
+ .tabs-bar::-webkit-scrollbar { display: none; }
517
+
518
+ .tabs-bar-btn {
519
+ padding: 0.6rem 1.1rem;
520
+ border: none;
521
+ background: none;
522
+ color: var(--text-secondary);
523
+ font-family: 'Source Serif 4', 'Noto Sans SC', 'Noto Sans TC', sans-serif;
524
+ font-size: var(--fs-sm);
525
+ font-weight: 500;
526
+ cursor: pointer;
527
+ white-space: nowrap;
528
+ border-bottom: 2px solid transparent;
529
+ transition: color var(--t), border-color var(--t), background var(--t);
530
+ }
531
+ .tabs-bar-btn:hover { color: var(--text-primary); background: rgba(255,255,255,0.04); }
532
+ .tabs-bar-btn.active { color: var(--accent); border-bottom-color: var(--accent); }
533
+
534
+ /* Tab panels */
535
+ .tab {
536
+ display: none;
537
+ padding: 1.25rem 1.5rem;
538
+ }
539
+ .tab.active { display: block; }
540
+ /* Fallback: show all tabs when JS unavailable */
541
+ .tabs:not([data-js]) .tab { display: block; }
542
+ .tabs:not([data-js]) .tab + .tab { border-top: 1px solid var(--border-subtle); }
543
+
544
+ /* --------------------------------------------------------------------------
545
+ Container — Columns
546
+ -------------------------------------------------------------------------- */
547
+ .cols {
548
+ display: grid;
549
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
550
+ gap: var(--gap);
551
+ margin: var(--gap) 0;
552
+ align-items: start;
553
+ }
554
+ .col {
555
+ min-width: 0; /* prevent overflow */
556
+ }
557
+ .col > p:last-child { margin-bottom: 0; }
558
+
559
+ /* Responsive: single column on small screens */
560
+ @media (max-width: 600px) {
561
+ .cols { grid-template-columns: 1fr; }
562
+ .left { float: none; max-width: 100%; margin: 0 0 var(--gap); }
563
+ }
564
+
565
+ /* --------------------------------------------------------------------------
566
+ TOC — in-document styles
567
+ (The toc plugin generates a nested <ul> at the {{toc}} position)
568
+ -------------------------------------------------------------------------- */
569
+ .toc-wrapper {
570
+ /* Wraps the generated TOC list */
571
+ }
572
+ nav.toc, .toc-list {
573
+ background: var(--bg-elevated);
574
+ border: 1px solid var(--border);
575
+ border-radius: var(--radius);
576
+ padding: 1rem 1.25rem;
577
+ margin: var(--gap) 0;
578
+ font-size: var(--fs-sm);
579
+ }
580
+ nav.toc ul, .toc-list ul {
581
+ padding-left: 1.25em;
582
+ margin-bottom: 0;
583
+ }
584
+ nav.toc li, .toc-list li { margin-bottom: 0.25em; }
585
+ nav.toc li::before, .toc-list li::before { display: none; }
586
+ nav.toc a, .toc-list a {
587
+ color: var(--text-secondary);
588
+ text-decoration: none;
589
+ transition: color var(--t);
590
+ }
591
+ nav.toc a:hover, .toc-list a:hover { color: var(--accent); }
592
+
593
+ /* --------------------------------------------------------------------------
594
+ Span — Colour classes
595
+ -------------------------------------------------------------------------- */
596
+ span.red { color: var(--span-red); }
597
+ span.yellow { color: var(--span-yellow); }
598
+ span.green { color: var(--span-green); }
599
+ span.blue { color: var(--span-blue); }
600
+
601
+ /* --------------------------------------------------------------------------
602
+ Span — Badge classes
603
+ -------------------------------------------------------------------------- */
604
+ span.success,
605
+ span.info,
606
+ span.warning,
607
+ span.danger {
608
+ padding: 0.15em 0.55em;
609
+ border-radius: 999px;
610
+ font-size: 0.8em;
611
+ font-weight: 600;
612
+ letter-spacing: 0.02em;
613
+ vertical-align: baseline;
614
+ border: 1px solid;
615
+ }
616
+ span.success { background: var(--success-bg); color: var(--success-text); border-color: var(--success-border); }
617
+ span.info { background: var(--info-bg); color: var(--info-text); border-color: var(--info-border); }
618
+ span.warning { background: var(--warning-bg); color: var(--warning-text); border-color: var(--warning-border); }
619
+ span.danger { background: var(--danger-bg); color: var(--danger-text); border-color: var(--danger-border); }
620
+
621
+ /* --------------------------------------------------------------------------
622
+ Custom plugin output styles
623
+ -------------------------------------------------------------------------- */
624
+
625
+ /* test-block (Phase 5 — dev only) */
626
+ div.test-block {
627
+ background: linear-gradient(135deg, #1a1a2e, #252848);
628
+ border: 1px dashed var(--accent-dim);
629
+ border-radius: var(--radius);
630
+ padding: 0.75rem 1.25rem;
631
+ font-family: 'JetBrains Mono', monospace;
632
+ font-size: var(--fs-sm);
633
+ color: var(--accent);
634
+ margin: var(--gap) 0;
635
+ }
636
+
637
+ /* test-inline (Phase 5 — dev only) */
638
+ span.test-inline {
639
+ background: rgba(95, 140, 255, 0.12);
640
+ color: var(--accent);
641
+ border: 1px dashed var(--accent-dim);
642
+ border-radius: var(--radius-sm);
643
+ padding: 0.1em 0.4em;
644
+ font-family: 'JetBrains Mono', monospace;
645
+ font-size: 0.875em;
646
+ }
647
+
648
+ /* YouTube embed (Phase 8) */
649
+ div.youtube-embed {
650
+ position: relative;
651
+ padding-bottom: 56.25%; /* 16:9 */
652
+ height: 0;
653
+ overflow: hidden;
654
+ border-radius: var(--radius);
655
+ background: #000;
656
+ margin: var(--gap) 0;
657
+ }
658
+ div.youtube-embed iframe {
659
+ position: absolute;
660
+ top: 0; left: 0;
661
+ width: 100%; height: 100%;
662
+ border: none;
663
+ }
664
+
665
+ /* Mermaid diagrams (Phase 10) */
666
+ div.mermaid {
667
+ background: var(--bg-elevated);
668
+ border: 1px solid var(--border);
669
+ border-radius: var(--radius);
670
+ padding: 1.5rem;
671
+ margin: var(--gap) 0;
672
+ overflow-x: auto;
673
+ text-align: center;
674
+ }
675
+
676
+ /* SMILES / chemical structures (Phase 11) */
677
+ div.smiles-render {
678
+ border-radius: 0;
679
+ }
680
+ div.smiles-render canvas {
681
+ border-radius: 0;
682
+ }
683
+
684
+ /* QR code (Phase 9) */
685
+ span.qrcode {
686
+ vertical-align: baseline;
687
+ background: #fff;
688
+ border-radius: var(--radius-sm);
689
+ padding: 4px;
690
+ }
691
+
692
+ /* Span with arbitrary class (Phase 7) */
693
+ .markdown-body span[class]:not(.test-inline):not(.qrcode):not(.katex):not(.katex-inner)
694
+ :not(.success):not(.info):not(.warning):not(.danger)
695
+ :not(.red):not(.yellow):not(.green):not(.blue) {
696
+ /* fallback for unrecognised span classes */
697
+ }
698
+
699
+ /* --------------------------------------------------------------------------
700
+ Focus indicators (keyboard navigation)
701
+ -------------------------------------------------------------------------- */
702
+ a:focus-visible,
703
+ .tabs-bar-btn:focus-visible,
704
+ details.spoil > summary:focus-visible {
705
+ outline: 2px solid var(--accent);
706
+ outline-offset: 3px;
707
+ border-radius: var(--radius-sm);
708
+ text-decoration: none;
709
+ }
710
+ .task-list-item input[type="checkbox"]:focus-visible {
711
+ outline: 2px solid var(--accent);
712
+ outline-offset: 2px;
713
+ }
714
+
715
+ /* --------------------------------------------------------------------------
716
+ Print
717
+ -------------------------------------------------------------------------- */
718
+ @media print {
719
+ body { background: #fff; color: #000; padding: 0; }
720
+ .markdown-body { background: #fff; border: none; box-shadow: none; padding: 0; max-width: 100%; }
721
+ a { color: #000; text-decoration: underline; }
722
+ code { background: #f4f4f4; border: 1px solid #ccc; }
723
+ pre { background: #f4f4f4; }
724
+ blockquote { border-left-color: #aaa; background: #f9f9f9; }
725
+ tr, iframe, video, pre, blockquote {
726
+ break-inside: avoid;
727
+ page-break-inside: avoid;
728
+ }
729
+ }