jekyll-theme-zer0 1.27.0 → 1.29.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 +812 -13
- data/_data/backlog.yml +356 -2
- data/_data/consumers.yml +252 -0
- data/_data/features.yml +234 -5
- data/_data/i18n/fr.yml +103 -0
- data/_data/i18n/manifest.yml +1529 -0
- data/_data/ingredient_densities.yml +122 -0
- data/_data/navigation/docs.yml +2 -0
- data/_data/navigation/main.yml +22 -0
- data/_data/recipe_courses.yml +64 -0
- data/_data/series.yml +19 -0
- data/_data/theme-manifest.yml +387 -277
- data/_data/ui-text.yml +8 -0
- data/_includes/README.md +36 -3
- 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/background-customizer.html +2 -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/cookie-consent.html +4 -4
- data/_includes/components/data-card.html +95 -0
- data/_includes/components/halfmoon.html +5 -1
- data/_includes/components/info-section.html +8 -3
- data/_includes/components/language-toggle.html +168 -21
- data/_includes/components/page-feedback.html +65 -2
- data/_includes/components/page-views-init.html +55 -0
- data/_includes/components/page-views.html +33 -0
- data/_includes/components/recipe-card.html +67 -0
- data/_includes/components/recipe-duration.html +50 -0
- data/_includes/components/recipe-grams.html +58 -0
- data/_includes/components/recipe-index.html +96 -0
- data/_includes/components/recipe-ingredients.html +90 -0
- data/_includes/components/recipe-meta.html +96 -0
- data/_includes/components/recipe-nutrition.html +57 -0
- data/_includes/components/recipe-qty.html +73 -0
- data/_includes/components/recipe-ratio.html +151 -0
- data/_includes/components/recipe-scaler.html +73 -0
- data/_includes/components/recipe-steps.html +86 -0
- data/_includes/components/recipe-temp.html +45 -0
- data/_includes/components/search-modal.html +2 -2
- data/_includes/components/shortcuts-modal.html +3 -0
- data/_includes/components/theme-controls-bar.html +10 -2
- data/_includes/components/theme-customizer.html +8 -2
- data/_includes/components/theme-info.html +8 -1
- data/_includes/content/jsonld-software.html +22 -3
- 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 +18 -16
- data/_includes/core/head.html +21 -0
- data/_includes/core/header.html +7 -4
- 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/local-graph.html +28 -2
- data/_includes/navigation/nav-tree.html +3 -3
- data/_includes/navigation/section-sidebar.html +93 -11
- data/_includes/navigation/sidebar-config.html +21 -0
- data/_includes/navigation/sidebar-left.html +2 -1
- data/_includes/navigation/sidebar-nav.html +4 -0
- data/_includes/navigation/sidebar-pagetree.html +150 -0
- data/_includes/navigation/sidebar-right.html +2 -1
- data/_includes/navigation/unified-drawer.html +8 -2
- data/_includes/obsidian/full-graph.html +165 -136
- data/_includes/setup/wizard.html +173 -86
- data/_includes/stats/stats-metrics.html +2 -2
- data/_layouts/404.html +260 -0
- data/_layouts/README.md +4 -0
- data/_layouts/admin.html +2 -2
- data/_layouts/article.html +5 -0
- 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/cookbook.html +88 -0
- data/_layouts/default.html +4 -4
- data/_layouts/home.html +5 -2
- data/_layouts/landing.html +9 -0
- data/_layouts/news.html +155 -31
- data/_layouts/recipe.html +274 -0
- data/_layouts/root.html +38 -5
- data/_layouts/section.html +96 -25
- data/_sass/components/_book.scss +423 -0
- data/_sass/components/_callout.scss +1 -1
- data/_sass/components/_footer.scss +37 -1
- data/_sass/components/_page-views.scss +36 -0
- data/_sass/components/_recipe.scss +506 -0
- data/_sass/components/_setup-wizard.scss +235 -0
- data/_sass/components/_ui-enhancements.scss +6 -6
- data/_sass/core/_navbar.scss +263 -15
- data/_sass/core/_obsidian.scss +286 -6
- data/_sass/layouts/_landing.scss +2 -2
- data/_sass/theme/_backgrounds.scss +21 -8
- data/_sass/tokens/_color.scss +6 -0
- data/_sass/tokens/_index.scss +2 -0
- data/_sass/tokens/_radius.scss +21 -0
- data/_sass/tokens/_typography.scss +4 -0
- data/_sass/utilities/_focus.scss +14 -0
- data/assets/css/main.scss +4 -0
- data/assets/js/auto-hide-nav.js +5 -1
- data/assets/js/halfmoon.js +26 -0
- data/assets/js/modules/navigation/navbar.js +55 -0
- data/assets/js/obsidian-graph.js +702 -264
- data/assets/js/obsidian-local-graph.js +161 -54
- data/assets/js/page-views.js +372 -0
- data/assets/js/recipe-scaler.js +501 -0
- data/assets/js/search-modal.js +14 -1
- data/assets/js/setup-wizard.js +322 -20
- data/scripts/README.md +29 -0
- data/scripts/bin/audit-consumer +39 -7
- data/scripts/bin/giscus-discussions +213 -14
- data/scripts/bin/manifest +66 -16
- data/scripts/bin/validate +5 -1
- data/scripts/ci/agent_review_result.py +164 -0
- data/scripts/ci/test_agent_review_result.py +172 -0
- data/scripts/design-system-check.rb +170 -0
- data/scripts/install/README.md +47 -6
- data/scripts/install/ai/client.sh +302 -93
- data/scripts/install/ai/prompts/spec.schema.json +1 -1
- 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/audit.sh +42 -2
- data/scripts/lint-liquid-raw.rb +137 -0
- data/scripts/propagate.rb +277 -0
- data/scripts/test/lib/run_tests.sh +2 -1
- data/scripts/test/lib/test_agent_review_result.sh +27 -0
- data/scripts/translate.rb +161 -15
- metadata +56 -2
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Setup wizard (_includes/setup/wizard.html + assets/js/setup-wizard.js)
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Feature: ZER0-067 · Redesign: T-040 / #408
|
|
5
|
+
//
|
|
6
|
+
// Three columns at lg+ (stepper / steps / live preview), stacked below. The
|
|
7
|
+
// two rules that matter most:
|
|
8
|
+
//
|
|
9
|
+
// 1. `.wizard-panes` is a GRID with every pane in the same cell, so the
|
|
10
|
+
// container is always exactly as tall as the tallest step; `.wizard-nav`
|
|
11
|
+
// is then pushed to the bottom of the card with `margin-top: auto`.
|
|
12
|
+
// Neither alone is enough: the grid stops the CONTAINER resizing, and the
|
|
13
|
+
// auto margin stops the BUTTONS floating up inside a short step.
|
|
14
|
+
// Together, Back/Next sit at the same y offset on every step.
|
|
15
|
+
// 2. The preview panel is sticky and always present, so it needs its own
|
|
16
|
+
// scroll region rather than growing the page.
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
// -----------------------------------------------------------------------------
|
|
20
|
+
// Vertical stepper
|
|
21
|
+
// -----------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
.wizard-stepper-wrap {
|
|
24
|
+
top: 1.5rem; // paired with .sticky-lg-top in the markup
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.wizard-stepper {
|
|
28
|
+
gap: 0.25rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.wizard-step {
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
gap: 0.75rem;
|
|
35
|
+
width: 100%;
|
|
36
|
+
padding: 0.625rem 0.75rem;
|
|
37
|
+
min-height: 44px; // WCAG touch target
|
|
38
|
+
text-align: left;
|
|
39
|
+
color: var(--zer0-color-ink-muted);
|
|
40
|
+
background: none;
|
|
41
|
+
border: 0;
|
|
42
|
+
border-radius: var(--zer0-radius-sm, 0.375rem);
|
|
43
|
+
transition: background-color 0.15s ease, color 0.15s ease;
|
|
44
|
+
|
|
45
|
+
&:hover:not(:disabled) {
|
|
46
|
+
color: var(--zer0-color-ink, inherit);
|
|
47
|
+
background: var(--zer0-color-bg-muted);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&:focus-visible {
|
|
51
|
+
outline: 2px solid var(--bs-primary);
|
|
52
|
+
outline-offset: 2px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Upcoming, and not reachable until every earlier step validates.
|
|
56
|
+
&.is-locked,
|
|
57
|
+
&:disabled {
|
|
58
|
+
opacity: 0.45;
|
|
59
|
+
cursor: not-allowed;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
&.is-active {
|
|
63
|
+
font-weight: 600;
|
|
64
|
+
color: var(--zer0-color-ink, inherit);
|
|
65
|
+
background: var(--zer0-color-bg-muted);
|
|
66
|
+
|
|
67
|
+
.wizard-step-marker {
|
|
68
|
+
color: #fff;
|
|
69
|
+
background: var(--bs-primary);
|
|
70
|
+
border-color: var(--bs-primary);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
&.is-done .wizard-step-marker {
|
|
75
|
+
color: var(--bs-success, #198754);
|
|
76
|
+
border-color: var(--bs-success, #198754);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.wizard-step-marker {
|
|
81
|
+
display: inline-flex;
|
|
82
|
+
align-items: center;
|
|
83
|
+
justify-content: center;
|
|
84
|
+
flex-shrink: 0;
|
|
85
|
+
width: 2rem;
|
|
86
|
+
height: 2rem;
|
|
87
|
+
font-size: 0.9rem;
|
|
88
|
+
border: 1px solid var(--bs-border-color);
|
|
89
|
+
border-radius: 50%;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.wizard-step-text {
|
|
93
|
+
min-width: 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.wizard-step-label {
|
|
97
|
+
display: block;
|
|
98
|
+
overflow: hidden;
|
|
99
|
+
text-overflow: ellipsis;
|
|
100
|
+
white-space: nowrap;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// "Draft saved" acknowledgement. Kept in the layout (no display toggling) so
|
|
104
|
+
// its appearance never shifts the stepper.
|
|
105
|
+
.wizard-draft-chip {
|
|
106
|
+
margin: 0.75rem 0 0;
|
|
107
|
+
padding: 0.25rem 0.5rem;
|
|
108
|
+
font-size: 0.75rem;
|
|
109
|
+
color: var(--bs-success, #198754);
|
|
110
|
+
opacity: 0;
|
|
111
|
+
transition: opacity 0.2s ease;
|
|
112
|
+
|
|
113
|
+
&.is-visible {
|
|
114
|
+
opacity: 1;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// -----------------------------------------------------------------------------
|
|
119
|
+
// Step panes — the stable-height half
|
|
120
|
+
// -----------------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
.wizard-panes {
|
|
123
|
+
// Every pane is stacked in ONE grid cell, so the row's height is
|
|
124
|
+
// max(pane heights) — computed by the browser, continuously, exactly.
|
|
125
|
+
//
|
|
126
|
+
// This used to be a flex column whose min-height JS measured and wrote
|
|
127
|
+
// inline. Measuring a box you have to un-hide, lay out, read and restore is
|
|
128
|
+
// a guess: it came back ~16px short of the tallest pane, and the shortest
|
|
129
|
+
// step's Back/Next sat 16px higher than everywhere else. Grid asks the
|
|
130
|
+
// layout engine the same question and gets the answer right, on every
|
|
131
|
+
// reflow, with no resize listener.
|
|
132
|
+
display: grid;
|
|
133
|
+
min-height: 26rem; // floor for the degenerate case of no panes
|
|
134
|
+
|
|
135
|
+
// The selector carries `.tab-content` purely for specificity: Bootstrap's
|
|
136
|
+
// `.tab-content > .tab-pane { display: none }` would otherwise take the
|
|
137
|
+
// cell's only occupant out of the grid on a tie.
|
|
138
|
+
&.tab-content > .tab-pane {
|
|
139
|
+
display: flex;
|
|
140
|
+
flex-direction: column;
|
|
141
|
+
grid-area: 1 / 1; // one cell, all panes
|
|
142
|
+
|
|
143
|
+
// Inactive panes stay in layout — that is the whole point — but must not
|
|
144
|
+
// be seen, focused, clicked, or read out. `visibility: hidden` does all
|
|
145
|
+
// four (it removes the subtree from the a11y tree and from the tab
|
|
146
|
+
// order), which `opacity: 0` alone would not.
|
|
147
|
+
visibility: hidden;
|
|
148
|
+
pointer-events: none;
|
|
149
|
+
|
|
150
|
+
&.active {
|
|
151
|
+
visibility: visible;
|
|
152
|
+
pointer-events: auto;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
> .tab-pane > .card {
|
|
157
|
+
display: flex;
|
|
158
|
+
flex: 1 1 auto;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
> .tab-pane > .card > .card-body {
|
|
162
|
+
display: flex;
|
|
163
|
+
flex: 1 1 auto;
|
|
164
|
+
flex-direction: column;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Pinned to the bottom of the card, so a short step does not float its
|
|
169
|
+
// Back/Next up the page relative to a tall one.
|
|
170
|
+
//
|
|
171
|
+
// Pinning the row's BOTTOM is only half the job: the test measures the Next
|
|
172
|
+
// button's TOP, so anything that changes the row's height moves it. Two things
|
|
173
|
+
// did, and both are fixed here rather than in the assertion.
|
|
174
|
+
.wizard-nav {
|
|
175
|
+
// 1. Never a block box. Step 1's nav is `text-end` with no `d-flex`, so its
|
|
176
|
+
// button was an inline-block on a line box and sat on the baseline — the
|
|
177
|
+
// descender space below it left that button ~2px above every other step's.
|
|
178
|
+
// `flex-end` is the base; the later steps' `justify-content-between`
|
|
179
|
+
// utility (Bootstrap emits `!important`) still wins where it is applied.
|
|
180
|
+
display: flex;
|
|
181
|
+
align-items: center;
|
|
182
|
+
justify-content: flex-end;
|
|
183
|
+
gap: 0.5rem;
|
|
184
|
+
margin-top: auto;
|
|
185
|
+
padding-top: 1rem;
|
|
186
|
+
|
|
187
|
+
// 2. Never let a label wrap. In the real three-column layout the middle
|
|
188
|
+
// column is ~270px, and "Review & Download" wrapped to a second line —
|
|
189
|
+
// making that one button a line-height taller. With the row pinned to the
|
|
190
|
+
// bottom, the extra line pushes the button's TOP up instead of its bottom
|
|
191
|
+
// down, which is the 16px the offset test caught on step 4.
|
|
192
|
+
.btn {
|
|
193
|
+
white-space: nowrap;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// -----------------------------------------------------------------------------
|
|
198
|
+
// Persistent live preview
|
|
199
|
+
// -----------------------------------------------------------------------------
|
|
200
|
+
|
|
201
|
+
.wizard-preview {
|
|
202
|
+
top: 1.5rem; // paired with .sticky-lg-top
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.wizard-preview-code {
|
|
206
|
+
max-height: 60vh;
|
|
207
|
+
margin-bottom: 0;
|
|
208
|
+
overflow: auto;
|
|
209
|
+
font-size: 0.78rem;
|
|
210
|
+
line-height: 1.45;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.wizard-preview-live {
|
|
214
|
+
font-size: 0.65rem;
|
|
215
|
+
text-transform: uppercase;
|
|
216
|
+
letter-spacing: 0.04em;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Below lg the three columns stack; the preview is no longer sticky and a
|
|
220
|
+
// shorter scroll region reads better under the form.
|
|
221
|
+
@media (max-width: 991.98px) {
|
|
222
|
+
.wizard-preview-code {
|
|
223
|
+
max-height: 20rem;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.wizard-stepper {
|
|
227
|
+
flex-direction: row !important;
|
|
228
|
+
flex-wrap: wrap;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.wizard-step {
|
|
232
|
+
width: auto;
|
|
233
|
+
flex: 1 1 auto;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
@@ -82,7 +82,7 @@ img {
|
|
|
82
82
|
left: 50%;
|
|
83
83
|
width: 0;
|
|
84
84
|
height: 0;
|
|
85
|
-
border-radius:
|
|
85
|
+
border-radius: var(--zer0-radius-circle);
|
|
86
86
|
background: rgba(255, 255, 255, 0.2);
|
|
87
87
|
transform: translate(-50%, -50%);
|
|
88
88
|
transition: width 0.6s, height 0.6s;
|
|
@@ -405,7 +405,7 @@ a:not(.btn) {
|
|
|
405
405
|
.btn {
|
|
406
406
|
.ripple {
|
|
407
407
|
position: absolute;
|
|
408
|
-
border-radius:
|
|
408
|
+
border-radius: var(--zer0-radius-circle);
|
|
409
409
|
background: rgba(255, 255, 255, 0.6);
|
|
410
410
|
transform: scale(0);
|
|
411
411
|
animation: ripple-animation 0.6s ease-out;
|
|
@@ -424,7 +424,7 @@ a:not(.btn) {
|
|
|
424
424
|
@media (max-width: 991.98px) {
|
|
425
425
|
.navbar-collapse {
|
|
426
426
|
background-color: var(--bs-body-bg);
|
|
427
|
-
border-radius:
|
|
427
|
+
border-radius: var(--zer0-radius-lg);
|
|
428
428
|
margin-top: 1rem;
|
|
429
429
|
padding: 1rem;
|
|
430
430
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
@@ -432,7 +432,7 @@ a:not(.btn) {
|
|
|
432
432
|
|
|
433
433
|
.navbar-nav .nav-link {
|
|
434
434
|
padding: 0.75rem 1rem;
|
|
435
|
-
border-radius:
|
|
435
|
+
border-radius: var(--zer0-radius);
|
|
436
436
|
transition: all 0.2s ease;
|
|
437
437
|
|
|
438
438
|
&:hover {
|
|
@@ -506,7 +506,7 @@ a:not(.btn) {
|
|
|
506
506
|
*:focus-visible {
|
|
507
507
|
outline: 2px solid var(--bs-primary);
|
|
508
508
|
outline-offset: 2px;
|
|
509
|
-
border-radius:
|
|
509
|
+
border-radius: var(--zer0-radius-sm);
|
|
510
510
|
}
|
|
511
511
|
|
|
512
512
|
// Enhanced active link states
|
|
@@ -530,7 +530,7 @@ a:not(.btn) {
|
|
|
530
530
|
// Better table responsiveness
|
|
531
531
|
@media (max-width: 768px) {
|
|
532
532
|
.table-responsive {
|
|
533
|
-
border-radius:
|
|
533
|
+
border-radius: var(--zer0-radius-lg);
|
|
534
534
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
535
535
|
}
|
|
536
536
|
|
data/_sass/core/_navbar.scss
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
// - Desktop >= 992px (inline nav; label density via @container bd-nav)
|
|
8
8
|
// - Mobile < 992px (offcanvas)
|
|
9
9
|
// Nav label tiers (center track / bd-nav container width):
|
|
10
|
-
// - >=
|
|
11
|
-
// -
|
|
10
|
+
// - >= 51rem (~816px): icon + full label
|
|
11
|
+
// - 41-50.99rem: label only (icons dropped so the labels still fit)
|
|
12
|
+
// - < 41rem (~656px): icon-only (tooltips on lg–xl viewports)
|
|
12
13
|
// ==============================================================================
|
|
13
14
|
|
|
14
15
|
// -----------------------------------------------------------------------------
|
|
@@ -399,16 +400,22 @@
|
|
|
399
400
|
transform: rotate(180deg);
|
|
400
401
|
}
|
|
401
402
|
|
|
402
|
-
//
|
|
403
|
-
//
|
|
404
|
-
//
|
|
405
|
-
|
|
403
|
+
// Label density degrades in three tiers, measured on the center track
|
|
404
|
+
// (the `bd-nav` container), so items fit instead of ellipsizing:
|
|
405
|
+
// >= 51rem (816px) icon + label — the roomy default
|
|
406
|
+
// 41-50.99rem label only — icons dropped to buy ~20px/item
|
|
407
|
+
// < 41rem (656px) icon only — labels no longer fit at all
|
|
408
|
+
// Each boundary is the MEASURED width the tier below it needs for the
|
|
409
|
+
// theme's seven demo items (815px with icons, 647px without), so a tier only
|
|
410
|
+
// engages once its own content fits. Items keep min-width:0 + ellipsis as the
|
|
411
|
+
// last-resort safety net for consumers with more or longer entries.
|
|
412
|
+
@container bd-nav (min-width: 41rem) {
|
|
406
413
|
#bdNavbar .navbar-nav {
|
|
407
414
|
gap: 0.125rem;
|
|
408
415
|
}
|
|
409
416
|
|
|
410
417
|
#bdNavbar .nav-link {
|
|
411
|
-
padding: 0.375rem
|
|
418
|
+
padding: 0.375rem;
|
|
412
419
|
}
|
|
413
420
|
|
|
414
421
|
#bdNavbar .nav-link .nav-link-text {
|
|
@@ -462,14 +469,36 @@
|
|
|
462
469
|
min-width: 1.25rem;
|
|
463
470
|
min-height: 0;
|
|
464
471
|
width: 1.25rem;
|
|
465
|
-
padding-left: 0
|
|
466
|
-
padding-right: 0
|
|
472
|
+
padding-left: 0;
|
|
473
|
+
padding-right: 0;
|
|
467
474
|
margin-left: 0 !important;
|
|
468
475
|
}
|
|
469
476
|
}
|
|
470
477
|
|
|
471
|
-
//
|
|
472
|
-
|
|
478
|
+
// Middle tier — the labels fit but the icons no longer do. Dropping the
|
|
479
|
+
// decorative icon (the label is the accessible name) and tightening the
|
|
480
|
+
// chevron buys back roughly 20px per item, which is the difference between
|
|
481
|
+
// "Notebooks" and "N…" at 992-1200px viewports.
|
|
482
|
+
@container bd-nav (min-width: 41rem) and (max-width: 50.99rem) {
|
|
483
|
+
#bdNavbar .nav-link i {
|
|
484
|
+
display: none;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
#bdNavbar .nav-item > .nav-link:not(.dropdown-toggle-split),
|
|
488
|
+
#bdNavbar .nav-hover-dropdown > .nav-link:first-child {
|
|
489
|
+
gap: 0;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Scoped with #bdNavbar to outrank the shared base rule at the top of this
|
|
493
|
+
// file, which sets the chevron to 1.5rem.
|
|
494
|
+
#bdNavbar .nav-hover-dropdown > .dropdown-toggle-split {
|
|
495
|
+
min-width: 1rem;
|
|
496
|
+
width: 1rem;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Icon-only when the center track is too narrow even for bare labels
|
|
501
|
+
@container bd-nav (max-width: 40.99rem) {
|
|
473
502
|
@include navbar-nav-icon-only;
|
|
474
503
|
}
|
|
475
504
|
}
|
|
@@ -489,6 +518,40 @@
|
|
|
489
518
|
--bs-offcanvas-width: min(21rem, 86vw);
|
|
490
519
|
}
|
|
491
520
|
|
|
521
|
+
// #bdNavbar lives INSIDE the fixed header, whose stacking context sits at
|
|
522
|
+
// Bootstrap's $zindex-fixed (1030) — below the body-level offcanvas
|
|
523
|
+
// backdrop (1040). The menu's own z-index (1045) only orders it within the
|
|
524
|
+
// header's context, so without help the whole open menu paints BEHIND the
|
|
525
|
+
// backdrop and none of its links are tappable. Lift the header above the
|
|
526
|
+
// backdrop only while its offcanvas is opening/open/closing. Browsers
|
|
527
|
+
// without :has() just keep the old (dimmed-menu) behavior.
|
|
528
|
+
body:has(#bdNavbar.offcanvas-lg.showing) header.fixed-top,
|
|
529
|
+
body:has(#bdNavbar.offcanvas-lg.show) header.fixed-top,
|
|
530
|
+
body:has(#bdNavbar.offcanvas-lg.hiding) header.fixed-top {
|
|
531
|
+
z-index: 1046; // $zindex-offcanvas (1045) + 1
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// ...but that lift must never bury Settings. #info-section is a body-level
|
|
535
|
+
// offcanvas at the SAME edge and the same z-index (1045), so while the nav
|
|
536
|
+
// menu is still on screen — including the ~300ms `.hiding` tail after a tap
|
|
537
|
+
// on its own "Settings" item — the lifted header painted the whole Settings
|
|
538
|
+
// panel out of sight. Drop the header back below the offcanvas layer for as
|
|
539
|
+
// long as Settings is on screen; navbar.js also closes the nav menu first so
|
|
540
|
+
// the two panels do not overlap at all in browsers that support it.
|
|
541
|
+
body:has(#info-section.offcanvas.showing) header.fixed-top,
|
|
542
|
+
body:has(#info-section.offcanvas.show) header.fixed-top,
|
|
543
|
+
body:has(#info-section.offcanvas.hiding) header.fixed-top {
|
|
544
|
+
z-index: 1030; // $zindex-fixed — back under the offcanvas backdrop
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Belt and braces for browsers without :has() — Settings outranks the header
|
|
548
|
+
// stacking context on its own.
|
|
549
|
+
#info-section.offcanvas.showing,
|
|
550
|
+
#info-section.offcanvas.show,
|
|
551
|
+
#info-section.offcanvas.hiding {
|
|
552
|
+
z-index: 1047; // above the lifted header (1046)
|
|
553
|
+
}
|
|
554
|
+
|
|
492
555
|
// Wrapper is inert on mobile so offcanvas layout matches pre-wrapper structure
|
|
493
556
|
#bdNavbar .bd-navbar-nav-viewport {
|
|
494
557
|
display: contents;
|
|
@@ -818,6 +881,156 @@
|
|
|
818
881
|
}
|
|
819
882
|
}
|
|
820
883
|
|
|
884
|
+
// -----------------------------------------------------------------------------
|
|
885
|
+
// Language section inside the Settings offcanvas
|
|
886
|
+
// (components/language-toggle.html variant="panel")
|
|
887
|
+
// -----------------------------------------------------------------------------
|
|
888
|
+
|
|
889
|
+
.nav-lang-panel .nav-lang-options {
|
|
890
|
+
--bs-list-group-border-radius: 0.375rem;
|
|
891
|
+
|
|
892
|
+
.list-group-item {
|
|
893
|
+
display: flex;
|
|
894
|
+
align-items: center;
|
|
895
|
+
gap: 0.625rem;
|
|
896
|
+
padding: 0.5rem 0.75rem;
|
|
897
|
+
min-height: 44px; // WCAG touch target
|
|
898
|
+
font-size: 0.9375rem;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
.nav-lang-code {
|
|
902
|
+
flex-shrink: 0;
|
|
903
|
+
min-width: 2.25rem;
|
|
904
|
+
padding: 0.05rem 0.35rem;
|
|
905
|
+
font-family: var(--zer0-font-mono);
|
|
906
|
+
font-size: 0.7rem;
|
|
907
|
+
line-height: 1.4;
|
|
908
|
+
text-align: center;
|
|
909
|
+
color: var(--zer0-color-ink-muted);
|
|
910
|
+
background: var(--zer0-color-bg-muted);
|
|
911
|
+
border-radius: var(--zer0-radius-sm);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
.nav-lang-name {
|
|
915
|
+
min-width: 0;
|
|
916
|
+
overflow: hidden;
|
|
917
|
+
text-overflow: ellipsis;
|
|
918
|
+
white-space: nowrap;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// -----------------------------------------------------------------------------
|
|
923
|
+
// Language menu — shared by BOTH variants (T-038 / #406)
|
|
924
|
+
// -----------------------------------------------------------------------------
|
|
925
|
+
// The current language reads as "you are here", not as a selected nav item, so
|
|
926
|
+
// it gets a tint + check icon rather than Bootstrap's `.active` primary fill.
|
|
927
|
+
// Rows are links even when a translation does not exist yet (they fall back to
|
|
928
|
+
// the source page), and the reason lives in one footnote instead of on every
|
|
929
|
+
// row — per-row "(Not yet translated)" was what made the menu wide.
|
|
930
|
+
|
|
931
|
+
.nav-lang-item {
|
|
932
|
+
display: flex;
|
|
933
|
+
align-items: center;
|
|
934
|
+
gap: 0.625rem;
|
|
935
|
+
|
|
936
|
+
&.is-current {
|
|
937
|
+
font-weight: 600;
|
|
938
|
+
color: var(--zer0-color-ink, inherit);
|
|
939
|
+
background: var(--zer0-color-bg-muted);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// The marker is the footnote's anchor; the note itself carries the wording.
|
|
943
|
+
&.is-untranslated .nav-lang-name {
|
|
944
|
+
color: var(--zer0-color-ink-muted);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
.nav-lang-check {
|
|
949
|
+
flex-shrink: 0;
|
|
950
|
+
margin-left: auto;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
.nav-lang-mark {
|
|
954
|
+
flex-shrink: 0;
|
|
955
|
+
margin-left: auto;
|
|
956
|
+
color: var(--zer0-color-ink-muted);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// "auto" — this language was machine-generated (scripts/translate.rb).
|
|
960
|
+
.nav-lang-auto {
|
|
961
|
+
flex-shrink: 0;
|
|
962
|
+
padding: 0.05rem 0.3rem;
|
|
963
|
+
font-family: var(--zer0-font-mono);
|
|
964
|
+
font-size: 0.625rem;
|
|
965
|
+
line-height: 1.4;
|
|
966
|
+
text-transform: lowercase;
|
|
967
|
+
color: var(--zer0-color-ink-muted);
|
|
968
|
+
background: var(--zer0-color-bg-muted);
|
|
969
|
+
border-radius: var(--zer0-radius-sm);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// The one footnote that replaced the per-row notices. It is the only element
|
|
973
|
+
// in the menu allowed to wrap — everything else ellipsises inside the 220px.
|
|
974
|
+
.nav-lang-note {
|
|
975
|
+
margin: 0;
|
|
976
|
+
padding: 0.25rem 0.75rem 0.125rem;
|
|
977
|
+
font-size: 0.75rem;
|
|
978
|
+
line-height: 1.35;
|
|
979
|
+
color: var(--zer0-color-ink-muted);
|
|
980
|
+
white-space: normal;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
.nav-lang-divider {
|
|
984
|
+
margin: 0.5rem 0 0.25rem;
|
|
985
|
+
opacity: 0.15;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
// -----------------------------------------------------------------------------
|
|
989
|
+
// Navbar dropdown variant (components/language-toggle.html, default variant)
|
|
990
|
+
// -----------------------------------------------------------------------------
|
|
991
|
+
|
|
992
|
+
.nav-lang-toggle {
|
|
993
|
+
.nav-lang-button {
|
|
994
|
+
display: inline-flex;
|
|
995
|
+
align-items: center;
|
|
996
|
+
justify-content: center;
|
|
997
|
+
width: 2.375rem; // 38px square — the icon carries the whole control
|
|
998
|
+
height: 2.375rem;
|
|
999
|
+
padding: 0;
|
|
1000
|
+
line-height: 1;
|
|
1001
|
+
|
|
1002
|
+
// Belt and braces: if `dropdown-toggle` is ever re-added, no caret returns.
|
|
1003
|
+
&::after {
|
|
1004
|
+
display: none;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.nav-lang-menu {
|
|
1009
|
+
min-width: 0;
|
|
1010
|
+
max-width: 220px;
|
|
1011
|
+
|
|
1012
|
+
.nav-lang-item {
|
|
1013
|
+
// Bootstrap's dropdown-item is nowrap; the name ellipsises instead so a
|
|
1014
|
+
// long native name cannot push the menu past its cap.
|
|
1015
|
+
overflow: hidden;
|
|
1016
|
+
|
|
1017
|
+
&.is-current {
|
|
1018
|
+
// Beat `.dropdown-item.active`'s specificity is unnecessary (we no
|
|
1019
|
+
// longer emit `.active`), but a hovered current row should not flip to
|
|
1020
|
+
// the link-hover colour and lose the "you are here" reading.
|
|
1021
|
+
color: var(--zer0-color-ink, inherit);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
.nav-lang-name {
|
|
1026
|
+
min-width: 0;
|
|
1027
|
+
overflow: hidden;
|
|
1028
|
+
text-overflow: ellipsis;
|
|
1029
|
+
white-space: nowrap;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
821
1034
|
// -----------------------------------------------------------------------------
|
|
822
1035
|
// Navigation Tooltips
|
|
823
1036
|
// Enhanced tooltips for compact desktop view
|
|
@@ -917,26 +1130,57 @@
|
|
|
917
1130
|
gap: 0.25rem;
|
|
918
1131
|
}
|
|
919
1132
|
|
|
1133
|
+
// Shortcut affordance chip on the search button — the design-system navbar
|
|
1134
|
+
// pattern (ui_kits/website/Navbar.jsx). Overrides Bootstrap's inverted <kbd>
|
|
1135
|
+
// so the chip reads as a quiet hint, not a highlighted key.
|
|
1136
|
+
#navbar .nav-search-kbd {
|
|
1137
|
+
align-items: center;
|
|
1138
|
+
margin-left: 0.1rem;
|
|
1139
|
+
padding: 0.05rem 0.35rem;
|
|
1140
|
+
font-family: var(--zer0-font-mono);
|
|
1141
|
+
font-size: 0.7rem;
|
|
1142
|
+
line-height: 1.4;
|
|
1143
|
+
color: var(--zer0-color-ink-muted);
|
|
1144
|
+
background: var(--zer0-color-bg-muted);
|
|
1145
|
+
border-radius: var(--zer0-radius-sm);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
// The bar spans the full viewport (header markup uses .container-fluid) with a
|
|
1149
|
+
// fluid gutter instead of a centred .container-xl track, so the menubar gets the
|
|
1150
|
+
// whole screen width. Consumers that want the old capped bar set
|
|
1151
|
+
// --zer0-navbar-max-width (e.g. 1320px) in their own stylesheet.
|
|
1152
|
+
#navbar .navbar-main {
|
|
1153
|
+
max-width: var(--zer0-navbar-max-width, 100%);
|
|
1154
|
+
margin-inline: auto;
|
|
1155
|
+
padding-inline: clamp(0.75rem, 1.5vw, 1.5rem);
|
|
1156
|
+
}
|
|
1157
|
+
|
|
920
1158
|
// Desktop (lg+): 3-column grid — [brand/title | main nav | utilities] so nav cannot paint over Search/Settings
|
|
921
1159
|
@media (min-width: 992px) {
|
|
922
1160
|
#navbar .navbar-main {
|
|
923
1161
|
display: grid !important;
|
|
924
1162
|
grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
|
|
925
1163
|
align-items: center;
|
|
926
|
-
column-gap: 0.
|
|
1164
|
+
column-gap: 0.75rem;
|
|
927
1165
|
row-gap: 0.25rem;
|
|
928
1166
|
flex-wrap: unset !important;
|
|
929
1167
|
container-type: inline-size;
|
|
930
1168
|
container-name: navbar-main;
|
|
931
1169
|
}
|
|
932
1170
|
|
|
1171
|
+
// The brand cluster is sized by its content (grid track 1 is `auto`), so an
|
|
1172
|
+
// unbounded title would starve the menubar of the width its labels need.
|
|
1173
|
+
// Cap it at a share of the BAR — `cqi` resolves against .navbar-main (the
|
|
1174
|
+
// named container), where a plain percentage would resolve against the
|
|
1175
|
+
// content-sized track and collapse the title to nothing. The title already
|
|
1176
|
+
// ellipsizes past the cap.
|
|
933
1177
|
#navbar .navbar-main-start {
|
|
934
1178
|
grid-column: 1;
|
|
935
1179
|
display: flex;
|
|
936
1180
|
align-items: center;
|
|
937
1181
|
gap: 0.375rem;
|
|
938
1182
|
min-width: 0;
|
|
939
|
-
max-width:
|
|
1183
|
+
max-width: 30cqi;
|
|
940
1184
|
flex-shrink: 1;
|
|
941
1185
|
}
|
|
942
1186
|
|
|
@@ -1012,8 +1256,12 @@
|
|
|
1012
1256
|
max-width: none;
|
|
1013
1257
|
}
|
|
1014
1258
|
|
|
1015
|
-
// Progressive brand degradation (container width, not viewport)
|
|
1016
|
-
|
|
1259
|
+
// Progressive brand degradation (container width, not viewport).
|
|
1260
|
+
// The home-link icons add ~108px to the brand cluster, so they only appear
|
|
1261
|
+
// once the bar is wide enough to carry them AND the full menubar
|
|
1262
|
+
// (815px of items + 328px brand + 146px utilities + gaps ≈ 82rem); 86rem
|
|
1263
|
+
// leaves headroom for a longer site title.
|
|
1264
|
+
@container navbar-main (min-width: 86rem) {
|
|
1017
1265
|
#navbar .navbar-home-links {
|
|
1018
1266
|
display: inline-flex !important;
|
|
1019
1267
|
}
|