Skip to main content

marco_core/render/
base_css.rs

1/// Base structural stylesheet for the viewer HTML preview.
2///
3/// This contains ALL HTML element rules and viewer component rules.
4/// It references CSS custom properties (set by the theme token files)
5/// with safe fallback values so it works even if a variable is not defined.
6///
7/// Theme files (`.css` in `assets/themes/html_viever/`) provide ONLY
8/// CSS custom property declarations (`--var: value`) — no structural rules.
9///
10/// Injection order in the final `<style>` block:
11///   1. `inline_bg_style` — instant background colour flash-prevention
12///   2. `base_css()`       — this file: all structure, via CSS custom properties
13///   3. `css`              — the active theme file: only token overrides
14///   4. `table_resize_css` — separate `<style>` block (interactive table/slider/anchor rules)
15pub fn base_css() -> &'static str {
16    BASE_CSS
17}
18
19const BASE_CSS: &str = r#"
20/* ═══════════════════════════════════════════════════════════════════════════
21   MARCO BASE STYLESHEET
22   All structural CSS for the HTML preview pane. Uses CSS custom properties
23   defined by the active theme token file. Safe fallbacks are provided for
24   every variable so this works standalone.
25   ═══════════════════════════════════════════════════════════════════════════ */
26
27/* ── Color-scheme hints (controls scrollbars, form controls, native UI) ─── */
28html.theme-light { color-scheme: light; }
29html.theme-dark  { color-scheme: dark;  }
30
31/* ── HTML element background (ensures full-page colour in static exports) ── */
32html { background-color: var(--bg-color, #fff); }
33
34/* ── Body ─────────────────────────────────────────────────────────────────── */
35body {
36    font-family: var(--body-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif);
37    font-size: var(--body-font-size, 16px);
38    line-height: var(--body-line-height, 1.6);
39    color: var(--text-color, #333);
40    background-color: var(--bg-color, #fff);
41    max-width: var(--body-max-width, 900px);
42    margin: 0 auto;
43    padding: var(--body-padding, 2rem);
44    transition: background-color 0.2s ease, color 0.2s ease;
45}
46
47body {
48    --mc-task-primary: var(--link-color, #0066cc);
49    --mc-task-accent:  var(--link-hover, #0052a3);
50}
51
52/* ── Headings ─────────────────────────────────────────────────────────────── */
53h1, h2, h3, h4, h5, h6 {
54    font-weight: 600;
55    margin-top: 1.5rem;
56    margin-bottom: 0.75rem;
57    line-height: 1.25;
58    /* Provide a real computed color for child elements (anchor icons, etc.). */
59    color: var(--heading-color, #1a1a1a);
60    /* Gradient: when --heading-gradient-end equals --heading-color the gradient
61       is invisible (solid colour). The viewer theme can set a custom accent. */
62    background: linear-gradient(
63        45deg,
64        var(--heading-color, #1a1a1a),
65        var(--heading-gradient-end, var(--heading-color, #1a1a1a))
66    );
67    -webkit-background-clip: text;
68    -webkit-text-fill-color: transparent;
69    background-clip: text;
70    position: relative;
71}
72
73h1 { font-size: 2rem; }
74h2 { font-size: 1.75rem; }
75h3 { font-size: 1.5rem; }
76h4 { font-size: 1.25rem; }
77h5 { font-size: 1.1rem; }
78h6 { font-size: 1rem; }
79
80/* Optional h1/h2 bottom border (e.g. GitHub theme sets this variable). */
81h1, h2 {
82    border-bottom: var(--h1h2-border-bottom, none);
83    padding-bottom: var(--h1h2-padding-bottom, 0);
84}
85
86/* Fix code/mark/emoji inside headings: restore visible fill. */
87h1 code, h2 code, h3 code, h4 code, h5 code, h6 code,
88h1 mark, h2 mark, h3 mark, h4 mark, h5 mark, h6 mark {
89    -webkit-text-fill-color: initial;
90    color: var(--text-color, #333);
91    background: none;
92    background-clip: unset;
93    -webkit-background-clip: unset;
94}
95
96h1 .marco-emoji, h2 .marco-emoji, h3 .marco-emoji,
97h4 .marco-emoji, h5 .marco-emoji, h6 .marco-emoji {
98    -webkit-text-fill-color: initial;
99    color: initial;
100}
101
102/* ── Paragraphs ───────────────────────────────────────────────────────────── */
103p {
104    margin: 0 0 1rem 0;
105    color: var(--text-color, #333);
106}
107
108/* ── Text formatting ──────────────────────────────────────────────────────── */
109strong, b {
110    font-weight: 700;
111    color: var(--strong-color, var(--text-color, #333));
112}
113
114em, i {
115    font-style: italic;
116    color: var(--text-color, #333);
117}
118
119del, s {
120    text-decoration: line-through;
121    color: var(--text-muted, #888);
122}
123
124mark {
125    background-color: var(--mark-bg, #fff8c5);
126    color: var(--mark-color, #1a1a1a);
127    padding: 0.1em 0.25em;
128    border-radius: 3px;
129}
130
131sup, sub {
132    font-size: 0.8em;
133    line-height: 0;
134    position: relative;
135    vertical-align: baseline;
136}
137
138sup { top: -0.5em; }
139sub { bottom: -0.25em; }
140
141kbd {
142    background-color: var(--bg-code, #f5f5f5);
143    border: 1px solid var(--border-color, #ddd);
144    border-radius: 4px;
145    color: var(--text-color, #333);
146    font-family: var(--code-font, 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace, 'Noto Sans Arabic', 'Noto Sans Hebrew', 'Noto Sans', Arial, sans-serif);
147    font-size: 0.875em;
148    padding: 0.2em 0.4em;
149    vertical-align: baseline;
150}
151
152abbr[title] {
153    border-bottom: 1px dotted var(--border-color, #ddd);
154    cursor: help;
155    text-decoration: none;
156}
157
158/* ── Links ────────────────────────────────────────────────────────────────── */
159/* Basic colour + hover. SVG icon overlays are in the `table_resize_css` block. */
160a {
161    color: var(--link-color, #0066cc);
162    text-decoration: none;
163}
164
165a:hover {
166    color: var(--link-hover, var(--link-color, #0052a3));
167    text-decoration: underline;
168}
169
170a:visited {
171    color: var(--link-color, #0066cc);
172}
173
174/* ── Inline code ──────────────────────────────────────────────────────────── */
175code {
176    font-family: var(--code-font, 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace, 'Noto Sans Arabic', 'Noto Sans Hebrew', 'Noto Sans', Arial, sans-serif);
177    font-size: 0.875em;
178    background-color: var(--bg-code, #f5f5f5);
179    border-radius: 4px;
180    padding: 0.2em 0.4em;
181}
182
183/* ── Code blocks ──────────────────────────────────────────────────────────── */
184pre {
185    background-color: var(--bg-pre, #f8f8f8);
186    border: 1px solid var(--border-color, #ddd);
187    border-radius: 6px;
188    margin: 1rem 0;
189    overflow: hidden;
190    position: relative;
191}
192
193pre[data-language]::before {
194    content: attr(data-language);
195    display: block;
196    background-color: var(--bg-pre, #f8f8f8);
197    color: var(--text-secondary, #666);
198    padding: 0.4rem 0.75rem;
199    font-size: 0.8rem;
200    font-family: var(--body-font, -apple-system, sans-serif);
201    font-weight: 400;
202    border-bottom: 1px solid var(--border-color, #ddd);
203    opacity: 0.8;
204}
205
206pre code {
207    display: block;
208    padding: 1rem;
209    background: transparent;
210    border-radius: 0;
211    font-size: 0.875em;
212    line-height: 1.5;
213    overflow-x: auto;
214    white-space: pre;
215    word-break: normal;
216}
217
218/* ── Nested code blocks (.nested-code-block) ──────────────────────────────── */
219.nested-code-block {
220    border: 1px solid var(--border-color, #ddd);
221    border-left: 4px solid var(--link-color, #0066cc);
222    border-radius: 6px;
223    margin: 1rem 0;
224    overflow: hidden;
225    background-color: var(--bg-pre, #f8f8f8);
226}
227
228.nested-code-block.level-2 { border-left-color: var(--blockquote-border, #ccc); }
229.nested-code-block.level-3 { border-left-color: var(--border-strong, #999); }
230.nested-code-block.level-4,
231.nested-code-block.level-5,
232.nested-code-block.level-6,
233.nested-code-block.level-7,
234.nested-code-block.level-8,
235.nested-code-block.level-9,
236.nested-code-block.level-10 { border-left-color: var(--text-muted, #888); }
237
238.nested-code-block .code-header {
239    background-color: var(--bg-secondary, #f5f5f5);
240    color: var(--text-muted, #888);
241    padding: 0.35rem 0.75rem;
242    font-size: 0.8em;
243    font-family: var(--code-font, monospace, 'Noto Sans Arabic', 'Noto Sans Hebrew', 'Noto Sans', Arial, sans-serif);
244    border-bottom: 1px solid var(--border-color, #ddd);
245}
246
247.nested-code-block .code-content {
248    padding: 0.75rem 1rem;
249    background-color: var(--bg-color, #fff);
250    min-height: 2rem;
251}
252
253.nested-code-block .code-content pre {
254    margin: 0.5rem 0;
255    border: 1px solid var(--border-color, #ddd);
256}
257
258.nested-code-block .code-content pre:before {
259    display: none !important;
260    content: none !important;
261}
262
263.nested-code-block .code-content p {
264    margin: 0.5rem 0;
265}
266
267.nested-code-block .code-content p:first-child { margin-top: 0; }
268.nested-code-block .code-content p:last-child  { margin-bottom: 0; }
269
270/* ── Code copy button ─────────────────────────────────────────────────────── */
271.0 {
272    position: relative;
273    margin: 1rem 0;
274}
275
276.marco-copy-btn {
277    position: absolute;
278    top: 0.4rem;
279    right: 0.4rem;
280    display: inline-flex;
281    align-items: center;
282    justify-content: center;
283    padding: 0.35rem;
284    border: none;
285    border-radius: 5px;
286    background: transparent;
287    color: var(--text-muted, #888);
288    opacity: 0;
289    cursor: pointer;
290    transition: opacity 0.15s ease, background-color 0.15s ease, color 0.15s ease;
291    z-index: 10;
292}
293
294.0:hover .marco-copy-btn {
295    opacity: 1;
296}
297
298.marco-copy-btn svg {
299    width: 1.1em;
300    height: 1.1em;
301    display: block;
302    stroke: currentColor;
303    fill: none;
304}
305
306.marco-copy-btn:hover {
307    background-color: var(--bg-secondary, #f5f5f5);
308    color: var(--link-color, #0066cc);
309    opacity: 1;
310}
311
312.marco-copy-btn:active {
313    background-color: var(--bg-code, #eee);
314}
315
316.marco-copy-btn.copied {
317    color: #1a7f37;
318    background-color: var(--bg-code, #eee);
319    opacity: 1;
320}
321
322/* ── Blockquote ───────────────────────────────────────────────────────────── */
323blockquote {
324    margin: 1rem 0;
325    padding: 0.75rem 1rem;
326    border-left: 4px solid var(--blockquote-border, #ccc);
327    background-color: var(--blockquote-bg, var(--bg-secondary, #f9f9f9));
328    color: var(--blockquote-text, var(--text-secondary, #666));
329    border-radius: 0 4px 4px 0;
330}
331
332blockquote > :first-child { margin-top: 0; }
333blockquote > :last-child  { margin-bottom: 0; }
334
335/* ── Lists ────────────────────────────────────────────────────────────────── */
336ul, ol {
337    margin: 0.5rem 0 1rem 0;
338    padding-left: 2rem;
339}
340
341li {
342    margin-bottom: 0.35rem;
343    color: var(--text-color, #333);
344}
345
346li + li { margin-top: 0.15rem; }
347
348/* ── Task lists ───────────────────────────────────────────────────────────── */
349.marco-task-list-item {
350    list-style-type: none;
351    margin-left: -1.5rem;
352    padding-left: 0;
353    display: flex;
354    align-items: flex-start;
355    gap: 0.4rem;
356}
357
358.marco-task-checkbox,
359.marco-task-list-item .marco-task-checkbox {
360    display: inline-flex;
361    align-items: center;
362    justify-content: center;
363    flex: 0 0 auto;
364    width: 1.15em;
365    height: 1.15em;
366    margin-top: 0.15em;
367    color: currentColor;
368}
369
370.marco-task-checkbox .marco-task-icon,
371.marco-task-list-item .marco-task-checkbox .marco-task-icon {
372    width: 1.15em;
373    height: 1.15em;
374    flex: 0 0 auto;
375}
376
377.marco-task-checkbox.checked,
378.marco-task-list-item .marco-task-checkbox.checked {
379    color: var(--mc-task-primary, var(--link-color, #0066cc));
380}
381
382.marco-task-checkbox.checked .marco-task-check,
383.marco-task-list-item .marco-task-checkbox.checked .marco-task-check {
384    stroke: var(--mc-task-accent, var(--link-hover, #0052a3));
385}
386
387.marco-task-list-item input[type="checkbox"] {
388    margin-right: 0.4rem;
389    accent-color: var(--mc-task-primary, var(--link-color, #0066cc));
390}
391
392/* ── Definition lists ─────────────────────────────────────────────────────── */
393dl { margin: 1rem 0; }
394
395dt {
396    font-weight: 700;
397    margin-top: 1rem;
398    color: var(--heading-color, #1a1a1a);
399    -webkit-text-fill-color: var(--heading-color, #1a1a1a);
400}
401
402dd {
403    margin-left: 2rem;
404    margin-bottom: 0.5rem;
405    color: var(--text-color, #333);
406}
407
408/* ── Tables ───────────────────────────────────────────────────────────────── */
409table {
410    border-collapse: collapse;
411    width: 100%;
412    margin: 1rem 0;
413    font-size: 0.95em;
414}
415
416th, td {
417    border: 1px solid var(--table-border, #ddd);
418    padding: 0.6rem 0.85rem;
419    text-align: left;
420}
421
422th {
423    background-color: var(--table-header-bg, #f5f5f5);
424    color: var(--table-header-color, var(--heading-color, #333));
425    font-weight: 600;
426}
427
428tr:nth-child(even) {
429    background-color: var(--table-stripe-bg, #fafafa);
430}
431
432tr:hover {
433    background-color: var(--toc-link-hover-bg, var(--bg-secondary, #f5f5f5));
434}
435
436/* Right/centre alignment for GFM auto-align tables */
437.marco-table-auto-align th[align="right"],
438.marco-table-auto-align td[align="right"] { text-align: right; }
439
440.marco-table-auto-align th[align="center"],
441.marco-table-auto-align td[align="center"] { text-align: center; }
442
443/* ── Horizontal rule ──────────────────────────────────────────────────────── */
444hr {
445    border: none;
446    border-top: 1px solid var(--border-color, #ddd);
447    margin: 1.5rem 0;
448}
449
450/* ── Images ───────────────────────────────────────────────────────────────── */
451img {
452    max-width: 100%;
453    height: auto;
454    display: block;
455    border-radius: 4px;
456}
457
458/* Figure caption: italicised <em> directly after an image */
459img + em {
460    display: block;
461    text-align: center;
462    font-style: italic;
463    color: var(--text-muted, #888);
464    margin-top: 0.4rem;
465    font-size: 0.9em;
466}
467
468/* ── Emoji ────────────────────────────────────────────────────────────────── */
469.marco-emoji {
470    font-size: 1.2em;
471    display: inline-block;
472    vertical-align: baseline;
473}
474
475/* ── Footnotes ────────────────────────────────────────────────────────────── */
476.footnote-ref {
477    font-size: 0.8em;
478    vertical-align: super;
479    color: var(--link-color, #0066cc);
480    font-weight: 700;
481    line-height: 0;
482}
483
484.footnote-backref {
485    font-size: 0.85em;
486    color: var(--link-color, #0066cc);
487    text-decoration: none;
488}
489
490.footnotes {
491    border-top: 1px solid var(--border-light, var(--border-color, #ddd));
492    margin-top: 2rem;
493    padding-top: 1rem;
494    font-size: 0.9em;
495    color: var(--text-secondary, #666);
496}
497
498/* ── Inline footnotes ─────────────────────────────────────────────────────── */
499.marco-inline-footnote {
500    font-size: 0.8em;
501    vertical-align: super;
502    color: var(--link-color, #0066cc);
503    cursor: default;
504    border-bottom: 1px dotted var(--link-color, #0066cc);
505    line-height: 0;
506}
507
508/* ── Admonitions ──────────────────────────────────────────────────────────── */
509.admonition {
510    margin: 0.75rem 0;
511    padding: 0.65rem 1rem;
512    border-left: 4px solid var(--admonition-border, var(--border-strong, #ccc));
513    background-color: var(--admonition-bg, var(--bg-secondary, #f9f9f9));
514    border-radius: 0 6px 6px 0;
515}
516
517.admonition p {
518    margin: 0.4rem 0;
519}
520
521.admonition p:first-child { margin-top: 0; }
522.admonition p:last-child  { margin-bottom: 0; }
523
524.admonition .markdown-alert-title {
525    display: flex;
526    align-items: center;
527    gap: 0.5rem;
528    font-weight: 600;
529    line-height: 1.2;
530    margin: 0 0 0.5rem 0;
531}
532
533.admonition .markdown-alert-icon {
534    display: inline-flex;
535    flex: 0 0 auto;
536    align-items: center;
537    justify-content: center;
538    line-height: 0;
539}
540
541.admonition .markdown-alert-icon svg {
542    width: 1.4em;
543    height: 1.4em;
544    display: block;
545    shape-rendering: auto;
546}
547
548.admonition .markdown-alert-emoji {
549    width: 1.4em;
550    height: 1.4em;
551    display: inline-flex;
552    align-items: center;
553    justify-content: center;
554    line-height: 1;
555    font-size: 1.2em;
556}
557
558/* Quote-style admonition (blockquote colours) */
559.admonition-quote {
560    border-left-color: var(--blockquote-border, #ccc);
561    background-color: var(--blockquote-bg, var(--bg-secondary, #f9f9f9));
562    color: var(--blockquote-text, var(--text-secondary, #666));
563}
564
565.admonition-quote .markdown-alert-title {
566    color: var(--link-color, #0066cc);
567}
568
569/* Semantic admonition types — use consistent GitHub-style accent colours */
570.admonition-note { border-left-color: #0969da; background-color: var(--note-bg, var(--admonition-bg, #ebf5fb)); }
571.admonition-note .markdown-alert-title { color: #0969da; }
572
573.admonition-tip  { border-left-color: #1a7f37; background-color: var(--tip-bg, var(--admonition-bg, #eafaf1)); }
574.admonition-tip  .markdown-alert-title { color: #1a7f37; }
575
576.admonition-important { border-left-color: #8250df; background-color: var(--important-bg, var(--admonition-bg, #f5f0ff)); }
577.admonition-important .markdown-alert-title { color: #8250df; }
578
579.admonition-warning { border-left-color: #d97706; background-color: var(--warning-bg, var(--admonition-bg, #fffbeb)); }
580.admonition-warning .markdown-alert-title { color: #d97706; }
581
582.admonition-caution { border-left-color: #cf222e; background-color: var(--caution-bg, var(--admonition-bg, #fef2f2)); }
583.admonition-caution .markdown-alert-title { color: #cf222e; }
584
585/* ── Platform mentions ────────────────────────────────────────────────────── */
586.marco-mention,
587platform-mention {
588    display: inline;
589    color: var(--link-color, #0066cc);
590    font-weight: 500;
591}
592
593.marco-mention:hover,
594platform-mention:hover {
595    color: var(--link-hover, var(--link-color, #0052a3));
596    text-decoration: underline;
597    cursor: pointer;
598}
599
600/* ── GFM autolinks ────────────────────────────────────────────────────────── */
601.marco-autolink {
602    color: var(--link-color, #0066cc);
603    text-decoration: none;
604}
605
606.marco-autolink:hover {
607    color: var(--link-hover, var(--link-color, #0052a3));
608    text-decoration: underline;
609}
610
611/* ── Table of Contents (.toc) ─────────────────────────────────────────────── */
612.toc {
613    margin: 1.5rem 0;
614    padding: 1rem 1.25rem;
615    background-color: var(--toc-bg, var(--bg-secondary, #f9f9f9));
616    border: 1px solid var(--toc-border, var(--border-color, #ddd));
617    border-radius: 6px;
618    box-shadow: 0 2px 6px var(--toc-shadow, rgba(0, 0, 0, 0.08));
619}
620
621.toc h4 {
622    margin: 0 0 0.75rem 0;
623    font-size: 1rem;
624    color: var(--toc-header-color, var(--heading-color, #333));
625    -webkit-text-fill-color: var(--toc-header-color, var(--heading-color, #333));
626    background: none;
627    -webkit-background-clip: unset;
628    background-clip: unset;
629    border-bottom: 1px solid var(--toc-header-border, var(--border-color, #ddd));
630    padding-bottom: 0.5rem;
631    font-weight: 600;
632}
633
634.toc ul {
635    list-style: none;
636    margin: 0;
637    padding-left: 0;
638}
639
640.toc li {
641    margin: 0.15rem 0;
642    line-height: 1.4;
643}
644
645.toc a {
646    display: block;
647    padding: 0.3rem 0.6rem;
648    color: var(--toc-link-color, var(--text-color, #333));
649    text-decoration: none;
650    border-radius: 4px;
651    -webkit-text-fill-color: var(--toc-link-color, var(--text-color, #333));
652    transition: background-color 0.12s ease, color 0.12s ease;
653}
654
655.toc a:hover {
656    background-color: var(--toc-link-hover-bg, var(--bg-secondary, #f0f0f0));
657    color: var(--toc-link-hover-color, var(--link-color, #0066cc));
658    -webkit-text-fill-color: var(--toc-link-hover-color, var(--link-color, #0066cc));
659}
660
661.toc a.active {
662    background-color: var(--toc-link-active-bg, #e0e7ff);
663    color: var(--toc-link-active-color, var(--link-color, #0066cc));
664    -webkit-text-fill-color: var(--toc-link-active-color, var(--link-color, #0066cc));
665    font-weight: 600;
666}
667
668/* Nested TOC levels */
669.toc ul ul {
670    padding-left: 1rem;
671    margin-top: 0.15rem;
672    margin-bottom: 0;
673}
674
675.toc ul ul li { margin: 0.1rem 0; }
676
677.toc ul ul a {
678    font-size: 0.9em;
679    padding: 0.2rem 0.5rem;
680}
681
682/* ── Tab blocks (.marco-tabs) ─────────────────────────────────────────────── */
683.marco-tabs {
684    margin: 1rem 0;
685    border: 1px solid var(--border-color, #ddd);
686    border-radius: 6px;
687    overflow: visible;
688}
689
690/* Keep radios in the accessibility tree while hiding them visually */
691.marco-tabs__radio {
692    position: absolute;
693    opacity: 0;
694    width: 0;
695    height: 0;
696    pointer-events: none;
697}
698
699.marco-tabs__tablist {
700    display: flex;
701    flex-wrap: wrap;
702    gap: 0;
703    border-bottom: 1px solid var(--border-color, #ddd);
704    background-color: var(--bg-secondary, #f9f9f9);
705    border-radius: 6px 6px 0 0;
706    padding: 0 0.25rem;
707}
708
709.marco-tabs__tab {
710    padding: 0.5rem 1rem;
711    cursor: pointer;
712    color: var(--text-secondary, #666);
713    font-size: 0.9em;
714    font-weight: 500;
715    border: none;
716    background: transparent;
717    border-bottom: 2px solid transparent;
718    margin-bottom: -1px;
719    transition: color 0.12s ease, border-color 0.12s ease;
720    user-select: none;
721}
722
723.marco-tabs__tab:hover {
724    color: var(--link-color, #0066cc);
725}
726
727.marco-tabs__panels {
728    border-radius: 0 0 6px 6px;
729}
730
731.marco-tabs__panel {
732    display: none;
733    padding: 1rem;
734}
735
736.marco-tabs__panel > :first-child { margin-top: 0; }
737.marco-tabs__panel > :last-child  { margin-bottom: 0; }
738
739/* Show the selected panel + style the selected tab label (up to 12 tabs) */
740.marco-tabs > input.marco-tabs__radio:nth-of-type(1):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(1),
741.marco-tabs > input.marco-tabs__radio:nth-of-type(2):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(2),
742.marco-tabs > input.marco-tabs__radio:nth-of-type(3):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(3),
743.marco-tabs > input.marco-tabs__radio:nth-of-type(4):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(4),
744.marco-tabs > input.marco-tabs__radio:nth-of-type(5):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(5),
745.marco-tabs > input.marco-tabs__radio:nth-of-type(6):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(6),
746.marco-tabs > input.marco-tabs__radio:nth-of-type(7):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(7),
747.marco-tabs > input.marco-tabs__radio:nth-of-type(8):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(8),
748.marco-tabs > input.marco-tabs__radio:nth-of-type(9):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(9),
749.marco-tabs > input.marco-tabs__radio:nth-of-type(10):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(10),
750.marco-tabs > input.marco-tabs__radio:nth-of-type(11):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(11),
751.marco-tabs > input.marco-tabs__radio:nth-of-type(12):checked ~ .marco-tabs__panels > .marco-tabs__panel:nth-of-type(12) {
752    display: block;
753}
754
755.marco-tabs > input.marco-tabs__radio:nth-of-type(1):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(1),
756.marco-tabs > input.marco-tabs__radio:nth-of-type(2):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(2),
757.marco-tabs > input.marco-tabs__radio:nth-of-type(3):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(3),
758.marco-tabs > input.marco-tabs__radio:nth-of-type(4):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(4),
759.marco-tabs > input.marco-tabs__radio:nth-of-type(5):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(5),
760.marco-tabs > input.marco-tabs__radio:nth-of-type(6):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(6),
761.marco-tabs > input.marco-tabs__radio:nth-of-type(7):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(7),
762.marco-tabs > input.marco-tabs__radio:nth-of-type(8):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(8),
763.marco-tabs > input.marco-tabs__radio:nth-of-type(9):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(9),
764.marco-tabs > input.marco-tabs__radio:nth-of-type(10):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(10),
765.marco-tabs > input.marco-tabs__radio:nth-of-type(11):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(11),
766.marco-tabs > input.marco-tabs__radio:nth-of-type(12):checked ~ .marco-tabs__tablist > .marco-tabs__tab:nth-of-type(12) {
767    color: var(--link-color, #0066cc);
768    border-bottom-color: var(--link-color, #0066cc);
769}
770
771/* ── Paged.js page paper colors ───────────────────────────────────────────── */
772/* Each theme defines --pagedjs-page-bg and --pagedjs-page-color via
773   .theme-light and .theme-dark blocks in its token file.               */
774.pagedjs_page {
775    background-color: var(--pagedjs-page-bg, #ffffff);
776    color: var(--pagedjs-page-color, var(--text-color, #333));
777}
778
779.pagedjs_margin .pagedjs_margin-content {
780    color: var(--text-muted, #888);
781    font-size: 0.8em;
782}
783
784/* ── WebKit scrollbar (HTML preview pane) ─────────────────────────────────── */
785::-webkit-scrollbar { width: 12px; height: 12px; }
786
787::-webkit-scrollbar-track {
788    background: var(--bg-secondary, #f5f5f5);
789}
790
791::-webkit-scrollbar-thumb {
792    background: var(--border-strong, #ccc);
793    border-radius: 0;
794}
795
796::-webkit-scrollbar-thumb:hover { opacity: 0.9; }
797
798/* ── Selection ────────────────────────────────────────────────────────────── */
799::selection {
800    background-color: var(--mark-bg, #b3d9ff);
801    color: var(--mark-color, #1a1a1a);
802}
803"#;
804
805#[cfg(test)]
806mod tests {
807    use super::*;
808
809    #[test]
810    fn smoke_base_css_non_empty() {
811        let css = base_css();
812        assert!(!css.is_empty(), "base_css() must not be empty");
813    }
814
815    #[test]
816    fn smoke_base_css_contains_key_selectors() {
817        let css = base_css();
818        assert!(css.contains("body {"), "body rule missing");
819        assert!(css.contains("blockquote {"), "blockquote rule missing");
820        assert!(css.contains(".admonition"), "admonition rule missing");
821        assert!(css.contains(".marco-tabs"), "tab block rule missing");
822        assert!(css.contains(".toc"), "TOC rule missing");
823        assert!(css.contains(".pagedjs_page"), "paged.js page rule missing");
824        assert!(
825            css.contains("var(--text-color"),
826            "text-color variable missing"
827        );
828        assert!(css.contains("var(--bg-color"), "bg-color variable missing");
829        assert!(
830            css.contains("var(--heading-color"),
831            "heading-color variable missing"
832        );
833    }
834
835    #[test]
836    fn smoke_base_css_no_format_braces() {
837        // The CSS must NOT contain unescaped `{` immediately followed by `{`
838        // (which would indicate accidental format!()-style escaping).
839        let css = base_css();
840        // Valid CSS has single braces; doubled braces are a format! artifact.
841        assert!(
842            !css.contains("{{"),
843            "base_css contains escaped braces ('{{') — remove them"
844        );
845        assert!(
846            !css.contains("}}"),
847            "base_css contains escaped braces ('}}') — remove them"
848        );
849    }
850}