jekyll-theme-zer0 1.19.1 → 1.20.2

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +395 -0
  3. data/README.md +27 -19
  4. data/_data/authors.yml +154 -5
  5. data/_data/backlog.yml +5 -5
  6. data/_data/content_statistics.yml +273 -297
  7. data/_data/features.yml +4 -25
  8. data/_data/navigation/README.md +24 -0
  9. data/_data/navigation/about.yml +2 -0
  10. data/_data/navigation/main.yml +2 -7
  11. data/_data/roadmap.yml +86 -12
  12. data/_includes/components/author-avatar-url.html +28 -0
  13. data/_includes/components/author-bio.html +86 -0
  14. data/_includes/components/author-card.html +184 -121
  15. data/_includes/components/author-eeat.html +10 -4
  16. data/_includes/components/info-section.html +1 -1
  17. data/_includes/components/mermaid.html +0 -3
  18. data/_includes/components/post-card.html +19 -9
  19. data/_includes/content/giscus.html +3 -2
  20. data/_includes/core/footer-fabs.html +28 -0
  21. data/_includes/core/footer.html +7 -17
  22. data/_includes/core/head.html +2 -2
  23. data/_includes/navigation/breadcrumbs.html +20 -2
  24. data/_includes/navigation/local-graph.html +18 -2
  25. data/_includes/obsidian/full-graph.html +4 -6
  26. data/_layouts/article.html +44 -74
  27. data/_layouts/author.html +274 -0
  28. data/_layouts/authors.html +55 -0
  29. data/_layouts/news.html +3 -3
  30. data/_layouts/note.html +21 -6
  31. data/_layouts/notebook.html +21 -6
  32. data/_layouts/root.html +31 -17
  33. data/_layouts/section.html +3 -3
  34. data/_plugins/author_pages_generator.rb +121 -0
  35. data/_sass/components/_author.scss +219 -0
  36. data/_sass/components/_content-tables.scss +16 -1
  37. data/_sass/components/_notes-index.scss +102 -0
  38. data/_sass/components/_search-modal.scss +40 -0
  39. data/_sass/components/_ui-enhancements.scss +570 -0
  40. data/_sass/core/_docs-code-examples.scss +463 -0
  41. data/_sass/core/_docs-layout.scss +0 -453
  42. data/_sass/core/_navbar.scss +253 -0
  43. data/_sass/core/_sidebar-extras.scss +79 -0
  44. data/_sass/core/_toc.scss +87 -0
  45. data/_sass/core/_variables.scss +7 -142
  46. data/_sass/custom.scss +24 -1122
  47. data/_sass/layouts/_global-chrome.scss +59 -0
  48. data/assets/css/main.scss +19 -2
  49. data/assets/js/author-profile.js +190 -0
  50. data/assets/js/modules/navigation/navbar.js +104 -0
  51. data/assets/js/obsidian-graph.js +2 -2
  52. data/assets/js/obsidian-local-graph.js +11 -5
  53. data/assets/vendor/cytoscape/cytoscape.min.js +32 -0
  54. data/scripts/README.md +39 -0
  55. data/scripts/bin/validate +11 -1
  56. data/scripts/dev/css-diff.sh +49 -0
  57. data/scripts/dev/shot.js +37 -0
  58. data/scripts/features/generate-preview-images +110 -6
  59. data/scripts/features/pixelate-preview-images +126 -0
  60. data/scripts/features/pixelate_images.py +662 -0
  61. data/scripts/github-setup.sh +0 -0
  62. data/scripts/lib/preview_generator.py +47 -3
  63. data/scripts/pixelate-preview-images.sh +12 -0
  64. data/scripts/test/integration/auto-version +10 -8
  65. data/scripts/test/lib/run_tests.sh +2 -0
  66. data/scripts/test/lib/test_content_review.sh +205 -0
  67. data/scripts/test/lib/test_pixelate_images.sh +108 -0
  68. metadata +25 -20
  69. data/_data/hub.yml +0 -68
  70. data/_data/hub_index.yml +0 -203
  71. data/_data/navigation/hub.yml +0 -110
  72. data/assets/vendor/font-awesome/css/all.min.css +0 -9
  73. data/assets/vendor/font-awesome/webfonts/fa-brands-400.ttf +0 -0
  74. data/assets/vendor/font-awesome/webfonts/fa-brands-400.woff2 +0 -0
  75. data/assets/vendor/font-awesome/webfonts/fa-regular-400.ttf +0 -0
  76. data/assets/vendor/font-awesome/webfonts/fa-regular-400.woff2 +0 -0
  77. data/assets/vendor/font-awesome/webfonts/fa-solid-900.ttf +0 -0
  78. data/assets/vendor/font-awesome/webfonts/fa-solid-900.woff2 +0 -0
  79. data/assets/vendor/font-awesome/webfonts/fa-v4compatibility.ttf +0 -0
  80. data/assets/vendor/font-awesome/webfonts/fa-v4compatibility.woff2 +0 -0
  81. data/assets/vendor/jquery/jquery-3.7.1.min.js +0 -2
  82. data/scripts/lib/hub.rb +0 -208
  83. data/scripts/provision-org-sites.rb +0 -252
  84. data/scripts/provision-org-sites.sh +0 -23
  85. data/scripts/sync-hub-metadata.rb +0 -184
  86. data/scripts/sync-hub-metadata.sh +0 -22
data/_sass/custom.scss CHANGED
@@ -1,1132 +1,34 @@
1
1
  // ==============================================================================
2
- // CUSTOM STYLES - Zer0-Mistakes Theme Customizations
2
+ // CUSTOM STYLES barrel Zer0-Mistakes "custom layer"
3
3
  // ==============================================================================
4
4
  //
5
- // DEPRECATION NOTICE As of v1.8, this monolithic partial is being decomposed.
6
- // Token-aware replacements live alongside it and are imported BEFORE this file
7
- // from assets/css/main.scss:
8
- // - components/cookie-banner (was lines ~189-234 below)
9
- // - components/back-to-top (was lines ~263-305 below)
10
- // - components/notes (was lines ~1069-1295 below)
11
- // - components/skeleton (was lines ~1040-1050 below)
12
- // - layouts/landing (was the .landing-hero / .landing-feature blocks)
13
- // - layouts/navbar-extras (was the .bd-toc-fab positioning block)
14
- // - utilities/motion (consolidates prefers-reduced-motion rules)
15
- // - utilities/focus (shared :focus-visible ring)
5
+ // This file used to be a ~1,100-line monolith mixing @imports with a grab-bag of
6
+ // rules (navbar, search modal, UI polish, grids, …). It has been decomposed into
7
+ // the focused partials imported below. It remains as a thin barrel so:
8
+ // 1. the compiled cascade order is unchanged (the partials are imported in the
9
+ // same order their rules originally appeared), and
10
+ // 2. forks that `@import "custom"` directly keep working.
16
11
  //
17
- // The legacy blocks remain here for one minor version so that forks which
18
- // import `custom.scss` directly keep working. They will be removed in v2.0.
19
- // Migration: delete the legacy block from your fork (or just rely on the new
20
- // partials, which use --zer0-* tokens for dark-mode safety).
12
+ // The core nav/content partials (notebooks, nav-tree, sidebar-categories,
13
+ // navbar, offcanvas-panels, obsidian) are imported directly from
14
+ // assets/css/main.scss § 7b, immediately before this barrel. The navbar fixed/
15
+ // grid layout and the search modal were relocated to core/_navbar.scss and
16
+ // components/_search-modal.scss respectively.
21
17
  // ==============================================================================
22
18
 
23
- // Import notebook-specific styles
24
- @import "notebooks";
19
+ // Page-frame globals: base resets, sticky helper, bottom shadow, min-height,
20
+ // landing-hero media placeholder shim.
21
+ @import "layouts/global-chrome";
25
22
 
26
- // Import navigation tree styles
27
- @import "core/nav-tree";
28
- @import "core/sidebar-categories";
23
+ // Table-of-contents styling (#TableOfContents + .toc sticky sidebar + collapse).
24
+ @import "core/toc";
29
25
 
30
- // Import navbar styles (extracted from navbar.html)
31
- @import "core/navbar";
32
- @import "core/offcanvas-panels";
26
+ // Sidebar / TOC active states + cookie-banner & back-to-top responsive shims.
27
+ @import "core/sidebar-extras";
33
28
 
34
- // Obsidian-flavoured markdown features (wiki-links, callouts, backlinks, …)
35
- @import "core/obsidian";
29
+ // Bootstrap component polish: buttons, cards, hero, code blocks, motion, mobile,
30
+ // focus, print — the "UI/UX enhancements" layer.
31
+ @import "components/ui-enhancements";
36
32
 
37
- html, body {
38
- max-width: 100%;
39
- // overflow-x: hidden;
40
- }
41
-
42
- * {
43
- box-sizing: border-box;
44
- }
45
-
46
- .make-me-sticky {
47
- position: -webkit-sticky;
48
- position: sticky;
49
- top: 0;
50
- padding: 0 15px;
51
- display: flex;
52
- flex-wrap: wrap;
53
- }
54
-
55
- .bottom-shadow {
56
- // background-color: rgba(255,255,255,0.95);
57
- box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, .35), inset 0 -1px 0 rgba(0, 0, 0, .15);
58
- }
59
-
60
- // Vendored Bootstrap build may omit vh utilities; landing hero uses this for stable min height
61
- .min-vh-50 {
62
- min-height: 50vh;
63
- }
64
-
65
- // MOVED → _sass/layouts/_landing.scss (token-aware version)
66
- // Retained shim: keeps the inline-loading aspect-ratio fallback for the hero
67
- // media slot so existing inline `aspect-ratio` markup in landing.html still
68
- // has a visible placeholder background while the image streams in.
69
- .landing-hero .landing-hero-media {
70
- background-color: rgba(255, 255, 255, 0.06);
71
- }
72
-
73
- #TableOfContents {
74
- overflow: hidden;
75
- text-overflow: ellipsis;
76
- // white-space: nowrap;
77
- }
78
-
79
- .toc {
80
- grid-area: toc;
81
- padding-top: 5rem;
82
- top: 0;
83
- right: 5rem;
84
- }
85
-
86
-
87
- @media (min-width: 992px) {
88
- .toc {
89
- position: -webkit-sticky;
90
- position: sticky;
91
- top: 5rem;
92
- right: 5rem;
93
- z-index: 2;
94
- height: calc(100vh - 7rem);
95
- overflow-y: auto
96
- }
97
- }
98
-
99
- .toc nav {
100
- font-size: .875rem
101
- }
102
-
103
- .toc nav ul {
104
- padding-left: 0;
105
- margin-bottom: 0;
106
- list-style: none
107
- }
108
-
109
- .toc nav ul ul {
110
- padding-left: 1rem;
111
- margin-top: .25rem
112
- }
113
-
114
- .toc nav li {
115
- margin-bottom: .25rem
116
- }
117
-
118
- .toc nav a {
119
- color: inherit
120
- }
121
-
122
- .toc nav a:not(:hover) {
123
- text-decoration: none
124
- }
125
-
126
- .toc nav a code {
127
- font: inherit
128
- }
129
-
130
- .toc-toggle {
131
- display: flex;
132
- align-items: center
133
- }
134
-
135
-
136
- @media (max-width: 989.98px) {
137
- .toc-collapse nav {
138
- padding:1.25rem;
139
- background-color: var(--bs-tertiary-bg);
140
- border: 1px solid var(--bs-border-color);
141
- border-radius: var(--bs-border-radius)
142
- }
143
- }
144
-
145
- @media (min-width: 990px) {
146
- .toc-collapse {
147
- display:block !important
148
- }
149
- }
150
-
151
-
152
- // Sidebar / docs layout: _sass/core/_docs-layout.scss
153
-
154
- // ==============================================================================
155
- // SIDEBAR & TOC ENHANCEMENTS
156
- // ==============================================================================
157
-
158
- // MOVED → _sass/layouts/_navbar-extras.scss (token-aware FAB stacking)
159
- // MOVED → _sass/components/_cookie-banner.scss (token-aware, dark-mode-safe)
160
- // Retained shim: keep stacked-button responsive sizing inside the banner
161
- // because it is a banner-internal concern, not a banner-shell concern.
162
- .cookie-consent-banner {
163
- @media (max-width: 768px) {
164
- .btn {
165
- width: 100%;
166
- margin-bottom: 0.5rem;
167
-
168
- &:last-child {
169
- margin-bottom: 0;
170
- }
171
- }
172
- }
173
- }
174
-
175
- // Active TOC link highlighting
176
- .bd-toc nav a.active {
177
- font-weight: 600;
178
- background-color: rgba(var(--bs-primary-rgb), 0.1);
179
- border-left-color: var(--bs-primary) !important;
180
- }
181
-
182
- // Smooth scroll behavior is declared once below (see "Smooth Scroll Enhancement")
183
-
184
- // Category sidebar active state (nav-tree--categories)
185
- .nav-tree--categories .sidebar-categories-link.active {
186
- font-weight: var(--zer0-font-weight-medium);
187
- background-color: color-mix(in srgb, var(--zer0-color-primary) 10%, transparent);
188
- color: var(--zer0-color-primary);
189
- }
190
-
191
- // Improve sidebar link hover states
192
- .bd-sidebar .list-group-item:hover,
193
- .bd-sidebar .list-group-item-action:hover {
194
- background-color: rgba(var(--bs-primary-rgb), 0.05);
195
- transition: background-color 0.2s ease;
196
- }
197
-
198
- // ==============================================================================
199
- // https://designkojo.com/add-ellipse-truncated-text-css-single-line-and-multi-line-options
200
-
201
-
202
- // MOVED → _sass/components/_back-to-top.scss (token-aware version)
203
- // Retained shim: keep the initial `display: none` (JS toggles it on scroll)
204
- // and the text/arrow label swap, which are content-level concerns the
205
- // component partial doesn't need to know about.
206
- #backToTopBtn {
207
- display: none;
208
-
209
- .text { display: inline-block; }
210
- .arrow { display: none; }
211
-
212
- @media (max-width: 600px) {
213
- .text { display: none; }
214
- .arrow { display: inline-block; }
215
- }
216
- }
217
-
218
- img {
219
- display: inline-block;
220
- max-width: 100%;
221
- height: auto;
222
- }
223
-
224
- // Navbar logo: global img { max-width: 100% } shrinks it inside tight flex/grid cells on small viewports
225
- // (Use a.navbar-brand only — div.navbar-brand.site-title should still shrink/truncate.)
226
- #navbar a.navbar-brand {
227
- flex-shrink: 0;
228
- }
229
- #navbar .navbar-brand img {
230
- width: 30px;
231
- height: 30px;
232
- min-width: 30px;
233
- min-height: 30px;
234
- max-width: none;
235
- object-fit: contain;
236
- flex-shrink: 0;
237
- }
238
-
239
- // ============================================
240
- // NAVBAR - Fixed positioning with auto-hide
241
- // ============================================
242
- // Uses Bootstrap's fixed-top class for positioning (z-index: 1030)
243
- // JavaScript adds/removes .navbar-hidden class on scroll
244
-
245
- #navbar {
246
- // Transition for smooth hide/show animation
247
- transition: transform 0.3s ease-in-out !important;
248
-
249
- // Ensure navbar background is opaque
250
- background-color: var(--bs-body-bg);
251
- }
252
-
253
- // Keep the outer Bootstrap navbar shell on one row (nanobar + nav); avoids rare wrap on wide pages
254
- #navbar > .navbar.navbar-expand-lg {
255
- flex-wrap: nowrap !important;
256
- align-items: center;
257
- }
258
-
259
- #navbar .navbar-main {
260
- align-items: center;
261
- }
262
-
263
- #navbar .site-title-text,
264
- #navbar .site-subtitle-text {
265
- display: inline-block;
266
- }
267
-
268
- #navbar .nav-search-button {
269
- display: inline-flex;
270
- align-items: center;
271
- gap: 0.25rem;
272
- }
273
-
274
- // Desktop (lg+): 3-column grid — [brand/title | main nav | utilities] so nav cannot paint over Search/Settings
275
- @media (min-width: 992px) {
276
- #navbar .navbar-main {
277
- display: grid !important;
278
- grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
279
- align-items: center;
280
- column-gap: 0.5rem;
281
- row-gap: 0.25rem;
282
- flex-wrap: unset !important;
283
- container-type: inline-size;
284
- container-name: navbar-main;
285
- }
286
-
287
- #navbar .navbar-main-start {
288
- grid-column: 1;
289
- display: flex;
290
- align-items: center;
291
- gap: 0.375rem;
292
- min-width: 0;
293
- max-width: none;
294
- flex-shrink: 1;
295
- }
296
-
297
- #navbar #bdNavbar {
298
- grid-column: 2;
299
- width: 100%;
300
- max-width: 100%;
301
- min-width: 0;
302
- justify-self: stretch;
303
- }
304
-
305
- #navbar .navbar-utility-controls {
306
- grid-column: 3;
307
- justify-self: end;
308
- flex-shrink: 0;
309
- min-width: 0;
310
- max-width: max-content;
311
- display: inline-flex;
312
- flex-wrap: nowrap;
313
- align-items: center;
314
- gap: 0.25rem;
315
- padding-left: 0.25rem;
316
- }
317
-
318
- #navbar .navbar-utility-controls .nav-search-button,
319
- #navbar .navbar-utility-controls .nav-settings-button {
320
- flex: 0 1 auto;
321
- min-width: 0;
322
- padding-left: 0.5rem;
323
- padding-right: 0.5rem;
324
- }
325
-
326
- // Brand cluster: logo stays fixed; title flexes and ellipsizes only when crowded
327
- #navbar .navbar-brand-group {
328
- display: inline-flex;
329
- align-items: center;
330
- flex-shrink: 0;
331
- flex-wrap: nowrap;
332
- gap: 0.375rem;
333
- min-width: 0;
334
- }
335
-
336
- #navbar .navbar-home-links {
337
- flex-shrink: 0;
338
- display: none;
339
- }
340
-
341
- #navbar .site-title,
342
- #navbar .site-subtitle {
343
- flex-shrink: 1;
344
- min-width: 0;
345
- }
346
-
347
- #navbar .site-title {
348
- flex: 1 1 auto;
349
- overflow: hidden;
350
- }
351
-
352
- #navbar .site-title .site-title-text {
353
- overflow: hidden;
354
- text-overflow: ellipsis;
355
- white-space: nowrap;
356
- vertical-align: bottom;
357
- max-width: none;
358
- }
359
-
360
- #navbar .site-subtitle .site-subtitle-text {
361
- overflow: hidden;
362
- text-overflow: ellipsis;
363
- white-space: nowrap;
364
- display: inline-block;
365
- vertical-align: bottom;
366
- max-width: none;
367
- }
368
-
369
- // Progressive brand degradation (container width, not viewport)
370
- @container navbar-main (min-width: 80rem) {
371
- #navbar .navbar-home-links {
372
- display: inline-flex !important;
373
- }
374
- }
375
-
376
- @container navbar-main (max-width: 68rem) {
377
- #navbar .site-subtitle {
378
- display: none !important;
379
- }
380
- }
381
-
382
- @container navbar-main (max-width: 50rem) {
383
- #navbar .site-title .site-title-text {
384
- max-width: 100%;
385
- }
386
- }
387
- }
388
-
389
- // Hidden state - slides up out of view
390
- // Using higher specificity to override Bootstrap's fixed-top
391
- #navbar.navbar-hidden {
392
- transform: translateY(-100%) !important;
393
- }
394
-
395
- // Respect user's motion preferences
396
- @media (prefers-reduced-motion: reduce) {
397
- #navbar {
398
- transition: none !important;
399
- }
400
- }
401
-
402
- @media (max-width: 991.98px) {
403
- #navbar .navbar-main {
404
- display: flex;
405
- align-items: center;
406
- justify-content: space-between;
407
- gap: 0.5rem;
408
- padding-left: 0.5rem;
409
- padding-right: 0.5rem;
410
- }
411
-
412
- #navbar .navbar-main-start {
413
- flex: 1 1 auto;
414
- min-width: 0;
415
- }
416
-
417
- #navbar .navbar-brand-group {
418
- flex: 0 1 auto;
419
- min-width: 0;
420
- }
421
-
422
- #navbar .site-title {
423
- flex: 1 1 auto;
424
- min-width: 0;
425
- }
426
-
427
- #navbar .site-title .nav-link {
428
- padding: 0;
429
- min-height: 2.5rem;
430
- align-items: center;
431
- }
432
-
433
- // Title fills the gap between logo and utility controls; ellipsis when crowded
434
- #navbar .site-title-text {
435
- max-width: 100%;
436
- white-space: nowrap;
437
- overflow: hidden;
438
- text-overflow: ellipsis;
439
- vertical-align: middle;
440
- }
441
-
442
- #navbar .navbar-toggler {
443
- width: 2.5rem;
444
- height: 2.5rem;
445
- }
446
-
447
- #navbar .nav-search-button {
448
- width: 2.5rem;
449
- height: 2.5rem;
450
- padding: 0;
451
- justify-content: center;
452
- }
453
- }
454
-
455
- .search-modal .modal-content {
456
- border-radius: 0.75rem;
457
- }
458
-
459
- .search-modal .input-group-text {
460
- background-color: var(--bs-tertiary-bg);
461
- border-color: var(--bs-border-color);
462
- }
463
-
464
- .search-modal kbd {
465
- background-color: var(--bs-tertiary-bg);
466
- color: var(--bs-body-color);
467
- }
468
-
469
- .search-modal .search-results {
470
- max-height: 50vh;
471
- overflow-y: auto;
472
- }
473
-
474
- .search-modal .list-group-item {
475
- border-color: var(--bs-border-color-translucent);
476
- }
477
-
478
- .nested-list-group {
479
- display: none;
480
- }
481
- .nested-list-group.show {
482
- display: block;
483
- }
484
- .folder {
485
- cursor: pointer;
486
- }
487
-
488
- // ==============================================================================
489
- // UI/UX ENHANCEMENTS - Modern, polished interactions
490
- // ==============================================================================
491
-
492
- // Hero Section Enhancements
493
- // NOTE: Exclude .zer0-bg-hero so skin-specific gradients from _backgrounds.scss take precedence
494
- .bg-primary:not(.zer0-bg-hero) {
495
- position: relative;
496
- overflow: hidden;
497
-
498
- &::before {
499
- content: '';
500
- position: absolute;
501
- top: 0;
502
- left: 0;
503
- right: 0;
504
- bottom: 0;
505
- background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 100%);
506
- pointer-events: none;
507
- }
508
- }
509
-
510
- // Hero content animations
511
- .bg-primary .container-xl {
512
- animation: fadeInUp 0.8s ease-out;
513
- }
514
-
515
- @keyframes fadeInUp {
516
- from {
517
- opacity: 0;
518
- transform: translateY(30px);
519
- }
520
- to {
521
- opacity: 1;
522
- transform: translateY(0);
523
- }
524
- }
525
-
526
- // Enhanced Button Styles
527
- .btn {
528
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
529
- position: relative;
530
- overflow: hidden;
531
-
532
- &::before {
533
- content: '';
534
- position: absolute;
535
- top: 50%;
536
- left: 50%;
537
- width: 0;
538
- height: 0;
539
- border-radius: 50%;
540
- background: rgba(255, 255, 255, 0.2);
541
- transform: translate(-50%, -50%);
542
- transition: width 0.6s, height 0.6s;
543
- }
544
-
545
- &:hover::before {
546
- width: 300px;
547
- height: 300px;
548
- }
549
-
550
- &:hover {
551
- transform: translateY(-2px);
552
- box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
553
- }
554
-
555
- &:active {
556
- transform: translateY(0);
557
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
558
- }
559
-
560
- &.btn-lg {
561
- padding: 0.75rem 1.5rem;
562
- font-size: 1.125rem;
563
- }
564
- }
565
-
566
- .btn-outline-light:hover {
567
- background-color: rgba(255, 255, 255, 0.95);
568
- color: var(--bs-primary);
569
- border-color: rgba(255, 255, 255, 0.95);
570
- }
571
-
572
- .btn-light:hover {
573
- background-color: rgba(255, 255, 255, 0.9);
574
- transform: translateY(-2px);
575
- }
576
-
577
- // Enhanced Card Styles
578
- .card {
579
- transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
580
- border: 1px solid rgba(0, 0, 0, 0.08);
581
-
582
- &:hover {
583
- transform: translateY(-8px);
584
- box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
585
- border-color: rgba(var(--bs-primary-rgb), 0.2);
586
- }
587
-
588
- .card-header {
589
- transition: all 0.3s ease;
590
- }
591
-
592
- &:hover .card-header {
593
- background-color: rgba(255, 255, 255, 0.1);
594
- }
595
- }
596
-
597
- // Feature Cards - Icon Animation
598
- .card-body {
599
- .rounded-circle {
600
- transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
601
- }
602
-
603
- i {
604
- transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
605
- }
606
- }
607
-
608
- .card:hover .rounded-circle {
609
- transform: scale(1.1) rotate(5deg);
610
- box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
611
- }
612
-
613
- .card:hover .rounded-circle i {
614
- transform: scale(1.2);
615
- }
616
-
617
- // Code Block Enhancements
618
- pre {
619
- position: relative;
620
- transition: all 0.3s ease;
621
- border: 1px solid rgba(0, 0, 0, 0.1);
622
-
623
- &:hover {
624
- border-color: rgba(var(--bs-primary-rgb), 0.3);
625
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
626
- }
627
-
628
- code {
629
- font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
630
- font-size: 0.875rem;
631
- line-height: 1.6;
632
- }
633
- }
634
-
635
- // Quick Links Bar Enhancements
636
- .bg-dark {
637
- .btn-outline-light {
638
- transition: all 0.3s ease;
639
- border-width: 2px;
640
-
641
- &:hover {
642
- background-color: rgba(255, 255, 255, 0.95);
643
- color: var(--bs-dark);
644
- transform: translateY(-2px);
645
- box-shadow: 0 4px 8px rgba(255, 255, 255, 0.2);
646
- }
647
- }
648
- }
649
-
650
- // Smooth Scroll Enhancement
651
- html {
652
- scroll-behavior: smooth;
653
- scroll-padding-top: 80px; // Account for fixed navbar
654
- }
655
-
656
- // Section Spacing Improvements
657
- // Ensure anchored elements clear the fixed navbar when scrolled to
658
- section,
659
- .py-5,
660
- [id] {
661
- scroll-margin-top: 80px;
662
- }
663
-
664
- // Landing Page Quick Links Animation
665
- .bg-dark {
666
- animation: slideDown 0.6s ease-out;
667
- }
668
-
669
- @keyframes slideDown {
670
- from {
671
- opacity: 0;
672
- transform: translateY(-20px);
673
- }
674
- to {
675
- opacity: 1;
676
- transform: translateY(0);
677
- }
678
- }
679
-
680
- // Feature Section Cards Stagger Animation
681
- .bg-body-tertiary .row.g-4 > * {
682
- animation: fadeInUp 0.6s ease-out backwards;
683
-
684
- &:nth-child(1) { animation-delay: 0.1s; }
685
- &:nth-child(2) { animation-delay: 0.2s; }
686
- &:nth-child(3) { animation-delay: 0.3s; }
687
- }
688
-
689
- // Installation Cards Enhancement
690
- #get-started .card {
691
- border-top: 3px solid transparent;
692
- transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
693
-
694
- &:hover {
695
- border-top-color: var(--bs-primary);
696
- }
697
-
698
- &.card-header.bg-primary ~ .card-body {
699
- border-top-color: var(--bs-primary);
700
- }
701
-
702
- &.card-header.bg-info ~ .card-body {
703
- border-top-color: var(--bs-info);
704
- }
705
-
706
- &.card-header.bg-secondary ~ .card-body {
707
- border-top-color: var(--bs-secondary);
708
- }
709
- }
710
-
711
- // Mobile Responsiveness Improvements
712
- @media (max-width: 768px) {
713
- .bg-primary .display-4 {
714
- font-size: 2rem;
715
- }
716
-
717
- .bg-primary .lead {
718
- font-size: 1rem;
719
- }
720
-
721
- .btn-lg {
722
- padding: 0.625rem 1.25rem;
723
- font-size: 1rem;
724
- }
725
-
726
- .card {
727
- margin-bottom: 1rem;
728
- }
729
-
730
- // Reduce hover effects on mobile for better performance
731
- .card:hover {
732
- transform: translateY(-4px);
733
- }
734
-
735
- .btn:hover {
736
- transform: none;
737
- }
738
- }
739
-
740
- // Loading State for Images
741
- img {
742
- transition: opacity 0.3s ease;
743
-
744
- &[loading="lazy"] {
745
- opacity: 0;
746
-
747
- &.loaded {
748
- opacity: 1;
749
- }
750
- }
751
- }
752
-
753
- // Focus States for Accessibility
754
- .btn:focus-visible,
755
- .card:focus-visible,
756
- a:focus-visible {
757
- outline: 3px solid rgba(var(--bs-primary-rgb), 0.5);
758
- outline-offset: 2px;
759
- }
760
-
761
- // Reduce Motion for Users Who Prefer It
762
- @media (prefers-reduced-motion: reduce) {
763
- *,
764
- *::before,
765
- *::after {
766
- animation-duration: 0.01ms !important;
767
- animation-iteration-count: 1 !important;
768
- transition-duration: 0.01ms !important;
769
- scroll-behavior: auto !important;
770
- }
771
- }
772
-
773
- // Table Enhancements
774
- .table {
775
- transition: all 0.3s ease;
776
-
777
- tbody tr {
778
- transition: background-color 0.2s ease;
779
-
780
- &:hover {
781
- background-color: rgba(var(--bs-primary-rgb), 0.05);
782
- }
783
- }
784
- }
785
-
786
- // Badge Enhancements
787
- .badge {
788
- transition: all 0.3s ease;
789
-
790
- &:hover {
791
- transform: scale(1.05);
792
- }
793
- }
794
-
795
- // Feature category badges on /features/
796
- .feature-categories {
797
- .badge {
798
- &:hover,
799
- &:focus-visible {
800
- color: var(--bs-badge-color, #fff);
801
- text-decoration: none;
802
- filter: brightness(1.12);
803
- transform: scale(1.05);
804
- outline: 2px solid rgba(var(--bs-primary-rgb), 0.55);
805
- outline-offset: 2px;
806
- }
807
- }
808
- }
809
-
810
- // Link Enhancements
811
- a:not(.btn) {
812
- transition: color 0.2s ease;
813
- text-decoration: none;
814
-
815
- &:hover {
816
- text-decoration: underline;
817
- text-underline-offset: 3px;
818
- }
819
- }
820
-
821
- // Container Enhancements
822
- .container-xl {
823
- position: relative;
824
- }
825
-
826
- // Hero Image Animation
827
- .bg-primary img {
828
- animation: fadeInRight 1s ease-out 0.3s backwards;
829
- filter: drop-shadow(0 10px 30px rgba(0, 0, 0, 0.3));
830
- transition: transform 0.3s ease;
831
-
832
- &:hover {
833
- transform: scale(1.02);
834
- }
835
- }
836
-
837
- @keyframes fadeInRight {
838
- from {
839
- opacity: 0;
840
- transform: translateX(30px);
841
- }
842
- to {
843
- opacity: 1;
844
- transform: translateX(0);
845
- }
846
- }
847
-
848
- // Improved Shadow Utilities
849
- .shadow-sm {
850
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08) !important;
851
- }
852
-
853
- .shadow {
854
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12) !important;
855
- }
856
-
857
- .shadow-lg {
858
- box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15) !important;
859
- }
860
-
861
- // Button Ripple Effect
862
- .btn {
863
- position: relative;
864
- overflow: hidden;
865
-
866
- .ripple {
867
- position: absolute;
868
- border-radius: 50%;
869
- background: rgba(255, 255, 255, 0.6);
870
- transform: scale(0);
871
- animation: ripple-animation 0.6s ease-out;
872
- pointer-events: none;
873
- }
874
- }
875
-
876
- @keyframes ripple-animation {
877
- to {
878
- transform: scale(4);
879
- opacity: 0;
880
- }
881
- }
882
-
883
- // Mobile Navigation Enhancements
884
- @media (max-width: 991.98px) {
885
- .navbar-collapse {
886
- background-color: var(--bs-body-bg);
887
- border-radius: 0.5rem;
888
- margin-top: 1rem;
889
- padding: 1rem;
890
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
891
- }
892
-
893
- .navbar-nav .nav-link {
894
- padding: 0.75rem 1rem;
895
- border-radius: 0.375rem;
896
- transition: all 0.2s ease;
897
-
898
- &:hover {
899
- background-color: rgba(var(--bs-primary-rgb), 0.1);
900
- }
901
- }
902
- }
903
-
904
- // Improved Mobile Hero Section
905
- @media (max-width: 768px) {
906
- .bg-primary {
907
- padding: 2rem 0 !important;
908
-
909
- .display-4 {
910
- font-size: 1.75rem;
911
- line-height: 1.3;
912
- }
913
-
914
- .lead {
915
- font-size: 0.95rem;
916
- }
917
-
918
- .btn-lg {
919
- width: 100%;
920
- margin-bottom: 0.5rem;
921
- }
922
- }
923
-
924
- // Better card spacing on mobile
925
- .row.g-4 > * {
926
- margin-bottom: 1rem;
927
- }
928
-
929
- // Improved code block readability on mobile
930
- pre {
931
- font-size: 0.8rem;
932
- overflow-x: auto;
933
- -webkit-overflow-scrolling: touch;
934
-
935
- &:not(.highlight) {
936
- padding: var(--zer0-space-2);
937
- }
938
- }
939
-
940
- .highlight:not(pre) pre,
941
- pre.highlight {
942
- padding: 0;
943
- }
944
- }
945
-
946
- // Touch-friendly tap targets
947
- @media (hover: none) and (pointer: coarse) {
948
- .btn,
949
- .card,
950
- a {
951
- min-height: 44px; // iOS HIG recommendation
952
- min-width: 44px;
953
- }
954
-
955
- // Disable hover effects on touch devices
956
- .card:hover {
957
- transform: none;
958
- }
959
-
960
- .btn:hover {
961
- transform: none;
962
- }
963
- }
964
-
965
- // Improved focus visibility for keyboard navigation
966
- *:focus-visible {
967
- outline: 2px solid var(--bs-primary);
968
- outline-offset: 2px;
969
- border-radius: 0.25rem;
970
- }
971
-
972
- // Enhanced active link states
973
- .nav-link.active,
974
- .btn.active {
975
- position: relative;
976
-
977
- &::after {
978
- content: '';
979
- position: absolute;
980
- bottom: 0;
981
- left: 50%;
982
- transform: translateX(-50%);
983
- width: 80%;
984
- height: 2px;
985
- background-color: currentColor;
986
- border-radius: 2px;
987
- }
988
- }
989
-
990
- // Better table responsiveness
991
- @media (max-width: 768px) {
992
- .table-responsive {
993
- border-radius: 0.5rem;
994
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
995
- }
996
-
997
- .table {
998
- font-size: 0.875rem;
999
-
1000
- th, td {
1001
- padding: 0.5rem;
1002
- }
1003
- }
1004
- }
1005
-
1006
- // Improved badge styling
1007
- .badge {
1008
- font-weight: 500;
1009
- letter-spacing: 0.025em;
1010
- padding: 0.35em 0.65em;
1011
- }
1012
-
1013
- // Enhanced form controls
1014
- .form-control:focus,
1015
- .form-select:focus {
1016
- border-color: var(--bs-primary);
1017
- box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 0.25);
1018
- transform: translateY(-1px);
1019
- transition: all 0.2s ease;
1020
- }
1021
-
1022
- // MOVED → _sass/components/_skeleton.scss (token-aware, dark-mode-safe)
1023
-
1024
- // Print optimizations
1025
- @media print {
1026
- .btn,
1027
- .card:hover,
1028
- .navbar,
1029
- .footer {
1030
- box-shadow: none !important;
1031
- transform: none !important;
1032
- }
1033
-
1034
- a[href^="#"]::after {
1035
- content: " (" attr(href) ")";
1036
- font-size: 0.8em;
1037
- color: #666;
1038
- }
1039
- }
1040
-
1041
- // ==============================================================================
1042
- // NOTES LAYOUT STYLES
1043
- // ==============================================================================
1044
- // MOVED → _sass/components/_notes.scss (token-aware, dark-mode-safe)
1045
- // The .note-header / .note-content / .related-notes / .note-navigation rules
1046
- // are now defined in the components partial. Difficulty badges remain here
1047
- // because they map to fixed semantic colors per the existing API.
1048
-
1049
- // Difficulty badge colors (semantic — kept as fixed values)
1050
- .badge-beginner {
1051
- background-color: var(--zer0-color-success, #198754) !important;
1052
- }
1053
-
1054
- .badge-intermediate {
1055
- background-color: var(--zer0-color-warning, #ffc107) !important;
1056
- color: #212529 !important;
1057
- }
1058
-
1059
- .badge-advanced {
1060
- background-color: var(--zer0-color-danger, #dc3545) !important;
1061
- }
1062
-
1063
- // Share buttons
1064
- .share-buttons {
1065
- margin-top: 2rem;
1066
- padding-top: 1.5rem;
1067
- border-top: 1px solid #dee2e6;
1068
-
1069
- .btn-share {
1070
- padding: 0.5rem 1rem;
1071
- border-radius: 0.375rem;
1072
- text-decoration: none;
1073
- display: inline-flex;
1074
- align-items: center;
1075
- gap: 0.5rem;
1076
- transition: transform 0.2s ease;
1077
-
1078
- &:hover {
1079
- transform: scale(1.05);
1080
- }
1081
- }
1082
- }
1083
-
1084
- // Notes index page styles
1085
- #notes-grid {
1086
- .note-card {
1087
- transition: opacity 0.3s ease, transform 0.3s ease;
1088
-
1089
- &[style*="display: none"] {
1090
- opacity: 0;
1091
- transform: scale(0.95);
1092
- }
1093
- }
1094
-
1095
- .card {
1096
- transition: transform 0.2s ease, box-shadow 0.2s ease;
1097
-
1098
- &:hover {
1099
- transform: translateY(-4px);
1100
- box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
1101
- }
1102
- }
1103
- }
1104
-
1105
- // ==============================================================================
1106
- // NOTEBOOKS INDEX PAGE STYLES
1107
- // ==============================================================================
1108
-
1109
- #notebooks-grid {
1110
- .notebook-card {
1111
- transition: opacity 0.3s ease, transform 0.3s ease;
1112
-
1113
- &[style*="display: none"] {
1114
- opacity: 0;
1115
- transform: scale(0.95);
1116
- }
1117
- }
1118
-
1119
- .card {
1120
- transition: transform 0.2s ease, box-shadow 0.2s ease;
1121
- border-left: 4px solid #0d6efd;
1122
-
1123
- &:hover {
1124
- transform: translateY(-4px);
1125
- box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
1126
- }
1127
-
1128
- .card-header {
1129
- border-bottom: none;
1130
- }
1131
- }
1132
- }
33
+ // Notes & notebooks index-page grids + difficulty badges.
34
+ @import "components/notes-index";