jekyll-theme-zer0 1.26.0 → 1.28.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 +558 -5
- data/README.md +10 -27
- data/_data/authors.yml +4 -3
- data/_data/backlog.yml +28 -0
- data/_data/consumers.yml +147 -0
- data/_data/features.yml +142 -23
- data/_data/i18n/fr.yml +98 -0
- data/_data/i18n/languages.yml +36 -0
- data/_data/i18n/manifest.yml +1502 -0
- data/_data/navigation/docs.yml +2 -0
- data/_data/navigation/main.yml +6 -0
- data/_data/series.yml +19 -0
- data/_data/theme-manifest.yml +348 -268
- data/_data/ui-text.yml +36 -246
- data/_includes/README.md +25 -2
- data/_includes/analytics/google-tag-manager-body.html +11 -2
- data/_includes/analytics/google-tag-manager-head.html +16 -6
- data/_includes/analytics/posthog.html +33 -4
- data/_includes/components/abc-letter.html +43 -0
- data/_includes/components/author-avatar-url.html +4 -2
- data/_includes/components/book-card.html +42 -0
- data/_includes/components/book-nav.html +80 -0
- data/_includes/components/book-plate.html +31 -0
- data/_includes/components/book-toc.html +47 -0
- data/_includes/components/bookshelf.html +68 -0
- data/_includes/components/card-grid.html +60 -0
- data/_includes/components/data-card.html +95 -0
- data/_includes/components/env-switcher.html +3 -1
- data/_includes/components/halfmoon.html +5 -1
- data/_includes/components/language-toggle.html +81 -0
- data/_includes/components/page-feedback.html +65 -2
- data/_includes/components/search-modal.html +2 -2
- data/_includes/components/shortcuts-modal.html +1 -1
- data/_includes/components/theme-controls-bar.html +10 -2
- data/_includes/components/theme-customizer.html +8 -2
- data/_includes/components/translation-notice.html +27 -0
- data/_includes/content/intro.html +16 -15
- data/_includes/content/seo.html +9 -3
- data/_includes/core/color-mode-init.html +13 -4
- data/_includes/core/favicon.html +46 -0
- data/_includes/core/footer.html +9 -4
- data/_includes/core/head.html +18 -0
- data/_includes/core/header.html +9 -4
- data/_includes/core/hreflang.html +33 -0
- data/_includes/core/i18n.html +36 -0
- data/_includes/custom/body-end.html +18 -0
- data/_includes/custom/body-start.html +17 -0
- data/_includes/custom/footer.html +18 -0
- data/_includes/custom/head.html +18 -0
- data/_includes/navigation/breadcrumbs.html +1 -1
- data/_includes/navigation/local-graph.html +28 -2
- data/_includes/navigation/nav-tree.html +3 -3
- data/_includes/navigation/navbar.html +5 -4
- data/_includes/navigation/sidebar-config.html +21 -0
- data/_includes/navigation/sidebar-nav.html +4 -0
- data/_includes/navigation/sidebar-pagetree.html +150 -0
- data/_includes/navigation/sidebar-right.html +3 -2
- data/_includes/navigation/unified-drawer.html +9 -3
- data/_includes/obsidian/full-graph.html +165 -136
- data/_layouts/404.html +260 -0
- data/_layouts/README.md +2 -0
- data/_layouts/article.html +7 -1
- data/_layouts/book-abc.html +106 -0
- data/_layouts/book-story.html +91 -0
- data/_layouts/book.html +113 -0
- data/_layouts/collection.html +17 -5
- data/_layouts/default.html +5 -3
- data/_layouts/home.html +5 -2
- data/_layouts/landing.html +9 -0
- data/_layouts/news.html +159 -33
- data/_layouts/root.html +29 -9
- data/_layouts/section.html +61 -17
- data/_sass/components/_book.scss +423 -0
- data/_sass/core/_navbar.scss +13 -0
- data/_sass/core/_obsidian.scss +295 -7
- data/_sass/layouts/_navbar-extras.scss +6 -1
- data/_sass/theme/_backgrounds.scss +21 -8
- data/assets/css/main.scss +1 -0
- data/assets/js/auto-hide-nav.js +5 -1
- data/assets/js/halfmoon.js +26 -0
- data/assets/js/obsidian-graph.js +707 -265
- data/assets/js/obsidian-local-graph.js +161 -54
- data/assets/js/search-modal.js +4 -1
- data/scripts/README.md +20 -26
- data/scripts/bin/audit-consumer +1 -1
- data/scripts/bin/manifest +31 -5
- data/scripts/bin/sync-plugins +0 -1
- data/scripts/bin/validate +5 -1
- data/scripts/dev/rasterize-svg.js +65 -0
- data/scripts/features/generate-preview-images +49 -1390
- data/scripts/features/install-preview-generator +55 -33
- data/scripts/install/README.md +55 -25
- data/scripts/install/ai/client.sh +302 -93
- data/scripts/install/ai/prompts/spec.schema.json +1 -1
- data/scripts/install/ai/prompts/wizard.system.md +8 -17
- data/scripts/install/ai/wizard.sh +10 -5
- data/scripts/install/apply.sh +7 -3
- data/scripts/install/cli.sh +54 -4
- data/scripts/install/config.sh +167 -0
- data/scripts/install/doctor.sh +38 -0
- data/scripts/install/plan.sh +10 -0
- data/scripts/install/spec.sh +15 -7
- data/scripts/install/template.sh +4 -0
- data/scripts/lib/README.md +1 -5
- data/scripts/lib/install/deploy/README.md +3 -9
- data/scripts/lib/preview_generator.py +2261 -1341
- data/scripts/propagate.rb +277 -0
- data/scripts/translate.rb +1204 -0
- metadata +34 -3
- data/_plugins/preview_image_generator.rb +0 -351
data/_sass/core/_obsidian.scss
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Feature: ZER0-045
|
|
1
2
|
// ============================================================================
|
|
2
3
|
// _obsidian.scss — Styles for Obsidian-flavoured Markdown features.
|
|
3
4
|
// Imported from _sass/custom.scss.
|
|
@@ -8,6 +9,9 @@
|
|
|
8
9
|
// - Note transclusion / image embeds
|
|
9
10
|
// - Callout cards beyond what Bootstrap's `.alert` provides
|
|
10
11
|
// - Backlinks panel
|
|
12
|
+
// - Full graph page (canvas shell, Obsidian-style controls, zoom bar,
|
|
13
|
+
// hover preview) — markup in _includes/obsidian/full-graph.html
|
|
14
|
+
// - Local graph side panel (FAB + offcanvas)
|
|
11
15
|
// ============================================================================
|
|
12
16
|
|
|
13
17
|
// --- Wiki-links ------------------------------------------------------------
|
|
@@ -196,23 +200,307 @@
|
|
|
196
200
|
}
|
|
197
201
|
}
|
|
198
202
|
|
|
203
|
+
// ----------------------------------------------------------------------------
|
|
204
|
+
// Full graph page — Obsidian-style site knowledge graph.
|
|
205
|
+
// Markup: _includes/obsidian/full-graph.html (included by
|
|
206
|
+
// pages/_docs/obsidian/graph.md); renderer: assets/js/obsidian-graph.js.
|
|
207
|
+
// The shell is the positioning context for the floating controls card, the
|
|
208
|
+
// zoom bar, and the hover preview card that overlay the cytoscape canvas.
|
|
209
|
+
// ----------------------------------------------------------------------------
|
|
210
|
+
.obsidian-graph-shell {
|
|
211
|
+
position: relative;
|
|
212
|
+
|
|
213
|
+
#obsidian-graph {
|
|
214
|
+
width: 100%;
|
|
215
|
+
height: 82vh;
|
|
216
|
+
min-height: 620px;
|
|
217
|
+
border: 1px solid rgba(var(--bs-border-color-rgb, 222, 226, 230), 0.55);
|
|
218
|
+
border-radius: var(--bs-border-radius-lg, 0.5rem);
|
|
219
|
+
background: rgba(var(--bs-body-bg-rgb, 255, 255, 255), 0.45);
|
|
220
|
+
-webkit-backdrop-filter: blur(14px) saturate(1.15);
|
|
221
|
+
backdrop-filter: blur(14px) saturate(1.15);
|
|
222
|
+
box-shadow:
|
|
223
|
+
0 1px 2px rgba(0, 0, 0, 0.03),
|
|
224
|
+
0 8px 24px rgba(0, 0, 0, 0.06),
|
|
225
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
|
226
|
+
position: relative;
|
|
227
|
+
overflow: hidden;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
[data-bs-theme="dark"] & #obsidian-graph {
|
|
231
|
+
background: rgba(var(--bs-body-bg-rgb, 33, 37, 41), 0.38);
|
|
232
|
+
box-shadow:
|
|
233
|
+
0 1px 2px rgba(0, 0, 0, 0.12),
|
|
234
|
+
0 8px 28px rgba(0, 0, 0, 0.22),
|
|
235
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.03);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// CSS-overlay fallback when the Fullscreen API is unavailable/blocked, plus
|
|
240
|
+
// the native :fullscreen state — both fill the viewport with a solid ground.
|
|
241
|
+
.obsidian-graph-shell-expanded {
|
|
242
|
+
position: fixed;
|
|
243
|
+
inset: 0;
|
|
244
|
+
z-index: var(--zer0-layer-offcanvas, 1045);
|
|
245
|
+
background: var(--bs-body-bg, #fff);
|
|
246
|
+
padding: 0.75rem;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.obsidian-graph-shell-expanded #obsidian-graph,
|
|
250
|
+
.obsidian-graph-shell:fullscreen #obsidian-graph {
|
|
251
|
+
height: 100%;
|
|
252
|
+
min-height: 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.obsidian-graph-shell:fullscreen {
|
|
256
|
+
background: var(--bs-body-bg, #fff);
|
|
257
|
+
padding: 0.75rem;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// --- Floating "Graph settings" card (Filters / Display / Forces) ------------
|
|
261
|
+
.obsidian-graph-controls {
|
|
262
|
+
position: absolute;
|
|
263
|
+
top: 0.75rem;
|
|
264
|
+
right: 0.75rem;
|
|
265
|
+
z-index: 20;
|
|
266
|
+
width: min(17.5rem, calc(100% - 1.5rem));
|
|
267
|
+
max-height: calc(100% - 1.5rem);
|
|
268
|
+
display: flex;
|
|
269
|
+
flex-direction: column;
|
|
270
|
+
background: rgba(var(--bs-body-bg-rgb, 255, 255, 255), 0.86);
|
|
271
|
+
-webkit-backdrop-filter: blur(10px) saturate(1.1);
|
|
272
|
+
backdrop-filter: blur(10px) saturate(1.1);
|
|
273
|
+
border: 1px solid var(--bs-border-color, #dee2e6);
|
|
274
|
+
border-radius: var(--bs-border-radius, 0.375rem);
|
|
275
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
|
276
|
+
overflow: hidden;
|
|
277
|
+
|
|
278
|
+
.obsidian-graph-controls-toggle {
|
|
279
|
+
display: flex;
|
|
280
|
+
align-items: center;
|
|
281
|
+
width: 100%;
|
|
282
|
+
text-align: left;
|
|
283
|
+
font-weight: 600;
|
|
284
|
+
color: var(--bs-body-color, #212529);
|
|
285
|
+
border: 0;
|
|
286
|
+
border-radius: 0;
|
|
287
|
+
|
|
288
|
+
&:focus-visible {
|
|
289
|
+
outline: 2px solid var(--bs-primary);
|
|
290
|
+
outline-offset: -2px;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.obsidian-graph-controls-chevron {
|
|
295
|
+
transition: transform 0.2s ease;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.obsidian-graph-controls-toggle[aria-expanded="true"] .obsidian-graph-controls-chevron {
|
|
299
|
+
transform: rotate(180deg);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.obsidian-graph-controls-body {
|
|
303
|
+
overflow-y: auto;
|
|
304
|
+
border-top: 1px solid var(--bs-border-color, #dee2e6);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.accordion {
|
|
308
|
+
--bs-accordion-bg: transparent;
|
|
309
|
+
font-size: 0.875rem;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.accordion-button {
|
|
313
|
+
font-size: 0.875rem;
|
|
314
|
+
font-weight: 600;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.form-label {
|
|
318
|
+
margin-bottom: 0.125rem;
|
|
319
|
+
color: var(--bs-secondary-color, #6c757d);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.form-range {
|
|
323
|
+
margin-bottom: 0.375rem;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Collection toggles double as the legend: color swatch + name + page count.
|
|
328
|
+
.obsidian-graph-collections {
|
|
329
|
+
max-height: 12.5rem;
|
|
330
|
+
overflow-y: auto;
|
|
331
|
+
|
|
332
|
+
.obsidian-graph-collection-filter {
|
|
333
|
+
margin-bottom: 0.125rem;
|
|
334
|
+
|
|
335
|
+
.form-check-label {
|
|
336
|
+
width: 100%;
|
|
337
|
+
cursor: pointer;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.swatch {
|
|
341
|
+
display: inline-block;
|
|
342
|
+
flex: 0 0 auto;
|
|
343
|
+
width: 0.7rem;
|
|
344
|
+
height: 0.7rem;
|
|
345
|
+
border-radius: 50%;
|
|
346
|
+
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.badge {
|
|
350
|
+
font-size: 0.7rem;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// --- Zoom / fit / fullscreen button stack -----------------------------------
|
|
356
|
+
.obsidian-graph-zoombar {
|
|
357
|
+
position: absolute;
|
|
358
|
+
right: 0.75rem;
|
|
359
|
+
bottom: 0.75rem;
|
|
360
|
+
z-index: 20;
|
|
361
|
+
border-radius: var(--bs-border-radius, 0.375rem);
|
|
362
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
|
|
363
|
+
overflow: hidden;
|
|
364
|
+
|
|
365
|
+
> .btn {
|
|
366
|
+
background: rgba(var(--bs-body-bg-rgb, 255, 255, 255), 0.88);
|
|
367
|
+
color: var(--bs-body-color, #212529);
|
|
368
|
+
border: 1px solid var(--bs-border-color, #dee2e6);
|
|
369
|
+
line-height: 1;
|
|
370
|
+
|
|
371
|
+
&:hover,
|
|
372
|
+
&:focus-visible {
|
|
373
|
+
background: var(--bs-tertiary-bg, #f8f9fa);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
&[aria-pressed="true"] {
|
|
377
|
+
background: rgba(var(--bs-primary-rgb), 0.12);
|
|
378
|
+
color: var(--bs-primary);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// --- Hover preview card (Obsidian-style page preview) -----------------------
|
|
384
|
+
.obsidian-graph-preview {
|
|
385
|
+
position: absolute;
|
|
386
|
+
z-index: 30;
|
|
387
|
+
width: min(17rem, calc(100% - 1.5rem));
|
|
388
|
+
pointer-events: none;
|
|
389
|
+
background: rgba(var(--bs-body-bg-rgb, 255, 255, 255), 0.94);
|
|
390
|
+
-webkit-backdrop-filter: blur(8px);
|
|
391
|
+
backdrop-filter: blur(8px);
|
|
392
|
+
border: 1px solid var(--bs-border-color, #dee2e6);
|
|
393
|
+
|
|
394
|
+
&[hidden] {
|
|
395
|
+
display: none;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.obsidian-graph-preview-swatch {
|
|
399
|
+
display: inline-block;
|
|
400
|
+
flex: 0 0 auto;
|
|
401
|
+
width: 0.65rem;
|
|
402
|
+
height: 0.65rem;
|
|
403
|
+
border-radius: 50%;
|
|
404
|
+
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.obsidian-graph-preview-excerpt {
|
|
408
|
+
display: -webkit-box;
|
|
409
|
+
-webkit-line-clamp: 3;
|
|
410
|
+
-webkit-box-orient: vertical;
|
|
411
|
+
overflow: hidden;
|
|
412
|
+
color: var(--bs-secondary-color, #6c757d);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// --- Stats badges, status line, tips box ------------------------------------
|
|
417
|
+
#obsidian-graph-stats {
|
|
418
|
+
display: flex;
|
|
419
|
+
flex-wrap: wrap;
|
|
420
|
+
gap: 0.375rem;
|
|
421
|
+
|
|
422
|
+
.badge {
|
|
423
|
+
font-size: 0.8125rem;
|
|
424
|
+
font-weight: 500;
|
|
425
|
+
padding: 0.35rem 0.6rem;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.obsidian-graph-status {
|
|
430
|
+
font-size: 0.8125rem;
|
|
431
|
+
color: var(--bs-secondary-color, #6c757d);
|
|
432
|
+
min-height: 1.25rem;
|
|
433
|
+
margin: 0.5rem 0 0;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.obsidian-graph-tips {
|
|
437
|
+
margin-top: 0.75rem;
|
|
438
|
+
padding: 0.625rem 0.75rem;
|
|
439
|
+
font-size: 0.8125rem;
|
|
440
|
+
color: var(--bs-secondary-color, #6c757d);
|
|
441
|
+
background: var(--bs-tertiary-bg, #f8f9fa);
|
|
442
|
+
border-left: 3px solid var(--bs-primary, #0d6efd);
|
|
443
|
+
border-radius: 0.25rem;
|
|
444
|
+
|
|
445
|
+
strong {
|
|
446
|
+
color: var(--bs-body-color, #212529);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Small screens: the floating card would cover most of the canvas — dock the
|
|
451
|
+
// controls above the graph instead, and shorten the canvas.
|
|
452
|
+
@media (max-width: 767.98px) {
|
|
453
|
+
.obsidian-graph-shell {
|
|
454
|
+
display: flex;
|
|
455
|
+
flex-direction: column;
|
|
456
|
+
|
|
457
|
+
#obsidian-graph {
|
|
458
|
+
height: 62vh;
|
|
459
|
+
min-height: 420px;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.obsidian-graph-controls {
|
|
464
|
+
position: static;
|
|
465
|
+
order: -1;
|
|
466
|
+
width: 100%;
|
|
467
|
+
max-height: none;
|
|
468
|
+
margin-bottom: 0.5rem;
|
|
469
|
+
backdrop-filter: none;
|
|
470
|
+
-webkit-backdrop-filter: none;
|
|
471
|
+
background: var(--bs-body-bg, #fff);
|
|
472
|
+
|
|
473
|
+
.obsidian-graph-controls-body {
|
|
474
|
+
max-height: 45vh;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
199
479
|
// ----------------------------------------------------------------------------
|
|
200
480
|
// Local graph side panel — Obsidian-style local graph view.
|
|
201
481
|
// Rendered by _includes/navigation/local-graph.html (body-level, after footer)
|
|
202
482
|
// and _includes/navigation/local-graph-fab.html (footer) via
|
|
203
483
|
// assets/js/obsidian-local-graph.js.
|
|
204
484
|
// ----------------------------------------------------------------------------
|
|
205
|
-
// ID selector
|
|
206
|
-
//
|
|
207
|
-
// rule
|
|
208
|
-
//
|
|
209
|
-
//
|
|
210
|
-
//
|
|
485
|
+
// ID selector kept for historical safety: `.zer0-bg-body` used to force
|
|
486
|
+
// `position: relative; z-index: 1` on every direct child (specificity 0,5,0),
|
|
487
|
+
// which beat the class rule and dropped the FAB into page flow. That elevation
|
|
488
|
+
// rule is gone (the body now isolates with the noise layer at z-index: -1 —
|
|
489
|
+
// see _sass/theme/_backgrounds.scss), but the id keeps the FAB immune to any
|
|
490
|
+
// future generic child rule. Mirrors `#aiChatToggle`. See ai-chat.html.
|
|
491
|
+
//
|
|
492
|
+
// Slot 2 on the left-side FAB stack: sits above the page-feedback FAB
|
|
493
|
+
// (slot 1 = var(--zer0-space-fab-offset)) — same stacking formula as
|
|
494
|
+
// .bd-toc-fab above #backToTopBtn on the right side.
|
|
211
495
|
#obsidianLocalGraphFab.obsidian-local-graph-fab {
|
|
212
496
|
position: fixed;
|
|
213
497
|
left: var(--zer0-space-fab-offset, 1rem);
|
|
214
498
|
right: auto;
|
|
215
|
-
bottom:
|
|
499
|
+
bottom: calc(
|
|
500
|
+
var(--zer0-space-fab-offset, 1rem) +
|
|
501
|
+
var(--zer0-space-fab-size, 3.5rem) +
|
|
502
|
+
var(--zer0-space-fab-gap, 0.75rem)
|
|
503
|
+
);
|
|
216
504
|
z-index: var(--zer0-layer-fab-local-graph);
|
|
217
505
|
|
|
218
506
|
&[hidden] {
|
|
@@ -80,7 +80,12 @@
|
|
|
80
80
|
&.bd-sidebar-fab--restore,
|
|
81
81
|
html.bd-sidebar-pref-hidden &.bd-sidebar-fab {
|
|
82
82
|
display: block !important;
|
|
83
|
-
|
|
83
|
+
// Stay at slot 2 (above the feedback FAB at slot 1) so neither overlaps.
|
|
84
|
+
bottom: calc(
|
|
85
|
+
var(--zer0-space-fab-offset, 1rem) +
|
|
86
|
+
var(--zer0-space-fab-size, 3.5rem) +
|
|
87
|
+
var(--zer0-space-fab-gap, 0.75rem)
|
|
88
|
+
);
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
@media (min-width: 992px) {
|
|
@@ -107,14 +107,27 @@
|
|
|
107
107
|
.zer0-bg-body {
|
|
108
108
|
@include zer0-bg-noise;
|
|
109
109
|
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
|
|
110
|
+
// The body forms its own stacking context (isolation) and the noise overlay
|
|
111
|
+
// is pushed into the NEGATIVE layer, so in-flow content naturally paints
|
|
112
|
+
// above the texture with no per-child elevation at all.
|
|
113
|
+
//
|
|
114
|
+
// History: this block used to elevate every direct child instead
|
|
115
|
+
// (`> *:not(.fixed-top):not(.position-fixed):not(.offcanvas):not(.modal)
|
|
116
|
+
// { position: relative; z-index: 1; }`). That rule (specificity 0,5,0)
|
|
117
|
+
// caused three consumer-reported mobile bugs:
|
|
118
|
+
// 1. it beat FAB class rules' `position: fixed` (0,1,0), dropping FABs
|
|
119
|
+
// into page flow and adding 16px of horizontal scroll;
|
|
120
|
+
// 2. it made <main> a z-index:1 stacking context, trapping the nested
|
|
121
|
+
// #bdSidebar offcanvas (z-index 1045) below the fixed header (1030) —
|
|
122
|
+
// its close button was unreachable on mobile;
|
|
123
|
+
// 3. every fixed/overlay descendant needed a bespoke carve-out or an
|
|
124
|
+
// id-selector specificity escape (see _sass/core/_obsidian.scss).
|
|
125
|
+
// Do NOT reintroduce a child z-index elevation here.
|
|
126
|
+
isolation: isolate;
|
|
127
|
+
|
|
128
|
+
&::after {
|
|
129
|
+
z-index: -1;
|
|
130
|
+
}
|
|
118
131
|
}
|
|
119
132
|
|
|
120
133
|
.zer0-bg-surface {
|
data/assets/css/main.scss
CHANGED
data/assets/js/auto-hide-nav.js
CHANGED
|
@@ -30,10 +30,14 @@
|
|
|
30
30
|
// Check for reduced motion preference
|
|
31
31
|
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
32
32
|
|
|
33
|
-
// Calculate and set body padding to prevent content jump
|
|
33
|
+
// Calculate and set body padding to prevent content jump.
|
|
34
|
+
// The measured height is also published as --zer0-header-height so
|
|
35
|
+
// stylesheets (theme or consumer) can align overlays with the real
|
|
36
|
+
// header instead of hard-coding its pixel height.
|
|
34
37
|
function updateBodyPadding() {
|
|
35
38
|
const navbarHeight = navbar.offsetHeight;
|
|
36
39
|
document.body.style.paddingTop = navbarHeight + 'px';
|
|
40
|
+
document.documentElement.style.setProperty('--zer0-header-height', navbarHeight + 'px');
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
// Initial padding setup
|
data/assets/js/halfmoon.js
CHANGED
|
@@ -7,15 +7,35 @@
|
|
|
7
7
|
(() => {
|
|
8
8
|
'use strict'
|
|
9
9
|
|
|
10
|
+
// Site config surfaced by root.html as <html> data attributes:
|
|
11
|
+
// - data-color-mode-lock: "true" pins the configured mode; visitor
|
|
12
|
+
// preference and OS scheme are ignored and the toggles are inert
|
|
13
|
+
// (core/color-mode-init.html applies the same rules pre-paint).
|
|
14
|
+
// - data-color-mode-default: the site's configured starting mode. It
|
|
15
|
+
// must rank ABOVE the OS preference here — otherwise this script
|
|
16
|
+
// overrides the init script's choice on first visit and the page
|
|
17
|
+
// flips modes after load.
|
|
18
|
+
const rootEl = document.documentElement
|
|
19
|
+
const isLocked = rootEl.getAttribute('data-color-mode-lock') === 'true'
|
|
20
|
+
const configDefault = rootEl.getAttribute('data-color-mode-default') || 'auto'
|
|
21
|
+
|
|
10
22
|
const getStoredTheme = () => localStorage.getItem('theme')
|
|
11
23
|
const setStoredTheme = theme => localStorage.setItem('theme', theme)
|
|
12
24
|
|
|
13
25
|
const getPreferredTheme = () => {
|
|
26
|
+
if (isLocked) {
|
|
27
|
+
return configDefault === 'auto' ? 'dark' : configDefault
|
|
28
|
+
}
|
|
29
|
+
|
|
14
30
|
const storedTheme = getStoredTheme()
|
|
15
31
|
if (storedTheme) {
|
|
16
32
|
return storedTheme
|
|
17
33
|
}
|
|
18
34
|
|
|
35
|
+
if (configDefault !== 'auto') {
|
|
36
|
+
return configDefault
|
|
37
|
+
}
|
|
38
|
+
|
|
19
39
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
|
20
40
|
}
|
|
21
41
|
|
|
@@ -65,6 +85,9 @@
|
|
|
65
85
|
}
|
|
66
86
|
|
|
67
87
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
|
88
|
+
if (isLocked) {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
68
91
|
const storedTheme = getStoredTheme()
|
|
69
92
|
if (storedTheme !== 'light' && storedTheme !== 'dark') {
|
|
70
93
|
setTheme(getPreferredTheme())
|
|
@@ -77,6 +100,9 @@
|
|
|
77
100
|
document.querySelectorAll('[data-bs-theme-value]')
|
|
78
101
|
.forEach(toggle => {
|
|
79
102
|
toggle.addEventListener('click', () => {
|
|
103
|
+
if (isLocked) {
|
|
104
|
+
return
|
|
105
|
+
}
|
|
80
106
|
const theme = toggle.getAttribute('data-bs-theme-value')
|
|
81
107
|
setStoredTheme(theme)
|
|
82
108
|
setTheme(theme)
|