@fluid-theme/core 0.4.3
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 +32 -0
- package/CHANGELOG.md +159 -0
- package/CLAUDE.md +104 -0
- package/GEMINI.md +48 -0
- package/LICENSE +21 -0
- package/README.md +253 -0
- package/dist/fluid.min.css +2 -0
- package/fluid-agent-kit/README.md +57 -0
- package/fluid-agent-kit/skills/accessibility.md +41 -0
- package/fluid-agent-kit/skills/css-conventions.md +51 -0
- package/fluid-agent-kit/skills/image-optimization.md +115 -0
- package/fluid-agent-kit/skills/ux-rules.md +43 -0
- package/package.json +68 -0
- package/src/animations/scroll-reveal.css +224 -0
- package/src/components/accordion.css +250 -0
- package/src/components/alert.css +453 -0
- package/src/components/avatar.css +192 -0
- package/src/components/badge.css +182 -0
- package/src/components/button.css +387 -0
- package/src/components/card.css +650 -0
- package/src/components/chip.css +143 -0
- package/src/components/dropdown.css +335 -0
- package/src/components/empty-state.css +105 -0
- package/src/components/form.css +508 -0
- package/src/components/hero.css +293 -0
- package/src/components/indicator.css +455 -0
- package/src/components/loading.css +274 -0
- package/src/components/modal.css +364 -0
- package/src/components/nav.css +726 -0
- package/src/components/scroll-progress.css +104 -0
- package/src/components/search-input.css +125 -0
- package/src/components/settings-panel.css +603 -0
- package/src/components/step-indicator.css +188 -0
- package/src/components/table.css +350 -0
- package/src/components/themed-images.css +229 -0
- package/src/components/tooltip.css +247 -0
- package/src/components/version-badge.css +70 -0
- package/src/core/base.css +884 -0
- package/src/core/reset.css +159 -0
- package/src/core/tokens.css +2416 -0
- package/src/fluid.css +242 -0
- package/src/layouts/positioning.css +626 -0
- package/src/sections/cta.css +210 -0
- package/src/sections/features.css +356 -0
- package/src/sections/footer.css +283 -0
- package/src/sections/stats.css +234 -0
- package/src/sections/team.css +181 -0
- package/src/sections/testimonials.css +251 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Fluid Theme — CSS Conventions
|
|
2
|
+
|
|
3
|
+
When writing or modifying CSS for a site built with The Fluid Theme, follow these rules.
|
|
4
|
+
|
|
5
|
+
## Layer Order (never violate)
|
|
6
|
+
|
|
7
|
+
```css
|
|
8
|
+
@layer reset, tokens, base, layouts, components, themes, utilities;
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Required Patterns
|
|
12
|
+
|
|
13
|
+
- **All values from tokens**: `var(--space-4)` not `16px`, `var(--color-text)` not `#333`
|
|
14
|
+
- **Logical properties only**: `margin-block-start` not `margin-top`, `inline-size` not `width`
|
|
15
|
+
- **Data attributes for variants**: `data-variant="danger"` not `.btn--danger`
|
|
16
|
+
- **Component-scoped private properties**: prefix with underscore `--_card-padding`
|
|
17
|
+
- **All components** wrapped in `@layer components { }`
|
|
18
|
+
|
|
19
|
+
## Token Quick Reference
|
|
20
|
+
|
|
21
|
+
| Category | Examples |
|
|
22
|
+
|----------|---------|
|
|
23
|
+
| Spacing | `--space-0` through `--space-24` |
|
|
24
|
+
| Typography | `--font-size-xs` through `--font-size-5xl` |
|
|
25
|
+
| Colors | `--color-text`, `--color-surface`, `--accent`, `--color-success/warning/error/info` |
|
|
26
|
+
| Borders | `--radius-sm` through `--radius-full`, `--border-width` |
|
|
27
|
+
| Shadows | `--shadow-xs` through `--shadow-xl` |
|
|
28
|
+
| Motion | `--duration-instant` through `--duration-slowest` |
|
|
29
|
+
|
|
30
|
+
## Component File Pattern
|
|
31
|
+
|
|
32
|
+
Every component CSS file should include:
|
|
33
|
+
1. Header comment with usage examples
|
|
34
|
+
2. Base styles
|
|
35
|
+
3. Variants via `data-*` attributes
|
|
36
|
+
4. Responsive behavior (container queries preferred over media queries)
|
|
37
|
+
5. Reduced motion: `@media (prefers-reduced-motion: reduce) { }`
|
|
38
|
+
|
|
39
|
+
## File Locations
|
|
40
|
+
|
|
41
|
+
- Components: `src/components/[name].css`
|
|
42
|
+
- Sections: `src/sections/[name].css`
|
|
43
|
+
- After creating a new component, add `@import` to `src/fluid.css`
|
|
44
|
+
|
|
45
|
+
## Never Do
|
|
46
|
+
|
|
47
|
+
- `padding: 16px` — use a token
|
|
48
|
+
- `margin-top: 1rem` — use logical property (`margin-block-start`)
|
|
49
|
+
- `.card--elevated` — use `data-variant="elevated"`
|
|
50
|
+
- `:focus { outline: none }` — never remove focus outlines
|
|
51
|
+
- Vendor prefixes — modern browsers only
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Image Optimization — Fluid Theme
|
|
2
|
+
|
|
3
|
+
This skill covers responsive images, performance optimization, and image utilities available in The Fluid Theme.
|
|
4
|
+
|
|
5
|
+
For the full guide with code examples, see `_docs/images-guide.md`.
|
|
6
|
+
|
|
7
|
+
## Quick Reference
|
|
8
|
+
|
|
9
|
+
### Format Priority
|
|
10
|
+
|
|
11
|
+
AVIF > WebP > JPEG > PNG. Use `<picture>` for format fallbacks:
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<div class="hero__background" data-focus="top">
|
|
15
|
+
<picture>
|
|
16
|
+
<source srcset="hero.avif" type="image/avif">
|
|
17
|
+
<source srcset="hero.webp" type="image/webp">
|
|
18
|
+
<img src="hero.jpg" alt="Description" width="1920" height="1080">
|
|
19
|
+
</picture>
|
|
20
|
+
</div>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Lazy Loading
|
|
24
|
+
|
|
25
|
+
Add `loading="lazy"` to ALL images except the first/hero image on each page:
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<!-- First image: above the fold, load eagerly -->
|
|
29
|
+
<img src="hero.jpg" alt="Hero" width="1920" height="1080">
|
|
30
|
+
|
|
31
|
+
<!-- All other images: lazy load -->
|
|
32
|
+
<img src="card.jpg" alt="Card" loading="lazy" width="1920" height="1080">
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Always Include Dimensions
|
|
36
|
+
|
|
37
|
+
Every `<img>` must have `width` and `height` attributes to prevent layout shift (CLS):
|
|
38
|
+
|
|
39
|
+
| Aspect Ratio | Dimensions |
|
|
40
|
+
|-------------|------------|
|
|
41
|
+
| 16:9 (video) | `width="1920" height="1080"` |
|
|
42
|
+
| 1:1 (square) | `width="800" height="800"` |
|
|
43
|
+
| 3:4 (portrait) | `width="800" height="1067"` |
|
|
44
|
+
| 21:9 (wide) | `width="1920" height="823"` |
|
|
45
|
+
| Avatar | `width="96" height="96"` |
|
|
46
|
+
|
|
47
|
+
### Focal Point Control
|
|
48
|
+
|
|
49
|
+
Use `data-focus` on `.hero__background` or directly on `.card__media`:
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<!-- Preset positions -->
|
|
53
|
+
<div class="hero__background" data-focus="top">
|
|
54
|
+
<img class="card__media" data-focus="left">
|
|
55
|
+
|
|
56
|
+
<!-- Custom position -->
|
|
57
|
+
<div class="hero__background" style="--focus-x: 30%; --focus-y: 20%;">
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Available presets: `top`, `bottom`, `left`, `right`, `center`
|
|
61
|
+
|
|
62
|
+
### Aspect Ratios
|
|
63
|
+
|
|
64
|
+
Use `data-aspect` on `.card__media`:
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<img class="card__media" data-aspect="video"> <!-- 16:9 -->
|
|
68
|
+
<img class="card__media" data-aspect="square"> <!-- 1:1 -->
|
|
69
|
+
<img class="card__media" data-aspect="portrait"> <!-- 3:4 -->
|
|
70
|
+
<img class="card__media" data-aspect="wide"> <!-- 21:9 -->
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Image Protection
|
|
74
|
+
|
|
75
|
+
Add `data-protected` to discourage casual right-click saving (not DRM):
|
|
76
|
+
|
|
77
|
+
```html
|
|
78
|
+
<div data-protected>
|
|
79
|
+
<img src="portfolio.jpg" alt="My work">
|
|
80
|
+
</div>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Limitations: Does NOT prevent screenshots, dev tools, or determined users.
|
|
84
|
+
|
|
85
|
+
### Orientation-Aware Images
|
|
86
|
+
|
|
87
|
+
Show different images based on viewport orientation:
|
|
88
|
+
|
|
89
|
+
```html
|
|
90
|
+
<img data-orientation="landscape" src="wide-shot.jpg" alt="Scene">
|
|
91
|
+
<img data-orientation="portrait" src="tall-crop.jpg" alt="Scene">
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Responsive Images Pattern
|
|
95
|
+
|
|
96
|
+
```html
|
|
97
|
+
<img
|
|
98
|
+
srcset="photo-640.webp 640w, photo-1024.webp 1024w, photo-1920.webp 1920w"
|
|
99
|
+
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
|
|
100
|
+
src="photo-1024.webp"
|
|
101
|
+
alt="Description"
|
|
102
|
+
loading="lazy"
|
|
103
|
+
width="1920" height="1080"
|
|
104
|
+
>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Checklist for New Pages
|
|
108
|
+
|
|
109
|
+
- [ ] First/hero image: no `loading="lazy"`, consider `fetchpriority="high"`
|
|
110
|
+
- [ ] All other images: `loading="lazy"`
|
|
111
|
+
- [ ] All images: `width` and `height` attributes set
|
|
112
|
+
- [ ] All images: meaningful `alt` text
|
|
113
|
+
- [ ] Hero backgrounds: consider `data-focus` for focal point control
|
|
114
|
+
- [ ] Card media: `data-aspect` set appropriately
|
|
115
|
+
- [ ] Images served in WebP or AVIF with fallbacks
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# UX Behavior Rules — Quick Reference
|
|
2
|
+
|
|
3
|
+
Full specification: `_docs/UX-BEHAVIOR-SPEC.md` (18 sections, 1031 lines).
|
|
4
|
+
|
|
5
|
+
Read the full spec before building interactive components. This is the condensed version.
|
|
6
|
+
|
|
7
|
+
## The 12 Rules
|
|
8
|
+
|
|
9
|
+
1. **Destructive Actions**: Confirmation modal required. Title names the specific item. Body explains consequences. Buttons: [Cancel] [Delete Specific Thing]. Add `autofocus` to Cancel. Use `[data-destructive]` on modal.
|
|
10
|
+
|
|
11
|
+
2. **Action Consistency**: Search entire project for similar patterns before implementing. Same display mode, same order, same styling everywhere.
|
|
12
|
+
|
|
13
|
+
3. **Modal Strategy**: Toast > inline alert > modal. Use minimum interruption. No nested modals. Use native `<dialog>` with `.showModal()`. Focus trapping is automatic — do NOT add manual focus trap JS.
|
|
14
|
+
|
|
15
|
+
4. **Feedback**: Every action gets feedback. Save -> toast. Delete -> toast with undo. Error -> inline alert. Silence after action = bug.
|
|
16
|
+
|
|
17
|
+
5. **Forms**: Validate on blur first, then keystroke after error shown. Specific error messages ("Email must include @" not "Invalid input"). Never reload page on error.
|
|
18
|
+
|
|
19
|
+
6. **Empty States**: Every list/table needs an empty state with explanation + CTA. Never just "No items found."
|
|
20
|
+
|
|
21
|
+
7. **Buttons**: Specific labels only. Never "Submit" / "OK" / "Yes" / "Click Here". One primary CTA per viewport. Destructive = `data-variant="danger"`, always last.
|
|
22
|
+
|
|
23
|
+
8. **Loading**: Feedback after 300ms. Skeleton for page loads, spinner for actions. Never blank screen.
|
|
24
|
+
|
|
25
|
+
9. **Responsive**: Modal -> bottom sheet on mobile. Table -> stacked rows. 44px minimum touch targets.
|
|
26
|
+
|
|
27
|
+
10. **Keyboard**: Every mouse interaction works via keyboard. Never remove focus outlines. Escape closes overlays.
|
|
28
|
+
|
|
29
|
+
11. **Tables**: Row actions consistent across all tables. `.table-wrap` wrapper required. `data-responsive` + `td[data-label]` for mobile.
|
|
30
|
+
|
|
31
|
+
12. **Consistency**: After ANY pattern implementation, search the entire project for other instances and update them to match.
|
|
32
|
+
|
|
33
|
+
## When to Read the Full Spec
|
|
34
|
+
|
|
35
|
+
| Task | Read Sections |
|
|
36
|
+
|------|--------------|
|
|
37
|
+
| Building modal/dialog | Sections 1, 3, 12 |
|
|
38
|
+
| Building form | Sections 5, 9, 12 |
|
|
39
|
+
| Adding action buttons | Sections 1, 2, 9 |
|
|
40
|
+
| Building table with actions | Sections 2, 13, 11 |
|
|
41
|
+
| Search or filters | Sections 14, 7 |
|
|
42
|
+
| Starting new project | Section 17 first |
|
|
43
|
+
| Full UX audit | Entire spec |
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fluid-theme/core",
|
|
3
|
+
"version": "0.4.3",
|
|
4
|
+
"description": "A modern, semantic CSS design system built on physics principles — not utility classes",
|
|
5
|
+
"main": "dist/fluid.min.css",
|
|
6
|
+
"style": "dist/fluid.min.css",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./dist/fluid.min.css",
|
|
9
|
+
"./src": "./src/fluid.css"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist/",
|
|
13
|
+
"src/",
|
|
14
|
+
"fluid-agent-kit/",
|
|
15
|
+
"CLAUDE.md",
|
|
16
|
+
"AGENTS.md",
|
|
17
|
+
"GEMINI.md",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"README.md",
|
|
20
|
+
"CHANGELOG.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"serve": "npx http-server . -o /index.html",
|
|
24
|
+
"build": "node scripts/build-css.mjs",
|
|
25
|
+
"prepublishOnly": "npm run build",
|
|
26
|
+
"optimize-images": "node scripts/optimize-images.js",
|
|
27
|
+
"test": "echo \"Visual testing only - open examples/foundation.html in browser\""
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"css",
|
|
31
|
+
"design-system",
|
|
32
|
+
"theme",
|
|
33
|
+
"framework",
|
|
34
|
+
"semantic",
|
|
35
|
+
"css-layers",
|
|
36
|
+
"custom-properties",
|
|
37
|
+
"logical-properties",
|
|
38
|
+
"oklch",
|
|
39
|
+
"no-build"
|
|
40
|
+
],
|
|
41
|
+
"author": "Neil White <dev+packages@agilemedia.agency>",
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/Agile-Media-Agency/the-fluid-theme.git"
|
|
46
|
+
},
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/Agile-Media-Agency/the-fluid-theme/issues"
|
|
49
|
+
},
|
|
50
|
+
"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
|
+
"browserslist": [
|
|
60
|
+
"supports css-cascade-layers",
|
|
61
|
+
"supports css-container-queries",
|
|
62
|
+
"supports css-logical-properties"
|
|
63
|
+
],
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"lightningcss": "^1.32.0",
|
|
66
|
+
"sharp": "^0.34.5"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scroll Reveal Animations
|
|
3
|
+
*
|
|
4
|
+
* Add [data-reveal] attribute to elements you want to animate in on scroll.
|
|
5
|
+
* Works with the scroll-reveal.js script or CSS-only with animation-timeline.
|
|
6
|
+
*
|
|
7
|
+
* Variants:
|
|
8
|
+
* data-reveal="fade" - Fade in
|
|
9
|
+
* data-reveal="fade-up" - Fade in from below
|
|
10
|
+
* data-reveal="fade-down" - Fade in from above
|
|
11
|
+
* data-reveal="fade-left" - Fade in from right
|
|
12
|
+
* data-reveal="fade-right"- Fade in from left
|
|
13
|
+
* data-reveal="scale" - Scale up
|
|
14
|
+
* data-reveal="blur" - Blur to focus
|
|
15
|
+
*
|
|
16
|
+
* Timing:
|
|
17
|
+
* data-reveal-delay="100" - Delay in ms (100, 200, 300, 400, 500)
|
|
18
|
+
* data-reveal-duration="slow" - Duration (fast, normal, slow)
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
@layer components {
|
|
22
|
+
/* Base reveal state - hidden by default */
|
|
23
|
+
[data-reveal] {
|
|
24
|
+
opacity: 0;
|
|
25
|
+
transition:
|
|
26
|
+
opacity var(--reveal-duration, var(--duration-slow)) var(--reveal-easing, cubic-bezier(0.16, 1, 0.3, 1)),
|
|
27
|
+
transform var(--reveal-duration, var(--duration-slow)) var(--reveal-easing, cubic-bezier(0.16, 1, 0.3, 1)),
|
|
28
|
+
filter var(--reveal-duration, var(--duration-slow)) var(--reveal-easing, cubic-bezier(0.16, 1, 0.3, 1));
|
|
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
|
+
}
|
|
156
|
+
|
|
157
|
+
/* Cascade: Medium energy, waterfall effect */
|
|
158
|
+
[data-motion="cascade"] [data-reveal] {
|
|
159
|
+
--reveal-duration: var(--duration-normal);
|
|
160
|
+
--reveal-easing: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
[data-motion="cascade"] .section:not([data-reveal]) {
|
|
164
|
+
opacity: 0;
|
|
165
|
+
transform: translateY(2rem);
|
|
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
|
+
}
|
|
170
|
+
|
|
171
|
+
[data-motion="cascade"] .section:not([data-reveal]).revealed {
|
|
172
|
+
opacity: 1;
|
|
173
|
+
transform: none;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* Rapids: Fast, direct */
|
|
177
|
+
[data-motion="rapids"] [data-reveal] {
|
|
178
|
+
--reveal-duration: var(--duration-fast);
|
|
179
|
+
--reveal-easing: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
[data-motion="rapids"] .section:not([data-reveal]) {
|
|
183
|
+
opacity: 0;
|
|
184
|
+
transform: scale(0.98);
|
|
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
|
+
}
|
|
189
|
+
|
|
190
|
+
[data-motion="rapids"] .section:not([data-reveal]).revealed {
|
|
191
|
+
opacity: 1;
|
|
192
|
+
transform: none;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* Tsunami: Dramatic, bold sweep */
|
|
196
|
+
[data-motion="tsunami"] [data-reveal] {
|
|
197
|
+
--reveal-duration: var(--duration-normal);
|
|
198
|
+
--reveal-easing: cubic-bezier(0.68, -0.2, 0.32, 1.2);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
[data-motion="tsunami"] .section:not([data-reveal]) {
|
|
202
|
+
opacity: 0;
|
|
203
|
+
transform: translateY(3rem) scale(0.97);
|
|
204
|
+
transition:
|
|
205
|
+
opacity var(--duration-normal) cubic-bezier(0.68, -0.2, 0.32, 1.2),
|
|
206
|
+
transform var(--duration-normal) cubic-bezier(0.68, -0.2, 0.32, 1.2);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
[data-motion="tsunami"] .section:not([data-reveal]).revealed {
|
|
210
|
+
opacity: 1;
|
|
211
|
+
transform: none;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* Reduced motion preference */
|
|
215
|
+
@media (prefers-reduced-motion: reduce) {
|
|
216
|
+
[data-reveal],
|
|
217
|
+
.section {
|
|
218
|
+
opacity: 1 !important;
|
|
219
|
+
transform: none !important;
|
|
220
|
+
filter: none !important;
|
|
221
|
+
transition: none !important;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|