jekyll-theme-zer0 1.29.0 → 1.30.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +715 -2
- data/_data/README.md +2 -0
- data/_data/ai.yml +5 -3
- data/_data/ai_pricing.yml +36 -0
- data/_data/backlog.yml +169 -18
- data/_data/consumers.yml +48 -5
- data/_data/features.yml +146 -20
- data/_data/feedback_types.yml +17 -12
- data/_data/landing.yml +5 -2
- data/_data/navigation/quickstart.yml +4 -0
- data/_data/site_builder.yml +874 -0
- data/_data/theme-manifest.yml +122 -114
- data/_data/ui-text.yml +18 -0
- data/_includes/README.md +11 -1
- data/_includes/analytics/posthog.html +2 -2
- data/_includes/components/admin-links.html +2 -2
- data/_includes/components/admin-tabs.html +2 -2
- data/_includes/components/ai-chat.html +14 -11
- data/_includes/components/analytics-dashboard.html +8 -8
- data/_includes/components/author-bio.html +1 -1
- data/_includes/components/author-card.html +10 -2
- data/_includes/components/author-eeat.html +4 -4
- data/_includes/components/background-customizer.html +8 -8
- data/_includes/components/background-image.html +114 -0
- data/_includes/components/background-settings.html +28 -15
- data/_includes/components/collection-manager.html +5 -5
- data/_includes/components/component-showcase.html +13 -13
- data/_includes/components/config-editor.html +12 -12
- data/_includes/components/config-viewer.html +8 -8
- data/_includes/components/cookie-consent.html +11 -11
- data/_includes/components/cta-button.html +7 -2
- data/_includes/components/dev-shortcuts.html +7 -7
- data/_includes/components/env-dashboard.html +8 -8
- data/_includes/components/env-switcher.html +9 -9
- data/_includes/components/feature-card.html +2 -2
- data/_includes/components/halfmoon.html +2 -2
- data/_includes/components/info-section.html +36 -36
- data/_includes/components/js-cdn.html +15 -15
- data/_includes/components/language-toggle.html +4 -4
- data/_includes/components/mermaid.html +72 -435
- data/_includes/components/nanobar.html +5 -5
- data/_includes/components/nav-editor.html +2 -2
- data/_includes/components/nav-export.html +2 -2
- data/_includes/components/nav-overview.html +2 -2
- data/_includes/components/page-feedback.html +45 -30
- data/_includes/components/page-views-init.html +1 -1
- data/_includes/components/post-card.html +22 -22
- data/_includes/components/post-type-badge.html +2 -2
- data/_includes/components/powered-by.html +2 -2
- data/_includes/components/preview-image.html +6 -0
- data/_includes/components/quick-index.html +2 -2
- data/_includes/components/search-modal.html +27 -2
- data/_includes/components/searchbar.html +2 -2
- data/_includes/components/svg-background.html +2 -2
- data/_includes/components/theme-customizer.html +2 -2
- data/_includes/components/theme-info.html +6 -6
- data/_includes/components/theme-preview-gallery.html +22 -22
- data/_includes/content/giscus.html +2 -2
- data/_includes/content/intro.html +8 -8
- data/_includes/content/jsonld-faq.html +2 -2
- data/_includes/content/jsonld-software.html +2 -2
- data/_includes/content/seo.html +4 -4
- data/_includes/content/sitemap.html +27 -27
- data/_includes/content/toc.html +183 -183
- data/_includes/core/branding.html +6 -6
- data/_includes/core/console-capture.html +32 -74
- data/_includes/core/favicon.html +49 -7
- data/_includes/core/footer-fabs.html +17 -3
- data/_includes/core/footer.html +31 -18
- data/_includes/core/head.html +102 -90
- data/_includes/core/header.html +71 -52
- data/_includes/docs/bootstrap-docs.html +8 -8
- data/_includes/landing/landing-install-cards.html +2 -2
- data/_includes/landing/landing-quick-links.html +1 -1
- data/_includes/navigation/admin-nav.html +2 -2
- data/_includes/navigation/nav-tree.html +8 -8
- data/_includes/navigation/navbar.html +12 -12
- data/_includes/navigation/section-sidebar.html +16 -16
- data/_includes/navigation/sidebar-config.html +36 -2
- data/_includes/navigation/sidebar-left.html +15 -15
- data/_includes/navigation/sidebar-right.html +6 -6
- data/_includes/obsidian/full-graph.html +2 -2
- data/_includes/setup/claude-session.html +72 -0
- data/_includes/setup/prereq-checklist.html +90 -0
- data/_includes/setup/wizard.html +906 -291
- data/_includes/stats/stats-categories.html +8 -8
- data/_includes/stats/stats-header.html +14 -14
- data/_includes/stats/stats-metrics.html +12 -12
- data/_includes/stats/stats-no-data.html +12 -12
- data/_includes/stats/stats-overview.html +6 -6
- data/_includes/stats/stats-tags.html +8 -8
- data/_layouts/404.html +38 -24
- data/_layouts/admin.html +22 -22
- data/_layouts/article.html +39 -34
- data/_layouts/author.html +20 -20
- data/_layouts/authors.html +2 -2
- data/_layouts/book-abc.html +12 -12
- data/_layouts/book-story.html +15 -15
- data/_layouts/book.html +12 -12
- data/_layouts/collection.html +33 -33
- data/_layouts/cookbook.html +12 -12
- data/_layouts/default.html +27 -24
- data/_layouts/home.html +23 -23
- data/_layouts/index.html +10 -10
- data/_layouts/landing.html +17 -17
- data/_layouts/news.html +44 -44
- data/_layouts/note.html +38 -38
- data/_layouts/notebook.html +34 -34
- data/_layouts/recipe.html +24 -24
- data/_layouts/root.html +73 -55
- data/_layouts/section.html +23 -23
- data/_layouts/setup.html +3 -3
- data/_layouts/sitemap-collection.html +49 -49
- data/_layouts/stats.html +40 -40
- data/_layouts/tag.html +12 -12
- data/_layouts/welcome.html +21 -21
- data/_sass/components/_mermaid.scss +375 -0
- data/_sass/components/_setup-wizard.scss +569 -40
- data/_sass/core/_navbar.scss +11 -31
- data/_sass/layouts/_navbar-extras.scss +14 -4
- data/assets/css/main.scss +1 -0
- data/assets/js/ai-chat.js +47 -5
- data/assets/js/fleet-feedback-capture.js +124 -0
- data/assets/js/fleet-feedback.js +853 -0
- data/assets/js/mermaid-diagrams.js +1267 -0
- data/assets/js/modules/navigation/config.js +9 -6
- data/assets/js/modules/navigation/scroll-spy.js +315 -80
- data/assets/js/modules/theme/appearance.js +8 -2
- data/assets/js/obsidian-wiki-links.js +8 -3
- data/assets/js/page-feedback.js +125 -192
- data/assets/js/search-modal.js +26 -0
- data/assets/js/setup-wizard.js +2112 -361
- data/assets/js/site-builder.js +1834 -0
- data/assets/js/ui-enhancements.js +11 -3
- data/scripts/README.md +15 -0
- data/scripts/ai/README.md +38 -0
- data/scripts/ai/api_call.rb +124 -0
- data/scripts/ai/usage.rb +314 -0
- data/scripts/ai/usage_report.rb +225 -0
- data/scripts/ci/test_visual_evidence_autogen.py +341 -0
- data/scripts/ci/visual_evidence_autogen.py +1060 -0
- data/scripts/content-review.rb +20 -1
- data/scripts/test/integration/mermaid +22 -8
- data/scripts/test/lib/run_tests.sh +1 -0
- data/scripts/test/lib/test_visual_evidence_autogen.sh +24 -0
- data/scripts/translate.rb +23 -1
- metadata +19 -2
data/_layouts/stats.html
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Features: ZER0-019, ZER0-043
|
|
3
3
|
layout: root
|
|
4
4
|
---
|
|
5
|
-
|
|
5
|
+
{% comment %}
|
|
6
6
|
===================================================================
|
|
7
7
|
STATS LAYOUT - Statistics dashboard layout
|
|
8
8
|
===================================================================
|
|
@@ -39,68 +39,68 @@ layout: root
|
|
|
39
39
|
- card: Card components for metric display
|
|
40
40
|
- badge: Badges for counts and labels
|
|
41
41
|
===================================================================
|
|
42
|
-
|
|
42
|
+
{% endcomment %}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
{% comment %} ================================================ {% endcomment %}
|
|
45
|
+
{% comment %} STATS LAYOUT CONTAINER {% endcomment %}
|
|
46
|
+
{% comment %} Full-width responsive container for dashboard {% endcomment %}
|
|
47
|
+
{% comment %} ================================================ {% endcomment %}
|
|
48
48
|
<div class="container-fluid py-4">
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
{% comment %} ================================================ {% endcomment %}
|
|
51
|
+
{% comment %} STATS HEADER SECTION {% endcomment %}
|
|
52
|
+
{% comment %} Page title, description, and metadata {% endcomment %}
|
|
53
|
+
{% comment %} ================================================ {% endcomment %}
|
|
54
54
|
{% include stats/stats-header.html %}
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
{% comment %} ================================================ {% endcomment %}
|
|
57
|
+
{% comment %} STATS VALIDATION CHECK {% endcomment %}
|
|
58
|
+
{% comment %} Verify data availability before rendering {% endcomment %}
|
|
59
|
+
{% comment %} ================================================ {% endcomment %}
|
|
60
60
|
{% if site.data.content_statistics %}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
{% comment %} ================================================ {% endcomment %}
|
|
63
|
+
{% comment %} OVERVIEW METRICS SECTION {% endcomment %}
|
|
64
|
+
{% comment %} High-level statistics cards {% endcomment %}
|
|
65
|
+
{% comment %} ================================================ {% endcomment %}
|
|
66
66
|
{% include stats/stats-overview.html %}
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
{% comment %} ================================================ {% endcomment %}
|
|
69
|
+
{% comment %} DETAILED ANALYTICS SECTIONS {% endcomment %}
|
|
70
|
+
{% comment %} Categories, tags, and metrics breakdown {% endcomment %}
|
|
71
|
+
{% comment %} ================================================ {% endcomment %}
|
|
72
72
|
<div class="row g-4 mb-5">
|
|
73
|
-
|
|
73
|
+
{% comment %} Categories Analysis {% endcomment %}
|
|
74
74
|
<div class="col-lg-6">
|
|
75
75
|
{% include stats/stats-categories.html %}
|
|
76
76
|
</div>
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
{% comment %} Tags Analysis {% endcomment %}
|
|
79
79
|
<div class="col-lg-6">
|
|
80
80
|
{% include stats/stats-tags.html %}
|
|
81
81
|
</div>
|
|
82
82
|
</div>
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
{% comment %} ================================================ {% endcomment %}
|
|
85
|
+
{% comment %} ADDITIONAL METRICS SECTION {% endcomment %}
|
|
86
|
+
{% comment %} Quick facts and summary information {% endcomment %}
|
|
87
|
+
{% comment %} ================================================ {% endcomment %}
|
|
88
88
|
{% include stats/stats-metrics.html %}
|
|
89
89
|
|
|
90
90
|
{% else %}
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
{% comment %} ================================================ {% endcomment %}
|
|
93
|
+
{% comment %} NO DATA AVAILABLE SECTION {% endcomment %}
|
|
94
|
+
{% comment %} Error state when statistics are not generated {% endcomment %}
|
|
95
|
+
{% comment %} ================================================ {% endcomment %}
|
|
96
96
|
{% include stats/stats-no-data.html %}
|
|
97
97
|
|
|
98
98
|
{% endif %}
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
{% comment %} ================================================ {% endcomment %}
|
|
101
|
+
{% comment %} MAIN CONTENT AREA {% endcomment %}
|
|
102
|
+
{% comment %} Additional page content below statistics {% endcomment %}
|
|
103
|
+
{% comment %} ================================================ {% endcomment %}
|
|
104
104
|
{% if content and content != empty %}
|
|
105
105
|
<div class="row mt-5">
|
|
106
106
|
<div class="col-12">
|
|
@@ -115,10 +115,10 @@ layout: root
|
|
|
115
115
|
|
|
116
116
|
</div>
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
{% comment %} ================================================ {% endcomment %}
|
|
119
|
+
{% comment %} STATS-SPECIFIC JAVASCRIPT {% endcomment %}
|
|
120
|
+
{% comment %} Initialize charts and interactive components {% endcomment %}
|
|
121
|
+
{% comment %} ================================================ {% endcomment %}
|
|
122
122
|
<script>
|
|
123
123
|
document.addEventListener('DOMContentLoaded', function() {
|
|
124
124
|
// Initialize tooltips for stats elements
|
data/_layouts/tag.html
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Feature: ZER0-019
|
|
3
3
|
layout: default
|
|
4
4
|
---
|
|
5
|
-
|
|
5
|
+
{% comment %}
|
|
6
6
|
===================================================================
|
|
7
7
|
TAG LAYOUT - Tag archive page displaying posts by tag
|
|
8
8
|
===================================================================
|
|
@@ -27,11 +27,11 @@ layout: default
|
|
|
27
27
|
- _includes/components/post-card.html: Reusable post card component
|
|
28
28
|
- Bootstrap 5 grid and badge components
|
|
29
29
|
===================================================================
|
|
30
|
-
|
|
30
|
+
{% endcomment %}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
{% comment %} ========================== {% endcomment %}
|
|
33
|
+
{% comment %} TAG HEADER SECTION {% endcomment %}
|
|
34
|
+
{% comment %} ========================== {% endcomment %}
|
|
35
35
|
<header class="tag-header mb-5">
|
|
36
36
|
<nav aria-label="breadcrumb" class="mb-3">
|
|
37
37
|
<ol class="breadcrumb">
|
|
@@ -60,9 +60,9 @@ layout: default
|
|
|
60
60
|
{{ content }}
|
|
61
61
|
</header>
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
{% comment %} ========================== {% endcomment %}
|
|
64
|
+
{% comment %} TAGGED POSTS GRID {% endcomment %}
|
|
65
|
+
{% comment %} ========================== {% endcomment %}
|
|
66
66
|
<section class="tagged-posts">
|
|
67
67
|
{% if tag_posts.size > 0 %}
|
|
68
68
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
|
|
@@ -71,7 +71,7 @@ layout: default
|
|
|
71
71
|
{% endfor %}
|
|
72
72
|
</div>
|
|
73
73
|
{% else %}
|
|
74
|
-
|
|
74
|
+
{% comment %} Empty state {% endcomment %}
|
|
75
75
|
<div class="text-center py-5">
|
|
76
76
|
<i class="bi bi-tag fs-1 text-muted"></i>
|
|
77
77
|
<p class="text-muted mt-3">No posts with this tag yet.</p>
|
|
@@ -82,9 +82,9 @@ layout: default
|
|
|
82
82
|
{% endif %}
|
|
83
83
|
</section>
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
{% comment %} ========================== {% endcomment %}
|
|
86
|
+
{% comment %} RELATED TAGS {% endcomment %}
|
|
87
|
+
{% comment %} ========================== {% endcomment %}
|
|
88
88
|
{% comment %} Find tags that appear with this tag {% endcomment %}
|
|
89
89
|
{% assign related_tags = "" | split: "" %}
|
|
90
90
|
{% for post in tag_posts %}
|
data/_layouts/welcome.html
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Features: ZER0-019, ZER0-046
|
|
3
3
|
layout: root
|
|
4
4
|
---
|
|
5
|
-
|
|
5
|
+
{% comment %}
|
|
6
6
|
===================================================================
|
|
7
7
|
WELCOME LAYOUT — Onboarding landing page for new sites
|
|
8
8
|
===================================================================
|
|
@@ -36,15 +36,15 @@ layout: root
|
|
|
36
36
|
Gemfile (github-pages + jekyll-remote-theme)
|
|
37
37
|
index.md (this layout)
|
|
38
38
|
===================================================================
|
|
39
|
-
|
|
39
|
+
{% endcomment %}
|
|
40
40
|
|
|
41
41
|
{% include components/setup-check.html %}
|
|
42
42
|
|
|
43
43
|
{% if site_needs_setup %}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
46
|
+
{% comment %} HERO {% endcomment %}
|
|
47
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
48
48
|
<section class="bg-body-tertiary border-bottom">
|
|
49
49
|
<div class="container-lg py-5">
|
|
50
50
|
<div class="row align-items-center g-4">
|
|
@@ -114,9 +114,9 @@ layout: root
|
|
|
114
114
|
</div>
|
|
115
115
|
</section>
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
118
|
+
{% comment %} MINIMAL STARTER INSTRUCTIONS {% endcomment %}
|
|
119
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
120
120
|
<section id="minimal-starter" class="container-lg py-5">
|
|
121
121
|
<div class="row justify-content-center">
|
|
122
122
|
<div class="col-lg-10">
|
|
@@ -129,7 +129,7 @@ layout: root
|
|
|
129
129
|
|
|
130
130
|
<div class="accordion mt-4" id="starterAccordion">
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
{% comment %} _config.yml {% endcomment %}
|
|
133
133
|
<div class="accordion-item">
|
|
134
134
|
<h3 class="accordion-header">
|
|
135
135
|
<button class="accordion-button" type="button"
|
|
@@ -171,7 +171,7 @@ site_configured: true
|
|
|
171
171
|
</div>
|
|
172
172
|
</div>
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
{% comment %} Gemfile {% endcomment %}
|
|
175
175
|
<div class="accordion-item">
|
|
176
176
|
<h3 class="accordion-header">
|
|
177
177
|
<button class="accordion-button collapsed" type="button"
|
|
@@ -197,7 +197,7 @@ gem "webrick", "~> 1.7"
|
|
|
197
197
|
</div>
|
|
198
198
|
</div>
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
{% comment %} index.md {% endcomment %}
|
|
201
201
|
<div class="accordion-item">
|
|
202
202
|
<h3 class="accordion-header">
|
|
203
203
|
<button class="accordion-button collapsed" type="button"
|
|
@@ -232,7 +232,7 @@ is set in `_config.yml`.
|
|
|
232
232
|
</div>
|
|
233
233
|
</div>
|
|
234
234
|
|
|
235
|
-
</div
|
|
235
|
+
</div>{% comment %} /accordion {% endcomment %}
|
|
236
236
|
|
|
237
237
|
<div class="alert alert-info d-flex align-items-start mt-4" role="alert">
|
|
238
238
|
<i class="bi bi-info-circle-fill me-2 mt-1"></i>
|
|
@@ -248,16 +248,16 @@ is set in `_config.yml`.
|
|
|
248
248
|
</div>
|
|
249
249
|
</section>
|
|
250
250
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
252
|
+
{% comment %} SETUP WIZARD {% endcomment %}
|
|
253
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
254
254
|
<section id="setup-wizard" class="bg-body-tertiary border-top py-5">
|
|
255
255
|
{% include setup/wizard.html %}
|
|
256
256
|
</section>
|
|
257
257
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
259
|
+
{% comment %} NEXT STEPS / RESOURCES {% endcomment %}
|
|
260
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
261
261
|
<section class="container-lg py-5">
|
|
262
262
|
<h2 class="mb-4"><i class="bi bi-signpost-2"></i> Next steps</h2>
|
|
263
263
|
<div class="row g-3">
|
|
@@ -321,9 +321,9 @@ is set in `_config.yml`.
|
|
|
321
321
|
|
|
322
322
|
{% else %}
|
|
323
323
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
324
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
325
|
+
{% comment %} CONFIGURED SITE — render the user's content {% endcomment %}
|
|
326
|
+
{% comment %} ============================================================ {% endcomment %}
|
|
327
327
|
<div class="container-lg py-4">
|
|
328
328
|
<div class="row justify-content-center">
|
|
329
329
|
<div class="col-lg-10">
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
// Feature: ZER0-013
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// Mermaid diagram figures
|
|
4
|
+
// ----------------------------------------------------------------------------
|
|
5
|
+
// Markup: built at runtime by assets/js/mermaid-diagrams.js from every
|
|
6
|
+
// ```mermaid fence: figure.zer0-diagram > [toolbar] + viewport
|
|
7
|
+
// > canvas > svg, + figcaption
|
|
8
|
+
// Loader: _includes/components/mermaid.html (pages with `mermaid: true`)
|
|
9
|
+
// Theming: every colour here is a token, and the SVG's own palette is
|
|
10
|
+
// derived from the same tokens in JS — so light / dark / wizard
|
|
11
|
+
// modes and all skins work without per-mode overrides, and
|
|
12
|
+
// nothing needs `!important` (which used to flatten per-node
|
|
13
|
+
// `style`/`classDef` colours and pie slices).
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
.zer0-diagram {
|
|
17
|
+
--zer0-diagram-surface: color-mix(in srgb, var(--zer0-color-bg-elevated) 55%, var(--bs-body-bg));
|
|
18
|
+
--zer0-diagram-padding: var(--zer0-space-3);
|
|
19
|
+
|
|
20
|
+
position: relative;
|
|
21
|
+
margin: var(--zer0-space-4) 0;
|
|
22
|
+
padding: 0;
|
|
23
|
+
background: var(--zer0-diagram-surface);
|
|
24
|
+
border: 1px solid var(--zer0-color-border);
|
|
25
|
+
border-radius: var(--zer0-radius-lg);
|
|
26
|
+
box-shadow: var(--zer0-shadow-xs);
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
transition: border-color var(--zer0-motion-duration-base) var(--zer0-motion-ease-standard),
|
|
29
|
+
box-shadow var(--zer0-motion-duration-base) var(--zer0-motion-ease-standard);
|
|
30
|
+
|
|
31
|
+
&:hover,
|
|
32
|
+
&:focus-within {
|
|
33
|
+
border-color: color-mix(in srgb, var(--zer0-color-primary) 35%, var(--zer0-color-border));
|
|
34
|
+
box-shadow: var(--zer0-shadow-sm);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// --- Toolbar ---------------------------------------------------------------
|
|
38
|
+
// On pointer devices it floats over the top-right corner and is hidden until
|
|
39
|
+
// the figure is hovered or holds focus. On touch devices there is no hover
|
|
40
|
+
// to reveal it, so it becomes a static, right-aligned row ABOVE the diagram
|
|
41
|
+
// — a floating bar that is always visible would cover the top of a phone-
|
|
42
|
+
// width diagram.
|
|
43
|
+
&__toolbar {
|
|
44
|
+
position: absolute;
|
|
45
|
+
top: var(--zer0-space-2);
|
|
46
|
+
right: var(--zer0-space-2);
|
|
47
|
+
z-index: 2;
|
|
48
|
+
display: inline-flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
gap: 0.125rem;
|
|
51
|
+
padding: 0.125rem;
|
|
52
|
+
background: color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
|
|
53
|
+
border: 1px solid var(--zer0-color-border-translucent);
|
|
54
|
+
border-radius: var(--zer0-radius-pill);
|
|
55
|
+
box-shadow: var(--zer0-shadow-sm);
|
|
56
|
+
backdrop-filter: blur(6px);
|
|
57
|
+
-webkit-backdrop-filter: blur(6px);
|
|
58
|
+
opacity: 0;
|
|
59
|
+
transition: opacity var(--zer0-motion-duration-fast) var(--zer0-motion-ease-standard);
|
|
60
|
+
|
|
61
|
+
@media (hover: none) {
|
|
62
|
+
position: static;
|
|
63
|
+
display: flex;
|
|
64
|
+
justify-content: flex-end;
|
|
65
|
+
margin: var(--zer0-space-2) var(--zer0-space-2) 0 auto;
|
|
66
|
+
width: fit-content;
|
|
67
|
+
max-width: calc(100% - 2 * var(--zer0-space-2));
|
|
68
|
+
opacity: 1;
|
|
69
|
+
box-shadow: none;
|
|
70
|
+
backdrop-filter: none;
|
|
71
|
+
-webkit-backdrop-filter: none;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
&:hover &__toolbar,
|
|
76
|
+
&:focus-within &__toolbar,
|
|
77
|
+
&__toolbar:focus-within,
|
|
78
|
+
&__toolbar--static {
|
|
79
|
+
opacity: 1;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&__btn {
|
|
83
|
+
display: inline-flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
width: 2rem;
|
|
87
|
+
height: 2rem;
|
|
88
|
+
padding: 0;
|
|
89
|
+
color: var(--zer0-color-ink-muted);
|
|
90
|
+
background: transparent;
|
|
91
|
+
border: 0;
|
|
92
|
+
border-radius: var(--zer0-radius-circle);
|
|
93
|
+
line-height: 1;
|
|
94
|
+
font-size: 0.95rem;
|
|
95
|
+
cursor: pointer;
|
|
96
|
+
transition: background-color var(--zer0-motion-duration-fast) var(--zer0-motion-ease-standard),
|
|
97
|
+
color var(--zer0-motion-duration-fast) var(--zer0-motion-ease-standard);
|
|
98
|
+
|
|
99
|
+
&:hover:not(:disabled) {
|
|
100
|
+
color: var(--zer0-color-ink);
|
|
101
|
+
background: var(--zer0-color-bg-muted);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
&:focus-visible {
|
|
105
|
+
outline: 2px solid var(--zer0-color-primary);
|
|
106
|
+
outline-offset: 1px;
|
|
107
|
+
color: var(--zer0-color-ink);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
&:disabled {
|
|
111
|
+
opacity: 0.35;
|
|
112
|
+
cursor: not-allowed;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
&.is-success { color: var(--zer0-color-success); }
|
|
116
|
+
&.is-failure { color: var(--zer0-color-danger); }
|
|
117
|
+
|
|
118
|
+
// Comfortable touch targets without changing the desktop density.
|
|
119
|
+
@media (hover: none) and (pointer: coarse) {
|
|
120
|
+
width: 2.25rem;
|
|
121
|
+
height: 2.25rem;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
&__sep {
|
|
126
|
+
width: 1px;
|
|
127
|
+
height: 1.125rem;
|
|
128
|
+
margin: 0 0.125rem;
|
|
129
|
+
background: var(--zer0-color-border);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
&__zoom {
|
|
133
|
+
min-width: 2.5rem;
|
|
134
|
+
padding: 0 0.25rem;
|
|
135
|
+
font-size: 0.75rem;
|
|
136
|
+
font-variant-numeric: tabular-nums;
|
|
137
|
+
text-align: center;
|
|
138
|
+
color: var(--zer0-color-ink-muted);
|
|
139
|
+
|
|
140
|
+
&[hidden] { display: none; }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// --- Viewport / canvas -----------------------------------------------------
|
|
144
|
+
&__viewport {
|
|
145
|
+
position: relative;
|
|
146
|
+
max-height: min(80vh, 60rem);
|
|
147
|
+
padding: var(--zer0-diagram-padding);
|
|
148
|
+
overflow: auto;
|
|
149
|
+
overscroll-behavior: contain;
|
|
150
|
+
scrollbar-width: thin;
|
|
151
|
+
outline: none;
|
|
152
|
+
|
|
153
|
+
&:focus-visible {
|
|
154
|
+
box-shadow: inset 0 0 0 2px var(--zer0-color-primary);
|
|
155
|
+
border-radius: var(--zer0-radius-lg);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
&.is-zoomed { cursor: grab; }
|
|
159
|
+
&.is-panning { cursor: grabbing; user-select: none; }
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
&__canvas {
|
|
163
|
+
display: block;
|
|
164
|
+
width: 100%;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Mermaid emits width="100%" + style="max-width: <natural>px". At 1:1 the
|
|
168
|
+
// SVG fills the viewport up to its natural size and is centred; when zoomed
|
|
169
|
+
// the JS sets an explicit width, the block overflows to the right and the
|
|
170
|
+
// viewport scrolls — a real layout, no transforms, so print/centring hold.
|
|
171
|
+
&__svg,
|
|
172
|
+
&__canvas > svg {
|
|
173
|
+
display: block;
|
|
174
|
+
height: auto;
|
|
175
|
+
margin: 0 auto;
|
|
176
|
+
max-width: 100%;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
&__caption {
|
|
180
|
+
padding: 0 var(--zer0-space-3) var(--zer0-space-3);
|
|
181
|
+
font-size: 0.875rem;
|
|
182
|
+
color: var(--zer0-color-ink-muted);
|
|
183
|
+
text-align: center;
|
|
184
|
+
|
|
185
|
+
&[hidden] { display: none; }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// --- Loading ---------------------------------------------------------------
|
|
189
|
+
&__skeleton {
|
|
190
|
+
min-height: 8rem;
|
|
191
|
+
border-radius: var(--zer0-radius);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// --- Error state -----------------------------------------------------------
|
|
195
|
+
// The diagram could not be parsed: say so, show why, and keep the source on
|
|
196
|
+
// the page — content is never lost to a typo.
|
|
197
|
+
&.has-error {
|
|
198
|
+
border-color: color-mix(in srgb, var(--zer0-color-warning) 55%, var(--zer0-color-border));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
&__error {
|
|
202
|
+
display: grid;
|
|
203
|
+
grid-template-columns: auto 1fr;
|
|
204
|
+
gap: var(--zer0-space-3);
|
|
205
|
+
align-items: flex-start;
|
|
206
|
+
padding: var(--zer0-space-3);
|
|
207
|
+
color: var(--bs-warning-text-emphasis, var(--zer0-color-ink));
|
|
208
|
+
background: var(--bs-warning-bg-subtle, var(--zer0-color-bg-elevated));
|
|
209
|
+
border-left: 0.25rem solid var(--zer0-color-warning);
|
|
210
|
+
border-radius: var(--zer0-radius);
|
|
211
|
+
|
|
212
|
+
> .bi {
|
|
213
|
+
font-size: 1.25rem;
|
|
214
|
+
line-height: 1;
|
|
215
|
+
padding-top: 0.125rem;
|
|
216
|
+
color: var(--zer0-color-warning);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
&__error-body { min-width: 0; }
|
|
221
|
+
|
|
222
|
+
&__error-title {
|
|
223
|
+
margin: 0 0 0.25rem;
|
|
224
|
+
font-weight: var(--zer0-font-weight-semibold, 600);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
&__error-message {
|
|
228
|
+
margin: 0 0 0.5rem;
|
|
229
|
+
padding: 0.5rem 0.75rem;
|
|
230
|
+
font-size: 0.8125rem;
|
|
231
|
+
white-space: pre-wrap;
|
|
232
|
+
word-break: break-word;
|
|
233
|
+
background: color-mix(in srgb, var(--bs-body-bg) 60%, transparent);
|
|
234
|
+
border: 0;
|
|
235
|
+
border-radius: var(--zer0-radius-sm);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
&__error-hint {
|
|
239
|
+
margin: 0;
|
|
240
|
+
font-size: 0.875rem;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
&__source {
|
|
244
|
+
margin-top: var(--zer0-space-3);
|
|
245
|
+
font-size: 0.875rem;
|
|
246
|
+
|
|
247
|
+
> summary {
|
|
248
|
+
cursor: pointer;
|
|
249
|
+
color: var(--zer0-color-ink-muted);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
pre {
|
|
253
|
+
margin: 0.5rem 0 0;
|
|
254
|
+
padding: var(--zer0-space-3);
|
|
255
|
+
max-height: 20rem;
|
|
256
|
+
overflow: auto;
|
|
257
|
+
background: var(--zer0-color-code-bg);
|
|
258
|
+
border: 1px solid var(--zer0-color-border);
|
|
259
|
+
border-radius: var(--zer0-radius);
|
|
260
|
+
font-size: 0.8125rem;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// --- Print -----------------------------------------------------------------
|
|
265
|
+
@media print {
|
|
266
|
+
border: 0;
|
|
267
|
+
box-shadow: none;
|
|
268
|
+
background: transparent;
|
|
269
|
+
break-inside: avoid;
|
|
270
|
+
|
|
271
|
+
.zer0-diagram__toolbar { display: none; }
|
|
272
|
+
.zer0-diagram__viewport { max-height: none; overflow: visible; }
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// --- Fullscreen lightbox -------------------------------------------------------
|
|
277
|
+
// A native <dialog> (top layer, focus trap, Escape) — the figure's canvas is
|
|
278
|
+
// moved in and back out, so it is the same SVG the reader was looking at.
|
|
279
|
+
.zer0-diagram-lightbox {
|
|
280
|
+
width: 100vw;
|
|
281
|
+
height: 100vh;
|
|
282
|
+
height: 100dvh;
|
|
283
|
+
max-width: none;
|
|
284
|
+
max-height: none;
|
|
285
|
+
margin: 0;
|
|
286
|
+
padding: 0;
|
|
287
|
+
border: 0;
|
|
288
|
+
color: var(--bs-body-color);
|
|
289
|
+
background: var(--bs-body-bg);
|
|
290
|
+
|
|
291
|
+
&::backdrop {
|
|
292
|
+
background: rgba(0, 0, 0, 0.6);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
&__inner {
|
|
296
|
+
display: flex;
|
|
297
|
+
flex-direction: column;
|
|
298
|
+
height: 100%;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
&__bar {
|
|
302
|
+
display: flex;
|
|
303
|
+
align-items: center;
|
|
304
|
+
justify-content: space-between;
|
|
305
|
+
gap: var(--zer0-space-3);
|
|
306
|
+
padding: var(--zer0-space-2) var(--zer0-space-3);
|
|
307
|
+
border-bottom: 1px solid var(--zer0-color-border);
|
|
308
|
+
background: var(--zer0-color-bg-elevated);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
&__title {
|
|
312
|
+
margin: 0;
|
|
313
|
+
min-width: 0;
|
|
314
|
+
overflow: hidden;
|
|
315
|
+
text-overflow: ellipsis;
|
|
316
|
+
white-space: nowrap;
|
|
317
|
+
font-weight: var(--zer0-font-weight-semibold, 600);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// The toolbar is static chrome here rather than a floating overlay.
|
|
321
|
+
.zer0-diagram__toolbar--static {
|
|
322
|
+
position: static;
|
|
323
|
+
flex: none;
|
|
324
|
+
box-shadow: none;
|
|
325
|
+
backdrop-filter: none;
|
|
326
|
+
-webkit-backdrop-filter: none;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
&__viewport {
|
|
330
|
+
flex: 1 1 auto;
|
|
331
|
+
max-height: none;
|
|
332
|
+
padding: var(--zer0-space-4);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.zer0-diagram__btn--close {
|
|
336
|
+
margin-left: 0.25rem;
|
|
337
|
+
color: var(--zer0-color-ink);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Lock page scroll while the lightbox is open.
|
|
342
|
+
.zer0-diagram-lightbox-open {
|
|
343
|
+
overflow: hidden;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// --- Progressive enhancement --------------------------------------------------
|
|
347
|
+
// Until the deferred scripts run, a raw ```mermaid fence would paint as a code
|
|
348
|
+
// block and then be swapped for the diagram — a visible flash of source. With
|
|
349
|
+
// JS available, paint it as a placeholder instead. The delayed animation is a
|
|
350
|
+
// safety net: if the scripts never arrive (blocked asset, old browser) the
|
|
351
|
+
// source fades back in, so a broken script can never hide content. Without JS
|
|
352
|
+
// (`html.no-js`) or when mermaid.min.js fails to load
|
|
353
|
+
// (`.zer0-diagram-unavailable`, set by the script) the fence stays a normal,
|
|
354
|
+
// readable code block.
|
|
355
|
+
.js:not(.zer0-diagram-unavailable) pre:has(> code.language-mermaid) {
|
|
356
|
+
min-height: 8rem;
|
|
357
|
+
color: transparent;
|
|
358
|
+
background: linear-gradient(
|
|
359
|
+
90deg,
|
|
360
|
+
var(--zer0-color-bg-elevated) 25%,
|
|
361
|
+
var(--zer0-color-bg-muted) 50%,
|
|
362
|
+
var(--zer0-color-bg-elevated) 75%
|
|
363
|
+
);
|
|
364
|
+
background-size: 200% 100%;
|
|
365
|
+
border-radius: var(--zer0-radius-lg);
|
|
366
|
+
animation:
|
|
367
|
+
zer0-skeleton-shimmer 1.5s ease-in-out infinite,
|
|
368
|
+
zer0-diagram-reveal 0s linear 8s forwards;
|
|
369
|
+
|
|
370
|
+
> code { color: inherit; }
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
@keyframes zer0-diagram-reveal {
|
|
374
|
+
to { color: inherit; animation: none; }
|
|
375
|
+
}
|