jekyll-theme-zer0 0.22.5 → 0.22.20
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 +196 -0
- data/README.md +66 -19
- data/_data/navigation/admin.yml +53 -0
- data/_data/theme_backgrounds.yml +121 -0
- data/_includes/components/admin-tabs.html +59 -0
- data/_includes/components/analytics-dashboard.html +232 -0
- data/_includes/components/background-customizer.html +159 -0
- data/_includes/components/background-settings.html +137 -0
- data/_includes/components/collection-manager.html +151 -0
- data/_includes/components/component-showcase.html +452 -0
- data/_includes/components/config-editor.html +207 -0
- data/_includes/components/config-viewer.html +479 -0
- data/_includes/components/cookie-consent.html +35 -100
- data/_includes/components/env-dashboard.html +154 -0
- data/_includes/components/feature-card.html +94 -0
- data/_includes/components/info-section.html +172 -149
- data/_includes/components/js-cdn.html +4 -1
- data/_includes/components/nanobar.html +117 -0
- data/_includes/components/nav-editor.html +99 -0
- data/_includes/components/setup-banner.html +28 -0
- data/_includes/components/setup-check.html +53 -0
- data/_includes/components/svg-background.html +42 -0
- data/_includes/components/theme-customizer.html +46 -0
- data/_includes/content/seo.html +68 -135
- data/_includes/core/footer.html +10 -12
- data/_includes/core/head.html +7 -27
- data/_includes/core/header.html +30 -17
- data/_includes/landing/landing-install-cards.html +18 -7
- data/_includes/navigation/admin-nav.html +95 -0
- data/_includes/navigation/navbar.html +45 -6
- data/_includes/navigation/sidebar-left.html +1 -1
- data/_includes/setup/wizard.html +330 -0
- data/_layouts/admin.html +166 -0
- data/_layouts/landing.html +15 -9
- data/_layouts/root.html +12 -6
- data/_layouts/setup.html +73 -0
- data/_plugins/preview_image_generator.rb +26 -12
- data/_sass/core/_navbar.scss +8 -2
- data/_sass/custom.scss +65 -10
- data/_sass/theme/_background-mixins.scss +95 -0
- data/_sass/theme/_backgrounds.scss +156 -0
- data/_sass/theme/_color-modes.scss +2 -1
- data/assets/backgrounds/gradients/air.svg +15 -0
- data/assets/backgrounds/gradients/aqua.svg +15 -0
- data/assets/backgrounds/gradients/contrast.svg +15 -0
- data/assets/backgrounds/gradients/dark.svg +15 -0
- data/assets/backgrounds/gradients/dirt.svg +15 -0
- data/assets/backgrounds/gradients/mint.svg +15 -0
- data/assets/backgrounds/gradients/neon.svg +15 -0
- data/assets/backgrounds/gradients/plum.svg +15 -0
- data/assets/backgrounds/gradients/sunrise.svg +15 -0
- data/assets/backgrounds/noise/air.svg +8 -0
- data/assets/backgrounds/noise/aqua.svg +8 -0
- data/assets/backgrounds/noise/contrast.svg +8 -0
- data/assets/backgrounds/noise/dark.svg +8 -0
- data/assets/backgrounds/noise/dirt.svg +8 -0
- data/assets/backgrounds/noise/mint.svg +8 -0
- data/assets/backgrounds/noise/neon.svg +8 -0
- data/assets/backgrounds/noise/plum.svg +8 -0
- data/assets/backgrounds/noise/sunrise.svg +8 -0
- data/assets/backgrounds/patterns/air.svg +7 -0
- data/assets/backgrounds/patterns/aqua.svg +7 -0
- data/assets/backgrounds/patterns/contrast.svg +4 -0
- data/assets/backgrounds/patterns/dark.svg +5 -0
- data/assets/backgrounds/patterns/dirt.svg +5 -0
- data/assets/backgrounds/patterns/mint.svg +6 -0
- data/assets/backgrounds/patterns/neon.svg +6 -0
- data/assets/backgrounds/patterns/plum.svg +6 -0
- data/assets/backgrounds/patterns/sunrise.svg +5 -0
- data/assets/js/background-customizer.js +73 -0
- data/assets/js/code-copy.js +18 -47
- data/assets/js/config-utility.js +307 -0
- data/assets/js/nanobar-init.js +63 -0
- data/assets/js/nav-editor.js +39 -0
- data/assets/js/palette-generator.js +415 -0
- data/assets/js/search-modal.js +31 -11
- data/assets/js/setup-wizard.js +306 -0
- data/assets/js/skin-editor.js +645 -0
- data/assets/js/theme-customizer.js +102 -0
- data/assets/js/ui-enhancements.js +2 -24
- data/assets/vendor/bootstrap/css/bootstrap.min.css +1 -0
- data/assets/vendor/bootstrap/js/bootstrap.bundle.min.js +1 -0
- data/scripts/README.md +45 -0
- data/scripts/features/generate-preview-images +297 -7
- data/scripts/features/install-preview-generator +51 -33
- data/scripts/fork-cleanup.sh +92 -19
- data/scripts/github-setup.sh +284 -0
- data/scripts/init_setup.sh +0 -1
- data/scripts/lib/frontmatter.sh +543 -0
- data/scripts/lib/migrate.sh +265 -0
- data/scripts/lib/preview_generator.py +607 -32
- data/scripts/lint-pages +508 -0
- data/scripts/migrate.sh +201 -0
- data/scripts/platform/setup-linux.sh +244 -0
- data/scripts/platform/setup-macos.sh +187 -0
- data/scripts/platform/setup-wsl.sh +196 -0
- metadata +73 -6
data/_layouts/setup.html
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: root
|
|
3
|
+
---
|
|
4
|
+
<!--
|
|
5
|
+
===================================================================
|
|
6
|
+
SETUP LAYOUT - Onboarding and configuration pages
|
|
7
|
+
===================================================================
|
|
8
|
+
|
|
9
|
+
File: setup.html
|
|
10
|
+
Path: _layouts/setup.html
|
|
11
|
+
Inherits: root.html
|
|
12
|
+
Purpose: Clean single-column layout for setup, onboarding, and
|
|
13
|
+
configuration guide pages. No sidebar clutter.
|
|
14
|
+
|
|
15
|
+
Features:
|
|
16
|
+
- Centered, readable content column
|
|
17
|
+
- Optional progress indicator via page.setup_step frontmatter
|
|
18
|
+
- Setup banner when site is unconfigured
|
|
19
|
+
- Minimal chrome — lets the user focus on getting configured
|
|
20
|
+
|
|
21
|
+
Usage:
|
|
22
|
+
layout: setup
|
|
23
|
+
setup_step: 2 # optional, highlights step in progress bar
|
|
24
|
+
setup_total: 4 # optional, total number of steps
|
|
25
|
+
===================================================================
|
|
26
|
+
-->
|
|
27
|
+
|
|
28
|
+
{% include components/setup-check.html %}
|
|
29
|
+
|
|
30
|
+
<div class="container-lg py-4">
|
|
31
|
+
<div class="row justify-content-center">
|
|
32
|
+
<div class="col-lg-9">
|
|
33
|
+
|
|
34
|
+
{% if site_needs_setup %}
|
|
35
|
+
<div class="alert alert-warning d-flex align-items-center mb-4" role="alert">
|
|
36
|
+
<i class="bi bi-exclamation-triangle-fill me-2"></i>
|
|
37
|
+
<div>
|
|
38
|
+
<strong>Setup required.</strong>
|
|
39
|
+
Your <code>_config.yml</code> still has default values.
|
|
40
|
+
Follow the instructions on this page or see the
|
|
41
|
+
<a href="{{ '/404.html' | relative_url }}" class="alert-link">setup guide</a>.
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
{% endif %}
|
|
45
|
+
|
|
46
|
+
{% if page.setup_step and page.setup_total %}
|
|
47
|
+
<!-- Progress indicator -->
|
|
48
|
+
<div class="mb-4">
|
|
49
|
+
<div class="d-flex justify-content-between small text-body-secondary mb-1">
|
|
50
|
+
<span>Step {{ page.setup_step }} of {{ page.setup_total }}</span>
|
|
51
|
+
<span>{{ page.setup_step | times: 100 | divided_by: page.setup_total }}% complete</span>
|
|
52
|
+
</div>
|
|
53
|
+
<div class="progress" style="height: 6px;">
|
|
54
|
+
<div class="progress-bar bg-primary"
|
|
55
|
+
role="progressbar"
|
|
56
|
+
style="width: {{ page.setup_step | times: 100 | divided_by: page.setup_total }}%"
|
|
57
|
+
aria-valuenow="{{ page.setup_step }}"
|
|
58
|
+
aria-valuemin="0"
|
|
59
|
+
aria-valuemax="{{ page.setup_total }}">
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
{% endif %}
|
|
64
|
+
|
|
65
|
+
{% if page.title %}
|
|
66
|
+
<h1 class="mb-3">{{ page.title }}</h1>
|
|
67
|
+
{% endif %}
|
|
68
|
+
|
|
69
|
+
{{ content }}
|
|
70
|
+
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
@@ -50,23 +50,31 @@ module Jekyll
|
|
|
50
50
|
preview = doc.data['preview']
|
|
51
51
|
return false if preview.nil? || preview.to_s.strip.empty?
|
|
52
52
|
|
|
53
|
+
# Reject non-path values (text descriptions used as preview)
|
|
54
|
+
return false unless preview.match?(/\.(png|jpe?g|gif|svg|webp)$/i) || preview.start_with?('http')
|
|
55
|
+
|
|
53
56
|
# Check if the preview file actually exists
|
|
54
57
|
site = doc.site
|
|
55
58
|
config = self.config(site)
|
|
56
59
|
|
|
60
|
+
# External URL — assume it exists
|
|
61
|
+
return true if preview.start_with?('http')
|
|
62
|
+
|
|
57
63
|
# Normalize the preview path using assets_prefix
|
|
58
64
|
normalized_preview = normalize_preview_path(preview, config)
|
|
59
65
|
|
|
60
|
-
# Build
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
# Build candidate file paths to check
|
|
67
|
+
candidates = []
|
|
68
|
+
if normalized_preview.start_with?('/')
|
|
69
|
+
candidates << File.join(site.source, normalized_preview.sub(/^\//, ''))
|
|
70
|
+
candidates << File.join(site.source, 'assets', normalized_preview.sub(/^\//, ''))
|
|
71
|
+
else
|
|
72
|
+
candidates << File.join(site.source, 'assets', normalized_preview)
|
|
73
|
+
candidates << File.join(site.source, normalized_preview)
|
|
74
|
+
candidates << File.join(site.source, config['output_dir'], normalized_preview)
|
|
75
|
+
end
|
|
68
76
|
|
|
69
|
-
File.exist?(
|
|
77
|
+
candidates.any? { |path| File.exist?(path) }
|
|
70
78
|
end
|
|
71
79
|
|
|
72
80
|
# Normalize a preview path by adding assets_prefix if needed
|
|
@@ -90,6 +98,9 @@ module Jekyll
|
|
|
90
98
|
preview = doc.data['preview']
|
|
91
99
|
return nil if preview.nil? || preview.to_s.strip.empty?
|
|
92
100
|
|
|
101
|
+
# Reject non-path values
|
|
102
|
+
return nil unless preview.match?(/\.(png|jpe?g|gif|svg|webp)$/i) || preview.start_with?('http')
|
|
103
|
+
|
|
93
104
|
site = doc.site
|
|
94
105
|
config = self.config(site)
|
|
95
106
|
|
|
@@ -162,7 +173,9 @@ module Jekyll
|
|
|
162
173
|
# Handle both Hash (from assign) and Document objects
|
|
163
174
|
if doc.is_a?(Hash)
|
|
164
175
|
preview = doc['preview']
|
|
165
|
-
|
|
176
|
+
return false if preview.nil? || preview.to_s.strip.empty?
|
|
177
|
+
# Only consider values that look like image paths or URLs
|
|
178
|
+
preview.to_s.match?(/\.(png|jpe?g|gif|svg|webp)$/i) || preview.to_s.start_with?('http')
|
|
166
179
|
else
|
|
167
180
|
PreviewImageGenerator.has_preview?(doc)
|
|
168
181
|
end
|
|
@@ -176,12 +189,13 @@ module Jekyll
|
|
|
176
189
|
if doc.is_a?(Hash)
|
|
177
190
|
preview = doc['preview']
|
|
178
191
|
return nil if preview.nil? || preview.to_s.strip.empty?
|
|
192
|
+
return nil unless preview.to_s.match?(/\.(png|jpe?g|gif|svg|webp)$/i) || preview.to_s.start_with?('http')
|
|
193
|
+
|
|
194
|
+
return preview if preview.start_with?('/') || preview.start_with?('http')
|
|
179
195
|
|
|
180
196
|
# Get config from context if available
|
|
181
197
|
site_config = @context.registers[:site].config['preview_images'] || {}
|
|
182
198
|
output_dir = site_config['output_dir'] || 'assets/images/previews'
|
|
183
|
-
|
|
184
|
-
return preview if preview.start_with?('/') || preview.start_with?('http')
|
|
185
199
|
"#{output_dir}/#{preview}"
|
|
186
200
|
else
|
|
187
201
|
PreviewImageGenerator.preview_path(doc)
|
data/_sass/core/_navbar.scss
CHANGED
|
@@ -367,6 +367,12 @@
|
|
|
367
367
|
box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.175);
|
|
368
368
|
border: 1px solid var(--bs-border-color-translucent);
|
|
369
369
|
}
|
|
370
|
+
|
|
371
|
+
// Right-align dropdowns near the end of the nav to prevent overflow clipping
|
|
372
|
+
.nav-hover-dropdown > .dropdown-menu.dropdown-menu-end {
|
|
373
|
+
left: auto;
|
|
374
|
+
right: 0;
|
|
375
|
+
}
|
|
370
376
|
|
|
371
377
|
// Smooth hover reveal animation
|
|
372
378
|
.nav-hover-dropdown .dropdown-menu {
|
|
@@ -743,7 +749,7 @@
|
|
|
743
749
|
}
|
|
744
750
|
|
|
745
751
|
// -----------------------------------------------------------------------------
|
|
746
|
-
// Info Section
|
|
752
|
+
// Info Section Offcanvas Tabs
|
|
747
753
|
// -----------------------------------------------------------------------------
|
|
748
754
|
|
|
749
755
|
#info-section {
|
|
@@ -775,7 +781,7 @@
|
|
|
775
781
|
padding-top: 1rem;
|
|
776
782
|
}
|
|
777
783
|
|
|
778
|
-
// Theme switcher (halfmoon):
|
|
784
|
+
// Theme switcher (halfmoon): keep dropdown positioned within offcanvas panel
|
|
779
785
|
.bd-theme-dropdown {
|
|
780
786
|
position: relative;
|
|
781
787
|
}
|
data/_sass/custom.scss
CHANGED
|
@@ -40,20 +40,33 @@ html, body {
|
|
|
40
40
|
min-height: 50vh;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// Landing layout: stable hero media slot (ratio) +
|
|
43
|
+
// Landing layout: stable hero media slot (CSS aspect-ratio) + smooth image fade-in.
|
|
44
|
+
// The inline `aspect-ratio` + `max-width` on .landing-hero-media in landing.html
|
|
45
|
+
// reserve the box size before this stylesheet loads — these rules are progressive
|
|
46
|
+
// enhancement on top of that.
|
|
44
47
|
.landing-hero {
|
|
45
48
|
.landing-hero-media {
|
|
46
49
|
max-width: min(100%, 28rem);
|
|
50
|
+
// Subtle background while the image streams in so the box isn't a flash of
|
|
51
|
+
// empty colored space against the hero gradient.
|
|
52
|
+
background-color: rgba(255, 255, 255, 0.06);
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
.landing-hero-
|
|
55
|
+
.landing-hero-img {
|
|
50
56
|
object-position: center;
|
|
57
|
+
opacity: 0;
|
|
58
|
+
transition: opacity 0.45s ease-out;
|
|
59
|
+
|
|
60
|
+
&.is-loaded {
|
|
61
|
+
opacity: 1;
|
|
62
|
+
}
|
|
51
63
|
}
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
@media (prefers-reduced-motion: reduce) {
|
|
55
|
-
.landing-hero .landing-hero-
|
|
67
|
+
.landing-hero .landing-hero-img {
|
|
56
68
|
transition: none;
|
|
69
|
+
opacity: 1;
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
72
|
|
|
@@ -170,9 +183,51 @@ html, body {
|
|
|
170
183
|
height: 56px;
|
|
171
184
|
}
|
|
172
185
|
|
|
173
|
-
// Cookie banner: above fixed navbar (1030), below offcanvas (1045) so drawers cover it
|
|
186
|
+
// Cookie banner: above fixed navbar (1030), below offcanvas (1045) so drawers cover it.
|
|
187
|
+
// Show/hide is driven by:
|
|
188
|
+
// - `[hidden]` attribute on initial render and after dismissal (no layout cost)
|
|
189
|
+
// - `.cookie-banner-visible` class to slide / fade into view
|
|
174
190
|
.cookie-consent-banner {
|
|
175
191
|
z-index: 1036;
|
|
192
|
+
background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);
|
|
193
|
+
backdrop-filter: blur(10px);
|
|
194
|
+
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
|
195
|
+
|
|
196
|
+
// Off-screen + transparent until JS adds .cookie-banner-visible.
|
|
197
|
+
// Using `transform` + `opacity` (and NOT `display: none`) keeps the transition smooth.
|
|
198
|
+
opacity: 0;
|
|
199
|
+
transform: translateY(100%);
|
|
200
|
+
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1),
|
|
201
|
+
opacity 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
|
202
|
+
will-change: transform, opacity;
|
|
203
|
+
|
|
204
|
+
// The `hidden` attribute (set in markup + after dismissal) removes the banner
|
|
205
|
+
// from the layout entirely so it can't intercept clicks while invisible.
|
|
206
|
+
&[hidden] {
|
|
207
|
+
display: none !important;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
&.cookie-banner-visible {
|
|
211
|
+
opacity: 1;
|
|
212
|
+
transform: translateY(0);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@media (max-width: 768px) {
|
|
216
|
+
.btn {
|
|
217
|
+
width: 100%;
|
|
218
|
+
margin-bottom: 0.5rem;
|
|
219
|
+
|
|
220
|
+
&:last-child {
|
|
221
|
+
margin-bottom: 0;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@media (prefers-reduced-motion: reduce) {
|
|
228
|
+
.cookie-consent-banner {
|
|
229
|
+
transition: none;
|
|
230
|
+
}
|
|
176
231
|
}
|
|
177
232
|
|
|
178
233
|
// Active TOC link highlighting
|
|
@@ -182,10 +237,7 @@ html, body {
|
|
|
182
237
|
border-left-color: var(--bs-primary) !important;
|
|
183
238
|
}
|
|
184
239
|
|
|
185
|
-
// Smooth scroll behavior
|
|
186
|
-
html {
|
|
187
|
-
scroll-behavior: smooth;
|
|
188
|
-
}
|
|
240
|
+
// Smooth scroll behavior is declared once below (see "Smooth Scroll Enhancement")
|
|
189
241
|
|
|
190
242
|
// Category active state
|
|
191
243
|
.btn-toggle-nav a.active {
|
|
@@ -476,7 +528,8 @@ img {
|
|
|
476
528
|
// ==============================================================================
|
|
477
529
|
|
|
478
530
|
// Hero Section Enhancements
|
|
479
|
-
.bg-
|
|
531
|
+
// NOTE: Exclude .zer0-bg-hero so skin-specific gradients from _backgrounds.scss take precedence
|
|
532
|
+
.bg-primary:not(.zer0-bg-hero) {
|
|
480
533
|
position: relative;
|
|
481
534
|
overflow: hidden;
|
|
482
535
|
|
|
@@ -639,8 +692,10 @@ html {
|
|
|
639
692
|
}
|
|
640
693
|
|
|
641
694
|
// Section Spacing Improvements
|
|
695
|
+
// Ensure anchored elements clear the fixed navbar when scrolled to
|
|
642
696
|
section,
|
|
643
|
-
.py-5
|
|
697
|
+
.py-5,
|
|
698
|
+
[id] {
|
|
644
699
|
scroll-margin-top: 80px;
|
|
645
700
|
}
|
|
646
701
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Background Mixins — reusable fffuel-style layered backgrounds
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
// Usage:
|
|
5
|
+
// @include zer0-bg-gradient; → applies gradient layer
|
|
6
|
+
// @include zer0-bg-noise; → applies noise texture overlay
|
|
7
|
+
// @include zer0-bg-pattern; → applies pattern overlay
|
|
8
|
+
// @include zer0-bg-layered; → combines gradient + noise
|
|
9
|
+
// ==========================================================================
|
|
10
|
+
|
|
11
|
+
/// Gradient background layer (hero / header areas)
|
|
12
|
+
@mixin zer0-bg-gradient {
|
|
13
|
+
position: relative;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
|
|
16
|
+
&::before {
|
|
17
|
+
content: "";
|
|
18
|
+
position: absolute;
|
|
19
|
+
inset: 0;
|
|
20
|
+
background-image: var(--zer0-bg-gradient);
|
|
21
|
+
background-size: cover;
|
|
22
|
+
background-position: center;
|
|
23
|
+
opacity: var(--zer0-bg-gradient-opacity, 0.6);
|
|
24
|
+
mix-blend-mode: var(--zer0-bg-blend, overlay);
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
z-index: 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// Noise texture overlay (body / footer areas)
|
|
31
|
+
@mixin zer0-bg-noise {
|
|
32
|
+
position: relative;
|
|
33
|
+
|
|
34
|
+
&::after {
|
|
35
|
+
content: "";
|
|
36
|
+
position: absolute;
|
|
37
|
+
inset: 0;
|
|
38
|
+
background-image: var(--zer0-bg-noise);
|
|
39
|
+
background-repeat: repeat;
|
|
40
|
+
background-size: 300px 300px;
|
|
41
|
+
opacity: var(--zer0-bg-texture-opacity, 0.04);
|
|
42
|
+
mix-blend-mode: var(--zer0-bg-blend, overlay);
|
|
43
|
+
pointer-events: none;
|
|
44
|
+
z-index: 0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// Pattern overlay (surface / card areas)
|
|
49
|
+
@mixin zer0-bg-pattern {
|
|
50
|
+
position: relative;
|
|
51
|
+
|
|
52
|
+
&::after {
|
|
53
|
+
content: "";
|
|
54
|
+
position: absolute;
|
|
55
|
+
inset: 0;
|
|
56
|
+
background-image: var(--zer0-bg-pattern);
|
|
57
|
+
background-repeat: repeat;
|
|
58
|
+
background-size: var(--zer0-bg-pattern-size, 60px 60px);
|
|
59
|
+
opacity: var(--zer0-bg-pattern-opacity, 0.08);
|
|
60
|
+
mix-blend-mode: var(--zer0-bg-blend, overlay);
|
|
61
|
+
pointer-events: none;
|
|
62
|
+
z-index: 0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// Layered: gradient + noise (for hero sections with depth)
|
|
67
|
+
@mixin zer0-bg-layered {
|
|
68
|
+
position: relative;
|
|
69
|
+
overflow: hidden;
|
|
70
|
+
|
|
71
|
+
&::before {
|
|
72
|
+
content: "";
|
|
73
|
+
position: absolute;
|
|
74
|
+
inset: 0;
|
|
75
|
+
background-image: var(--zer0-bg-gradient);
|
|
76
|
+
background-size: cover;
|
|
77
|
+
background-position: center;
|
|
78
|
+
opacity: var(--zer0-bg-gradient-opacity, 0.6);
|
|
79
|
+
mix-blend-mode: var(--zer0-bg-blend, overlay);
|
|
80
|
+
pointer-events: none;
|
|
81
|
+
z-index: 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
&::after {
|
|
85
|
+
content: "";
|
|
86
|
+
position: absolute;
|
|
87
|
+
inset: 0;
|
|
88
|
+
background-image: var(--zer0-bg-noise);
|
|
89
|
+
background-repeat: repeat;
|
|
90
|
+
background-size: 300px 300px;
|
|
91
|
+
opacity: var(--zer0-bg-texture-opacity, 0.04);
|
|
92
|
+
pointer-events: none;
|
|
93
|
+
z-index: 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Backgrounds — fffuel-style SVG background system for zer0-mistakes theme
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
// Each skin maps to gradient, pattern, and noise SVGs.
|
|
5
|
+
// CSS custom properties drive the layering; mixins in _background-mixins.scss
|
|
6
|
+
// apply them to layout zones.
|
|
7
|
+
// ==========================================================================
|
|
8
|
+
|
|
9
|
+
@import "background-mixins";
|
|
10
|
+
|
|
11
|
+
// --------------------------------------------------------------------------
|
|
12
|
+
// Default custom properties (no skin / fallback)
|
|
13
|
+
// --------------------------------------------------------------------------
|
|
14
|
+
:root {
|
|
15
|
+
--zer0-bg-gradient: none;
|
|
16
|
+
--zer0-bg-pattern: none;
|
|
17
|
+
--zer0-bg-noise: none;
|
|
18
|
+
--zer0-bg-gradient-opacity: 0.6;
|
|
19
|
+
--zer0-bg-texture-opacity: 0.04;
|
|
20
|
+
--zer0-bg-pattern-opacity: 0.08;
|
|
21
|
+
--zer0-bg-blend: overlay;
|
|
22
|
+
--zer0-bg-pattern-size: 60px 60px;
|
|
23
|
+
--zer0-bg-enabled: 1; // 1 = on, 0 = off
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// --------------------------------------------------------------------------
|
|
27
|
+
// Per-skin custom properties
|
|
28
|
+
// Use #{} interpolation so legacy sass-converter passes url() through as-is.
|
|
29
|
+
// Paths are relative to assets/css/main.css so they resolve correctly under
|
|
30
|
+
// any baseurl (e.g. /zer0-pages-remote/ on GitHub Pages subdirectory deploys).
|
|
31
|
+
// --------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
[data-theme-skin="air"] {
|
|
34
|
+
--zer0-bg-gradient: #{"url('../backgrounds/gradients/air.svg')"};
|
|
35
|
+
--zer0-bg-pattern: #{"url('../backgrounds/patterns/air.svg')"};
|
|
36
|
+
--zer0-bg-noise: #{"url('../backgrounds/noise/air.svg')"};
|
|
37
|
+
--zer0-bg-pattern-size: 50px 50px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
[data-theme-skin="aqua"] {
|
|
41
|
+
--zer0-bg-gradient: #{"url('../backgrounds/gradients/aqua.svg')"};
|
|
42
|
+
--zer0-bg-pattern: #{"url('../backgrounds/patterns/aqua.svg')"};
|
|
43
|
+
--zer0-bg-noise: #{"url('../backgrounds/noise/aqua.svg')"};
|
|
44
|
+
--zer0-bg-pattern-size: 48px 48px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
[data-theme-skin="contrast"] {
|
|
48
|
+
--zer0-bg-gradient: #{"url('../backgrounds/gradients/contrast.svg')"};
|
|
49
|
+
--zer0-bg-pattern: #{"url('../backgrounds/patterns/contrast.svg')"};
|
|
50
|
+
--zer0-bg-noise: #{"url('../backgrounds/noise/contrast.svg')"};
|
|
51
|
+
--zer0-bg-pattern-size: 40px 40px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
[data-theme-skin="dark"] {
|
|
55
|
+
--zer0-bg-gradient: #{"url('../backgrounds/gradients/dark.svg')"};
|
|
56
|
+
--zer0-bg-pattern: #{"url('../backgrounds/patterns/dark.svg')"};
|
|
57
|
+
--zer0-bg-noise: #{"url('../backgrounds/noise/dark.svg')"};
|
|
58
|
+
--zer0-bg-pattern-size: 60px 60px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
[data-theme-skin="dirt"] {
|
|
62
|
+
--zer0-bg-gradient: #{"url('../backgrounds/gradients/dirt.svg')"};
|
|
63
|
+
--zer0-bg-pattern: #{"url('../backgrounds/patterns/dirt.svg')"};
|
|
64
|
+
--zer0-bg-noise: #{"url('../backgrounds/noise/dirt.svg')"};
|
|
65
|
+
--zer0-bg-pattern-size: 50px 50px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
[data-theme-skin="neon"] {
|
|
69
|
+
--zer0-bg-gradient: #{"url('../backgrounds/gradients/neon.svg')"};
|
|
70
|
+
--zer0-bg-pattern: #{"url('../backgrounds/patterns/neon.svg')"};
|
|
71
|
+
--zer0-bg-noise: #{"url('../backgrounds/noise/neon.svg')"};
|
|
72
|
+
--zer0-bg-pattern-size: 48px 48px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
[data-theme-skin="mint"] {
|
|
76
|
+
--zer0-bg-gradient: #{"url('../backgrounds/gradients/mint.svg')"};
|
|
77
|
+
--zer0-bg-pattern: #{"url('../backgrounds/patterns/mint.svg')"};
|
|
78
|
+
--zer0-bg-noise: #{"url('../backgrounds/noise/mint.svg')"};
|
|
79
|
+
--zer0-bg-pattern-size: 50px 50px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
[data-theme-skin="plum"] {
|
|
83
|
+
--zer0-bg-gradient: #{"url('../backgrounds/gradients/plum.svg')"};
|
|
84
|
+
--zer0-bg-pattern: #{"url('../backgrounds/patterns/plum.svg')"};
|
|
85
|
+
--zer0-bg-noise: #{"url('../backgrounds/noise/plum.svg')"};
|
|
86
|
+
--zer0-bg-pattern-size: 55px 55px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
[data-theme-skin="sunrise"] {
|
|
90
|
+
--zer0-bg-gradient: #{"url('../backgrounds/gradients/sunrise.svg')"};
|
|
91
|
+
--zer0-bg-pattern: #{"url('../backgrounds/patterns/sunrise.svg')"};
|
|
92
|
+
--zer0-bg-noise: #{"url('../backgrounds/noise/sunrise.svg')"};
|
|
93
|
+
--zer0-bg-pattern-size: 50px 50px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// --------------------------------------------------------------------------
|
|
97
|
+
// Utility classes — apply these to layout zones
|
|
98
|
+
// --------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
.zer0-bg-hero {
|
|
101
|
+
@include zer0-bg-layered;
|
|
102
|
+
|
|
103
|
+
> * { position: relative; z-index: 1; }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.zer0-bg-body {
|
|
107
|
+
@include zer0-bg-noise;
|
|
108
|
+
|
|
109
|
+
// Elevate children above the ::before / ::after pseudo-element backgrounds,
|
|
110
|
+
// but exclude fixed-position, offcanvas, and modal elements whose
|
|
111
|
+
// positioning must not be overridden.
|
|
112
|
+
> *:not(.fixed-top):not(.offcanvas):not(.modal) { position: relative; z-index: 1; }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.zer0-bg-surface {
|
|
116
|
+
@include zer0-bg-pattern;
|
|
117
|
+
|
|
118
|
+
> * { position: relative; z-index: 1; }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.zer0-bg-footer {
|
|
122
|
+
@include zer0-bg-noise;
|
|
123
|
+
|
|
124
|
+
> * { position: relative; z-index: 1; }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// --------------------------------------------------------------------------
|
|
128
|
+
// Accessibility: respect reduced-motion
|
|
129
|
+
// --------------------------------------------------------------------------
|
|
130
|
+
@media (prefers-reduced-motion: reduce) {
|
|
131
|
+
.zer0-bg-hero,
|
|
132
|
+
.zer0-bg-body,
|
|
133
|
+
.zer0-bg-surface,
|
|
134
|
+
.zer0-bg-footer {
|
|
135
|
+
&::before,
|
|
136
|
+
&::after {
|
|
137
|
+
animation: none !important;
|
|
138
|
+
transition: none !important;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// --------------------------------------------------------------------------
|
|
144
|
+
// Kill switch: when backgrounds are disabled
|
|
145
|
+
// --------------------------------------------------------------------------
|
|
146
|
+
[data-zer0-bg="off"] {
|
|
147
|
+
.zer0-bg-hero,
|
|
148
|
+
.zer0-bg-body,
|
|
149
|
+
.zer0-bg-surface,
|
|
150
|
+
.zer0-bg-footer {
|
|
151
|
+
&::before,
|
|
152
|
+
&::after {
|
|
153
|
+
display: none !important;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#e8f4f8"/>
|
|
5
|
+
<stop offset="50%" stop-color="#b8d4e3"/>
|
|
6
|
+
<stop offset="100%" stop-color="#6fa8dc"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<filter id="f1">
|
|
9
|
+
<feTurbulence type="fractalNoise" baseFrequency="0.006" numOctaves="4" seed="2"/>
|
|
10
|
+
<feDisplacementMap in="SourceGraphic" scale="60"/>
|
|
11
|
+
</filter>
|
|
12
|
+
</defs>
|
|
13
|
+
<rect width="100%" height="100%" fill="url(#g1)"/>
|
|
14
|
+
<rect width="100%" height="100%" fill="url(#g1)" filter="url(#f1)" opacity="0.5"/>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#0077b6"/>
|
|
5
|
+
<stop offset="50%" stop-color="#00b4d8"/>
|
|
6
|
+
<stop offset="100%" stop-color="#90e0ef"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<filter id="f1">
|
|
9
|
+
<feTurbulence type="fractalNoise" baseFrequency="0.008" numOctaves="4" seed="5"/>
|
|
10
|
+
<feDisplacementMap in="SourceGraphic" scale="70"/>
|
|
11
|
+
</filter>
|
|
12
|
+
</defs>
|
|
13
|
+
<rect width="100%" height="100%" fill="url(#g1)"/>
|
|
14
|
+
<rect width="100%" height="100%" fill="url(#g1)" filter="url(#f1)" opacity="0.5"/>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#111111"/>
|
|
5
|
+
<stop offset="50%" stop-color="#333333"/>
|
|
6
|
+
<stop offset="100%" stop-color="#ffcc00"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<filter id="f1">
|
|
9
|
+
<feTurbulence type="fractalNoise" baseFrequency="0.005" numOctaves="3" seed="8"/>
|
|
10
|
+
<feDisplacementMap in="SourceGraphic" scale="50"/>
|
|
11
|
+
</filter>
|
|
12
|
+
</defs>
|
|
13
|
+
<rect width="100%" height="100%" fill="url(#g1)"/>
|
|
14
|
+
<rect width="100%" height="100%" fill="url(#g1)" filter="url(#f1)" opacity="0.4"/>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#1a1a2e"/>
|
|
5
|
+
<stop offset="50%" stop-color="#16213e"/>
|
|
6
|
+
<stop offset="100%" stop-color="#0f3460"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<filter id="f1">
|
|
9
|
+
<feTurbulence type="fractalNoise" baseFrequency="0.007" numOctaves="4" seed="12"/>
|
|
10
|
+
<feDisplacementMap in="SourceGraphic" scale="55"/>
|
|
11
|
+
</filter>
|
|
12
|
+
</defs>
|
|
13
|
+
<rect width="100%" height="100%" fill="url(#g1)"/>
|
|
14
|
+
<rect width="100%" height="100%" fill="url(#g1)" filter="url(#f1)" opacity="0.5"/>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#5c4033"/>
|
|
5
|
+
<stop offset="50%" stop-color="#8b6914"/>
|
|
6
|
+
<stop offset="100%" stop-color="#d4a574"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<filter id="f1">
|
|
9
|
+
<feTurbulence type="fractalNoise" baseFrequency="0.009" numOctaves="4" seed="20"/>
|
|
10
|
+
<feDisplacementMap in="SourceGraphic" scale="65"/>
|
|
11
|
+
</filter>
|
|
12
|
+
</defs>
|
|
13
|
+
<rect width="100%" height="100%" fill="url(#g1)"/>
|
|
14
|
+
<rect width="100%" height="100%" fill="url(#g1)" filter="url(#f1)" opacity="0.5"/>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#2d6a4f"/>
|
|
5
|
+
<stop offset="50%" stop-color="#52b788"/>
|
|
6
|
+
<stop offset="100%" stop-color="#95d5b2"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<filter id="f1">
|
|
9
|
+
<feTurbulence type="fractalNoise" baseFrequency="0.007" numOctaves="4" seed="30"/>
|
|
10
|
+
<feDisplacementMap in="SourceGraphic" scale="60"/>
|
|
11
|
+
</filter>
|
|
12
|
+
</defs>
|
|
13
|
+
<rect width="100%" height="100%" fill="url(#g1)"/>
|
|
14
|
+
<rect width="100%" height="100%" fill="url(#g1)" filter="url(#f1)" opacity="0.5"/>
|
|
15
|
+
</svg>
|