@fluid-theme/core 0.4.3 → 2.1.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.
- package/AGENTS.md +6 -29
- package/CHANGELOG.md +564 -2
- package/CLAUDE.md +201 -14
- package/GEMINI.md +6 -45
- package/README.md +17 -8
- package/assets/js/compare.js +77 -0
- package/assets/js/fit-text.js +103 -0
- package/assets/js/lightbox.js +153 -0
- package/assets/js/scroll-reveal.js +72 -0
- package/assets/js/toc-build.mjs +86 -0
- package/assets/js/toc.js +384 -0
- package/dist/fluid-1x.min.css +4 -0
- package/dist/fluid-fonts-archivo.min.css +2 -0
- package/dist/fluid-fonts-bodoni.min.css +2 -0
- package/dist/fluid-fonts.min.css +2 -0
- package/dist/fluid-legacy-1x.css +3 -0
- package/dist/fluid-nav.min.css +3 -0
- package/dist/fluid-toc.min.css +3 -0
- package/dist/fluid-zero.min.css +3 -0
- package/dist/fluid.min.css +3 -2
- package/dist/fonts/OFL-archivo.txt +93 -0
- package/dist/fonts/OFL-bodoni-moda.txt +93 -0
- package/dist/fonts/OFL-hanken-grotesk.txt +93 -0
- package/dist/fonts/OFL-newsreader.txt +93 -0
- package/dist/fonts/OFL-schibsted-grotesk.txt +93 -0
- package/dist/fonts/archivo-latin-wdth-italic.woff2 +0 -0
- package/dist/fonts/archivo-latin-wdth-normal.woff2 +0 -0
- package/dist/fonts/bodoni-moda-latin-opsz-italic.woff2 +0 -0
- package/dist/fonts/bodoni-moda-latin-opsz-normal.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
- package/dist/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/dist/fonts/schibsted-grotesk-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
- package/fluid-agent-kit/README.md +1 -0
- package/fluid-agent-kit/skills/accessibility.md +3 -1
- package/fluid-agent-kit/skills/css-conventions.md +22 -5
- package/fluid-agent-kit/skills/image-optimization.md +2 -0
- package/fluid-agent-kit/skills/preset-composition.md +108 -0
- package/package.json +36 -11
- package/src/animations/scroll-reveal.css +75 -193
- package/src/components/accordion.css +6 -47
- package/src/components/alert.css +47 -88
- package/src/components/avatar.css +4 -20
- package/src/components/badge.css +25 -48
- package/src/components/button.css +69 -175
- package/src/components/card.css +146 -481
- package/src/components/chip.css +46 -12
- package/src/components/compare.css +234 -0
- package/src/components/dropdown.css +10 -67
- package/src/components/empty-state.css +4 -0
- package/src/components/form.css +113 -81
- package/src/components/gallery.css +252 -0
- package/src/components/hero.css +203 -88
- package/src/components/indicator.css +23 -117
- package/src/components/loading.css +7 -29
- package/src/components/modal.css +12 -65
- package/src/components/nav-modes.css +261 -0
- package/src/components/nav.css +324 -392
- package/src/components/search-input.css +4 -2
- package/src/components/step-indicator.css +26 -27
- package/src/components/table.css +64 -171
- package/src/components/toc.css +254 -0
- package/src/components/tooltip.css +5 -46
- package/src/core/base.css +393 -547
- package/src/core/reset.css +17 -5
- package/src/core/tokens.css +426 -2276
- package/src/fluid.css +258 -17
- package/src/fonts/OFL-newsreader.txt +93 -0
- package/src/fonts/OFL-schibsted-grotesk.txt +93 -0
- package/src/fonts/fluid-fonts.css +55 -0
- package/src/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
- package/src/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/src/fonts/schibsted-grotesk-latin-wght-italic.woff2 +0 -0
- package/src/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
- package/src/layouts/positioning.css +6 -3
- package/src/legacy-1x.css +61 -0
- package/src/sections/cta.css +33 -101
- package/src/sections/features.css +42 -219
- package/src/sections/footer.css +53 -134
- package/src/sections/stats.css +40 -153
- package/src/sections/team.css +24 -113
- package/src/sections/testimonials.css +34 -148
- package/src/zero/base.css +166 -0
- package/src/zero/tokens.css +64 -0
- package/src/zero.css +20 -0
- package/starters/workflows/README.md +40 -0
- package/starters/workflows/dependabot.yml +21 -0
- package/starters/workflows/update-fluid-theme.yml +296 -0
- package/themes/fonts/OFL-archivo.txt +93 -0
- package/themes/fonts/OFL-bodoni-moda.txt +93 -0
- package/themes/fonts/OFL-hanken-grotesk.txt +93 -0
- package/themes/fonts/archivo-latin-wdth-italic.woff2 +0 -0
- package/themes/fonts/archivo-latin-wdth-normal.woff2 +0 -0
- package/themes/fonts/archivo.css +20 -0
- package/themes/fonts/bodoni-moda-latin-opsz-italic.woff2 +0 -0
- package/themes/fonts/bodoni-moda-latin-opsz-normal.woff2 +0 -0
- package/themes/fonts/bodoni.css +35 -0
- package/themes/fonts/hanken-grotesk-latin-wght-italic.woff2 +0 -0
- package/themes/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
- package/themes/gallery.css +105 -0
- package/themes/swiss.css +53 -0
- package/src/components/scroll-progress.css +0 -104
- package/src/components/settings-panel.css +0 -603
- package/src/components/themed-images.css +0 -229
- package/src/components/version-badge.css +0 -70
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Preset Composition — Per-Preset Layout DNA
|
|
2
|
+
|
|
3
|
+
> **Superseded (2026-10-23, Pass 0).** This describes the preset/palette system, which was removed. What the theme is now, and its knobs: [`_docs/STATUS.md`](../../_docs/STATUS.md). Kept as history.
|
|
4
|
+
|
|
5
|
+
When building a page with Fluid, the active `data-preset` is a COMPLETE design decision: it drives which layouts and arrangements you compose, not just colors and fonts. This skill maps each preset to the compositions that suit it.
|
|
6
|
+
|
|
7
|
+
Full preset reference: `_docs/theming-guide.md` ("Visual Presets in Depth").
|
|
8
|
+
|
|
9
|
+
## The Two Mechanisms
|
|
10
|
+
|
|
11
|
+
**1. Runtime arrangement — `data-arrange="auto"`** (opt-in, on `.hero` and `.features`):
|
|
12
|
+
|
|
13
|
+
- `.hero` — requires flat markup: `hero__headline`, `hero__subheadline`, `hero__actions`, optional `hero__media` as **direct children** (no `hero__content` wrapper). The preset then remaps the arrangement via `grid-template-areas`. `data-arrange` wins over `data-layout`.
|
|
14
|
+
- `.features` — the preset remaps the grid's shape and density.
|
|
15
|
+
|
|
16
|
+
| Preset | Hero signature | Features signature |
|
|
17
|
+
|--------|----------------|--------------------|
|
|
18
|
+
| **still** | Swiss left rail + asymmetric void | Ruled hairline grid |
|
|
19
|
+
| **serene** | Editorial offset: full-width headline, copy hangs right | Single literary column |
|
|
20
|
+
| **rapids** | Poster split: giant headline left, caption column right | Dense 4-up |
|
|
21
|
+
| **tsunami** | Cinema poster: bottom-anchored massive headline, subheadline as kicker | Monumental 2-up |
|
|
22
|
+
| **flowing / stream / cascade** | Centered classic stack | Default responsive card grid |
|
|
23
|
+
|
|
24
|
+
**2. Composition-time choices (the important one)**: when generating page markup for a given preset, CHOOSE section variants, hero `data-layout` (`center` / `split` / `split-reverse`), grid densities, and content order that match the preset's layout DNA below. This applies to ALL sections — not just the two with `data-arrange`.
|
|
25
|
+
|
|
26
|
+
## Layout DNA
|
|
27
|
+
|
|
28
|
+
| Preset | Canvas | Section rhythm | Hero to prefer | Grid density | Alignment bias |
|
|
29
|
+
|--------|--------|----------------|----------------|--------------|----------------|
|
|
30
|
+
| **still** | Focused 768px column | 32px, tight | Left-rail split, restrained size | Compact, ruled | Flush left |
|
|
31
|
+
| **serene** | 42rem literary column | 144px intervals | Full-width serif headline + offset deck | Single column | Centered, unboxed |
|
|
32
|
+
| **stream** | 1536px wide canvas | 64px | Wide split | 3–4 col cards | Left, horizontal |
|
|
33
|
+
| **flowing** | 1280px | 80px | Balanced centered | 3-up | Centered |
|
|
34
|
+
| **cascade** | 1280px | 64px | Friendly centered | Generous cards | Centered |
|
|
35
|
+
| **rapids** | 1536px | 32px, dense | Poster split, oversized type | Dense 4-up | Hard left |
|
|
36
|
+
| **tsunami** | Full width | 96px cinematic | Full-bleed, bottom-anchored | Monumental 2-up | Left, bottom-anchored |
|
|
37
|
+
|
|
38
|
+
### still — Swiss precision
|
|
39
|
+
|
|
40
|
+
Mono grayscale default palette, system fonts, restrained display sizes, left-aligned Swiss grid, hairline rules.
|
|
41
|
+
|
|
42
|
+
- DO: compact tables and ruled grids; flush-left headlines; 2-col asymmetric splits with deliberate void
|
|
43
|
+
- DON'T: centered hero copy; decorative gradients; pill shapes
|
|
44
|
+
|
|
45
|
+
### serene — literary calm
|
|
46
|
+
|
|
47
|
+
Large graceful serif display, morandi default palette (dusty lavender accent), extravagant whitespace.
|
|
48
|
+
|
|
49
|
+
- DO: single-column flows; generous stacked sections; full-width serif headline with offset deck; centered unboxed feature lists
|
|
50
|
+
- DON'T: packed multi-column grids; dense dashboards
|
|
51
|
+
|
|
52
|
+
### stream — tech-forward
|
|
53
|
+
|
|
54
|
+
Plus Jakarta Sans, fluid deep-teal accent, professional and balanced.
|
|
55
|
+
|
|
56
|
+
- DO: wide split heroes; 3–4 col card grids; horizontal nav emphasis; dashboard patterns
|
|
57
|
+
- DON'T: narrow editorial columns
|
|
58
|
+
|
|
59
|
+
### flowing — the versatile default
|
|
60
|
+
|
|
61
|
+
Outfit/DM Sans, brand medium-blue accent. Balanced centered heroes, 3-up grids — the reference point when no other DNA applies.
|
|
62
|
+
|
|
63
|
+
### cascade — warm and bubbly
|
|
64
|
+
|
|
65
|
+
Nunito, bold vivid-purple accent, maximum roundness.
|
|
66
|
+
|
|
67
|
+
- DO: friendly centered layouts; generous card grids; pill buttons
|
|
68
|
+
- DON'T: sharp-edged dense tables
|
|
69
|
+
|
|
70
|
+
### rapids — bold poster energy
|
|
71
|
+
|
|
72
|
+
Syne/Space Grotesk at 800–900 weight, electric coral accent, oversized display type.
|
|
73
|
+
|
|
74
|
+
- DO: poster splits; dense 4-up packs; tight rhythm; hard offset shadows
|
|
75
|
+
- DON'T: airy whitespace; serif elegance
|
|
76
|
+
|
|
77
|
+
### tsunami — cinematic maximum
|
|
78
|
+
|
|
79
|
+
Bebas Neue massive display (hero headlines up to 6.5rem), storm-teal accent, asymmetric corners.
|
|
80
|
+
|
|
81
|
+
- DO: full-bleed bottom-anchored heroes; monumental 2-up grids; kicker-above-headline patterns
|
|
82
|
+
- DON'T: small centered cards; subtle anything
|
|
83
|
+
|
|
84
|
+
### Identity presets
|
|
85
|
+
|
|
86
|
+
- **editorial** — extreme-whitespace serif essay (38rem column, 8rem sections): single-column prose only
|
|
87
|
+
- **brutalist** — monospace ruled rawness: hard borders, raw grids, zero decoration
|
|
88
|
+
- **neon** — dark glowing cyberpunk: dark surfaces, glow shadows, high-tech density
|
|
89
|
+
|
|
90
|
+
## Default Palettes
|
|
91
|
+
|
|
92
|
+
Each water preset ships a default palette family + accent, so switching presets changes the color mood too:
|
|
93
|
+
|
|
94
|
+
| Preset | Family | Default accent |
|
|
95
|
+
|--------|--------|----------------|
|
|
96
|
+
| still | mono | grayscale slate |
|
|
97
|
+
| serene | morandi | dusty lavender |
|
|
98
|
+
| stream | fluid | deep teal |
|
|
99
|
+
| flowing | fluid | brand medium blue |
|
|
100
|
+
| cascade | bold | vivid purple |
|
|
101
|
+
| rapids | bold | electric coral |
|
|
102
|
+
| tsunami | tsunami | storm teal |
|
|
103
|
+
|
|
104
|
+
Explicit `data-palette` / `data-accent` always override. Do NOT add a `data-palette` unless the user asks for a specific color mood — the default family is part of the preset's design.
|
|
105
|
+
|
|
106
|
+
## Never Mix DNA
|
|
107
|
+
|
|
108
|
+
Never mix arrangement DNA across presets on one page. If the user's content fights the preset's DNA (e.g., a dense data table on serene), keep the preset's rhythm and adapt the section — or suggest a better-suited preset. Do not import another preset's arrangement to solve it.
|
package/package.json
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-theme/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "A modern, semantic CSS design system built on physics principles — not utility classes",
|
|
5
5
|
"main": "dist/fluid.min.css",
|
|
6
6
|
"style": "dist/fluid.min.css",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./dist/fluid.min.css",
|
|
9
|
+
"./zero": "./dist/fluid-zero.min.css",
|
|
10
|
+
"./fonts": "./dist/fluid-fonts.min.css",
|
|
11
|
+
"./fonts-archivo": "./dist/fluid-fonts-archivo.min.css",
|
|
12
|
+
"./fonts-bodoni": "./dist/fluid-fonts-bodoni.min.css",
|
|
13
|
+
"./legacy-1x": "./dist/fluid-legacy-1x.css",
|
|
14
|
+
"./1x": "./dist/fluid-1x.min.css",
|
|
15
|
+
"./toc": "./dist/fluid-toc.min.css",
|
|
16
|
+
"./nav": "./dist/fluid-nav.min.css",
|
|
17
|
+
"./toc-build": "./assets/js/toc-build.mjs",
|
|
18
|
+
"./themes/swiss": "./themes/swiss.css",
|
|
19
|
+
"./themes/gallery": "./themes/gallery.css",
|
|
20
|
+
"./themes/*": "./themes/*",
|
|
9
21
|
"./src": "./src/fluid.css"
|
|
10
22
|
},
|
|
11
23
|
"files": [
|
|
12
24
|
"dist/",
|
|
25
|
+
"themes/",
|
|
26
|
+
"starters/workflows/",
|
|
27
|
+
"assets/js/",
|
|
13
28
|
"src/",
|
|
14
29
|
"fluid-agent-kit/",
|
|
15
30
|
"CLAUDE.md",
|
|
@@ -24,7 +39,14 @@
|
|
|
24
39
|
"build": "node scripts/build-css.mjs",
|
|
25
40
|
"prepublishOnly": "npm run build",
|
|
26
41
|
"optimize-images": "node scripts/optimize-images.js",
|
|
27
|
-
"test": "
|
|
42
|
+
"test:reveal": "node scripts/reveal-check.mjs",
|
|
43
|
+
"test:forms": "node scripts/form-check.mjs",
|
|
44
|
+
"test:axe": "node scripts/axe-check.mjs",
|
|
45
|
+
"test:focus": "node scripts/focus-check.mjs",
|
|
46
|
+
"test:toc": "node scripts/toc-check.mjs",
|
|
47
|
+
"test:nav": "node scripts/nav-check.mjs",
|
|
48
|
+
"test": "echo \"Visual testing only - open examples/foundation.html in browser\"",
|
|
49
|
+
"test:zero": "node scripts/visual-scan.mjs scripts/fixtures/zero.html && node scripts/axe-check.mjs --pages scripts/fixtures/zero.html && node scripts/focus-check.mjs --page scripts/fixtures/zero.html"
|
|
28
50
|
},
|
|
29
51
|
"keywords": [
|
|
30
52
|
"css",
|
|
@@ -48,21 +70,24 @@
|
|
|
48
70
|
"url": "https://github.com/Agile-Media-Agency/the-fluid-theme/issues"
|
|
49
71
|
},
|
|
50
72
|
"homepage": "https://thefluidtheme.com",
|
|
51
|
-
"engines": {
|
|
52
|
-
"browsers": [
|
|
53
|
-
"last 2 Chrome versions",
|
|
54
|
-
"last 2 Firefox versions",
|
|
55
|
-
"last 2 Safari versions",
|
|
56
|
-
"last 2 Edge versions"
|
|
57
|
-
]
|
|
58
|
-
},
|
|
59
73
|
"browserslist": [
|
|
60
74
|
"supports css-cascade-layers",
|
|
61
75
|
"supports css-container-queries",
|
|
62
76
|
"supports css-logical-properties"
|
|
63
77
|
],
|
|
64
78
|
"devDependencies": {
|
|
79
|
+
"@capsizecss/core": "^4.1.3",
|
|
80
|
+
"@capsizecss/metrics": "^4.4.0",
|
|
81
|
+
"@fontsource-variable/newsreader": "^5.3.0",
|
|
82
|
+
"@fontsource-variable/schibsted-grotesk": "^5.3.0",
|
|
83
|
+
"axe-core": "^4.11.1",
|
|
84
|
+
"lighthouse": "^13.0.3",
|
|
65
85
|
"lightningcss": "^1.32.0",
|
|
66
|
-
"
|
|
86
|
+
"playwright": "^1.64.1",
|
|
87
|
+
"puppeteer": "^24.40.0",
|
|
88
|
+
"sharp": "^0.35.5"
|
|
89
|
+
},
|
|
90
|
+
"publishConfig": {
|
|
91
|
+
"access": "public"
|
|
67
92
|
}
|
|
68
93
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Scroll Reveal Animations
|
|
2
|
+
* Scroll Reveal Animations (opt-in)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Only elements that carry [data-reveal] ever animate, and only once
|
|
5
|
+
* assets/js/scroll-reveal.js has set data-reveal-ready on <html>. Without
|
|
6
|
+
* the script, with scripting off, or with reduced motion asked for, nothing
|
|
7
|
+
* is hidden: the hidden start state exists only under all three conditions.
|
|
8
|
+
* A bare .section is never hidden (that blanked the stack's pages, #61).
|
|
6
9
|
*
|
|
7
10
|
* Variants:
|
|
8
11
|
* data-reveal="fade" - Fade in
|
|
@@ -16,209 +19,88 @@
|
|
|
16
19
|
* Timing:
|
|
17
20
|
* data-reveal-delay="100" - Delay in ms (100, 200, 300, 400, 500)
|
|
18
21
|
* data-reveal-duration="slow" - Duration (fast, normal, slow)
|
|
22
|
+
* data-reveal-stagger on a parent staggers its [data-reveal] children
|
|
19
23
|
*/
|
|
20
24
|
|
|
21
25
|
@layer components {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
will-change: opacity, transform;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/* Revealed state */
|
|
33
|
-
[data-reveal].revealed,
|
|
34
|
-
[data-reveal][data-revealed] {
|
|
35
|
-
opacity: 1;
|
|
36
|
-
transform: none;
|
|
37
|
-
filter: none;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/* Fade variants - starting positions */
|
|
41
|
-
[data-reveal="fade-up"] {
|
|
42
|
-
transform: translateY(2rem);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
[data-reveal="fade-down"] {
|
|
46
|
-
transform: translateY(-2rem);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
[data-reveal="fade-left"] {
|
|
50
|
-
transform: translateX(2rem);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
[data-reveal="fade-right"] {
|
|
54
|
-
transform: translateX(-2rem);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
[data-reveal="scale"] {
|
|
58
|
-
transform: scale(0.95);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
[data-reveal="blur"] {
|
|
62
|
-
filter: blur(8px);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/* Delays */
|
|
66
|
-
[data-reveal-delay="100"] { transition-delay: 100ms; }
|
|
67
|
-
[data-reveal-delay="200"] { transition-delay: 200ms; }
|
|
68
|
-
[data-reveal-delay="300"] { transition-delay: 300ms; }
|
|
69
|
-
[data-reveal-delay="400"] { transition-delay: 400ms; }
|
|
70
|
-
[data-reveal-delay="500"] { transition-delay: 500ms; }
|
|
71
|
-
|
|
72
|
-
/* Durations */
|
|
73
|
-
[data-reveal-duration="fast"] { --reveal-duration: var(--duration-fast); }
|
|
74
|
-
[data-reveal-duration="normal"] { --reveal-duration: var(--duration-slow); }
|
|
75
|
-
[data-reveal-duration="slow"] { --reveal-duration: var(--duration-slower); }
|
|
76
|
-
|
|
77
|
-
/* Stagger children - useful for grids and lists */
|
|
78
|
-
[data-reveal-stagger] > [data-reveal]:nth-child(1) { transition-delay: calc(var(--reveal-stagger, 100ms) * 0); }
|
|
79
|
-
[data-reveal-stagger] > [data-reveal]:nth-child(2) { transition-delay: calc(var(--reveal-stagger, 100ms) * 1); }
|
|
80
|
-
[data-reveal-stagger] > [data-reveal]:nth-child(3) { transition-delay: calc(var(--reveal-stagger, 100ms) * 2); }
|
|
81
|
-
[data-reveal-stagger] > [data-reveal]:nth-child(4) { transition-delay: calc(var(--reveal-stagger, 100ms) * 3); }
|
|
82
|
-
[data-reveal-stagger] > [data-reveal]:nth-child(5) { transition-delay: calc(var(--reveal-stagger, 100ms) * 4); }
|
|
83
|
-
[data-reveal-stagger] > [data-reveal]:nth-child(6) { transition-delay: calc(var(--reveal-stagger, 100ms) * 5); }
|
|
84
|
-
[data-reveal-stagger] > [data-reveal]:nth-child(7) { transition-delay: calc(var(--reveal-stagger, 100ms) * 6); }
|
|
85
|
-
[data-reveal-stagger] > [data-reveal]:nth-child(8) { transition-delay: calc(var(--reveal-stagger, 100ms) * 7); }
|
|
86
|
-
|
|
87
|
-
/* ========================================
|
|
88
|
-
AUTO-REVEAL BY MOTION STYLE
|
|
89
|
-
Sections auto-animate based on theme motion setting
|
|
90
|
-
======================================== */
|
|
91
|
-
|
|
92
|
-
/* Still: No animations */
|
|
93
|
-
[data-motion="still"] [data-reveal] {
|
|
94
|
-
opacity: 1;
|
|
95
|
-
transform: none;
|
|
96
|
-
filter: none;
|
|
97
|
-
transition: none;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/* Serene: Very slow, gentle fade */
|
|
101
|
-
[data-motion="serene"] [data-reveal] {
|
|
102
|
-
--reveal-duration: var(--duration-slower);
|
|
103
|
-
--reveal-easing: cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
[data-motion="serene"] .section:not([data-reveal]) {
|
|
107
|
-
opacity: 0;
|
|
108
|
-
transform: scale(1.02);
|
|
109
|
-
transition:
|
|
110
|
-
opacity var(--duration-slowest) cubic-bezier(0.25, 0.1, 0.25, 1),
|
|
111
|
-
transform var(--duration-slowest) cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
[data-motion="serene"] .section:not([data-reveal]).revealed {
|
|
115
|
-
opacity: 1;
|
|
116
|
-
transform: none;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/* Stream: Gentle horizontal flow */
|
|
120
|
-
[data-motion="stream"] [data-reveal] {
|
|
121
|
-
--reveal-duration: var(--duration-slow);
|
|
122
|
-
--reveal-easing: cubic-bezier(0.22, 1, 0.36, 1);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
[data-motion="stream"] .section:not([data-reveal]) {
|
|
126
|
-
opacity: 0;
|
|
127
|
-
transform: translateX(-1rem);
|
|
128
|
-
transition:
|
|
129
|
-
opacity var(--duration-slow) cubic-bezier(0.22, 1, 0.36, 1),
|
|
130
|
-
transform var(--duration-slow) cubic-bezier(0.22, 1, 0.36, 1);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
[data-motion="stream"] .section:not([data-reveal]).revealed {
|
|
134
|
-
opacity: 1;
|
|
135
|
-
transform: none;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/* Flowing: Smooth ease-in-out, organic */
|
|
139
|
-
[data-motion="flowing"] [data-reveal] {
|
|
140
|
-
--reveal-duration: var(--duration-slow);
|
|
141
|
-
--reveal-easing: cubic-bezier(0.16, 1, 0.3, 1);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
[data-motion="flowing"] .section:not([data-reveal]) {
|
|
145
|
-
opacity: 0;
|
|
146
|
-
transform: translateY(1.5rem);
|
|
147
|
-
transition:
|
|
148
|
-
opacity var(--duration-slow) cubic-bezier(0.16, 1, 0.3, 1),
|
|
149
|
-
transform var(--duration-slow) cubic-bezier(0.16, 1, 0.3, 1);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
[data-motion="flowing"] .section:not([data-reveal]).revealed {
|
|
153
|
-
opacity: 1;
|
|
154
|
-
transform: none;
|
|
155
|
-
}
|
|
26
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
27
|
+
/* Hidden start state: the script is running and the element has not
|
|
28
|
+
been revealed yet. */
|
|
29
|
+
/* Headlines never animate in. A bare data-reveal rises 12px and fades. */
|
|
30
|
+
:root[data-reveal-ready] [data-reveal]:not(.revealed, [data-revealed], h1, h2, h3, .display, .hero__headline) {
|
|
31
|
+
opacity: 0;
|
|
32
|
+
}
|
|
156
33
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
--reveal-easing: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
161
|
-
}
|
|
34
|
+
:root[data-reveal-ready] [data-reveal=""]:not(.revealed, [data-revealed], h1, h2, h3, .display, .hero__headline) {
|
|
35
|
+
translate: 0 12px;
|
|
36
|
+
}
|
|
162
37
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
transition:
|
|
167
|
-
opacity var(--duration-normal) cubic-bezier(0.34, 1.56, 0.64, 1),
|
|
168
|
-
transform var(--duration-normal) cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
169
|
-
}
|
|
38
|
+
:root[data-reveal-ready] [data-reveal="fade-up"]:not(.revealed, [data-revealed]) {
|
|
39
|
+
transform: translateY(2rem);
|
|
40
|
+
}
|
|
170
41
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
42
|
+
:root[data-reveal-ready] [data-reveal="fade-down"]:not(.revealed, [data-revealed]) {
|
|
43
|
+
transform: translateY(-2rem);
|
|
44
|
+
}
|
|
175
45
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
--reveal-easing: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
180
|
-
}
|
|
46
|
+
:root[data-reveal-ready] [data-reveal="fade-left"]:not(.revealed, [data-revealed]) {
|
|
47
|
+
transform: translateX(2rem);
|
|
48
|
+
}
|
|
181
49
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
transition:
|
|
186
|
-
opacity var(--duration-fast) cubic-bezier(0.25, 0.46, 0.45, 0.94),
|
|
187
|
-
transform var(--duration-fast) cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
188
|
-
}
|
|
50
|
+
:root[data-reveal-ready] [data-reveal="fade-right"]:not(.revealed, [data-revealed]) {
|
|
51
|
+
transform: translateX(-2rem);
|
|
52
|
+
}
|
|
189
53
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
54
|
+
:root[data-reveal-ready] [data-reveal="scale"]:not(.revealed, [data-revealed]) {
|
|
55
|
+
transform: scale(0.95);
|
|
56
|
+
}
|
|
194
57
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
--reveal-easing: cubic-bezier(0.68, -0.2, 0.32, 1.2);
|
|
199
|
-
}
|
|
58
|
+
:root[data-reveal-ready] [data-reveal="blur"]:not(.revealed, [data-revealed]) {
|
|
59
|
+
filter: blur(8px);
|
|
60
|
+
}
|
|
200
61
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
62
|
+
[data-reveal] {
|
|
63
|
+
transition:
|
|
64
|
+
opacity var(--reveal-duration, var(--duration-slow)) var(--reveal-easing, var(--ease-settle)),
|
|
65
|
+
translate var(--reveal-duration, var(--duration-slow)) var(--reveal-easing, var(--ease-settle)),
|
|
66
|
+
transform var(--reveal-duration, var(--duration-slow)) var(--reveal-easing, var(--ease-settle)),
|
|
67
|
+
filter var(--reveal-duration, var(--duration-slow)) var(--reveal-easing, var(--ease-settle));
|
|
68
|
+
}
|
|
208
69
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
70
|
+
/* While the script switches the page to ready, below-the-fold content
|
|
71
|
+
goes to its hidden start state at once instead of fading out. */
|
|
72
|
+
[data-reveal-init] [data-reveal] {
|
|
73
|
+
transition: none;
|
|
74
|
+
}
|
|
213
75
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
filter: none !important;
|
|
221
|
-
transition: none !important;
|
|
76
|
+
/* A sideways start position adds 2rem of horizontal overflow until the
|
|
77
|
+
element is revealed, so a phone could scroll sideways (services
|
|
78
|
+
template: 32px at every width up to 1024px). Sections holding one clip
|
|
79
|
+
it; clip, unlike hidden, leaves vertical overflow and sticky alone. */
|
|
80
|
+
.section:has([data-reveal="fade-left"], [data-reveal="fade-right"]) {
|
|
81
|
+
overflow-x: clip;
|
|
222
82
|
}
|
|
83
|
+
|
|
84
|
+
/* Delays */
|
|
85
|
+
[data-reveal-delay="100"] { transition-delay: 100ms; }
|
|
86
|
+
[data-reveal-delay="200"] { transition-delay: 200ms; }
|
|
87
|
+
[data-reveal-delay="300"] { transition-delay: 300ms; }
|
|
88
|
+
[data-reveal-delay="400"] { transition-delay: 400ms; }
|
|
89
|
+
[data-reveal-delay="500"] { transition-delay: 500ms; }
|
|
90
|
+
|
|
91
|
+
/* Durations */
|
|
92
|
+
[data-reveal-duration="fast"] { --reveal-duration: var(--duration-fast); }
|
|
93
|
+
[data-reveal-duration="normal"] { --reveal-duration: var(--duration-slow); }
|
|
94
|
+
[data-reveal-duration="slow"] { --reveal-duration: var(--duration-slower); }
|
|
95
|
+
|
|
96
|
+
/* Stagger children - useful for grids and lists */
|
|
97
|
+
[data-reveal-stagger] > [data-reveal]:nth-child(1) { transition-delay: calc(var(--reveal-stagger, 100ms) * 0); }
|
|
98
|
+
[data-reveal-stagger] > [data-reveal]:nth-child(2) { transition-delay: calc(var(--reveal-stagger, 100ms) * 1); }
|
|
99
|
+
[data-reveal-stagger] > [data-reveal]:nth-child(3) { transition-delay: calc(var(--reveal-stagger, 100ms) * 2); }
|
|
100
|
+
[data-reveal-stagger] > [data-reveal]:nth-child(4) { transition-delay: calc(var(--reveal-stagger, 100ms) * 3); }
|
|
101
|
+
[data-reveal-stagger] > [data-reveal]:nth-child(5) { transition-delay: calc(var(--reveal-stagger, 100ms) * 4); }
|
|
102
|
+
[data-reveal-stagger] > [data-reveal]:nth-child(6) { transition-delay: calc(var(--reveal-stagger, 100ms) * 5); }
|
|
103
|
+
[data-reveal-stagger] > [data-reveal]:nth-child(7) { transition-delay: calc(var(--reveal-stagger, 100ms) * 6); }
|
|
104
|
+
[data-reveal-stagger] > [data-reveal]:nth-child(8) { transition-delay: calc(var(--reveal-stagger, 100ms) * 7); }
|
|
223
105
|
}
|
|
224
106
|
}
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
/* Bordered variant: each item is a card */
|
|
58
58
|
.accordion[data-variant="bordered"] .accordion__item {
|
|
59
59
|
border: var(--border-width) solid var(--color-border-subtle);
|
|
60
|
-
border-radius: var(--radius-
|
|
60
|
+
border-radius: var(--radius-card);
|
|
61
61
|
overflow: hidden;
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -68,9 +68,8 @@
|
|
|
68
68
|
/* Separated variant: elevated card items */
|
|
69
69
|
.accordion[data-variant="separated"] .accordion__item {
|
|
70
70
|
border: var(--border-width) solid var(--color-border-subtle);
|
|
71
|
-
border-radius: var(--radius-
|
|
71
|
+
border-radius: var(--radius-card);
|
|
72
72
|
background: var(--color-surface-raised);
|
|
73
|
-
box-shadow: var(--shadow-xs);
|
|
74
73
|
overflow: hidden;
|
|
75
74
|
}
|
|
76
75
|
|
|
@@ -137,15 +136,15 @@
|
|
|
137
136
|
|
|
138
137
|
/* Hover */
|
|
139
138
|
.accordion__trigger:hover {
|
|
140
|
-
color: var(--accent);
|
|
139
|
+
color: var(--accent-ink);
|
|
141
140
|
background-color: color-mix(in oklch, var(--accent) 5%, transparent);
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
/* Focus */
|
|
145
144
|
.accordion__trigger:focus-visible {
|
|
146
|
-
outline:
|
|
145
|
+
outline: var(--focus-ring-width) solid var(--color-focus);
|
|
147
146
|
outline-offset: -2px;
|
|
148
|
-
border-radius: var(--radius-
|
|
147
|
+
border-radius: calc(var(--radius-control) * 0.6);
|
|
149
148
|
}
|
|
150
149
|
|
|
151
150
|
|
|
@@ -201,50 +200,10 @@
|
|
|
201
200
|
}
|
|
202
201
|
|
|
203
202
|
|
|
204
|
-
/* ========================================
|
|
205
|
-
THEME-SPECIFIC STYLES
|
|
206
|
-
======================================== */
|
|
207
|
-
|
|
208
|
-
/* Still: no animation */
|
|
209
|
-
[data-motion="still"] .accordion__trigger::after {
|
|
210
|
-
transition: none;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/* Serene: rounded, soft */
|
|
214
|
-
[data-motion="serene"] .accordion[data-variant="separated"] .accordion__item,
|
|
215
|
-
[data-motion="serene"] .accordion[data-variant="bordered"] .accordion__item {
|
|
216
|
-
border-radius: var(--radius-xl);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/* Cascade: bouncy, bubbly */
|
|
220
|
-
[data-motion="cascade"] .accordion[data-variant="separated"] .accordion__item,
|
|
221
|
-
[data-motion="cascade"] .accordion[data-variant="bordered"] .accordion__item {
|
|
222
|
-
border-radius: var(--radius-xl);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/* Rapids: hard shadow on separated */
|
|
226
|
-
[data-motion="rapids"] .accordion[data-variant="separated"] .accordion__item {
|
|
227
|
-
box-shadow: var(--shadow-offset);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/* Tsunami: asymmetric corners */
|
|
231
|
-
[data-motion="tsunami"] .accordion[data-variant="separated"] .accordion__item,
|
|
232
|
-
[data-motion="tsunami"] .accordion[data-variant="bordered"] .accordion__item {
|
|
233
|
-
border-radius: var(--radius-asymmetric, 0 24px 0 0);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
203
|
|
|
237
204
|
/* ========================================
|
|
238
205
|
REDUCED MOTION
|
|
239
206
|
======================================== */
|
|
240
207
|
|
|
241
|
-
|
|
242
|
-
.accordion__trigger {
|
|
243
|
-
transition: none;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
.accordion__trigger::after {
|
|
247
|
-
transition: none;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
208
|
+
/* Reduced motion: the reset shortens every transition. */
|
|
250
209
|
}
|