jekyll-theme-zer0 1.24.0 → 1.26.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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +124 -0
  3. data/README.md +4 -4
  4. data/_data/authors.yml +1 -0
  5. data/_data/backlog.yml +26 -1
  6. data/_data/features.yml +73 -45
  7. data/_data/feedback_types.yml +148 -0
  8. data/_data/navigation/README.md +16 -6
  9. data/_data/navigation/main.yml +0 -8
  10. data/_data/roadmap.yml +1 -0
  11. data/_includes/README.md +10 -7
  12. data/_includes/analytics/google-analytics.html +1 -0
  13. data/_includes/analytics/google-tag-manager-body.html +1 -0
  14. data/_includes/analytics/google-tag-manager-head.html +1 -0
  15. data/_includes/analytics/posthog.html +1 -0
  16. data/_includes/components/README.md +3 -1
  17. data/_includes/components/admin-links.html +63 -0
  18. data/_includes/components/admin-tabs.html +1 -0
  19. data/_includes/components/ai-chat.html +27 -5
  20. data/_includes/components/author-eeat.html +1 -0
  21. data/_includes/components/background-customizer.html +1 -0
  22. data/_includes/components/background-settings.html +36 -37
  23. data/_includes/components/component-showcase.html +1 -0
  24. data/_includes/components/cookie-consent.html +1 -0
  25. data/_includes/components/dev-shortcuts.html +1 -8
  26. data/_includes/components/env-switcher.html +90 -138
  27. data/_includes/components/feature-card.html +1 -1
  28. data/_includes/components/halfmoon.html +22 -41
  29. data/_includes/components/info-section.html +127 -130
  30. data/_includes/components/mermaid.html +1 -0
  31. data/_includes/components/nanobar.html +1 -0
  32. data/_includes/components/page-feedback.html +252 -0
  33. data/_includes/components/post-type-badge.html +1 -0
  34. data/_includes/components/preview-image.html +1 -0
  35. data/_includes/components/search-modal.html +1 -0
  36. data/_includes/components/searchbar.html +1 -0
  37. data/_includes/components/shortcuts-modal.html +1 -0
  38. data/_includes/components/theme-info.html +21 -30
  39. data/_includes/components/theme-preview-gallery.html +1 -0
  40. data/_includes/content/backlinks.html +1 -0
  41. data/_includes/content/giscus.html +1 -0
  42. data/_includes/content/intro.html +20 -62
  43. data/_includes/content/jsonld-faq.html +1 -0
  44. data/_includes/content/seo.html +1 -0
  45. data/_includes/content/sitemap.html +1 -0
  46. data/_includes/content/toc.html +1 -0
  47. data/_includes/core/color-mode-init.html +1 -0
  48. data/_includes/core/console-capture.html +89 -0
  49. data/_includes/core/footer.html +1 -0
  50. data/_includes/core/head.html +5 -0
  51. data/_includes/core/header.html +5 -15
  52. data/_includes/navigation/admin-nav.html +1 -0
  53. data/_includes/navigation/breadcrumbs.html +1 -0
  54. data/_includes/navigation/local-graph-fab.html +3 -9
  55. data/_includes/navigation/local-graph.html +4 -9
  56. data/_includes/navigation/navbar.html +1 -0
  57. data/_includes/navigation/sidebar-categories.html +56 -14
  58. data/_includes/navigation/sidebar-config.html +115 -0
  59. data/_includes/navigation/sidebar-folders.html +168 -62
  60. data/_includes/navigation/sidebar-left.html +29 -52
  61. data/_includes/navigation/sidebar-nav.html +30 -0
  62. data/_includes/navigation/sidebar-right.html +1 -0
  63. data/_includes/navigation/toc-fab.html +3 -9
  64. data/_includes/navigation/unified-drawer.html +7 -14
  65. data/_includes/obsidian/full-graph.html +1 -0
  66. data/_includes/setup/wizard.html +1 -0
  67. data/_includes/stats/stats-categories.html +1 -0
  68. data/_includes/stats/stats-header.html +1 -0
  69. data/_includes/stats/stats-metrics.html +1 -0
  70. data/_includes/stats/stats-overview.html +1 -0
  71. data/_includes/stats/stats-tags.html +1 -0
  72. data/_layouts/admin.html +1 -0
  73. data/_layouts/article.html +1 -0
  74. data/_layouts/author.html +1 -0
  75. data/_layouts/authors.html +1 -0
  76. data/_layouts/collection.html +1 -0
  77. data/_layouts/default.html +14 -37
  78. data/_layouts/home.html +1 -0
  79. data/_layouts/index.html +1 -0
  80. data/_layouts/landing.html +1 -0
  81. data/_layouts/news.html +1 -0
  82. data/_layouts/note.html +1 -0
  83. data/_layouts/notebook.html +1 -0
  84. data/_layouts/root.html +6 -2
  85. data/_layouts/search.html +1 -0
  86. data/_layouts/section.html +1 -0
  87. data/_layouts/setup.html +1 -0
  88. data/_layouts/sitemap-collection.html +1 -0
  89. data/_layouts/stats.html +1 -0
  90. data/_layouts/tag.html +1 -0
  91. data/_layouts/welcome.html +1 -0
  92. data/_plugins/author_pages_generator.rb +1 -0
  93. data/_plugins/obsidian_links.rb +1 -0
  94. data/_plugins/preview_image_generator.rb +1 -0
  95. data/_plugins/search_and_sitemap_generator.rb +1 -0
  96. data/_plugins/theme_version.rb +1 -0
  97. data/_sass/components/_author.scss +12 -1
  98. data/_sass/components/_footer.scss +22 -0
  99. data/_sass/components/_page-feedback.scss +276 -0
  100. data/_sass/components/_ui-enhancements.scss +9 -0
  101. data/_sass/core/_docs-layout.scss +3 -78
  102. data/_sass/core/_navbar.scss +10 -27
  103. data/_sass/core/_obsidian.scss +2 -2
  104. data/_sass/core/code-copy.scss +10 -0
  105. data/_sass/custom.scss +1 -0
  106. data/_sass/notebooks.scss +1 -0
  107. data/_sass/theme/_backgrounds.scss +7 -2
  108. data/_sass/tokens/_layers.scss +4 -0
  109. data/_sass/utilities/_layout.scss +11 -0
  110. data/assets/css/main.scss +3 -1
  111. data/assets/js/ai-chat.js +1 -0
  112. data/assets/js/author-profile.js +1 -0
  113. data/assets/js/auto-hide-nav.js +1 -0
  114. data/assets/js/back-to-top.js +1 -0
  115. data/assets/js/background-customizer.js +1 -0
  116. data/assets/js/code-copy.js +1 -0
  117. data/assets/js/halfmoon.js +23 -22
  118. data/assets/js/modules/navigation/gestures.js +1 -0
  119. data/assets/js/modules/navigation/keyboard.js +1 -0
  120. data/assets/js/modules/navigation/scroll-spy.js +1 -0
  121. data/assets/js/modules/navigation/sidebar-state.js +1 -0
  122. data/assets/js/modules/navigation/sidebar-visibility.js +1 -0
  123. data/assets/js/modules/navigation/smooth-scroll.js +1 -0
  124. data/assets/js/modules/theme/appearance.js +52 -16
  125. data/assets/js/nanobar-init.js +1 -0
  126. data/assets/js/navigation.js +1 -0
  127. data/assets/js/obsidian-graph.js +1 -0
  128. data/assets/js/obsidian-wiki-links.js +1 -0
  129. data/assets/js/page-feedback.js +660 -0
  130. data/assets/js/palette-generator.js +1 -0
  131. data/assets/js/particles-source.js +1 -0
  132. data/assets/js/search-modal.js +1 -0
  133. data/assets/js/setup-wizard.js +1 -0
  134. data/assets/js/share-actions.js +1 -0
  135. data/assets/js/skin-editor.js +1 -0
  136. data/assets/js/table-copy.js +1 -0
  137. data/assets/js/theme-customizer.js +1 -0
  138. data/scripts/analyze-commits.sh +1 -0
  139. data/scripts/bin/giscus-discussions +1 -0
  140. data/scripts/bin/install +1 -0
  141. data/scripts/bin/validate +1 -0
  142. data/scripts/build +1 -0
  143. data/scripts/content-review.rb +1 -0
  144. data/scripts/convert-notebooks.sh +4 -3
  145. data/scripts/fix-markdown-format.sh +1 -0
  146. data/scripts/generate-preview-images.sh +1 -0
  147. data/scripts/generate-roadmap.sh +1 -0
  148. data/scripts/install-preview-generator.sh +1 -0
  149. data/scripts/release +1 -0
  150. data/scripts/requirements.txt +11 -0
  151. data/scripts/setup.sh +1 -0
  152. data/scripts/tag-features +136 -0
  153. data/scripts/validate-features.rb +7 -0
  154. data/scripts/vendor-install.sh +1 -0
  155. metadata +13 -4
  156. data/_data/prompts.yml +0 -302
  157. data/_plugins/admin_page_urls.rb +0 -16
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-001, ZER0-008, ZER0-019
2
3
  layout: root
3
4
  ---
4
5
  <!--
@@ -45,53 +46,29 @@ layout: root
45
46
  -->
46
47
 
47
48
  {%- comment -%}
48
- Resolve effective sidebar visibility. Precedence:
49
- 1. page.sidebar in front matter wins (true | false | hash)
50
- 2. Otherwise, post_type=featured|breaking → false (full-bleed reading)
51
- 3. Otherwise, default to true
52
- This is the single source of truth so child layouts (article.html, note.html)
53
- do not need to mutate page state.
49
+ Sidebar visibility + nav mode are resolved by the shared include below
50
+ (single source of truth, also used by core/header.html and the sidebar
51
+ includes). It sets:
52
+ sidebar_enabled — false when the page opts out (`sidebar: false`,
53
+ or featured/breaking post_type by default)
54
+ sidebar_has_content true only when the resolved nav mode will render;
55
+ `sidebar: true` without a resolvable nav still
56
+ enables the right TOC but must not reserve an
57
+ empty left column.
54
58
  {%- endcomment -%}
55
- {%- assign _effective_sidebar = page.sidebar -%}
56
- {%- if _effective_sidebar == nil -%}
57
- {%- if page.post_type == "featured" or page.post_type == "breaking" -%}
58
- {%- assign _effective_sidebar = false -%}
59
- {%- else -%}
60
- {%- assign _effective_sidebar = true -%}
61
- {%- endif -%}
62
- {%- endif -%}
63
-
64
- {%- comment -%}
65
- Left sidebar column is only useful when sidebar-left.html has nav to render
66
- (matches header.html mobile toggle logic). `sidebar: true` without `nav`
67
- still enables the right TOC but must not reserve an empty left column.
68
- {%- endcomment -%}
69
- {%- assign _sidebar_has_content = false -%}
70
- {%- if _effective_sidebar != false -%}
71
- {%- assign _sidebar_nav = nil -%}
72
- {%- if page.sidebar and page.sidebar.nav -%}
73
- {%- assign _sidebar_nav = page.sidebar.nav -%}
74
- {%- endif -%}
75
- {%- if _sidebar_nav -%}
76
- {%- if _sidebar_nav == "auto" or _sidebar_nav == "categories" -%}
77
- {%- assign _sidebar_has_content = true -%}
78
- {%- elsif site.data.navigation[_sidebar_nav] -%}
79
- {%- assign _sidebar_has_content = true -%}
80
- {%- endif -%}
81
- {%- endif -%}
82
- {%- endif -%}
59
+ {% include navigation/sidebar-config.html %}
83
60
 
84
61
  <!-- ================================================ -->
85
62
  <!-- MAIN LAYOUT CONTAINER -->
86
63
  <!-- Bootstrap responsive container with custom grid -->
87
64
  <!-- ================================================ -->
88
- <div class="container-xxl bd-gutter mt-3 my-md-4 bd-layout{% unless _sidebar_has_content %} bd-layout--no-sidebar{% endunless %}">
65
+ <div class="container-xxl bd-gutter mt-3 my-md-4 bd-layout{% unless sidebar_has_content %} bd-layout--no-sidebar{% endunless %}">
89
66
 
90
67
  <!-- ================================ -->
91
68
  <!-- LEFT SIDEBAR - Navigation -->
92
69
  <!-- ================================ -->
93
70
  <!-- Site navigation, content outline, and offcanvas menu for mobile -->
94
- {% if _sidebar_has_content %}
71
+ {% if sidebar_has_content %}
95
72
  <aside class="bd-sidebar">
96
73
  {% include navigation/sidebar-left.html %}
97
74
  </aside>
@@ -130,7 +107,7 @@ layout: root
130
107
  <!-- RIGHT SIDEBAR - Table of Contents -->
131
108
  <!-- =============================== -->
132
109
  <!-- Page outline, shortcuts, and related links (hidden on mobile) -->
133
- {% unless _effective_sidebar == false %}
110
+ {% unless sidebar_enabled == false %}
134
111
  <div class="bd-toc text-body-secondary">
135
112
  {% include navigation/sidebar-right.html %}
136
113
  </div>
data/_layouts/home.html CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Feature: ZER0-019
2
3
  layout: root
3
4
  ---
4
5
  <!--
data/_layouts/index.html CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Feature: ZER0-019
2
3
  layout: root
3
4
  ---
4
5
  <!--
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Feature: ZER0-019
2
3
  layout: root
3
4
  ---
4
5
  <!--
data/_layouts/news.html CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-019, ZER0-062
2
3
  layout: root
3
4
  source: "https://getbootstrap.com/docs/5.3/examples/blog/#"
4
5
  ---
data/_layouts/note.html CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-019, ZER0-035, ZER0-058
2
3
  layout: default
3
4
  ---
4
5
  {% assign page_absolute_url = page.url | absolute_url %}
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-012, ZER0-019, ZER0-035
2
3
  layout: default
3
4
  ---
4
5
  <!--
data/_layouts/root.html CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-001, ZER0-019, ZER0-031, ZER0-060
2
3
  ---
3
4
  <!--
4
5
  ===================================================================
@@ -20,7 +21,7 @@
20
21
  - head.html: Meta tags, stylesheets, and external resources
21
22
  - svg.html: Inline SVG symbols for icons
22
23
  - header.html: Main navigation and site branding
23
- - info-section.html: Site-wide announcements or notices
24
+ - info-section.html: Settings offcanvas (Appearance / Site / Developer)
24
25
  - footer.html: Site footer with links and copyright
25
26
  - js-cdn.html: JavaScript dependencies and custom scripts
26
27
 
@@ -87,7 +88,7 @@
87
88
  <!-- Keyboard shortcuts help modal (triggered by `?`) — page-invariant. -->
88
89
  {% include_cached components/shortcuts-modal.html %}
89
90
 
90
- <!-- Site-wide information banner or announcement section -->
91
+ <!-- Settings offcanvas (Appearance / Site / Developer tabs) -->
91
92
  {% include components/info-section.html %}
92
93
 
93
94
  <!-- Setup banner for unconfigured sites — page-invariant. -->
@@ -124,6 +125,9 @@
124
125
  <!-- AI Chat Assistant -->
125
126
  {%- include components/ai-chat.html -%}
126
127
 
128
+ <!-- Page-feedback capture widget ("Improve this page" → GitHub issue) -->
129
+ {%- include components/page-feedback.html -%}
130
+
127
131
  <!-- JavaScript dependencies and custom scripts -->
128
132
  <div>
129
133
  <!-- Search functionality -->
data/_layouts/search.html CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-019, ZER0-042
2
3
  # Bare layout that renders the client-side search index as pure JSON.
3
4
  # Used by /search.json (see search.json in the site root); downstream
4
5
  # sites get the endpoint automatically via the theme gem.
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-019, ZER0-063
2
3
  layout: root
3
4
  ---
4
5
  <!--
data/_layouts/setup.html CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-019, ZER0-067
2
3
  layout: root
3
4
  ---
4
5
  <!--
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-019, ZER0-042
2
3
  layout: root
3
4
  ---
4
5
  <!--
data/_layouts/stats.html CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-019, ZER0-043
2
3
  layout: root
3
4
  ---
4
5
  <!--
data/_layouts/tag.html CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Feature: ZER0-019
2
3
  layout: default
3
4
  ---
4
5
  <!--
@@ -1,4 +1,5 @@
1
1
  ---
2
+ # Features: ZER0-019, ZER0-046
2
3
  layout: root
3
4
  ---
4
5
  <!--
@@ -1,3 +1,4 @@
1
+ # Feature: ZER0-061
1
2
  # frozen_string_literal: true
2
3
 
3
4
  #
@@ -1,3 +1,4 @@
1
+ # Features: ZER0-044, ZER0-059
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'digest'
@@ -1,3 +1,4 @@
1
+ # Feature: ZER0-004
1
2
  # frozen_string_literal: true
2
3
 
3
4
  #
@@ -1,3 +1,4 @@
1
+ # Feature: ZER0-042
1
2
  # frozen_string_literal: true
2
3
 
3
4
  #
@@ -1,3 +1,4 @@
1
+ # Feature: ZER0-021
1
2
  # frozen_string_literal: true
2
3
 
3
4
  #
@@ -46,9 +46,20 @@
46
46
  }
47
47
  }
48
48
 
49
- // Expertise chips
49
+ // "About the Author" card: the text column sits in a flex row next to the
50
+ // avatar. Flexbox's default `min-width: auto` propagates the widest nowrap
51
+ // child (a long expertise badge) as the column's minimum, blowing the card —
52
+ // and with it the whole page — past the viewport on small phones (≤340px).
53
+ .author-card .card-body .flex-grow-1 {
54
+ min-width: 0;
55
+ }
56
+
57
+ // Expertise chips — allow the label to wrap instead of forcing the card wide
58
+ // (Bootstrap badges are white-space: nowrap by default).
50
59
  .author-expertise .badge {
51
60
  font-weight: 500;
61
+ white-space: normal;
62
+ text-align: start;
52
63
  }
53
64
 
54
65
  // Shared tagline styling (full "About the Author" card + profile hero)
@@ -127,6 +127,28 @@
127
127
  }
128
128
  }
129
129
 
130
+ // WCAG 2.5.8 target size: the dark block's text links render ~19px tall and
131
+ // the icon-only social links (below md) ~16px wide — under the 24px minimum.
132
+ // Block padding grows the tap target without changing the visual text size;
133
+ // icon links get an explicit minimum box. (`d-block` links — e.g. the
134
+ // truncated Latest Posts titles — keep their display but gain the padding.)
135
+ .footer-dark-block {
136
+ ul.list-unstyled li > a,
137
+ p > a {
138
+ display: inline-block;
139
+ padding-block: 0.25rem;
140
+ }
141
+
142
+ ul.list-inline li > a {
143
+ display: inline-flex;
144
+ align-items: center;
145
+ justify-content: center;
146
+ gap: 0.25rem;
147
+ min-width: 1.75rem;
148
+ min-height: 1.75rem;
149
+ }
150
+ }
151
+
130
152
  .footer-post-link {
131
153
  max-width: 100%;
132
154
  }
@@ -0,0 +1,276 @@
1
+ // ============================================================================
2
+ // Page-feedback widget — global FAB + capture modal
3
+ // ----------------------------------------------------------------------------
4
+ // Markup: _includes/components/page-feedback.html
5
+ // Behaviour: assets/js/page-feedback.js
6
+ // Tokens: shared FAB + layer scale (_sass/tokens/_spacing.scss, _layers.scss)
7
+ // Theming: leans on Bootstrap 5.3 CSS variables (--bs-body-bg / -color /
8
+ // -border-color) so it follows [data-bs-theme] light/dark for free.
9
+ // ============================================================================
10
+
11
+ // --- Global FAB (bottom-left, clear of the right-hand FAB stack) ------------
12
+ .pf-fab {
13
+ position: fixed;
14
+ bottom: var(--zer0-space-fab-offset, 1rem);
15
+ left: var(--zer0-space-fab-offset, 1rem);
16
+ z-index: var(--zer0-layer-fab-feedback, 1051);
17
+
18
+ display: inline-flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ width: var(--zer0-space-fab-size, 3.5rem);
22
+ height: var(--zer0-space-fab-size, 3.5rem);
23
+ padding: 0;
24
+ border: 0;
25
+ border-radius: 50%;
26
+ background-color: var(--zer0-color-primary, var(--bs-primary));
27
+ color: #fff;
28
+ font-size: 1.25rem;
29
+ opacity: .9;
30
+ box-shadow: var(--zer0-shadow-fab, 0 .5rem 1rem rgba(0, 0, 0, .25));
31
+ transition:
32
+ opacity var(--zer0-motion-duration-fast, 120ms) var(--zer0-motion-ease-standard, ease),
33
+ transform var(--zer0-motion-duration-fast, 120ms) var(--zer0-motion-ease-standard, ease);
34
+
35
+ &:hover,
36
+ &:focus-visible {
37
+ opacity: 1;
38
+ color: #fff;
39
+ transform: translateY(-2px);
40
+ }
41
+ }
42
+
43
+ // Lock background scroll while the dialog is open (set by page-feedback.js).
44
+ .pf-no-scroll { overflow: hidden; }
45
+
46
+ // --- Modal overlay ----------------------------------------------------------
47
+ .pf-overlay {
48
+ position: fixed;
49
+ inset: 0;
50
+ z-index: var(--zer0-layer-feedback-modal, 1096); // above the cookie banner (1095)
51
+ display: flex;
52
+ align-items: flex-end; // bottom sheet on phones
53
+ justify-content: center;
54
+ background: rgba(0, 0, 0, .5);
55
+ opacity: 0;
56
+ transition: opacity var(--zer0-motion-duration, 180ms) var(--zer0-motion-ease-standard, ease);
57
+
58
+ &[hidden] { display: none; }
59
+ &.pf-overlay--open { opacity: 1; }
60
+
61
+ @media (min-width: 576px) {
62
+ align-items: center;
63
+ padding: var(--zer0-space-3, 1rem);
64
+ }
65
+ }
66
+
67
+ .pf-dialog {
68
+ display: flex;
69
+ flex-direction: column;
70
+ width: 100%;
71
+ max-width: 40rem;
72
+ max-height: 92vh;
73
+ overflow: hidden;
74
+ color: var(--bs-body-color);
75
+ background: var(--bs-body-bg);
76
+ border: 1px solid var(--bs-border-color, rgba(0, 0, 0, .15));
77
+ border-radius: 1rem 1rem 0 0;
78
+ transform: translateY(20px);
79
+ transition: transform var(--zer0-motion-duration, 180ms) var(--zer0-motion-ease-standard, ease);
80
+
81
+ .pf-overlay--open & { transform: translateY(0); }
82
+
83
+ @media (min-width: 576px) { border-radius: 1rem; }
84
+ }
85
+
86
+ // --- Header -----------------------------------------------------------------
87
+ .pf-header {
88
+ display: flex;
89
+ align-items: flex-start;
90
+ justify-content: space-between;
91
+ gap: var(--zer0-space-2, .5rem);
92
+ padding: var(--zer0-space-3, 1rem) var(--zer0-space-3, 1rem) var(--zer0-space-2, .5rem);
93
+ border-bottom: 1px solid var(--bs-border-color, rgba(0, 0, 0, .1));
94
+ }
95
+
96
+ .pf-title { display: flex; align-items: center; }
97
+
98
+ .pf-intro { font-size: .875rem; line-height: 1.4; }
99
+
100
+ .pf-close {
101
+ flex-shrink: 0;
102
+ color: var(--bs-body-color);
103
+ background: transparent;
104
+ border: 0;
105
+ opacity: .6;
106
+ &:hover, &:focus-visible { opacity: 1; }
107
+ }
108
+
109
+ // --- Body (scrolls) ---------------------------------------------------------
110
+ .pf-body {
111
+ flex: 1 1 auto;
112
+ overflow-y: auto;
113
+ padding: var(--zer0-space-3, 1rem);
114
+ display: flex;
115
+ flex-direction: column;
116
+ gap: var(--zer0-space-3, 1rem);
117
+ }
118
+
119
+ .pf-field { border: 0; padding: 0; margin: 0; min-width: 0; }
120
+
121
+ .pf-legend,
122
+ .pf-label {
123
+ display: block;
124
+ font-size: .8125rem;
125
+ font-weight: 600;
126
+ text-transform: uppercase;
127
+ letter-spacing: .02em;
128
+ color: var(--bs-secondary-color, var(--zer0-color-ink-muted, #6c757d));
129
+ margin-bottom: var(--zer0-space-2, .5rem);
130
+ }
131
+
132
+ .pf-help { font-size: .8125rem; margin: .35rem 0 0; }
133
+
134
+ // --- Type selector ----------------------------------------------------------
135
+ .pf-types-group {
136
+ font-size: .75rem;
137
+ font-weight: 600;
138
+ color: var(--bs-secondary-color, #6c757d);
139
+ margin: var(--zer0-space-2, .5rem) 0 .35rem;
140
+ }
141
+
142
+ .pf-types-grid {
143
+ display: grid;
144
+ grid-template-columns: 1fr;
145
+ gap: .5rem;
146
+
147
+ @media (min-width: 480px) { grid-template-columns: 1fr 1fr; }
148
+ }
149
+
150
+ .pf-type {
151
+ display: flex;
152
+ align-items: flex-start;
153
+ gap: .625rem;
154
+ text-align: left;
155
+ padding: .625rem .75rem;
156
+ background: var(--bs-body-bg);
157
+ border: 1px solid var(--bs-border-color, rgba(0, 0, 0, .15));
158
+ border-radius: .625rem;
159
+ cursor: pointer;
160
+ transition: border-color 120ms ease, background-color 120ms ease;
161
+
162
+ &:hover { border-color: var(--zer0-color-primary, var(--bs-primary)); }
163
+
164
+ &:focus-visible {
165
+ outline: 2px solid var(--zer0-color-primary, var(--bs-primary));
166
+ outline-offset: 2px;
167
+ }
168
+
169
+ &.pf-type--active {
170
+ border-color: var(--zer0-color-primary, var(--bs-primary));
171
+ background: color-mix(in srgb, var(--bs-primary) 10%, transparent);
172
+ box-shadow: inset 0 0 0 1px var(--zer0-color-primary, var(--bs-primary));
173
+ }
174
+ }
175
+
176
+ .pf-type-icon { flex-shrink: 0; margin-top: .1rem; font-size: 1rem; color: var(--zer0-color-primary, var(--bs-primary)); }
177
+ .pf-type-text { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
178
+ .pf-type-label { font-weight: 600; font-size: .9rem; line-height: 1.2; }
179
+ .pf-type-desc { font-size: .78rem; line-height: 1.3; color: var(--bs-secondary-color, #6c757d); }
180
+
181
+ // --- Context / logs ---------------------------------------------------------
182
+ .pf-summary { cursor: pointer; font-weight: 600; font-size: .875rem; }
183
+ .pf-context-count { color: var(--bs-secondary-color, #6c757d); font-weight: 400; }
184
+
185
+ .pf-context-list {
186
+ list-style: none;
187
+ margin: .5rem 0 0;
188
+ padding: 0;
189
+ font-size: .8125rem;
190
+
191
+ li { display: flex; gap: .5rem; padding: .15rem 0; }
192
+ }
193
+ .pf-context-key { flex: 0 0 4rem; color: var(--bs-secondary-color, #6c757d); }
194
+ .pf-context-val { min-width: 0; word-break: break-word; }
195
+
196
+ .pf-logs { margin-top: .75rem; }
197
+ .pf-check { display: flex; align-items: center; gap: .4rem; font-size: .8125rem; font-weight: 500; }
198
+ .pf-logs-preview {
199
+ max-height: 9rem;
200
+ overflow: auto;
201
+ margin: .5rem 0 0;
202
+ padding: .5rem .625rem;
203
+ font-size: .72rem;
204
+ line-height: 1.4;
205
+ white-space: pre-wrap;
206
+ word-break: break-word;
207
+ background: var(--bs-tertiary-bg, rgba(0, 0, 0, .04));
208
+ border: 1px solid var(--bs-border-color, rgba(0, 0, 0, .1));
209
+ border-radius: .5rem;
210
+ }
211
+
212
+ // --- AI enrichment ----------------------------------------------------------
213
+ .pf-ai-head { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; }
214
+ .pf-ai-hint { font-size: .8125rem; }
215
+ .pf-ai-result { margin-top: .625rem; font-size: .875rem; }
216
+ .pf-ai-card {
217
+ padding: .75rem .875rem;
218
+ background: var(--bs-tertiary-bg, rgba(0, 0, 0, .04));
219
+ border: 1px solid var(--bs-border-color, rgba(0, 0, 0, .1));
220
+ border-radius: .625rem;
221
+
222
+ p { margin: 0 0 .5rem; }
223
+ p:last-child { margin-bottom: 0; }
224
+ }
225
+ .pf-ai-badges .badge { margin-right: .25rem; }
226
+ .pf-ai-questions { margin: .25rem 0 .5rem 1.1rem; padding: 0; }
227
+ .pf-ai-labels code { font-size: .78rem; }
228
+ .pf-ai-error { color: var(--bs-danger-text-emphasis, var(--bs-danger)); }
229
+ .pf-ai-spinner,
230
+ .pf-ai-note i { color: var(--zer0-color-primary, var(--bs-primary)); }
231
+ .pf-ai-spinner {
232
+ display: inline-block;
233
+ width: .85rem;
234
+ height: .85rem;
235
+ border: 2px solid currentColor;
236
+ border-right-color: transparent;
237
+ border-radius: 50%;
238
+ vertical-align: -.1rem;
239
+ animation: pf-spin .7s linear infinite;
240
+ }
241
+ @keyframes pf-spin { to { transform: rotate(360deg); } }
242
+
243
+ // --- Status line ------------------------------------------------------------
244
+ .pf-status:empty { display: none; }
245
+ .pf-status {
246
+ font-size: .8125rem;
247
+ margin: 0;
248
+ padding: .5rem .625rem;
249
+ border-radius: .5rem;
250
+
251
+ &.pf-status--ok { background: var(--bs-success-bg-subtle, #d1e7dd); color: var(--bs-success-text-emphasis, #0a3622); }
252
+ &.pf-status--warn { background: var(--bs-warning-bg-subtle, #fff3cd); color: var(--bs-warning-text-emphasis, #664d03); }
253
+ &.pf-status--pending { background: var(--bs-info-bg-subtle, #cff4fc); color: var(--bs-info-text-emphasis, #055160); }
254
+ a { color: inherit; text-decoration: underline; }
255
+ }
256
+
257
+ // --- Footer -----------------------------------------------------------------
258
+ .pf-footer {
259
+ display: flex;
260
+ align-items: center;
261
+ justify-content: space-between;
262
+ gap: var(--zer0-space-2, .5rem);
263
+ padding: var(--zer0-space-2, .5rem) var(--zer0-space-3, 1rem);
264
+ border-top: 1px solid var(--bs-border-color, rgba(0, 0, 0, .1));
265
+ background: var(--bs-body-bg);
266
+ }
267
+ .pf-footer-primary { display: flex; gap: .5rem; }
268
+ .pf-copy { text-decoration: none; }
269
+
270
+ // --- Reduced motion ---------------------------------------------------------
271
+ @media (prefers-reduced-motion: reduce) {
272
+ .pf-fab,
273
+ .pf-overlay,
274
+ .pf-dialog { transition: none; }
275
+ .pf-ai-spinner { animation: none; }
276
+ }
@@ -26,6 +26,15 @@ img {
26
26
  // UI/UX ENHANCEMENTS - Modern, polished interactions
27
27
  // ==============================================================================
28
28
 
29
+ // WCAG 2.5.8 target size: breadcrumb links render as bare ~19px text lines.
30
+ // Block padding + matching negative margin grows the tap box past 24px
31
+ // without shifting the visual baseline or the bar's height.
32
+ .breadcrumbs .breadcrumb-item > a {
33
+ display: inline-block;
34
+ padding-block: 0.25rem;
35
+ margin-block: -0.25rem;
36
+ }
37
+
29
38
  // Hero Section Enhancements
30
39
  // NOTE: Exclude .zer0-bg-hero so skin-specific gradients from _backgrounds.scss take precedence
31
40
  .bg-primary:not(.zer0-bg-hero) {
@@ -1,3 +1,4 @@
1
+ // Feature: ZER0-008
1
2
  /*!
2
3
  * Docs layout — trimmed Bootstrap-docs-adjacent styles for zer0-mistakes.
3
4
  * Replaces the former full _docs.scss vendor snapshot (~3.2k lines).
@@ -545,7 +546,8 @@ a.bd-intro-badge--tag:focus {
545
546
  white-space: nowrap;
546
547
  }
547
548
 
548
- // Plain link buttons: reserve the same trailing space as .dropdown-toggle::after.
549
+ // Plain link buttons: reserve the same trailing space as .dropdown-toggle::after
550
+ // so the plain "Improve" / "Edit on GitHub" buttons line up with the Share caret.
549
551
  .bd-intro-action-link.btn::after {
550
552
  content: "";
551
553
  display: inline-block;
@@ -553,83 +555,6 @@ a.bd-intro-badge--tag:focus {
553
555
  flex-shrink: 0;
554
556
  visibility: hidden;
555
557
  }
556
-
557
- // Copilot Agent prompt menu — compact, proportional to the trigger button.
558
- // Scoped here so the Share dropdown keeps Bootstrap defaults.
559
- .copilot-agent-menu.dropdown-menu {
560
- --bs-dropdown-min-width: 0;
561
- width: max-content;
562
- max-width: min(22rem, 90vw);
563
- padding: var(--zer0-space-1) 0;
564
- border-radius: var(--bs-border-radius);
565
- border-color: var(--zer0-color-border);
566
- }
567
-
568
- .copilot-agent-menu {
569
- .dropdown-header {
570
- padding: var(--zer0-space-1) var(--zer0-space-2) calc(var(--zer0-space-1) * .5);
571
- font-size: var(--zer0-text-sm);
572
- font-weight: var(--zer0-font-weight-semibold);
573
- line-height: var(--zer0-leading-tight);
574
- color: var(--zer0-color-ink-muted);
575
- white-space: normal;
576
- }
577
-
578
- .dropdown-divider {
579
- margin: var(--zer0-space-1) 0;
580
- }
581
-
582
- .dropdown-item {
583
- white-space: normal;
584
- padding: var(--zer0-space-1) var(--zer0-space-2);
585
- line-height: var(--zer0-leading-normal);
586
- border-radius: calc(var(--bs-border-radius) - 2px);
587
-
588
- &:hover,
589
- &:focus {
590
- .copilot-agent-item__desc {
591
- color: inherit;
592
- opacity: .85;
593
- }
594
- }
595
- }
596
- }
597
-
598
- .copilot-agent-item {
599
- display: flex;
600
- align-items: flex-start;
601
- gap: var(--zer0-space-2);
602
- min-width: 0;
603
- }
604
-
605
- .copilot-agent-item__icon {
606
- flex-shrink: 0;
607
- margin-top: .125rem;
608
- font-size: var(--zer0-text-sm);
609
- line-height: 1;
610
- opacity: .85;
611
- }
612
-
613
- .copilot-agent-item__text {
614
- display: flex;
615
- flex-direction: column;
616
- gap: .125rem;
617
- min-width: 0;
618
- }
619
-
620
- .copilot-agent-item__label {
621
- font-size: var(--zer0-text-sm);
622
- font-weight: var(--zer0-font-weight-medium);
623
- line-height: var(--zer0-leading-tight);
624
- }
625
-
626
- .copilot-agent-item__desc {
627
- display: block;
628
- font-size: .8125rem;
629
- font-weight: var(--zer0-font-weight-regular);
630
- line-height: var(--zer0-leading-normal);
631
- color: var(--zer0-color-ink-muted);
632
- }
633
558
  }
634
559
 
635
560
  .bd-toc {