jekyll-theme-zer0 1.28.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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1143 -13
  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 +507 -2
  7. data/_data/consumers.yml +157 -9
  8. data/_data/features.yml +303 -20
  9. data/_data/feedback_types.yml +17 -12
  10. data/_data/i18n/fr.yml +12 -7
  11. data/_data/i18n/manifest.yml +39 -12
  12. data/_data/ingredient_densities.yml +122 -0
  13. data/_data/landing.yml +5 -2
  14. data/_data/navigation/main.yml +16 -0
  15. data/_data/navigation/quickstart.yml +4 -0
  16. data/_data/recipe_courses.yml +64 -0
  17. data/_data/site_builder.yml +874 -0
  18. data/_data/theme-manifest.yml +160 -124
  19. data/_data/ui-text.yml +26 -0
  20. data/_includes/README.md +26 -2
  21. data/_includes/analytics/posthog.html +2 -2
  22. data/_includes/components/admin-links.html +2 -2
  23. data/_includes/components/admin-tabs.html +2 -2
  24. data/_includes/components/ai-chat.html +14 -11
  25. data/_includes/components/analytics-dashboard.html +8 -8
  26. data/_includes/components/author-bio.html +1 -1
  27. data/_includes/components/author-card.html +10 -2
  28. data/_includes/components/author-eeat.html +4 -4
  29. data/_includes/components/background-customizer.html +10 -10
  30. data/_includes/components/background-image.html +114 -0
  31. data/_includes/components/background-settings.html +28 -15
  32. data/_includes/components/collection-manager.html +5 -5
  33. data/_includes/components/component-showcase.html +13 -13
  34. data/_includes/components/config-editor.html +12 -12
  35. data/_includes/components/config-viewer.html +8 -8
  36. data/_includes/components/cookie-consent.html +15 -15
  37. data/_includes/components/cta-button.html +7 -2
  38. data/_includes/components/dev-shortcuts.html +7 -7
  39. data/_includes/components/env-dashboard.html +8 -8
  40. data/_includes/components/env-switcher.html +9 -9
  41. data/_includes/components/feature-card.html +2 -2
  42. data/_includes/components/halfmoon.html +2 -2
  43. data/_includes/components/info-section.html +42 -37
  44. data/_includes/components/js-cdn.html +15 -15
  45. data/_includes/components/language-toggle.html +168 -21
  46. data/_includes/components/mermaid.html +72 -435
  47. data/_includes/components/nanobar.html +5 -5
  48. data/_includes/components/nav-editor.html +2 -2
  49. data/_includes/components/nav-export.html +2 -2
  50. data/_includes/components/nav-overview.html +2 -2
  51. data/_includes/components/page-feedback.html +45 -30
  52. data/_includes/components/page-views-init.html +55 -0
  53. data/_includes/components/page-views.html +33 -0
  54. data/_includes/components/post-card.html +22 -22
  55. data/_includes/components/post-type-badge.html +2 -2
  56. data/_includes/components/powered-by.html +2 -2
  57. data/_includes/components/preview-image.html +6 -0
  58. data/_includes/components/quick-index.html +2 -2
  59. data/_includes/components/recipe-card.html +67 -0
  60. data/_includes/components/recipe-duration.html +50 -0
  61. data/_includes/components/recipe-grams.html +58 -0
  62. data/_includes/components/recipe-index.html +96 -0
  63. data/_includes/components/recipe-ingredients.html +90 -0
  64. data/_includes/components/recipe-meta.html +96 -0
  65. data/_includes/components/recipe-nutrition.html +57 -0
  66. data/_includes/components/recipe-qty.html +73 -0
  67. data/_includes/components/recipe-ratio.html +151 -0
  68. data/_includes/components/recipe-scaler.html +73 -0
  69. data/_includes/components/recipe-steps.html +86 -0
  70. data/_includes/components/recipe-temp.html +45 -0
  71. data/_includes/components/search-modal.html +29 -4
  72. data/_includes/components/searchbar.html +2 -2
  73. data/_includes/components/shortcuts-modal.html +3 -0
  74. data/_includes/components/svg-background.html +2 -2
  75. data/_includes/components/theme-customizer.html +2 -2
  76. data/_includes/components/theme-info.html +14 -7
  77. data/_includes/components/theme-preview-gallery.html +22 -22
  78. data/_includes/content/giscus.html +2 -2
  79. data/_includes/content/intro.html +8 -8
  80. data/_includes/content/jsonld-faq.html +2 -2
  81. data/_includes/content/jsonld-software.html +24 -5
  82. data/_includes/content/seo.html +4 -4
  83. data/_includes/content/sitemap.html +27 -27
  84. data/_includes/content/toc.html +183 -183
  85. data/_includes/core/branding.html +6 -6
  86. data/_includes/core/console-capture.html +32 -74
  87. data/_includes/core/favicon.html +49 -7
  88. data/_includes/core/footer-fabs.html +17 -3
  89. data/_includes/core/footer.html +49 -34
  90. data/_includes/core/head.html +110 -86
  91. data/_includes/core/header.html +76 -54
  92. data/_includes/docs/bootstrap-docs.html +8 -8
  93. data/_includes/landing/landing-install-cards.html +2 -2
  94. data/_includes/landing/landing-quick-links.html +1 -1
  95. data/_includes/navigation/admin-nav.html +2 -2
  96. data/_includes/navigation/nav-tree.html +8 -8
  97. data/_includes/navigation/navbar.html +12 -12
  98. data/_includes/navigation/section-sidebar.html +109 -27
  99. data/_includes/navigation/sidebar-config.html +36 -2
  100. data/_includes/navigation/sidebar-left.html +17 -16
  101. data/_includes/navigation/sidebar-right.html +8 -7
  102. data/_includes/obsidian/full-graph.html +2 -2
  103. data/_includes/setup/claude-session.html +72 -0
  104. data/_includes/setup/prereq-checklist.html +90 -0
  105. data/_includes/setup/wizard.html +924 -222
  106. data/_includes/stats/stats-categories.html +8 -8
  107. data/_includes/stats/stats-header.html +14 -14
  108. data/_includes/stats/stats-metrics.html +14 -14
  109. data/_includes/stats/stats-no-data.html +12 -12
  110. data/_includes/stats/stats-overview.html +6 -6
  111. data/_includes/stats/stats-tags.html +8 -8
  112. data/_layouts/404.html +38 -24
  113. data/_layouts/README.md +2 -0
  114. data/_layouts/admin.html +24 -24
  115. data/_layouts/article.html +43 -33
  116. data/_layouts/author.html +20 -20
  117. data/_layouts/authors.html +2 -2
  118. data/_layouts/book-abc.html +12 -12
  119. data/_layouts/book-story.html +15 -15
  120. data/_layouts/book.html +12 -12
  121. data/_layouts/collection.html +33 -33
  122. data/_layouts/cookbook.html +88 -0
  123. data/_layouts/default.html +31 -28
  124. data/_layouts/home.html +23 -23
  125. data/_layouts/index.html +10 -10
  126. data/_layouts/landing.html +17 -17
  127. data/_layouts/news.html +44 -44
  128. data/_layouts/note.html +38 -38
  129. data/_layouts/notebook.html +34 -34
  130. data/_layouts/recipe.html +274 -0
  131. data/_layouts/root.html +92 -55
  132. data/_layouts/section.html +62 -33
  133. data/_layouts/setup.html +3 -3
  134. data/_layouts/sitemap-collection.html +49 -49
  135. data/_layouts/stats.html +40 -40
  136. data/_layouts/tag.html +12 -12
  137. data/_layouts/welcome.html +21 -21
  138. data/_sass/components/_callout.scss +1 -1
  139. data/_sass/components/_footer.scss +37 -1
  140. data/_sass/components/_mermaid.scss +375 -0
  141. data/_sass/components/_page-views.scss +36 -0
  142. data/_sass/components/_recipe.scss +506 -0
  143. data/_sass/components/_setup-wizard.scss +764 -0
  144. data/_sass/components/_ui-enhancements.scss +6 -6
  145. data/_sass/core/_navbar.scss +261 -46
  146. data/_sass/layouts/_landing.scss +2 -2
  147. data/_sass/layouts/_navbar-extras.scss +14 -4
  148. data/_sass/tokens/_color.scss +6 -0
  149. data/_sass/tokens/_index.scss +2 -0
  150. data/_sass/tokens/_radius.scss +21 -0
  151. data/_sass/tokens/_typography.scss +4 -0
  152. data/_sass/utilities/_focus.scss +14 -0
  153. data/assets/css/main.scss +4 -0
  154. data/assets/js/ai-chat.js +47 -5
  155. data/assets/js/fleet-feedback-capture.js +124 -0
  156. data/assets/js/fleet-feedback.js +853 -0
  157. data/assets/js/mermaid-diagrams.js +1267 -0
  158. data/assets/js/modules/navigation/config.js +9 -6
  159. data/assets/js/modules/navigation/navbar.js +55 -0
  160. data/assets/js/modules/navigation/scroll-spy.js +315 -80
  161. data/assets/js/modules/theme/appearance.js +8 -2
  162. data/assets/js/obsidian-wiki-links.js +8 -3
  163. data/assets/js/page-feedback.js +125 -192
  164. data/assets/js/page-views.js +372 -0
  165. data/assets/js/recipe-scaler.js +501 -0
  166. data/assets/js/search-modal.js +36 -0
  167. data/assets/js/setup-wizard.js +2279 -226
  168. data/assets/js/site-builder.js +1834 -0
  169. data/assets/js/ui-enhancements.js +11 -3
  170. data/scripts/README.md +44 -0
  171. data/scripts/ai/README.md +38 -0
  172. data/scripts/ai/api_call.rb +124 -0
  173. data/scripts/ai/usage.rb +314 -0
  174. data/scripts/ai/usage_report.rb +225 -0
  175. data/scripts/bin/audit-consumer +39 -7
  176. data/scripts/bin/giscus-discussions +213 -14
  177. data/scripts/bin/manifest +35 -12
  178. data/scripts/ci/agent_review_result.py +164 -0
  179. data/scripts/ci/test_agent_review_result.py +172 -0
  180. data/scripts/ci/test_visual_evidence_autogen.py +341 -0
  181. data/scripts/ci/visual_evidence_autogen.py +1060 -0
  182. data/scripts/content-review.rb +20 -1
  183. data/scripts/design-system-check.rb +170 -0
  184. data/scripts/lib/audit.sh +42 -2
  185. data/scripts/lint-liquid-raw.rb +137 -0
  186. data/scripts/test/integration/mermaid +22 -8
  187. data/scripts/test/lib/run_tests.sh +3 -1
  188. data/scripts/test/lib/test_agent_review_result.sh +27 -0
  189. data/scripts/test/lib/test_visual_evidence_autogen.sh +24 -0
  190. data/scripts/translate.rb +94 -16
  191. metadata +48 -2
@@ -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
+ }
@@ -0,0 +1,36 @@
1
+ // Feature: ZER0-083
2
+ // ============================================================================
3
+ // Page-view counter badge
4
+ // ----------------------------------------------------------------------------
5
+ // Markup: _includes/components/page-views.html
6
+ // Behaviour: assets/js/page-views.js
7
+ // Config: _config.yml → page_views:
8
+ // Theming: inherits the surrounding meta-row color (.post-meta is
9
+ // .text-muted), so it follows [data-bs-theme] light/dark for free.
10
+ // ============================================================================
11
+
12
+ .page-views {
13
+ display: inline-flex;
14
+ align-items: baseline;
15
+ gap: .25rem;
16
+ white-space: nowrap;
17
+
18
+ // The badge is server-rendered hidden and revealed by JS once a count is
19
+ // known. `!important` because a utility class on the include's `class`
20
+ // param (e.g. `d-inline-flex`) would otherwise win over [hidden].
21
+ &[hidden] {
22
+ display: none !important;
23
+ }
24
+
25
+ // Digits change as the count updates — tabular figures keep the meta row
26
+ // from reflowing when 9 becomes 10.
27
+ &__count {
28
+ font-variant-numeric: tabular-nums;
29
+ }
30
+
31
+ // Leading separator for meta rows; hides with the badge because it lives
32
+ // inside it (see the include's `separator` param).
33
+ &__sep {
34
+ display: inline;
35
+ }
36
+ }