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.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +715 -2
  3. data/_data/README.md +2 -0
  4. data/_data/ai.yml +5 -3
  5. data/_data/ai_pricing.yml +36 -0
  6. data/_data/backlog.yml +169 -18
  7. data/_data/consumers.yml +48 -5
  8. data/_data/features.yml +146 -20
  9. data/_data/feedback_types.yml +17 -12
  10. data/_data/landing.yml +5 -2
  11. data/_data/navigation/quickstart.yml +4 -0
  12. data/_data/site_builder.yml +874 -0
  13. data/_data/theme-manifest.yml +122 -114
  14. data/_data/ui-text.yml +18 -0
  15. data/_includes/README.md +11 -1
  16. data/_includes/analytics/posthog.html +2 -2
  17. data/_includes/components/admin-links.html +2 -2
  18. data/_includes/components/admin-tabs.html +2 -2
  19. data/_includes/components/ai-chat.html +14 -11
  20. data/_includes/components/analytics-dashboard.html +8 -8
  21. data/_includes/components/author-bio.html +1 -1
  22. data/_includes/components/author-card.html +10 -2
  23. data/_includes/components/author-eeat.html +4 -4
  24. data/_includes/components/background-customizer.html +8 -8
  25. data/_includes/components/background-image.html +114 -0
  26. data/_includes/components/background-settings.html +28 -15
  27. data/_includes/components/collection-manager.html +5 -5
  28. data/_includes/components/component-showcase.html +13 -13
  29. data/_includes/components/config-editor.html +12 -12
  30. data/_includes/components/config-viewer.html +8 -8
  31. data/_includes/components/cookie-consent.html +11 -11
  32. data/_includes/components/cta-button.html +7 -2
  33. data/_includes/components/dev-shortcuts.html +7 -7
  34. data/_includes/components/env-dashboard.html +8 -8
  35. data/_includes/components/env-switcher.html +9 -9
  36. data/_includes/components/feature-card.html +2 -2
  37. data/_includes/components/halfmoon.html +2 -2
  38. data/_includes/components/info-section.html +36 -36
  39. data/_includes/components/js-cdn.html +15 -15
  40. data/_includes/components/language-toggle.html +4 -4
  41. data/_includes/components/mermaid.html +72 -435
  42. data/_includes/components/nanobar.html +5 -5
  43. data/_includes/components/nav-editor.html +2 -2
  44. data/_includes/components/nav-export.html +2 -2
  45. data/_includes/components/nav-overview.html +2 -2
  46. data/_includes/components/page-feedback.html +45 -30
  47. data/_includes/components/page-views-init.html +1 -1
  48. data/_includes/components/post-card.html +22 -22
  49. data/_includes/components/post-type-badge.html +2 -2
  50. data/_includes/components/powered-by.html +2 -2
  51. data/_includes/components/preview-image.html +6 -0
  52. data/_includes/components/quick-index.html +2 -2
  53. data/_includes/components/search-modal.html +27 -2
  54. data/_includes/components/searchbar.html +2 -2
  55. data/_includes/components/svg-background.html +2 -2
  56. data/_includes/components/theme-customizer.html +2 -2
  57. data/_includes/components/theme-info.html +6 -6
  58. data/_includes/components/theme-preview-gallery.html +22 -22
  59. data/_includes/content/giscus.html +2 -2
  60. data/_includes/content/intro.html +8 -8
  61. data/_includes/content/jsonld-faq.html +2 -2
  62. data/_includes/content/jsonld-software.html +2 -2
  63. data/_includes/content/seo.html +4 -4
  64. data/_includes/content/sitemap.html +27 -27
  65. data/_includes/content/toc.html +183 -183
  66. data/_includes/core/branding.html +6 -6
  67. data/_includes/core/console-capture.html +32 -74
  68. data/_includes/core/favicon.html +49 -7
  69. data/_includes/core/footer-fabs.html +17 -3
  70. data/_includes/core/footer.html +31 -18
  71. data/_includes/core/head.html +102 -90
  72. data/_includes/core/header.html +71 -52
  73. data/_includes/docs/bootstrap-docs.html +8 -8
  74. data/_includes/landing/landing-install-cards.html +2 -2
  75. data/_includes/landing/landing-quick-links.html +1 -1
  76. data/_includes/navigation/admin-nav.html +2 -2
  77. data/_includes/navigation/nav-tree.html +8 -8
  78. data/_includes/navigation/navbar.html +12 -12
  79. data/_includes/navigation/section-sidebar.html +16 -16
  80. data/_includes/navigation/sidebar-config.html +36 -2
  81. data/_includes/navigation/sidebar-left.html +15 -15
  82. data/_includes/navigation/sidebar-right.html +6 -6
  83. data/_includes/obsidian/full-graph.html +2 -2
  84. data/_includes/setup/claude-session.html +72 -0
  85. data/_includes/setup/prereq-checklist.html +90 -0
  86. data/_includes/setup/wizard.html +906 -291
  87. data/_includes/stats/stats-categories.html +8 -8
  88. data/_includes/stats/stats-header.html +14 -14
  89. data/_includes/stats/stats-metrics.html +12 -12
  90. data/_includes/stats/stats-no-data.html +12 -12
  91. data/_includes/stats/stats-overview.html +6 -6
  92. data/_includes/stats/stats-tags.html +8 -8
  93. data/_layouts/404.html +38 -24
  94. data/_layouts/admin.html +22 -22
  95. data/_layouts/article.html +39 -34
  96. data/_layouts/author.html +20 -20
  97. data/_layouts/authors.html +2 -2
  98. data/_layouts/book-abc.html +12 -12
  99. data/_layouts/book-story.html +15 -15
  100. data/_layouts/book.html +12 -12
  101. data/_layouts/collection.html +33 -33
  102. data/_layouts/cookbook.html +12 -12
  103. data/_layouts/default.html +27 -24
  104. data/_layouts/home.html +23 -23
  105. data/_layouts/index.html +10 -10
  106. data/_layouts/landing.html +17 -17
  107. data/_layouts/news.html +44 -44
  108. data/_layouts/note.html +38 -38
  109. data/_layouts/notebook.html +34 -34
  110. data/_layouts/recipe.html +24 -24
  111. data/_layouts/root.html +73 -55
  112. data/_layouts/section.html +23 -23
  113. data/_layouts/setup.html +3 -3
  114. data/_layouts/sitemap-collection.html +49 -49
  115. data/_layouts/stats.html +40 -40
  116. data/_layouts/tag.html +12 -12
  117. data/_layouts/welcome.html +21 -21
  118. data/_sass/components/_mermaid.scss +375 -0
  119. data/_sass/components/_setup-wizard.scss +569 -40
  120. data/_sass/core/_navbar.scss +11 -31
  121. data/_sass/layouts/_navbar-extras.scss +14 -4
  122. data/assets/css/main.scss +1 -0
  123. data/assets/js/ai-chat.js +47 -5
  124. data/assets/js/fleet-feedback-capture.js +124 -0
  125. data/assets/js/fleet-feedback.js +853 -0
  126. data/assets/js/mermaid-diagrams.js +1267 -0
  127. data/assets/js/modules/navigation/config.js +9 -6
  128. data/assets/js/modules/navigation/scroll-spy.js +315 -80
  129. data/assets/js/modules/theme/appearance.js +8 -2
  130. data/assets/js/obsidian-wiki-links.js +8 -3
  131. data/assets/js/page-feedback.js +125 -192
  132. data/assets/js/search-modal.js +26 -0
  133. data/assets/js/setup-wizard.js +2112 -361
  134. data/assets/js/site-builder.js +1834 -0
  135. data/assets/js/ui-enhancements.js +11 -3
  136. data/scripts/README.md +15 -0
  137. data/scripts/ai/README.md +38 -0
  138. data/scripts/ai/api_call.rb +124 -0
  139. data/scripts/ai/usage.rb +314 -0
  140. data/scripts/ai/usage_report.rb +225 -0
  141. data/scripts/ci/test_visual_evidence_autogen.py +341 -0
  142. data/scripts/ci/visual_evidence_autogen.py +1060 -0
  143. data/scripts/content-review.rb +20 -1
  144. data/scripts/test/integration/mermaid +22 -8
  145. data/scripts/test/lib/run_tests.sh +1 -0
  146. data/scripts/test/lib/test_visual_evidence_autogen.sh +24 -0
  147. data/scripts/translate.rb +23 -1
  148. metadata +19 -2
@@ -1,4 +1,4 @@
1
- <!--
1
+ {% comment %}
2
2
  ===================================================================
3
3
  ANALYTICS DASHBOARD — PostHog & tracking configuration overview
4
4
  ===================================================================
@@ -11,11 +11,11 @@
11
11
  Dependencies: Bootstrap 5 card/table/badge, site.posthog config
12
12
  Used by: pages/_about/settings/analytics.md
13
13
  ===================================================================
14
- -->
14
+ {% endcomment %}
15
15
 
16
16
  {% assign ph = site.posthog %}
17
17
 
18
- <!-- Status cards -->
18
+ {% comment %} Status cards {% endcomment %}
19
19
  <div class="row g-3 mb-4">
20
20
  <div class="col-6 col-lg-3">
21
21
  <div class="card text-center h-100 {% if ph.enabled %}border-success{% else %}border-warning{% endif %}">
@@ -55,10 +55,10 @@
55
55
  </div>
56
56
  </div>
57
57
 
58
- <!-- Configuration Details -->
58
+ {% comment %} Configuration Details {% endcomment %}
59
59
  <div class="row g-4">
60
60
 
61
- <!-- PostHog Settings -->
61
+ {% comment %} PostHog Settings {% endcomment %}
62
62
  <div class="col-lg-6">
63
63
  <div class="card h-100">
64
64
  <div class="card-header"><i class="bi bi-gear me-1"></i> PostHog Configuration</div>
@@ -105,7 +105,7 @@
105
105
  </div>
106
106
  </div>
107
107
 
108
- <!-- Privacy & Compliance -->
108
+ {% comment %} Privacy & Compliance {% endcomment %}
109
109
  <div class="col-lg-6">
110
110
  <div class="card h-100">
111
111
  <div class="card-header"><i class="bi bi-shield-lock me-1"></i> Privacy & Compliance</div>
@@ -162,7 +162,7 @@
162
162
  </div>
163
163
  </div>
164
164
 
165
- <!-- Custom Events -->
165
+ {% comment %} Custom Events {% endcomment %}
166
166
  {% if ph.custom_events %}
167
167
  <h5 class="mt-4 mb-3"><i class="bi bi-lightning me-1"></i> Custom Event Tracking</h5>
168
168
  <div class="row g-3">
@@ -221,7 +221,7 @@
221
221
  </div>
222
222
  {% endif %}
223
223
 
224
- <!-- External Links -->
224
+ {% comment %} External Links {% endcomment %}
225
225
  <div class="mt-4">
226
226
  <a href="https://us.posthog.com" target="_blank" rel="noopener" class="btn btn-outline-primary btn-sm me-2">
227
227
  <i class="bi bi-box-arrow-up-right me-1"></i> Open PostHog Dashboard
@@ -73,7 +73,7 @@
73
73
  <i class="bi bi-person-badge me-2" aria-hidden="true"></i>{{ bio_heading }}
74
74
  </h2>
75
75
 
76
- {% include components/author-card.html author=include.author style="full" %}
76
+ {% include components/author-card.html author=include.author style="full" heading_level=3 %}
77
77
 
78
78
  {% if show_profile_link and bio_profile_url %}
79
79
  <div class="mt-3">
@@ -192,10 +192,18 @@
192
192
  {% endif %}
193
193
  {% endif %}
194
194
  <div class="flex-grow-1">
195
- <h5 class="card-title mb-1" itemprop="name">
195
+ {%- comment -%}
196
+ Level is a PARAMETER, size is not. This card renders under an <h2> in
197
+ author-bio.html and under different ancestors elsewhere, so a
198
+ hardcoded level cannot be correct everywhere -- picking <h5> for its
199
+ font-size is what produced the h2 -> h5 skip in issue #436. The
200
+ default keeps the historic level for any caller that does not say.
201
+ {%- endcomment -%}
202
+ {%- assign _ac_level = include.heading_level | default: 5 -%}
203
+ <h{{ _ac_level }} class="h5 card-title mb-1" itemprop="name">
196
204
  {%- if profile_url -%}<a href="{{ profile_url }}" class="text-decoration-none text-reset" itemprop="url">{{ author_name }}</a>{%- else -%}{{ author_name }}{%- endif -%}
197
205
  {%- if author_data.ai -%} <span class="badge author-ai-badge align-middle" title="AI author persona"><i class="bi bi-robot me-1" aria-hidden="true"></i>AI</span>{%- endif -%}
198
- </h5>
206
+ </h{{ _ac_level }}>
199
207
  {% if author_data.role %}<p class="text-primary mb-2" itemprop="jobTitle">{{ author_data.role }}</p>{% endif %}
200
208
  {% if author_data.tagline %}<p class="author-tagline fst-italic text-body-secondary mb-2">{{ author_data.tagline }}</p>{% endif %}
201
209
  {% if show_bio and author_data.bio %}<p class="card-text text-muted" itemprop="description">{{ author_data.bio }}</p>{% endif %}
@@ -1,5 +1,5 @@
1
1
  {% comment %} Feature: ZER0-054 {% endcomment %}
2
- <!--
2
+ {% comment %}
3
3
  ===================================================================
4
4
  AUTHOR E-E-A-T BLOCK - Experience, Expertise, Authority, Trust
5
5
  ===================================================================
@@ -21,7 +21,7 @@
21
21
  - _data/authors.yml: Author data
22
22
  - Bootstrap 5 utility classes
23
23
  ===================================================================
24
- -->
24
+ {% endcomment %}
25
25
 
26
26
  {% assign author_key = include.author_key | default: "bamr87" %}
27
27
  {% assign author = site.data.authors[author_key] %}
@@ -36,7 +36,7 @@
36
36
  {% if author %}
37
37
 
38
38
  {% if eeat_style == "banner" %}
39
- <!-- E-E-A-T Author Banner -->
39
+ {% comment %} E-E-A-T Author Banner {% endcomment %}
40
40
  <div class="bg-body-secondary border-top border-bottom py-4 mt-5" itemscope itemtype="https://schema.org/Person">
41
41
  <div class="container-xl px-4 px-md-5">
42
42
  <div class="row align-items-center g-3">
@@ -91,7 +91,7 @@
91
91
  </div>
92
92
 
93
93
  {% elsif eeat_style == "card" %}
94
- <!-- E-E-A-T Author Card -->
94
+ {% comment %} E-E-A-T Author Card {% endcomment %}
95
95
  <div class="card border-0 shadow-sm" itemscope itemtype="https://schema.org/Person">
96
96
  <div class="card-body p-4">
97
97
  <div class="d-flex align-items-start">
@@ -1,5 +1,5 @@
1
1
  {% comment %} Feature: ZER0-065 {% endcomment %}
2
- <!--
2
+ {% comment %}
3
3
  ===================================================================
4
4
  BACKGROUND CUSTOMIZER — fffuel-style background settings panel
5
5
  ===================================================================
@@ -14,12 +14,12 @@
14
14
  - _sass/theme/_backgrounds.scss (CSS custom properties)
15
15
  - Bootstrap 5 offcanvas + form components
16
16
  ===================================================================
17
- -->
17
+ {% endcomment %}
18
18
 
19
19
  {% assign skins = "air,aqua,contrast,dark,dirt,neon,mint,plum,sunrise" | split: "," %}
20
20
  {% assign current_skin = site.theme_skin | default: "dark" %}
21
21
 
22
- <!-- Floating toggle button -->
22
+ {% comment %} Floating toggle button {% endcomment %}
23
23
  <button class="btn btn-sm btn-outline-secondary position-fixed bottom-0 end-0 m-3 rounded-circle"
24
24
  style="z-index: 1090; width: 40px; height: 40px;"
25
25
  type="button"
@@ -30,7 +30,7 @@
30
30
  <i class="bi bi-palette2"></i>
31
31
  </button>
32
32
 
33
- <!-- Offcanvas panel -->
33
+ {% comment %} Offcanvas panel {% endcomment %}
34
34
  <div class="offcanvas offcanvas-end" tabindex="-1" id="zer0BgCustomizer" aria-labelledby="zer0BgCustomizerLabel">
35
35
  <div class="offcanvas-header">
36
36
  <h2 class="offcanvas-title h5" id="zer0BgCustomizerLabel">
@@ -40,7 +40,7 @@
40
40
  </div>
41
41
 
42
42
  <div class="offcanvas-body">
43
- <!-- Skin selector -->
43
+ {% comment %} Skin selector {% endcomment %}
44
44
  <div class="mb-4">
45
45
  <label class="form-label fw-semibold">Theme Skin</label>
46
46
  <div class="d-flex flex-wrap gap-2" id="zer0SkinButtons">
@@ -56,7 +56,7 @@
56
56
 
57
57
  <hr>
58
58
 
59
- <!-- Background toggle -->
59
+ {% comment %} Background toggle {% endcomment %}
60
60
  <div class="mb-3">
61
61
  <div class="form-check form-switch">
62
62
  <input class="form-check-input" type="checkbox" id="zer0BgToggle" checked>
@@ -66,7 +66,7 @@
66
66
 
67
67
  <hr>
68
68
 
69
- <!-- Opacity sliders -->
69
+ {% comment %} Opacity sliders {% endcomment %}
70
70
  <div class="mb-3">
71
71
  <label class="form-label" for="zer0GradientOpacity">Gradient opacity</label>
72
72
  <input type="range" class="form-range" id="zer0GradientOpacity"
@@ -96,7 +96,7 @@
96
96
  </div>
97
97
  </div>
98
98
 
99
- <!-- Customizer interaction logic -->
99
+ {% comment %} Customizer interaction logic {% endcomment %}
100
100
  <script>
101
101
  document.addEventListener("DOMContentLoaded", function () {
102
102
  if (typeof zer0Bg === "undefined") return;
@@ -0,0 +1,114 @@
1
+ {% comment %} Feature: ZER0-004 {% endcomment %}
2
+ {% comment %}
3
+ BACKGROUND IMAGE - Cover art painted as a CSS background, announced correctly
4
+
5
+ Sibling to components/preview-image.html. Reach for THIS one when the art is
6
+ painted as a CSS background on an otherwise empty box; reach for
7
+ preview-image.html when the art is an <img> in the content flow.
8
+
9
+ WHY THIS EXISTS. A CSS background is invisible to assistive technology. A box
10
+ painted with cover art and nothing else announces nothing at all, so the
11
+ reader is told there is an element and never told what it shows. The fix is
12
+ role="img" plus an aria-label, which makes the box a single graphic with a
13
+ name. The theme already did this by hand in three places
14
+ (components/abc-letter.html, layouts/article.html rating stars,
15
+ components/theme-customizer.html) without it being a named convention.
16
+
17
+ TWO BRANCHES, and the second is not optional:
18
+
19
+ real image -> role="img" aria-label="..." (a graphic with a name)
20
+ decorative -> aria-hidden="true", and NO role and NO aria-label
21
+
22
+ Combining aria-hidden with role="img" is worse than either alone: it
23
+ announces a graphic and then hides it. A gradient placeholder carries no
24
+ information the surrounding text does not already carry, so it is hidden.
25
+
26
+ Usage:
27
+ {%- include components/background-image.html
28
+ src=post.preview
29
+ alt=post.title
30
+ class="card-cover"
31
+ style="height: 180px;"
32
+ -%}
33
+
34
+ {%- comment -%} decorative fallback: omit alt, or pass decorative=true {%- endcomment -%}
35
+ {%- include components/background-image.html class="card-cover card-cover-empty" -%}
36
+
37
+ Params:
38
+ src - image path (optional; omit for the decorative branch)
39
+ alt - accessible name; REQUIRED for the real-image branch
40
+ class - CSS classes on the box (default: "bg-cover")
41
+ style - extra inline style, appended after the background shorthand
42
+ decorative - force the decorative branch even when src is present
43
+ tag - element name (default: div)
44
+
45
+ Path convention is preview-image.html's, duplicated rather than extracted:
46
+ it is ~14 lines of Liquid, and a third shared include to save them buys less
47
+ than it costs in indirection. preview-image.html remains the source of the
48
+ convention -- change it there first.
49
+ - /images/previews/x.png -> /assets/images/previews/x.png
50
+ - /assets/images/previews/x.png -> unchanged
51
+ - https://example.com/x.png -> unchanged (external URL)
52
+
53
+ DO NOT apply this to a box that wraps text. role="img" makes the element a
54
+ single graphic and its descendants stop being exposed -- so putting it on
55
+ _includes/content/intro.html, which paints a background AND wraps the page
56
+ <h1>, would delete the heading from the accessibility tree.
57
+ {% endcomment %}
58
+ {%- assign bgi_src = include.src -%}
59
+ {%- assign bgi_alt = include.alt -%}
60
+ {%- assign bgi_class = include.class | default: "bg-cover" -%}
61
+ {%- assign bgi_style = include.style -%}
62
+ {%- assign bgi_tag = include.tag | default: "div" -%}
63
+
64
+ {%- comment -%} Decorative is the DEFAULT, and the real-image branch has to earn
65
+ it: an image AND a name AND no explicit decorative flag. Written as a
66
+ positive test on purpose -- the failure mode of getting this backwards is
67
+ role="img" aria-label="", an unnamed graphic, which is worse for a screen
68
+ reader than either branch done right. Falling back to aria-hidden is safe.
69
+
70
+ NOTE: `x == blank` does NOT match nil in Liquid 4 -- blank matches empty
71
+ strings and collections only. An earlier version of this file tested
72
+ `bgi_src == blank` and every decorative call rendered as an unnamed
73
+ graphic. Test truthiness AND emptiness, both. {%- endcomment -%}
74
+ {%- assign bgi_decorative = true -%}
75
+ {%- if include.decorative != true -%}
76
+ {%- if bgi_src and bgi_src != "" -%}
77
+ {%- if bgi_alt and bgi_alt != "" -%}
78
+ {%- assign bgi_decorative = false -%}
79
+ {%- endif -%}
80
+ {%- endif -%}
81
+ {%- endif -%}
82
+
83
+ {%- comment -%} Path resolution -- see preview-image.html {%- endcomment -%}
84
+ {%- assign bgi_assets_prefix = site.preview_images.assets_prefix | default: '/assets' -%}
85
+ {%- assign bgi_auto_prefix = site.preview_images.auto_prefix | default: true -%}
86
+ {%- if bgi_src == nil or bgi_src == "" -%}
87
+ {%- assign bgi_final_src = nil -%}
88
+ {%- elsif bgi_src contains '://' -%}
89
+ {%- assign bgi_final_src = bgi_src -%}
90
+ {%- elsif bgi_auto_prefix and bgi_src != blank -%}
91
+ {%- if bgi_src contains bgi_assets_prefix -%}
92
+ {%- assign bgi_final_src = bgi_src | relative_url -%}
93
+ {%- else -%}
94
+ {%- assign bgi_final_src = bgi_assets_prefix | append: bgi_src | relative_url -%}
95
+ {%- endif -%}
96
+ {%- elsif bgi_src != blank -%}
97
+ {%- assign bgi_final_src = bgi_src | relative_url -%}
98
+ {%- endif -%}
99
+
100
+ {%- comment -%} One capture for the whole attribute value, so "is there a style
101
+ at all" is a single test. `!= blank` would not do here: a capture that
102
+ produced nothing is an empty string, and "" == blank is true, but the
103
+ surrounding whitespace control makes that fragile to edit. Compare to ""
104
+ explicitly. {%- endcomment -%}
105
+ {%- capture bgi_background -%}
106
+ {%- if bgi_final_src %}background-image: url('{{ bgi_final_src }}'); background-size: cover; background-position: center;{% endif %}{{ bgi_style }}
107
+ {%- endcapture -%}
108
+ {%- assign bgi_background = bgi_background | strip -%}
109
+
110
+ {%- if bgi_decorative -%}
111
+ <{{ bgi_tag }} class="{{ bgi_class }}" aria-hidden="true"{% if bgi_background != "" %} style="{{ bgi_background }}"{% endif %}></{{ bgi_tag }}>
112
+ {%- else -%}
113
+ <{{ bgi_tag }} class="{{ bgi_class }}" role="img" aria-label="{{ bgi_alt | escape }}"{% if bgi_background != "" %} style="{{ bgi_background }}"{% endif %}></{{ bgi_tag }}>
114
+ {%- endif -%}
@@ -1,5 +1,5 @@
1
1
  {% comment %} Feature: ZER0-077 {% endcomment %}
2
- <!--
2
+ {% comment %}
3
3
  ===================================================================
4
4
  BACKGROUND SETTINGS — fffuel-style background controls (tab content)
5
5
  ===================================================================
@@ -17,32 +17,33 @@
17
17
  Section headings match the h6 pattern used by the parent
18
18
  info-section.html so the Appearance tab reads as one surface.
19
19
  ===================================================================
20
- -->
20
+ {% endcomment %}
21
21
 
22
22
  {% assign skins = "air,aqua,contrast,dark,dirt,neon,mint,plum,sunrise" | split: "," %}
23
23
  {% assign current_skin = site.theme_skin | default: "dark" %}
24
24
 
25
- <!-- Skin selector -->
25
+ {% comment %} Skin selector {% endcomment %}
26
26
  <div class="mb-4">
27
- <h6 class="text-body-secondary small text-uppercase fw-semibold mb-2">
27
+ <h3 class="h6 text-body-secondary small text-uppercase fw-semibold mb-2">
28
28
  <i class="bi bi-palette2 me-1" aria-hidden="true"></i>Theme Skin
29
- </h6>
29
+ </h3>
30
30
  <div class="d-flex flex-wrap gap-2" id="zer0SkinButtons" role="group" aria-label="Theme skin">
31
31
  {% for skin in skins %}
32
32
  <button class="btn btn-sm btn-outline-primary{% if skin == current_skin %} active{% endif %}"
33
33
  data-skin="{{ skin }}"
34
- type="button">
34
+ type="button"
35
+ aria-pressed="{% if skin == current_skin %}true{% else %}false{% endif %}">
35
36
  {{ skin | capitalize }}
36
37
  </button>
37
38
  {% endfor %}
38
39
  </div>
39
40
  </div>
40
41
 
41
- <!-- SVG background toggle + layer opacity -->
42
+ {% comment %} SVG background toggle + layer opacity {% endcomment %}
42
43
  <div class="mb-4">
43
- <h6 class="text-body-secondary small text-uppercase fw-semibold mb-2">
44
+ <h3 class="h6 text-body-secondary small text-uppercase fw-semibold mb-2">
44
45
  <i class="bi bi-image me-1" aria-hidden="true"></i>Background
45
- </h6>
46
+ </h3>
46
47
 
47
48
  <div class="d-flex align-items-center justify-content-between p-3 bg-body-tertiary rounded mb-3">
48
49
  <label class="form-check-label" for="zer0BgToggle">SVG backgrounds</label>
@@ -83,18 +84,32 @@
83
84
  </button>
84
85
  </div>
85
86
 
86
- <!-- Customizer interaction logic -->
87
+ {% comment %} Customizer interaction logic {% endcomment %}
87
88
  <script>
88
89
  document.addEventListener("DOMContentLoaded", function () {
89
90
  if (typeof zer0Bg === "undefined") return;
90
91
 
91
92
  // Skin buttons
93
+ // `.active` is a Bootstrap visual class and carries no accessibility
94
+ // semantics, so selection is also exposed via aria-pressed (WCAG 4.1.2),
95
+ // matching the sibling color-mode group. Both are set in one place so no
96
+ // code path can leave them disagreeing.
97
+ function markActiveSkinButton(btn) {
98
+ document.querySelectorAll("#zer0SkinButtons .btn").forEach(function (b) {
99
+ b.classList.remove("active");
100
+ b.setAttribute("aria-pressed", "false");
101
+ });
102
+ if (btn) {
103
+ btn.classList.add("active");
104
+ btn.setAttribute("aria-pressed", "true");
105
+ }
106
+ }
107
+
92
108
  document.querySelectorAll("#zer0SkinButtons [data-skin]").forEach(function (btn) {
93
109
  btn.addEventListener("click", function () {
94
110
  var skin = this.getAttribute("data-skin");
95
111
  zer0Bg.setSkin(skin);
96
- document.querySelectorAll("#zer0SkinButtons .btn").forEach(function (b) { b.classList.remove("active"); });
97
- this.classList.add("active");
112
+ markActiveSkinButton(this);
98
113
  });
99
114
  });
100
115
 
@@ -128,9 +143,7 @@ document.addEventListener("DOMContentLoaded", function () {
128
143
  document.getElementById(id + "Val").textContent = defaults[id];
129
144
  });
130
145
  toggle.checked = true;
131
- document.querySelectorAll("#zer0SkinButtons .btn").forEach(function (b) { b.classList.remove("active"); });
132
- var active = document.querySelector('#zer0SkinButtons [data-skin="{{ current_skin }}"]');
133
- if (active) active.classList.add("active");
146
+ markActiveSkinButton(document.querySelector('#zer0SkinButtons [data-skin="{{ current_skin }}"]'));
134
147
  });
135
148
  });
136
149
  </script>
@@ -1,4 +1,4 @@
1
- <!--
1
+ {% comment %}
2
2
  ===================================================================
3
3
  COLLECTION MANAGER — Jekyll collections overview
4
4
  ===================================================================
@@ -11,9 +11,9 @@
11
11
  Dependencies: Bootstrap 5 table/card/badge, site.collections
12
12
  Used by: pages/_about/settings/collections.md
13
13
  ===================================================================
14
- -->
14
+ {% endcomment %}
15
15
 
16
- <!-- Summary cards -->
16
+ {% comment %} Summary cards {% endcomment %}
17
17
  <div class="row g-3 mb-4">
18
18
  <div class="col-6 col-lg-3">
19
19
  <div class="card text-center h-100 border-primary">
@@ -61,7 +61,7 @@
61
61
  </div>
62
62
  </div>
63
63
 
64
- <!-- Collections table -->
64
+ {% comment %} Collections table {% endcomment %}
65
65
  <div class="table-responsive">
66
66
  <table class="table table-hover align-middle">
67
67
  <thead class="table-dark">
@@ -104,7 +104,7 @@
104
104
  </table>
105
105
  </div>
106
106
 
107
- <!-- Collection defaults from _config.yml -->
107
+ {% comment %} Collection defaults from _config.yml {% endcomment %}
108
108
  <h5 class="mt-4 mb-3"><i class="bi bi-sliders me-1"></i> Collection Defaults</h5>
109
109
  <div class="accordion" id="collDefaultsAccordion">
110
110
  {% for collection in site.collections %}
@@ -1,5 +1,5 @@
1
1
  {% comment %} Feature: ZER0-071 {% endcomment %}
2
- <!--
2
+ {% comment %}
3
3
  ===================================================================
4
4
  COMPONENT SHOWCASE - Live Bootstrap 5 demo gallery
5
5
  ===================================================================
@@ -33,12 +33,12 @@
33
33
  showcase safe for remote-theme consumers who may lack /docs/, /posts/,
34
34
  /categories/, /tags/, or /docs/customization/.
35
35
  ===================================================================
36
- -->
36
+ {% endcomment %}
37
37
  {% assign sections = include.sections | default: "alerts,buttons,badges,cards,accordion,tabs,progress,breadcrumbs,table,tooltips,list-group" %}
38
38
  {% assign section_list = sections | split: "," %}
39
39
 
40
40
  {% if section_list contains "alerts" %}
41
- <!-- ===== ALERTS ===== -->
41
+ {% comment %} ===== ALERTS ===== {% endcomment %}
42
42
  <h3 id="showcase-alerts">Alerts</h3>
43
43
  <p>Contextual feedback messages for user actions and system status:</p>
44
44
  <div class="row g-3 mb-4">
@@ -70,7 +70,7 @@
70
70
  {% endif %}
71
71
 
72
72
  {% if section_list contains "buttons" %}
73
- <!-- ===== BUTTONS ===== -->
73
+ {% comment %} ===== BUTTONS ===== {% endcomment %}
74
74
  <h3 id="showcase-buttons">Buttons</h3>
75
75
  <p>A complete button system with contextual colors, outlines, and sizes:</p>
76
76
  <div class="mb-4">
@@ -102,7 +102,7 @@
102
102
  {% endif %}
103
103
 
104
104
  {% if section_list contains "badges" %}
105
- <!-- ===== BADGES ===== -->
105
+ {% comment %} ===== BADGES ===== {% endcomment %}
106
106
  <h3 id="showcase-badges">Badges</h3>
107
107
  <p>Contextual labels, status indicators, and notification counters:</p>
108
108
  <div class="mb-4">
@@ -132,7 +132,7 @@
132
132
  {% endif %}
133
133
 
134
134
  {% if section_list contains "cards" %}
135
- <!-- ===== CARDS ===== -->
135
+ {% comment %} ===== CARDS ===== {% endcomment %}
136
136
  <h3 id="showcase-cards">Cards</h3>
137
137
  <p>Responsive card layouts — the building block of post listings, feature displays, and documentation:</p>
138
138
  <div class="row row-cols-1 row-cols-md-3 g-4 mb-4">
@@ -191,7 +191,7 @@
191
191
  {% endif %}
192
192
 
193
193
  {% if section_list contains "accordion" %}
194
- <!-- ===== ACCORDION ===== -->
194
+ {% comment %} ===== ACCORDION ===== {% endcomment %}
195
195
  <h3 id="showcase-accordion">Accordion</h3>
196
196
  <p>Collapsible content sections — ideal for FAQs and detailed documentation:</p>
197
197
  <div class="accordion mb-4" id="showcaseAccordion">
@@ -235,7 +235,7 @@
235
235
  {% endif %}
236
236
 
237
237
  {% if section_list contains "tabs" %}
238
- <!-- ===== TABS ===== -->
238
+ {% comment %} ===== TABS ===== {% endcomment %}
239
239
  <h3 id="showcase-tabs">Tabs</h3>
240
240
  <p>Tabbed content panels for organizing related information:</p>
241
241
  <ul class="nav nav-tabs mb-0" id="showcaseTabs" role="tablist">
@@ -281,7 +281,7 @@ theme: jekyll-theme-zer0</code></pre>
281
281
  {% endif %}
282
282
 
283
283
  {% if section_list contains "progress" %}
284
- <!-- ===== PROGRESS BARS ===== -->
284
+ {% comment %} ===== PROGRESS BARS ===== {% endcomment %}
285
285
  <h3 id="showcase-progress">Progress Bars</h3>
286
286
  <p>Visual indicators for build status, completion tracking, and loading states:</p>
287
287
  <div class="mb-4">
@@ -325,7 +325,7 @@ theme: jekyll-theme-zer0</code></pre>
325
325
  {% endif %}
326
326
 
327
327
  {% if section_list contains "breadcrumbs" %}
328
- <!-- ===== BREADCRUMBS ===== -->
328
+ {% comment %} ===== BREADCRUMBS ===== {% endcomment %}
329
329
  <h3 id="showcase-breadcrumbs">Breadcrumbs</h3>
330
330
  <p>Hierarchical navigation trail showing current page position:</p>
331
331
  {% comment %} Existence-guard the demo breadcrumb links so they never 404 on
@@ -357,7 +357,7 @@ theme: jekyll-theme-zer0</code></pre>
357
357
  {% endif %}
358
358
 
359
359
  {% if section_list contains "table" %}
360
- <!-- ===== TABLE ===== -->
360
+ {% comment %} ===== TABLE ===== {% endcomment %}
361
361
  <h3 id="showcase-table">Responsive Table</h3>
362
362
  <p>Styled tables with Bootstrap — all Markdown tables automatically receive Bootstrap styling:</p>
363
363
  <div class="table-responsive mb-4">
@@ -407,7 +407,7 @@ theme: jekyll-theme-zer0</code></pre>
407
407
  {% endif %}
408
408
 
409
409
  {% if section_list contains "tooltips" %}
410
- <!-- ===== TOOLTIPS ===== -->
410
+ {% comment %} ===== TOOLTIPS ===== {% endcomment %}
411
411
  <h3 id="showcase-tooltips">Tooltips</h3>
412
412
  <p>Interactive hints and contextual information on hover:</p>
413
413
  <div class="d-flex flex-wrap gap-3 mb-4">
@@ -436,7 +436,7 @@ document.addEventListener('DOMContentLoaded', () => {
436
436
  {% endif %}
437
437
 
438
438
  {% if section_list contains "list-group" %}
439
- <!-- ===== LIST GROUP ===== -->
439
+ {% comment %} ===== LIST GROUP ===== {% endcomment %}
440
440
  <h3 id="showcase-list-group">List Group</h3>
441
441
  <p>Organized content lists with icons, badges, and action states:</p>
442
442
  {% comment %} Existence-guard the demo list-group links (issue #219). Each target
@@ -1,4 +1,4 @@
1
- <!--
1
+ {% comment %}
2
2
  ===================================================================
3
3
  CONFIG EDITOR — Form-based configuration builder
4
4
  ===================================================================
@@ -11,15 +11,15 @@
11
11
  Dependencies: Bootstrap 5.3, assets/js/config-utility.js
12
12
  Data source: site.* variables pre-populate fields
13
13
  ===================================================================
14
- -->
14
+ {% endcomment %}
15
15
 
16
16
  <div id="configEditor">
17
17
  <div class="row">
18
18
 
19
- <!-- ── Left: Form ────────────────────────────────────────────────── -->
19
+ {% comment %} ── Left: Form ────────────────────────────────────────────────── {% endcomment %}
20
20
  <div class="col-lg-6 mb-4 mb-lg-0">
21
21
 
22
- <!-- Site Identity -->
22
+ {% comment %} Site Identity {% endcomment %}
23
23
  <div class="card mb-3">
24
24
  <div class="card-header">
25
25
  <i class="bi bi-person-badge me-1"></i> Site Identity
@@ -53,7 +53,7 @@
53
53
  </div>
54
54
  </div>
55
55
 
56
- <!-- GitHub -->
56
+ {% comment %} GitHub {% endcomment %}
57
57
  <div class="card mb-3">
58
58
  <div class="card-header">
59
59
  <i class="bi bi-github me-1"></i> GitHub
@@ -79,7 +79,7 @@
79
79
  </div>
80
80
  </div>
81
81
 
82
- <!-- URLs & Deployment -->
82
+ {% comment %} URLs & Deployment {% endcomment %}
83
83
  <div class="card mb-3">
84
84
  <div class="card-header">
85
85
  <i class="bi bi-link-45deg me-1"></i> URLs &amp; Deployment
@@ -121,7 +121,7 @@
121
121
  </div>
122
122
  </div>
123
123
 
124
- <!-- Personalization -->
124
+ {% comment %} Personalization {% endcomment %}
125
125
  <div class="card mb-3">
126
126
  <div class="card-header">
127
127
  <i class="bi bi-palette me-1"></i> Personalization
@@ -151,7 +151,7 @@
151
151
  </div>
152
152
  </div>
153
153
 
154
- <!-- Analytics -->
154
+ {% comment %} Analytics {% endcomment %}
155
155
  <div class="card mb-3">
156
156
  <div class="card-header">
157
157
  <i class="bi bi-graph-up me-1"></i> Analytics
@@ -174,9 +174,9 @@
174
174
  </div>
175
175
  </div>
176
176
 
177
- </div><!-- /col form -->
177
+ </div>{% comment %} /col form {% endcomment %}
178
178
 
179
- <!-- ── Right: Live YAML Preview ──────────────────────────────────── -->
179
+ {% comment %} ── Right: Live YAML Preview ──────────────────────────────────── {% endcomment %}
180
180
  <div class="col-lg-6">
181
181
  <div class="sticky-top" style="top:80px">
182
182
  <div class="card">
@@ -201,7 +201,7 @@
201
201
  <strong>Tip:</strong> Changes are reflected instantly in the preview. Download the file and replace your project's <code>_config.yml</code>, then restart your dev server.
202
202
  </div>
203
203
  </div>
204
- </div><!-- /col preview -->
204
+ </div>{% comment %} /col preview {% endcomment %}
205
205
 
206
- </div><!-- /row -->
206
+ </div>{% comment %} /row {% endcomment %}
207
207
  </div>