create-zudo-doc 0.2.9 → 0.2.11

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.
@@ -35,6 +35,14 @@
35
35
 
36
36
  @import "@takazudo/zudo-doc/safelist.css";
37
37
 
38
+ /* Content typography (`.zd-content` rules + admonitions + mermaid layout).
39
+ Shipped by @takazudo/zudo-doc as the single source of truth — do not inline
40
+ these rules here (they used to live here and drifted; see
41
+ zudolab/zudo-doc#2188). The @layer zd-flow order it relies on is declared
42
+ above (line 11); the safelist import above generates the component utilities
43
+ its headings/links/etc. depend on. */
44
+ @import "@takazudo/zudo-doc/content.css";
45
+
38
46
  /* ========================================
39
47
  * Tailwind v4 content sources
40
48
  *
@@ -290,410 +298,6 @@ body {
290
298
  }
291
299
  }
292
300
 
293
- /* ========================================
294
- * Content typography (.zd-content)
295
- *
296
- * Direct element styling — no prose plugin.
297
- * Uses :where() for zero specificity (easy to override).
298
- * Font size pattern inspired by zpaper: paired size + line-height.
299
- * ======================================== */
300
-
301
- .zd-content {
302
- color: var(--color-fg);
303
- font-size: var(--text-body);
304
- line-height: var(--leading-relaxed);
305
- }
306
-
307
- /* ── Flow spacing (vertical rhythm) ── */
308
-
309
- /* In the `zd-flow` cascade layer (declared at the top of this file) so the
310
- * unlayered `tailwindcss/utilities` import wins over it: unlayered declarations
311
- * always beat layered ones regardless of specificity or source order. Both this
312
- * rule and a `mt-*` utility have specificity (0,1,0); without the layer this
313
- * rule comes later in source order and silently kills every `mt-*` on a
314
- * `.zd-content` direct child. zd-flow sits ABOVE zd-preflight so this rule still
315
- * beats preflight's `* { margin: 0 }` reset and the .zd-content rhythm is
316
- * preserved for plain content blocks. The layer is scoped to ONLY this flow rule
317
- * — every other `.zd-content` author rule (links, code, lists, headings, the
318
- * `:first-child` reset, etc.) stays unlayered so utilities do NOT flip those.
319
- * See zudolab/zudo-doc#2082 / #2109. */
320
- @layer zd-flow {
321
- .zd-content > :where(* + *) {
322
- margin-top: var(--flow-space, var(--spacing-vsp-md));
323
- }
324
- }
325
-
326
- /* ── Headings ── */
327
-
328
- .zd-content :where(h2) {
329
- font-size: var(--text-title);
330
- font-weight: var(--font-weight-bold);
331
- line-height: var(--leading-tight);
332
- margin-top: var(--spacing-vsp-2xl);
333
- margin-bottom: var(--spacing-vsp-xs);
334
- padding-top: var(--spacing-vsp-sm);
335
- border-top: 3px solid transparent;
336
- border-image: linear-gradient(to right, var(--color-fg), transparent) 1;
337
- }
338
-
339
- .zd-content :where(h3) {
340
- font-size: var(--text-body);
341
- font-weight: var(--font-weight-bold);
342
- line-height: var(--leading-snug);
343
- margin-top: var(--spacing-vsp-xl);
344
- margin-bottom: var(--spacing-vsp-xs);
345
- padding-top: var(--spacing-vsp-xs);
346
- border-top: 2px solid transparent;
347
- border-image: linear-gradient(to right, var(--color-muted), transparent) 1;
348
- }
349
-
350
- .zd-content :where(h4) {
351
- font-size: var(--text-body);
352
- font-weight: var(--font-weight-semibold);
353
- line-height: var(--leading-snug);
354
- margin-top: var(--spacing-vsp-lg);
355
- margin-bottom: var(--spacing-vsp-xs);
356
- padding-top: var(--spacing-vsp-xs);
357
- border-top: 1px solid transparent;
358
- border-image: linear-gradient(to right, var(--color-muted), transparent) 1;
359
- }
360
-
361
- .zd-content :where(h5, h6) {
362
- font-size: var(--text-small);
363
- font-weight: var(--font-weight-semibold);
364
- line-height: var(--leading-snug);
365
- margin-top: var(--spacing-vsp-md);
366
- margin-bottom: var(--spacing-vsp-2xs);
367
- }
368
-
369
- /* ── Heading auto-links ── */
370
-
371
- .zd-content :where(h2, h3, h4, h5, h6) .hash-link {
372
- text-decoration: none;
373
- margin-left: var(--spacing-hsp-sm);
374
- opacity: 0;
375
- transition: opacity 0.15s;
376
- }
377
-
378
- .zd-content :where(h2, h3, h4, h5, h6) .hash-link::after {
379
- content: "#";
380
- color: var(--color-accent);
381
- }
382
-
383
- .zd-content :where(h2, h3, h4, h5, h6):hover .hash-link {
384
- opacity: 1;
385
- }
386
-
387
- .zd-content :where(h2, h3, h4, h5, h6) .hash-link:focus-visible {
388
- opacity: 1;
389
- outline: 2px solid var(--color-accent);
390
- outline-offset: 2px;
391
- }
392
-
393
- /* Tighten spacing after headings */
394
- .zd-content :where(h2 + *, h3 + *, h4 + *, h5 + *, h6 + *) {
395
- margin-top: 0;
396
- }
397
-
398
- /* ── Paragraphs ── */
399
-
400
- .zd-content :where(p) {
401
- margin-top: 0;
402
- margin-bottom: var(--spacing-vsp-md);
403
- }
404
-
405
- /* ── Links ── */
406
-
407
- .zd-content :where(a:not(.block):not([data-site-nav] *)) {
408
- color: var(--color-accent);
409
- text-decoration: underline;
410
- }
411
-
412
- .zd-content :where(a:not(.block):not([data-site-nav] *):hover) {
413
- color: var(--color-accent-hover);
414
- }
415
-
416
- /* ── Bold / Strong ── */
417
-
418
- .zd-content :where(strong) {
419
- font-weight: var(--font-weight-bold);
420
- color: var(--color-fg);
421
- }
422
-
423
- /* ── Lists ── */
424
-
425
- .zd-content :where(ul) {
426
- list-style-type: disc;
427
- padding-left: var(--spacing-hsp-xl);
428
- margin-bottom: var(--spacing-vsp-md);
429
- }
430
-
431
- .zd-content :where(ol) {
432
- list-style-type: decimal;
433
- padding-left: var(--spacing-hsp-xl);
434
- margin-bottom: var(--spacing-vsp-md);
435
- }
436
-
437
- .zd-content :where(li) {
438
- margin-bottom: var(--spacing-vsp-xs);
439
- }
440
-
441
- .zd-content :where(li::marker) {
442
- color: var(--color-muted);
443
- }
444
-
445
- .zd-content :where(li > ul, li > ol) {
446
- margin-top: var(--spacing-vsp-xs);
447
- margin-bottom: 0;
448
- }
449
-
450
- /* ── Blockquotes ── */
451
-
452
- .zd-content :where(blockquote) {
453
- border-left: 3px solid var(--color-muted);
454
- padding-left: var(--spacing-hsp-lg);
455
- color: var(--color-muted);
456
- font-style: italic;
457
- margin-bottom: var(--spacing-vsp-md);
458
- }
459
-
460
- .zd-content :where(blockquote p) {
461
- margin-bottom: var(--spacing-vsp-xs);
462
- }
463
-
464
- /* ── Inline code ── */
465
-
466
- .zd-content :where(code:not(pre code)) {
467
- font-size: var(--text-small);
468
- font-weight: var(--font-weight-medium);
469
- font-family: var(--font-mono);
470
- background-color: var(--color-code-bg);
471
- color: var(--color-code-fg);
472
- border-radius: var(--radius-DEFAULT);
473
- padding: 2px var(--spacing-hsp-xs);
474
- }
475
-
476
- /* ── Code blocks (pre) ── */
477
-
478
- .zd-content :where(pre) {
479
- font-size: var(--text-small);
480
- line-height: var(--leading-relaxed);
481
- border: 1px solid var(--color-muted);
482
- padding: var(--spacing-vsp-sm) var(--spacing-hsp-lg);
483
- margin-bottom: var(--spacing-vsp-md);
484
- overflow-x: auto;
485
- }
486
-
487
- .zd-content :where(pre code) {
488
- background: transparent;
489
- padding: 0;
490
- border: none;
491
- color: inherit;
492
- font-size: inherit;
493
- }
494
-
495
- /* ── Tables ── */
496
-
497
- .zd-content :where(table) {
498
- width: 100%;
499
- border-collapse: collapse;
500
- font-size: var(--text-small);
501
- margin-bottom: var(--spacing-vsp-md);
502
- }
503
-
504
- .zd-content :where(th),
505
- .zd-content :where(td) {
506
- padding: var(--spacing-vsp-xs) var(--spacing-hsp-md);
507
- border-bottom: 1px solid var(--color-muted);
508
- overflow-wrap: break-word;
509
- }
510
-
511
- .zd-content :where(th) {
512
- font-weight: var(--font-weight-semibold);
513
- text-align: left;
514
- border-bottom-width: 2px;
515
- }
516
-
517
- /* ── Horizontal rules ── */
518
-
519
- .zd-content :where(hr) {
520
- border: none;
521
- border-top: 1px solid var(--color-muted);
522
- margin: var(--spacing-vsp-xl) 0;
523
- }
524
-
525
- /* ── Images ── */
526
-
527
- .zd-content :where(img) {
528
- max-width: 100%;
529
- height: auto;
530
- }
531
-
532
- /* ── Definition lists ── */
533
-
534
- .zd-content :where(dt) {
535
- font-weight: var(--font-weight-semibold);
536
- margin-top: var(--spacing-vsp-md);
537
- }
538
-
539
- .zd-content :where(dd) {
540
- padding-left: var(--spacing-hsp-xl);
541
- margin-bottom: var(--spacing-vsp-xs);
542
- }
543
-
544
- /* ========================================
545
- * Admonitions ([data-admonition])
546
- *
547
- * Variant→color mapping: note→accent, tip→success, info→info,
548
- * warning→warning, danger→danger. Background tint uses
549
- * `color-mix(in srgb, var(--color-X) 12%, var(--color-bg))` for an opaque
550
- * per-theme tinted backdrop. Class names are dynamic (admonition-${variant})
551
- * so Tailwind cannot scan them; rules must live here explicitly.
552
- * See zudolab/zudo-doc#1357 / #1444 / #1456.
553
- * ======================================== */
554
-
555
- [data-admonition] {
556
- border-left: 4px solid var(--color-muted);
557
- /* Asymmetric padding mirrors the Astro reference: generous top, snug bottom. */
558
- padding: var(--spacing-vsp-md) var(--spacing-hsp-lg) var(--spacing-vsp-2xs);
559
- background-color: color-mix(in srgb, var(--color-muted) 12%, var(--color-bg));
560
- border-radius: 0 var(--radius-DEFAULT) var(--radius-DEFAULT) 0;
561
- }
562
-
563
- .admonition-title {
564
- font-weight: var(--font-weight-semibold);
565
- font-size: var(--text-small);
566
- margin-bottom: var(--spacing-vsp-2xs);
567
- }
568
-
569
- /* Variant icon — emoji rendered via ::before so the stub markup stays
570
- * variant-agnostic and the icon vocabulary lives next to its color rule. */
571
- .admonition-title::before {
572
- margin-right: var(--spacing-hsp-2xs);
573
- }
574
-
575
- .admonition-body > :first-child {
576
- margin-top: 0;
577
- }
578
-
579
- .admonition-body > :last-child {
580
- margin-bottom: 0;
581
- }
582
-
583
- [data-admonition="note"],
584
- .admonition-note {
585
- border-left-color: var(--color-accent);
586
- background-color: color-mix(in srgb, var(--color-accent) 12%, var(--color-bg));
587
- }
588
-
589
- [data-admonition="note"] .admonition-title,
590
- .admonition-note .admonition-title {
591
- color: var(--color-accent);
592
- }
593
-
594
- [data-admonition="note"] .admonition-title::before,
595
- .admonition-note .admonition-title::before {
596
- content: "📝";
597
- }
598
-
599
- [data-admonition="tip"],
600
- .admonition-tip {
601
- border-left-color: var(--color-success);
602
- background-color: color-mix(in srgb, var(--color-success) 12%, var(--color-bg));
603
- }
604
-
605
- [data-admonition="tip"] .admonition-title,
606
- .admonition-tip .admonition-title {
607
- color: var(--color-success);
608
- }
609
-
610
- [data-admonition="tip"] .admonition-title::before,
611
- .admonition-tip .admonition-title::before {
612
- content: "💡";
613
- }
614
-
615
- [data-admonition="info"],
616
- .admonition-info {
617
- border-left-color: var(--color-info);
618
- background-color: color-mix(in srgb, var(--color-info) 12%, var(--color-bg));
619
- }
620
-
621
- [data-admonition="info"] .admonition-title,
622
- .admonition-info .admonition-title {
623
- color: var(--color-info);
624
- }
625
-
626
- [data-admonition="info"] .admonition-title::before,
627
- .admonition-info .admonition-title::before {
628
- content: "ℹ️";
629
- }
630
-
631
- [data-admonition="warning"],
632
- .admonition-warning {
633
- border-left-color: var(--color-warning);
634
- background-color: color-mix(in srgb, var(--color-warning) 12%, var(--color-bg));
635
- }
636
-
637
- [data-admonition="warning"] .admonition-title,
638
- .admonition-warning .admonition-title {
639
- color: var(--color-warning);
640
- }
641
-
642
- [data-admonition="warning"] .admonition-title::before,
643
- .admonition-warning .admonition-title::before {
644
- content: "⚠️";
645
- }
646
-
647
- [data-admonition="danger"],
648
- .admonition-danger {
649
- border-left-color: var(--color-danger);
650
- background-color: color-mix(in srgb, var(--color-danger) 12%, var(--color-bg));
651
- }
652
-
653
- [data-admonition="danger"] .admonition-title,
654
- .admonition-danger .admonition-title {
655
- color: var(--color-danger);
656
- }
657
-
658
- [data-admonition="danger"] .admonition-title::before,
659
- .admonition-danger .admonition-title::before {
660
- content: "🚨";
661
- }
662
-
663
- /* github-alerts [!IMPORTANT] → magenta/accent-adjacent (p5 = magenta palette slot) */
664
- [data-admonition="important"],
665
- .admonition-important {
666
- border-left-color: var(--color-p5);
667
- background-color: color-mix(in srgb, var(--color-p5) 12%, var(--color-bg));
668
- }
669
-
670
- [data-admonition="important"] .admonition-title,
671
- .admonition-important .admonition-title {
672
- color: var(--color-p5);
673
- }
674
-
675
- [data-admonition="important"] .admonition-title::before,
676
- .admonition-important .admonition-title::before {
677
- content: "❗";
678
- }
679
-
680
- /* github-alerts [!CAUTION] → danger-adjacent (high severity, distinct from danger/🚨) */
681
- [data-admonition="caution"],
682
- .admonition-caution {
683
- border-left-color: var(--color-danger);
684
- background-color: color-mix(in srgb, var(--color-danger) 12%, var(--color-bg));
685
- }
686
-
687
- [data-admonition="caution"] .admonition-title,
688
- .admonition-caution .admonition-title {
689
- color: var(--color-danger);
690
- }
691
-
692
- [data-admonition="caution"] .admonition-title::before,
693
- .admonition-caution .admonition-title::before {
694
- content: "⛔";
695
- }
696
-
697
301
  /* ========================================
698
302
  * Code block buttons (copy + word wrap)
699
303
  * ======================================== */
@@ -901,25 +505,6 @@ pre[class^="syntect-"] .line .highlighted-word {
901
505
  margin: 0;
902
506
  }
903
507
 
904
- /* ========================================
905
- * Mermaid diagrams
906
- * ======================================== */
907
-
908
- .zd-content .mermaid {
909
- @apply my-vsp-lg flex justify-center;
910
- }
911
-
912
- .zd-content .mermaid svg {
913
- max-width: 100%;
914
- height: auto;
915
- overflow: visible;
916
- }
917
-
918
- /* Prevent mermaid edge labels from clipping text (foreignObject uses overflow:hidden) */
919
- .zd-content .mermaid foreignObject {
920
- overflow: visible;
921
- }
922
-
923
508
  /* KaTeX math equations */
924
509
  .katex {
925
510
  font-size: 1.1em;
@@ -1132,6 +717,20 @@ pre[class^="syntect-"] .line .highlighted-word {
1132
717
  }
1133
718
  }
1134
719
 
720
+ /* Suppress sidebar geometry transitions during an SPA swap (#2198).
721
+ * swapRootAttributes wipes data-sidebar-hidden mid-swap, so without this the
722
+ * sidebar would animate open (attribute absent) and then animate shut again
723
+ * when the toggle island restores the attribute on zfb:after-swap — a visible
724
+ * flash + slide. The island sets data-sidebar-no-transition for the swap
725
+ * window and removes it (double rAF) after restoring the hidden state, so the
726
+ * wipe/restore apply instantly and a later user toggle still animates. */
727
+ html[data-sidebar-no-transition] #desktop-sidebar,
728
+ html[data-sidebar-no-transition] .zd-sidebar-content-wrapper,
729
+ html[data-sidebar-no-transition] .zd-doc-content-band,
730
+ html[data-sidebar-no-transition] .zd-desktop-sidebar-toggle {
731
+ transition: none !important;
732
+ }
733
+
1135
734
  /* ── Find-in-page highlight (W7A: unconditional — Tauri feature gates at runtime) ── */
1136
735
  .find-match {
1137
736
  background-color: color-mix(in oklch, var(--color-warning) 40%, transparent);
@@ -1271,4 +870,148 @@ dialog.zd-enlarge-dialog::backdrop {
1271
870
  }
1272
871
  }
1273
872
 
873
+ /* ========================================
874
+ * Mermaid enlarge (.zd-mermaid-enlargeable) — issue #2176 / #2178
875
+ *
876
+ * Unlike images (SSR-wrapped in figure.zd-enlargeable), mermaid diagrams render
877
+ * client-side, so the mermaid-enlarge island injects the `.zd-enlarge-btn` into
878
+ * each rendered `.mermaid` container and adds `.zd-mermaid-enlargeable` (which
879
+ * makes the container position:relative so the button anchors to it). The
880
+ * button + close-button visuals are SHARED with image-enlarge above
881
+ * (`.zd-enlarge-btn`, `.zd-enlarge-dialog-close`).
882
+ * ======================================== */
883
+
884
+ .zd-mermaid-enlargeable {
885
+ position: relative;
886
+ border: 1px solid transparent;
887
+ border-radius: var(--radius-DEFAULT);
888
+ transition: border-color var(--default-transition-duration);
889
+ }
890
+
891
+ /* The diagram is always enlargeable once the button is injected — show a subtle
892
+ * border affordance, accent on hover (mirrors the image-enlarge affordance). */
893
+ .zd-mermaid-enlargeable:has(.zd-enlarge-btn) {
894
+ cursor: pointer;
895
+ border-color: var(--color-muted);
896
+ }
897
+
898
+ .zd-mermaid-enlargeable:has(.zd-enlarge-btn):hover {
899
+ border-color: var(--color-accent);
900
+ }
901
+
902
+ /* Zoom/pan dialog. The `<dialog>` stays transform-free (see DIALOG_STYLE in
903
+ * mermaid-enlarge.tsx); the transform lives on .zd-mermaid-transform. */
904
+ dialog.zd-mermaid-dialog::backdrop {
905
+ background: color-mix(in oklch, var(--color-overlay) 80%, transparent);
906
+ }
907
+
908
+ /* Pan viewport — fills the dialog and clips the (possibly zoomed) diagram.
909
+ * touch-action:none so pointer-drag pans on touch without the browser
910
+ * intercepting the gesture for scrolling. */
911
+ .zd-mermaid-viewport {
912
+ width: 100%;
913
+ height: 100%;
914
+ overflow: hidden;
915
+ display: flex;
916
+ align-items: center;
917
+ justify-content: center;
918
+ touch-action: none;
919
+ }
920
+
921
+ .zd-mermaid-viewport[data-pan-active] {
922
+ cursor: grab;
923
+ /* In pan mode a drag should pan, not select diagram text. Scoped to
924
+ * [data-pan-active] so text stays selectable when pan mode is off. */
925
+ -webkit-user-select: none;
926
+ user-select: none;
927
+ }
928
+
929
+ .zd-mermaid-viewport[data-pan-active]:active {
930
+ cursor: grabbing;
931
+ }
932
+
933
+ .zd-mermaid-transform {
934
+ width: 100%;
935
+ height: 100%;
936
+ display: flex;
937
+ align-items: center;
938
+ justify-content: center;
939
+ will-change: transform;
940
+ }
941
+
942
+ /* SVG sizing — fit the cloned mermaid svg inside the dialog like
943
+ * object-fit:contain. The svg fills the viewport box (100% x 100%) and its
944
+ * viewBox content is letterboxed/centered by the default
945
+ * preserveAspectRatio="xMidYMid meet". A TALL diagram (e.g. a state diagram) no
946
+ * longer gets forced to full dialog width with `height:auto` driving the height
947
+ * far past the viewport via its aspect ratio — it now shrinks to fit the height
948
+ * instead. max-width/max-height !important neutralize the inline px sizing
949
+ * mermaid bakes onto the svg (without it the diagram renders tiny). Scoped to
950
+ * .zd-mermaid-transform (the cloned-diagram wrapper) so it does NOT hit the
951
+ * toolbar / close-button icon svgs that also live inside the dialog. */
952
+ .zd-mermaid-transform svg {
953
+ max-width: 100% !important;
954
+ max-height: 100% !important;
955
+ width: 100%;
956
+ height: 100%;
957
+ }
958
+
959
+ /* Edge labels (e.g. "Yes"/"No") render inside a tightly-sized <foreignObject>;
960
+ * when the cloned diagram is upscaled to fill the dialog, sub-pixel overflow
961
+ * makes the browser clip the last glyph at the foreignObject's right edge.
962
+ * Letting the foreignObject overflow render keeps the full label visible. */
963
+ .zd-mermaid-transform svg foreignObject {
964
+ overflow: visible;
965
+ }
966
+
967
+ /* Toolbar — bottom-right pill of zoom/pan controls (2× sized buttons). */
968
+ .zd-mermaid-toolbar {
969
+ position: absolute;
970
+ bottom: var(--spacing-image-overlay-inset);
971
+ right: var(--spacing-image-overlay-inset);
972
+ display: flex;
973
+ gap: var(--spacing-hsp-xs);
974
+ padding: var(--spacing-hsp-xs);
975
+ border: 1px solid var(--color-muted);
976
+ border-radius: var(--radius-DEFAULT);
977
+ background: color-mix(in oklch, var(--color-surface) 92%, transparent);
978
+ z-index: var(--z-index-local-2);
979
+ }
980
+
981
+ .zd-mermaid-tool-btn {
982
+ display: flex;
983
+ align-items: center;
984
+ justify-content: center;
985
+ width: calc(var(--spacing-icon-lg) * 2);
986
+ height: calc(var(--spacing-icon-lg) * 2);
987
+ padding: var(--spacing-vsp-2xs);
988
+ border: none;
989
+ border-radius: var(--radius-DEFAULT);
990
+ background: transparent;
991
+ color: var(--color-fg);
992
+ cursor: pointer;
993
+ transition:
994
+ background-color var(--default-transition-duration),
995
+ opacity var(--default-transition-duration);
996
+ }
997
+
998
+ .zd-mermaid-tool-btn:hover:not([disabled]) {
999
+ background: color-mix(in oklch, var(--color-muted) 25%, transparent);
1000
+ }
1001
+
1002
+ .zd-mermaid-tool-btn[aria-pressed="true"] {
1003
+ background: color-mix(in oklch, var(--color-accent) 30%, transparent);
1004
+ color: var(--color-accent);
1005
+ }
1006
+
1007
+ .zd-mermaid-tool-btn[disabled] {
1008
+ opacity: 0.4;
1009
+ cursor: default;
1010
+ }
1011
+
1012
+ .zd-mermaid-tool-btn > svg {
1013
+ width: calc(var(--spacing-icon-md) * 2);
1014
+ height: calc(var(--spacing-icon-md) * 2);
1015
+ }
1016
+
1274
1017
  /* @slot:global-css:feature-styles */