jekyll-theme-zer0 0.17.0 → 0.18.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cedad3b535f19c489e0d874be9c116789f981fc042743150be32b06f7d6481c7
4
- data.tar.gz: 0cd8445680be5c73980338a85aba69a8edb5e9484003fd74daf80c104690e22d
3
+ metadata.gz: e3cdc2d41bf042b7f0f71b9f43dd9347c43bbbbb500cf95ef6bf2deed492fcb5
4
+ data.tar.gz: cb4b0b4bf44a66294fb4d6fab901932fc4a024c2a8f4c9b46c0fcfe69895d825
5
5
  SHA512:
6
- metadata.gz: 35520e071daded7969373b51f103d8a8440db28b03044ca1db0c01832d676cbcfc32d677d285ce612c8f79a6a2fa2fa8023570457a28cba83615fea8363bd1eb
7
- data.tar.gz: 654aa816eeb3b3e1019f0686eb2516eb4404e17ad4e533f764d32240fd1454a6c893a6e376fb907387b0a5f3cd514c1e364b365df92ed07e1279a90144ffc222
6
+ metadata.gz: 874947c58a3abea526c10aab5d5936a30705e6f87286e2779be094717f7297328adfbdff8a946dfa228969bd4d655bf75c7689f3a29b84e880ce078b74bbc4e9
7
+ data.tar.gz: ee12a3e265ead26b0566b6e8cecb1165fb8bf2b6bc7c3513cd15b4f9baa2d9acca2abfbc2e8e239284f4c5546bee100552991aa5d4b34827351b636fbb9df151
data/CHANGELOG.md CHANGED
@@ -1,5 +1,79 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.18.0] - 2026-01-19
4
+
5
+ ### Added
6
+ - **Search Modal**: New site-wide search popup with live results, keyboard shortcuts (`/`, `Cmd/Ctrl+K`), and offcanvas entry
7
+ - **Search Index**: Generated `search.json` index including page content for client-side search
8
+
9
+ ### Changed
10
+ - **Navigation**: Added search button to the main navbar with improved mobile layout support
11
+
12
+ ### Fixed
13
+ - **Search UX**: Highlight query matches and show content-based snippets where the match occurs
14
+
15
+ ## [0.17.5] - 2026-01-17
16
+
17
+ ### Changed
18
+ - Version bump: patch release
19
+
20
+ ### Commits in this release
21
+ - eeb8ea3 fix(ui): remove cursor tilt and prep v0.17.4
22
+
23
+ ## [0.17.4] - 2026-01-16
24
+
25
+ ### Changed
26
+ - Version bump: patch release
27
+
28
+ ### Fixed
29
+ - **UI/UX**: Removed cursor-based 3D parallax tilt effect on cards to prevent perspective shifts on hover
30
+ - **Config YAML**: Corrected anchor definitions used by gravatar and local repo settings to pass YAML validation
31
+
32
+ ### Commits in this release
33
+ - 226b0a5 chore(structure): reorganize root directory for better maintainability
34
+
35
+ ## [0.17.3] - 2026-01-15
36
+
37
+ ### Changed
38
+ - Version bump: patch release
39
+
40
+ ### Commits in this release
41
+ - a0c1df4 fix(ui): fix Mermaid dark mode and cookie banner rendering
42
+
43
+
44
+ ## [0.17.2] - 2025-12-31
45
+
46
+ ### Fixed
47
+ - **Mermaid Dark Mode**: Fixed diagram rendering issues in dark mode by dynamically detecting Bootstrap theme (`data-bs-theme`) and switching Mermaid theme accordingly
48
+ - **Cookie Consent Banner**: Fixed banner appearing twice on initial page load by implementing CSS-first visibility control and removing inline style conflicts
49
+
50
+ ### Enhanced
51
+ - **UI/UX Improvements**: Comprehensive frontend enhancements including:
52
+ - Smooth scroll animations with Intersection Observer
53
+ - Enhanced card hover effects with 3D parallax on desktop
54
+ - Improved button styles with ripple effects and better transitions
55
+ - Better code block styling with enhanced copy functionality
56
+ - Mobile-responsive improvements with touch-friendly tap targets
57
+ - Improved focus states for accessibility
58
+ - Hero section animations with staggered fade-in effects
59
+
60
+ ### Added
61
+ - **UI Enhancements Module**: New `assets/js/ui-enhancements.js` for scroll animations, card interactions, and smooth scrolling
62
+ - **Enhanced Code Copy**: Improved copy-to-clipboard functionality with better visual feedback and fallback support
63
+
64
+ ### Changed
65
+ - **CI Configuration**: Made HTMLProofer non-blocking for pre-existing link issues
66
+ - **Documentation**: Enhanced contributing guide and release pipeline documentation 4630c33 (fix(ui): fix Mermaid dark mode and cookie banner rendering)
67
+
68
+ ## [0.17.1] - 2025-12-24
69
+
70
+ ### Changed
71
+ - Version bump: patch release
72
+
73
+ ### Commits in this release
74
+ - d56de0b fix(ci): update Gemfile.lock for v0.17.0 and improve HTMLProofer config
75
+
76
+
3
77
  ## [0.17.0] - 2025-12-23
4
78
 
5
79
  ### Added
data/README.md CHANGED
@@ -569,7 +569,7 @@ graph LR
569
569
  | [🤖 Copilot Instructions]({{ site.resources.github_repo | default: '' | join: '' }}/blob/{{ site.branch }}/.github/copilot-instructions.md) | AI development guidelines |
570
570
  | [⌨️ Keyboard Navigation]({{ site.resources.github_repo | default: '' | join: '' }}/blob/{{ site.branch }}/docs/keyboard-navigation.md) | Accessibility shortcuts guide |
571
571
  | [📓 Jupyter Notebooks]({{ site.resources.github_repo | default: '' | join: '' }}/blob/{{ site.branch }}/docs/JUPYTER_NOTEBOOKS.md) | Notebook conversion documentation |
572
- | [📝 PRD](PRD.md) | Product requirements & roadmap |
572
+ | [📝 PRD](docs/PRD.md) | Product requirements & roadmap |
573
573
  | [🔒 Privacy Policy]({{ '/privacy-policy/' | relative_url }}) | GDPR/CCPA compliant privacy docs |
574
574
 
575
575
  ---
@@ -49,7 +49,7 @@ Usage: Include in root.html layout
49
49
  Configuration: Uses site.posthog settings from _config.yml
50
50
  {% endcomment %}
51
51
 
52
- <div id="cookieConsent" class="cookie-consent-banner position-fixed bottom-0 start-0 end-0 bg-dark text-light p-3 shadow-lg" style="z-index: 9999; transform: translateY(100%); transition: transform 0.3s ease-in-out;">
52
+ <div id="cookieConsent" class="cookie-consent-banner position-fixed bottom-0 start-0 end-0 bg-dark text-light p-3 shadow-lg">
53
53
  <div class="container-fluid">
54
54
  <div class="row align-items-center">
55
55
  <div class="col-12 col-lg-8">
@@ -248,18 +248,42 @@ Configuration: Uses site.posthog settings from _config.yml
248
248
  // Show consent banner
249
249
  function showConsentBanner() {
250
250
  const banner = document.getElementById('cookieConsent');
251
- if (banner) {
252
- setTimeout(() => {
253
- banner.style.transform = 'translateY(0)';
254
- }, 1000); // Show after 1 second
255
- }
251
+ if (!banner) return;
252
+
253
+ // Ensure banner starts completely hidden - remove all classes and inline styles
254
+ banner.classList.remove('cookie-banner-showing', 'cookie-banner-visible');
255
+ banner.removeAttribute('style'); // Remove all inline styles to let CSS take over
256
+
257
+ // Wait for the delay, then show and animate in one smooth motion
258
+ setTimeout(() => {
259
+ // First, make it visible but still off-screen (using class for CSS control)
260
+ banner.classList.add('cookie-banner-showing');
261
+
262
+ // Force a reflow to ensure the display change is applied
263
+ void banner.offsetHeight;
264
+
265
+ // On the next frame, animate it in smoothly
266
+ requestAnimationFrame(() => {
267
+ requestAnimationFrame(() => {
268
+ banner.classList.add('cookie-banner-visible');
269
+ });
270
+ });
271
+ }, 1000); // Show after 1 second
256
272
  }
257
273
 
258
274
  // Hide consent banner
259
275
  function hideConsentBanner() {
260
276
  const banner = document.getElementById('cookieConsent');
261
277
  if (banner) {
262
- banner.style.transform = 'translateY(100%)';
278
+ // Remove visible class to trigger transition out
279
+ banner.classList.remove('cookie-banner-visible');
280
+
281
+ // Hide after transition completes
282
+ banner.addEventListener('transitionend', function hideAfterTransition() {
283
+ banner.classList.remove('cookie-banner-showing');
284
+ banner.removeAttribute('style'); // Clean up inline styles
285
+ banner.removeEventListener('transitionend', hideAfterTransition);
286
+ }, { once: true });
263
287
  }
264
288
  }
265
289
 
@@ -281,14 +305,27 @@ Configuration: Uses site.posthog settings from _config.yml
281
305
 
282
306
  // Initialize on DOM content loaded
283
307
  document.addEventListener('DOMContentLoaded', function() {
308
+ const banner = document.getElementById('cookieConsent');
309
+
310
+ // Ensure banner starts completely hidden BEFORE any checks
311
+ // Remove all classes and inline styles - let CSS handle hiding
312
+ if (banner) {
313
+ banner.classList.remove('cookie-banner-showing', 'cookie-banner-visible');
314
+ banner.removeAttribute('style');
315
+ }
316
+
284
317
  const existingConsent = getConsentState();
285
318
 
286
319
  if (existingConsent) {
287
- // Apply existing consent
320
+ // Apply existing consent and ensure banner stays hidden
288
321
  applyConsent(existingConsent);
289
322
  updateModalUI(existingConsent);
323
+ if (banner) {
324
+ banner.classList.remove('cookie-banner-showing', 'cookie-banner-visible');
325
+ banner.removeAttribute('style');
326
+ }
290
327
  } else {
291
- // Show consent banner for new visitors
328
+ // Show consent banner for new visitors (with delay)
292
329
  showConsentBanner();
293
330
  }
294
331
 
@@ -348,12 +385,40 @@ Configuration: Uses site.posthog settings from _config.yml
348
385
  </script>
349
386
 
350
387
  <style>
388
+ /* Banner base styles */
389
+ #cookieConsent {
390
+ z-index: 9999;
391
+ transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
392
+ }
393
+
394
+ /* Banner starts completely hidden - CSS enforces this */
395
+ #cookieConsent:not(.cookie-banner-showing) {
396
+ display: none !important;
397
+ visibility: hidden !important;
398
+ opacity: 0 !important;
399
+ transform: translateY(100%) !important;
400
+ }
401
+
351
402
  .cookie-consent-banner {
352
403
  background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);
353
404
  backdrop-filter: blur(10px);
354
405
  border-top: 1px solid rgba(255, 255, 255, 0.1);
355
406
  }
356
407
 
408
+ /* Only show banner when explicitly enabled via JavaScript class */
409
+ #cookieConsent.cookie-banner-showing {
410
+ display: block !important;
411
+ visibility: visible !important;
412
+ opacity: 0;
413
+ transform: translateY(100%);
414
+ }
415
+
416
+ /* Animate in when visible class is added */
417
+ #cookieConsent.cookie-banner-showing.cookie-banner-visible {
418
+ opacity: 1 !important;
419
+ transform: translateY(0) !important;
420
+ }
421
+
357
422
  .cursor-pointer {
358
423
  cursor: pointer;
359
424
  }
@@ -379,4 +444,11 @@ Configuration: Uses site.posthog settings from _config.yml
379
444
  margin-bottom: 0;
380
445
  }
381
446
  }
447
+
448
+ /* Respect reduced motion preferences */
449
+ @media (prefers-reduced-motion: reduce) {
450
+ .cookie-consent-banner {
451
+ transition: none !important;
452
+ }
453
+ }
382
454
  </style>
@@ -29,4 +29,7 @@
29
29
  crossorigin="anonymous"></script>
30
30
 
31
31
  <!-- Navigation ES6 Modules - Enhanced sidebar, scroll spy, keyboard shortcuts, gestures -->
32
- <script type="module" src="{{ '/assets/js/modules/navigation/index.js' | relative_url }}"></script>
32
+ <script type="module" src="{{ '/assets/js/modules/navigation/index.js' | relative_url }}"></script>
33
+
34
+ <!-- Search modal controller -->
35
+ <script src="{{ '/assets/js/search-modal.js' | relative_url }}"></script>
@@ -47,6 +47,108 @@
47
47
  <!-- Initialize Mermaid with custom configuration -->
48
48
  <script>
49
49
  document.addEventListener('DOMContentLoaded', function() {
50
+ // ============================================================
51
+ // Helper function to detect Bootstrap theme
52
+ // ============================================================
53
+ function getBootstrapTheme() {
54
+ // Check data-bs-theme attribute on html element
55
+ var htmlTheme = document.documentElement.getAttribute('data-bs-theme');
56
+ if (htmlTheme === 'dark' || htmlTheme === 'light') {
57
+ return htmlTheme;
58
+ }
59
+ // Fallback to prefers-color-scheme
60
+ if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
61
+ return 'dark';
62
+ }
63
+ return 'light';
64
+ }
65
+
66
+ // ============================================================
67
+ // Helper function to get Mermaid theme configuration
68
+ // ============================================================
69
+ function getMermaidConfig(theme) {
70
+ var isDark = theme === 'dark';
71
+
72
+ if (isDark) {
73
+ // Dark mode configuration
74
+ return {
75
+ theme: 'dark',
76
+ themeVariables: {
77
+ primaryColor: '#0d6efd',
78
+ primaryTextColor: '#ffffff',
79
+ primaryBorderColor: '#0a58ca',
80
+ lineColor: '#6c757d',
81
+ secondaryColor: '#6c757d',
82
+ tertiaryColor: '#212529',
83
+ background: '#212529',
84
+ mainBkg: '#212529',
85
+ secondBkg: '#343a40',
86
+ tertiaryBkg: '#495057',
87
+ textColor: '#ffffff',
88
+ secondaryTextColor: '#adb5bd',
89
+ tertiaryTextColor: '#6c757d',
90
+ lineColor: '#6c757d',
91
+ border1: '#495057',
92
+ border2: '#6c757d',
93
+ noteBkgColor: '#343a40',
94
+ noteTextColor: '#ffffff',
95
+ noteBorderColor: '#6c757d',
96
+ actorBkg: '#0d6efd',
97
+ actorBorder: '#0a58ca',
98
+ actorTextColor: '#ffffff',
99
+ actorLineColor: '#ffffff',
100
+ signalColor: '#ffffff',
101
+ signalTextColor: '#ffffff',
102
+ labelBoxBkgColor: '#343a40',
103
+ labelBoxBorderColor: '#6c757d',
104
+ labelTextColor: '#ffffff',
105
+ loopTextColor: '#ffffff',
106
+ activationBorderColor: '#0d6efd',
107
+ activationBkgColor: '#0d6efd',
108
+ sequenceNumberColor: '#ffffff',
109
+ sectionBkgColor: '#343a40',
110
+ altSectionBkgColor: '#495057',
111
+ excludeBkgColor: '#495057',
112
+ taskBorderColor: '#0d6efd',
113
+ taskBkgColor: '#0d6efd',
114
+ taskTextLightColor: '#ffffff',
115
+ taskTextColor: '#ffffff',
116
+ taskTextDarkColor: '#000000',
117
+ taskTextOutsideColor: '#ffffff',
118
+ taskTextClickableColor: '#0d6efd',
119
+ activeTaskBorderColor: '#0a58ca',
120
+ activeTaskBkgColor: '#0a58ca',
121
+ gridColor: '#6c757d',
122
+ doneTaskBkgColor: '#198754',
123
+ doneTaskBorderColor: '#146c43',
124
+ critBorderColor: '#dc3545',
125
+ critBkgColor: '#dc3545',
126
+ todayLineColor: '#ffc107'
127
+ }
128
+ };
129
+ } else {
130
+ // Light mode configuration
131
+ return {
132
+ theme: 'default',
133
+ themeVariables: {
134
+ primaryColor: '#007bff',
135
+ primaryTextColor: '#fff',
136
+ primaryBorderColor: '#0056b3',
137
+ lineColor: '#6c757d',
138
+ secondaryColor: '#6c757d',
139
+ tertiaryColor: '#f8f9fa',
140
+ background: '#ffffff',
141
+ mainBkg: '#ffffff',
142
+ secondBkg: '#f8f9fa',
143
+ tertiaryBkg: '#e9ecef',
144
+ textColor: '#212529',
145
+ secondaryTextColor: '#6c757d',
146
+ tertiaryTextColor: '#adb5bd'
147
+ }
148
+ };
149
+ }
150
+ }
151
+
50
152
  // ============================================================
51
153
  // Step 1: Convert native markdown code blocks to mermaid divs
52
154
  // This enables ```mermaid syntax to work with GitHub Pages
@@ -86,20 +188,16 @@
86
188
  });
87
189
 
88
190
  // ============================================================
89
- // Step 2: Initialize Mermaid with custom configuration
191
+ // Step 2: Initialize Mermaid with theme-aware configuration
90
192
  // ============================================================
91
193
 
194
+ var bootstrapTheme = getBootstrapTheme();
195
+ var mermaidThemeConfig = getMermaidConfig(bootstrapTheme);
196
+
92
197
  mermaid.initialize({
93
198
  startOnLoad: false, // We'll manually run after conversion
94
- theme: 'forest', // Options: default, forest, dark, neutral, base
95
- themeVariables: {
96
- primaryColor: '#007bff',
97
- primaryTextColor: '#fff',
98
- primaryBorderColor: '#0056b3',
99
- lineColor: '#6c757d',
100
- secondaryColor: '#6c757d',
101
- tertiaryColor: '#f8f9fa'
102
- },
199
+ theme: mermaidThemeConfig.theme,
200
+ themeVariables: mermaidThemeConfig.themeVariables,
103
201
  flowchart: {
104
202
  useMaxWidth: true,
105
203
  htmlLabels: true,
@@ -139,10 +237,82 @@
139
237
 
140
238
  // Run mermaid to render all .mermaid divs
141
239
  mermaid.run().then(function() {
142
- console.log('Mermaid.js: All diagrams rendered successfully');
240
+ console.log('Mermaid.js: All diagrams rendered successfully with theme:', bootstrapTheme);
143
241
  }).catch(function(error) {
144
242
  console.warn('Mermaid.js: Some diagrams failed to render', error);
145
243
  });
244
+
245
+ // ============================================================
246
+ // Step 4: Watch for theme changes and re-render diagrams
247
+ // ============================================================
248
+
249
+ // Create a MutationObserver to watch for theme changes
250
+ var themeObserver = new MutationObserver(function(mutations) {
251
+ mutations.forEach(function(mutation) {
252
+ if (mutation.type === 'attributes' && mutation.attributeName === 'data-bs-theme') {
253
+ var newTheme = getBootstrapTheme();
254
+ var newMermaidConfig = getMermaidConfig(newTheme);
255
+
256
+ // Update Mermaid configuration
257
+ mermaid.initialize({
258
+ startOnLoad: false,
259
+ theme: newMermaidConfig.theme,
260
+ themeVariables: newMermaidConfig.themeVariables,
261
+ flowchart: {
262
+ useMaxWidth: true,
263
+ htmlLabels: true,
264
+ curve: 'basis'
265
+ },
266
+ sequence: {
267
+ diagramMarginX: 50,
268
+ diagramMarginY: 10,
269
+ actorMargin: 50,
270
+ width: 150,
271
+ height: 65,
272
+ boxMargin: 10,
273
+ boxTextMargin: 5,
274
+ noteMargin: 10,
275
+ messageMargin: 35,
276
+ mirrorActors: true,
277
+ bottomMarginAdj: 1,
278
+ useMaxWidth: true
279
+ },
280
+ gantt: {
281
+ titleTopMargin: 25,
282
+ barHeight: 20,
283
+ barGap: 4,
284
+ topPadding: 50,
285
+ leftPadding: 75,
286
+ gridLineStartPadding: 35,
287
+ fontSize: 11,
288
+ numberSectionStyles: 4,
289
+ axisFormat: '%Y-%m-%d'
290
+ },
291
+ securityLevel: 'loose'
292
+ });
293
+
294
+ // Re-render all diagrams with new theme
295
+ var mermaidDivs = document.querySelectorAll('.mermaid');
296
+ mermaidDivs.forEach(function(div) {
297
+ var content = div.textContent || div.innerText;
298
+ div.innerHTML = '';
299
+ div.textContent = content;
300
+ });
301
+
302
+ mermaid.run().then(function() {
303
+ console.log('Mermaid.js: Diagrams re-rendered with theme:', newTheme);
304
+ }).catch(function(error) {
305
+ console.warn('Mermaid.js: Some diagrams failed to re-render', error);
306
+ });
307
+ }
308
+ });
309
+ });
310
+
311
+ // Start observing the html element for theme changes
312
+ themeObserver.observe(document.documentElement, {
313
+ attributes: true,
314
+ attributeFilter: ['data-bs-theme']
315
+ });
146
316
  });
147
317
  </script>
148
318
 
@@ -157,12 +327,17 @@
157
327
  margin: 2rem auto;
158
328
  background-color: transparent;
159
329
  overflow-x: auto;
330
+ padding: 1rem;
331
+ border-radius: 0.5rem;
332
+ transition: background-color 0.3s ease;
160
333
  }
161
334
 
162
335
  /* Ensure diagrams are responsive */
163
336
  .mermaid svg {
164
337
  max-width: 100%;
165
338
  height: auto;
339
+ display: block;
340
+ margin: 0 auto;
166
341
  }
167
342
 
168
343
  /* Hide code blocks before conversion (prevent flash of unstyled content) */
@@ -173,15 +348,86 @@
173
348
  transition: opacity 0.2s;
174
349
  }
175
350
 
176
- /* Dark mode compatibility */
351
+ /* Dark mode compatibility - Bootstrap theme aware */
352
+ [data-bs-theme="dark"] .mermaid {
353
+ background-color: rgba(33, 37, 41, 0.5);
354
+ border: 1px solid rgba(108, 117, 125, 0.2);
355
+ }
356
+
357
+ [data-bs-theme="dark"] .mermaid svg {
358
+ /* Ensure SVG elements are visible in dark mode */
359
+ color-scheme: dark;
360
+ }
361
+
362
+ [data-bs-theme="dark"] .mermaid svg text {
363
+ fill: #ffffff !important;
364
+ }
365
+
366
+ [data-bs-theme="dark"] .mermaid svg .node rect,
367
+ [data-bs-theme="dark"] .mermaid svg .node polygon,
368
+ [data-bs-theme="dark"] .mermaid svg .cluster rect {
369
+ fill: #343a40 !important;
370
+ stroke: #6c757d !important;
371
+ }
372
+
373
+ [data-bs-theme="dark"] .mermaid svg .edgePath .path {
374
+ stroke: #6c757d !important;
375
+ }
376
+
377
+ [data-bs-theme="dark"] .mermaid svg .edgeLabel {
378
+ background-color: #212529 !important;
379
+ color: #ffffff !important;
380
+ }
381
+
382
+ [data-bs-theme="dark"] .mermaid svg .edgeLabel text {
383
+ fill: #ffffff !important;
384
+ }
385
+
386
+ /* Light mode styling */
387
+ [data-bs-theme="light"] .mermaid {
388
+ background-color: rgba(248, 249, 250, 0.5);
389
+ border: 1px solid rgba(0, 0, 0, 0.1);
390
+ }
391
+
392
+ [data-bs-theme="light"] .mermaid svg text {
393
+ fill: #212529 !important;
394
+ }
395
+
396
+ /* Fallback for prefers-color-scheme if data-bs-theme is not set */
177
397
  @media (prefers-color-scheme: dark) {
178
- .mermaid {
179
- filter: brightness(0.9);
398
+ html:not([data-bs-theme]) .mermaid {
399
+ background-color: rgba(33, 37, 41, 0.5);
400
+ border: 1px solid rgba(108, 117, 125, 0.2);
180
401
  }
181
402
  }
182
403
 
404
+ /* Smooth theme transition */
405
+ .mermaid svg {
406
+ transition: opacity 0.3s ease;
407
+ }
408
+
409
+ /* Loading state */
410
+ .mermaid:not(:has(svg)) {
411
+ min-height: 100px;
412
+ display: flex;
413
+ align-items: center;
414
+ justify-content: center;
415
+ }
416
+
417
+ .mermaid:not(:has(svg))::after {
418
+ content: 'Loading diagram...';
419
+ color: var(--bs-secondary);
420
+ font-size: 0.875rem;
421
+ }
422
+
183
423
  /* Print styles */
184
424
  @media print {
425
+ .mermaid {
426
+ background-color: transparent !important;
427
+ border: none !important;
428
+ page-break-inside: avoid;
429
+ }
430
+
185
431
  .mermaid svg {
186
432
  max-width: 100% !important;
187
433
  page-break-inside: avoid;
@@ -0,0 +1,56 @@
1
+ <!--
2
+ ===================================================================
3
+ SEARCH MODAL - Site-wide Search Popup
4
+ ===================================================================
5
+
6
+ File: search-modal.html
7
+ Path: _includes/components/search-modal.html
8
+ Purpose: Provide a modal search experience with keyboard shortcut support
9
+
10
+ Notes:
11
+ - Uses /sitemap/ for query-based search results
12
+ - Keyboard shortcut handled by navigation keyboard module ("/")
13
+ ===================================================================
14
+ -->
15
+
16
+ {%- assign ui_text = site.data.ui-text[site.locale] | default: site.data.ui-text.en -%}
17
+ {%- assign search_placeholder = ui_text.search_placeholder_text | default: "Enter your search term..." -%}
18
+
19
+ <div class="modal fade search-modal" id="siteSearchModal" tabindex="-1" aria-labelledby="siteSearchModalLabel" aria-hidden="true">
20
+ <div class="modal-dialog modal-dialog-centered">
21
+ <div class="modal-content">
22
+ <div class="modal-header">
23
+ <h5 class="modal-title" id="siteSearchModalLabel">
24
+ <i class="bi bi-search me-2"></i>Search
25
+ </h5>
26
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
27
+ </div>
28
+ <div class="modal-body">
29
+ <form action="{{ '/sitemap/' | relative_url }}" method="get" data-search-form>
30
+ <label class="visually-hidden" for="site-search-input">Search</label>
31
+ <div class="input-group">
32
+ <span class="input-group-text">
33
+ <i class="bi bi-search" aria-hidden="true"></i>
34
+ </span>
35
+ <input
36
+ id="site-search-input"
37
+ type="search"
38
+ name="q"
39
+ class="form-control"
40
+ placeholder="{{ search_placeholder }}"
41
+ autocomplete="off"
42
+ data-search-input
43
+ >
44
+ <button class="btn btn-primary" type="submit">Search</button>
45
+ </div>
46
+ <div class="form-text mt-2">
47
+ Press <kbd>/</kbd> or <kbd>⌘</kbd>/<kbd>Ctrl</kbd>+<kbd>K</kbd> to open search, <kbd>Esc</kbd> to close.
48
+ </div>
49
+ </form>
50
+ <div class="search-results mt-3" data-search-results>
51
+ <div class="text-muted small" data-search-empty>Start typing to see results.</div>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
@@ -32,24 +32,23 @@
32
32
 
33
33
  <!-- Title Section -->
34
34
 
35
- <div class="navbar-brand">
36
- <a class="nav-link" href="{{ page.url | relative_url }}">
37
- <i class="d-sm-inline d-md-none {{ site.default_icon }} {{ site.default_icon }}-{{ site.title_icon | default: 'house' }}" aria-hidden="true"></i>
38
- <!-- Display name if there's enough space, else icon only -->
39
- <span class="d-none d-md-inline">
35
+ <div class="navbar-brand site-title">
36
+ <a class="nav-link" href="{{ '/' | relative_url }}">
37
+ <i class="d-none d-md-inline {{ site.default_icon }} {{ site.default_icon }}-{{ site.title_icon | default: 'house' }}" aria-hidden="true"></i>
38
+ <!-- Always show the title on mobile; truncate if space is tight -->
39
+ <span class="site-title-text">
40
40
  {{ site.title }}
41
41
  </span>
42
42
  </a>
43
43
  </div>
44
44
 
45
- <div class="navbar-brand">
46
- <!-- If a subtitle exists -->
47
- {%- if site.subtitle -%}
48
- <a class="nav-link" href="{{ page.url | relative_url }}">
49
- <i class="d-sm-inline d-md-none {{ site.default_icon }} {{ site.default_icon }}-{{ site.subtitle_icon | default: 'journal' }}" aria-hidden="true"></i>
50
- <span class="d-none d-md-inline">
45
+ <!-- If a subtitle exists -->
46
+ {%- if site.subtitle -%}
47
+ <div class="navbar-brand site-subtitle d-none d-lg-inline">
48
+ <a class="nav-link" href="{{ '/' | relative_url }}">
49
+ <span class="site-subtitle-text">
51
50
  {{ site.subtitle }}
52
51
  </span>
53
52
  </a>
54
- {% endif %}
55
- </div>
53
+ </div>
54
+ {% endif %}
@@ -42,6 +42,7 @@
42
42
  <script defer src="{{ '/assets/js/halfmoon.js' | relative_url }}"></script>
43
43
  <script defer src="{{ '/assets/js/side-bar-folders.js' | relative_url }}"></script>
44
44
  <script defer src="{{ '/assets/js/code-copy.js' | relative_url }}"></script>
45
+ <script defer src="{{ '/assets/js/ui-enhancements.js' | relative_url }}"></script>
45
46
 
46
47
  <!-- ================================ -->
47
48
  <!-- THIRD PARTY INTEGRATIONS -->