@fluid-theme/core 0.4.3 → 2.0.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 +543 -2
- package/CLAUDE.md +193 -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.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-newsreader.txt +93 -0
- package/dist/fonts/OFL-schibsted-grotesk.txt +93 -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 +29 -3
- 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/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
package/src/components/card.css
CHANGED
|
@@ -1,419 +1,241 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fluid
|
|
2
|
+
* Fluid Theme - Card Component
|
|
3
3
|
* @layer components
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Open by default: no box, padding, shadow or lift. Media in true colour at
|
|
6
|
+
* its natural ratio (or data-aspect), then the body under an ink hairline:
|
|
7
|
+
* eyebrow, serif title, dek, meta. In a .grid the cards share a hang line:
|
|
8
|
+
* image bottoms and hairlines line up across a row whatever each image's
|
|
9
|
+
* ratio, and the bodies hang from it. Hover underlines the title; nothing
|
|
10
|
+
* moves. A card with no media carries the rule on its own top edge, so a
|
|
11
|
+
* child theme that writes .card { border: … } replaces it.
|
|
8
12
|
*
|
|
9
13
|
* Usage:
|
|
10
|
-
* <article class="card">...</article>
|
|
11
|
-
* <div class="card" data-variant="elevated">...</div>
|
|
12
|
-
* <article class="card" data-variant="outlined">...</article>
|
|
13
|
-
* <a href="#" class="card" data-interactive>Clickable card</a>
|
|
14
|
-
*
|
|
15
|
-
* Structure (optional):
|
|
16
14
|
* <article class="card">
|
|
17
|
-
* <img class="card__media" src="..." alt="...">
|
|
18
|
-
* <div class="card__content">
|
|
15
|
+
* <img class="card__media" src="..." alt="..." width="800" height="600">
|
|
16
|
+
* <div class="card__content"> (.card__body works too)
|
|
17
|
+
* <p class="eyebrow">Essay</p>
|
|
19
18
|
* <h3 class="card__title">Title</h3>
|
|
20
|
-
* <p class="card__description">
|
|
19
|
+
* <p class="card__description">Dek</p>
|
|
20
|
+
* <p class="card__meta">12 May 2026</p>
|
|
21
21
|
* </div>
|
|
22
22
|
* <footer class="card__footer">Actions</footer>
|
|
23
23
|
* </article>
|
|
24
|
+
*
|
|
25
|
+
* Boxed cards: data-variant="outlined" (hairline box), "filled" (surface),
|
|
26
|
+
* "elevated" (raised surface; a shadow only when --shadow-style is not 0).
|
|
27
|
+
* Opt-ins: data-treatment="duotone" (hue from --accent; wrap the image in
|
|
28
|
+
* .card__media-wrap), data-layout="horizontal", data-type="profile|stat|
|
|
29
|
+
* feature|testimonial|pricing".
|
|
24
30
|
*/
|
|
25
31
|
|
|
26
32
|
@layer components {
|
|
27
|
-
/* Base card */
|
|
28
33
|
.card {
|
|
29
|
-
/* Container for queries - only when explicitly enabled */
|
|
30
34
|
container-name: card;
|
|
31
|
-
|
|
32
|
-
/* Layout */
|
|
35
|
+
position: relative;
|
|
33
36
|
display: flex;
|
|
34
37
|
flex-direction: column;
|
|
35
|
-
|
|
36
|
-
/* Prevent collapse in grid/flex layouts */
|
|
37
38
|
min-inline-size: 0;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
color: inherit;
|
|
40
|
+
background-color: var(--_card-bg, transparent);
|
|
41
|
+
border: var(--border-width) solid var(--_card-border, transparent);
|
|
42
|
+
/* Only a boxed card is rounded: an open card paints its top edge only,
|
|
43
|
+
and a radius bent that hairline into an arc ("a smile") over it. */
|
|
44
|
+
border-radius: var(--_card-radius, 0);
|
|
45
|
+
box-shadow: var(--_card-shadow, none);
|
|
45
46
|
overflow: clip;
|
|
46
47
|
overflow-clip-margin: 4px;
|
|
47
|
-
|
|
48
|
-
/* Transitions */
|
|
49
|
-
transition:
|
|
50
|
-
box-shadow var(--duration-normal) var(--ease-fluid),
|
|
51
|
-
border-color var(--duration-normal) var(--ease-fluid),
|
|
52
|
-
transform var(--duration-normal) var(--ease-settle);
|
|
53
48
|
}
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
.card[data-container] {
|
|
57
|
-
container-type: inline-size;
|
|
58
|
-
}
|
|
50
|
+
.card[data-container] { container-type: inline-size; }
|
|
59
51
|
|
|
60
52
|
|
|
61
53
|
/* ========================================
|
|
62
|
-
VARIANTS
|
|
63
|
-
Different visual treatments
|
|
54
|
+
BOXED VARIANTS
|
|
64
55
|
======================================== */
|
|
65
56
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
--_card-
|
|
69
|
-
box-shadow: var(--shadow-md);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.card[data-variant="elevated"]:hover {
|
|
73
|
-
box-shadow: var(--shadow-lg);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/* Dark mode: use accent glow since shadows are barely visible on dark */
|
|
77
|
-
@media (prefers-color-scheme: dark) {
|
|
78
|
-
.card[data-variant="elevated"] {
|
|
79
|
-
box-shadow:
|
|
80
|
-
0 0 0 1px oklch(from var(--accent) l c h / 0.15),
|
|
81
|
-
0 4px 20px oklch(from var(--accent) l c h / 0.1);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.card[data-variant="elevated"]:hover {
|
|
85
|
-
box-shadow:
|
|
86
|
-
0 0 0 1px oklch(from var(--accent) l c h / 0.25),
|
|
87
|
-
0 8px 30px oklch(from var(--accent) l c h / 0.15);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/* Also support explicit dark theme */
|
|
92
|
-
[data-theme="dark"] .card[data-variant="elevated"] {
|
|
93
|
-
box-shadow:
|
|
94
|
-
0 0 0 1px oklch(from var(--accent) l c h / 0.15),
|
|
95
|
-
0 4px 20px oklch(from var(--accent) l c h / 0.1);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
[data-theme="dark"] .card[data-variant="elevated"]:hover {
|
|
99
|
-
box-shadow:
|
|
100
|
-
0 0 0 1px oklch(from var(--accent) l c h / 0.25),
|
|
101
|
-
0 8px 30px oklch(from var(--accent) l c h / 0.15);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/* Outlined - border emphasis */
|
|
105
|
-
.card[data-variant="outlined"] {
|
|
106
|
-
--_card-bg: transparent;
|
|
57
|
+
.card:is([data-variant="outlined"], [data-variant="filled"], [data-variant="elevated"]) {
|
|
58
|
+
--_card-pad: var(--space-m);
|
|
59
|
+
--_card-rule: transparent;
|
|
107
60
|
--_card-border: var(--color-border);
|
|
61
|
+
--_card-radius: var(--radius-card);
|
|
108
62
|
}
|
|
109
63
|
|
|
110
|
-
|
|
111
|
-
.card[data-variant="ghost"] {
|
|
112
|
-
--_card-bg: transparent;
|
|
113
|
-
--_card-border: transparent;
|
|
114
|
-
}
|
|
64
|
+
.card[data-variant="filled"] { --_card-bg: var(--color-surface); --_card-border: transparent; }
|
|
115
65
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
--_card-
|
|
119
|
-
--_card-border: transparent;
|
|
66
|
+
.card[data-variant="elevated"] {
|
|
67
|
+
--_card-bg: var(--color-surface-raised);
|
|
68
|
+
--_card-shadow: var(--shadow-md);
|
|
120
69
|
}
|
|
121
70
|
|
|
122
71
|
|
|
123
72
|
/* ========================================
|
|
124
73
|
INTERACTIVE CARDS
|
|
125
|
-
Clickable/hoverable cards
|
|
126
74
|
======================================== */
|
|
127
75
|
|
|
128
76
|
.card[data-interactive],
|
|
129
77
|
a.card {
|
|
130
78
|
cursor: pointer;
|
|
131
79
|
text-decoration: none;
|
|
132
|
-
color: inherit;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
.card[data-interactive]:hover,
|
|
136
|
-
a.card:hover {
|
|
137
|
-
--_card-border: var(--accent);
|
|
138
|
-
box-shadow: var(--shadow-sm);
|
|
139
80
|
}
|
|
140
81
|
|
|
141
|
-
.card[data-interactive]:
|
|
142
|
-
|
|
143
|
-
|
|
82
|
+
:is(.card[data-interactive], a.card):hover .card__title {
|
|
83
|
+
text-decoration-line: underline;
|
|
84
|
+
text-decoration-color: var(--accent-ink);
|
|
85
|
+
text-decoration-thickness: 0.06em;
|
|
86
|
+
text-underline-offset: 0.22em;
|
|
144
87
|
}
|
|
145
88
|
|
|
146
|
-
.card[data-interactive]:focus-visible
|
|
147
|
-
|
|
148
|
-
outline: 2px
|
|
149
|
-
box-shadow:
|
|
150
|
-
var(--shadow-glow),
|
|
151
|
-
0 0 0 2px var(--color-background),
|
|
152
|
-
0 0 0 4px var(--accent);
|
|
89
|
+
:is(.card[data-interactive], a.card):focus-visible {
|
|
90
|
+
outline: var(--focus-ring-width) solid var(--color-focus);
|
|
91
|
+
outline-offset: 2px;
|
|
153
92
|
}
|
|
154
93
|
|
|
155
94
|
|
|
156
95
|
/* ========================================
|
|
157
|
-
|
|
158
|
-
Optional semantic sections
|
|
96
|
+
STRUCTURE
|
|
159
97
|
======================================== */
|
|
160
98
|
|
|
161
|
-
/* Media - images, video, etc. */
|
|
162
99
|
.card__media {
|
|
163
|
-
/* Full width, maintain aspect */
|
|
164
100
|
inline-size: 100%;
|
|
165
101
|
block-size: auto;
|
|
166
|
-
object-fit: cover;
|
|
167
|
-
|
|
168
|
-
/* Remove from flow for overlay positioning */
|
|
169
102
|
flex-shrink: 0;
|
|
170
|
-
|
|
171
|
-
/* Auto-apply theme-aware duotone tint */
|
|
172
|
-
filter: grayscale(100%) contrast(1.1);
|
|
173
|
-
transition: filter var(--duration-normal) var(--ease-fluid);
|
|
103
|
+
border-radius: var(--radius-card);
|
|
174
104
|
}
|
|
175
105
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
overflow: hidden;
|
|
106
|
+
:is(.card__media, .card__media-wrap) + :is(.card__content, .card__body) {
|
|
107
|
+
margin-block-start: var(--_card-pad, var(--space-s));
|
|
108
|
+
border-block-start: var(--border-width) solid var(--_card-rule, var(--color-border-strong));
|
|
180
109
|
}
|
|
181
110
|
|
|
182
|
-
.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
inset: 0;
|
|
186
|
-
background: linear-gradient(
|
|
187
|
-
135deg,
|
|
188
|
-
var(--duotone-dark, oklch(0.3 0.1 220)) 0%,
|
|
189
|
-
var(--duotone-light, oklch(0.7 0.1 200)) 100%
|
|
190
|
-
);
|
|
191
|
-
mix-blend-mode: multiply;
|
|
192
|
-
opacity: 0.85;
|
|
193
|
-
pointer-events: none;
|
|
194
|
-
transition: opacity var(--duration-normal) var(--ease-fluid);
|
|
111
|
+
/* An open card with no media: the rule is the card's own top edge. */
|
|
112
|
+
.card:not([data-variant]):not(:has(> :is(.card__media, .card__media-wrap))) {
|
|
113
|
+
border-block-start-color: var(--_card-rule, var(--color-border-strong));
|
|
195
114
|
}
|
|
196
115
|
|
|
197
|
-
|
|
198
|
-
.card:hover .card__media {
|
|
199
|
-
filter: grayscale(60%) contrast(1.05);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.card:hover .card__media-wrap::after {
|
|
203
|
-
opacity: 0.6;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/* Opt-out of duotone effect */
|
|
207
|
-
.card__media[data-no-duotone],
|
|
208
|
-
.card[data-no-duotone] .card__media {
|
|
209
|
-
filter: none;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/* Focal point control for card media */
|
|
213
|
-
.card__media[data-focus="top"] { object-position: center top; }
|
|
214
|
-
.card__media[data-focus="bottom"] { object-position: center bottom; }
|
|
215
|
-
.card__media[data-focus="left"] { object-position: left center; }
|
|
216
|
-
.card__media[data-focus="right"] { object-position: right center; }
|
|
217
|
-
.card__media[data-focus="center"] { object-position: center center; }
|
|
218
|
-
|
|
219
|
-
/* Custom focal point via CSS custom properties */
|
|
220
|
-
.card__media[style*="--focus"] {
|
|
221
|
-
object-position: var(--focus-x, 50%) var(--focus-y, 50%);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/* Aspect ratio variants for media */
|
|
225
|
-
.card__media[data-aspect="square"] {
|
|
226
|
-
aspect-ratio: 1;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
.card__media[data-aspect="video"] {
|
|
230
|
-
aspect-ratio: 16 / 9;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
.card__media[data-aspect="portrait"] {
|
|
234
|
-
aspect-ratio: 3 / 4;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
.card__media[data-aspect="wide"] {
|
|
238
|
-
aspect-ratio: 21 / 9;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/* Content area */
|
|
242
|
-
.card__content {
|
|
116
|
+
:is(.card__content, .card__body) {
|
|
243
117
|
flex: 1;
|
|
244
|
-
padding: var(--space-5);
|
|
245
118
|
display: flex;
|
|
246
119
|
flex-direction: column;
|
|
247
|
-
gap: var(--space-
|
|
120
|
+
gap: var(--space-xs);
|
|
121
|
+
padding: var(--_card-pad, 0);
|
|
122
|
+
padding-block-start: var(--_card-pad, var(--space-s));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* The hang line: in a .grid, a card with media spans two rows of the
|
|
126
|
+
grid (three with a footer) as a subgrid, the media bottom-aligned in
|
|
127
|
+
the first. Needs subgrid; without it cards keep the flex column. */
|
|
128
|
+
@supports (grid-template-rows: subgrid) {
|
|
129
|
+
.grid > .card:has(> .card__media, > .card__media-wrap):not([data-layout]) {
|
|
130
|
+
display: grid;
|
|
131
|
+
grid-row: span 2;
|
|
132
|
+
grid-template-rows: subgrid;
|
|
133
|
+
row-gap: 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.grid > .card:has(> .card__media, > .card__media-wrap):has(> .card__footer):not([data-layout]) { grid-row: span 3; }
|
|
137
|
+
|
|
138
|
+
.grid > .card > :is(.card__media, .card__media-wrap) { align-self: end; }
|
|
248
139
|
}
|
|
249
140
|
|
|
250
|
-
|
|
141
|
+
.card :is(.eyebrow, p) { margin: 0; }
|
|
142
|
+
|
|
251
143
|
.card__title {
|
|
252
|
-
font-
|
|
253
|
-
font-
|
|
254
|
-
|
|
144
|
+
font-family: var(--font-heading);
|
|
145
|
+
font-size: var(--step-1);
|
|
146
|
+
font-weight: calc(var(--weight-medium) + var(--_dark-weight));
|
|
147
|
+
line-height: var(--leading-heading);
|
|
148
|
+
letter-spacing: var(--tracking-normal);
|
|
149
|
+
text-wrap: balance;
|
|
255
150
|
margin: 0;
|
|
256
151
|
}
|
|
257
152
|
|
|
258
|
-
/*
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
153
|
+
/* A title link is not a link in running text: no underline at rest,
|
|
154
|
+
the accent underline on hover and focus (spec §9). */
|
|
155
|
+
.card__title a { text-decoration-color: transparent; }
|
|
156
|
+
.card__title a:is(:hover, :focus-visible) { text-decoration-color: var(--accent-ink); }
|
|
157
|
+
|
|
263
158
|
|
|
264
|
-
/* Metadata - tags, dates, etc. */
|
|
265
159
|
.card__meta {
|
|
266
160
|
display: flex;
|
|
267
161
|
flex-wrap: wrap;
|
|
268
162
|
gap: var(--space-2);
|
|
269
|
-
font-size: var(--
|
|
270
|
-
color: var(--color-text-
|
|
163
|
+
font-size: var(--step--1);
|
|
164
|
+
color: var(--color-text-muted);
|
|
165
|
+
font-variant-numeric: lining-nums proportional-nums; /* tabular widens the comma */
|
|
271
166
|
}
|
|
272
167
|
|
|
273
|
-
/* Footer - actions, links */
|
|
274
168
|
.card__footer {
|
|
275
|
-
padding: var(--space-4) var(--space-5);
|
|
276
|
-
border-block-start: 1px solid var(--color-border-subtle);
|
|
277
169
|
display: flex;
|
|
278
170
|
gap: var(--space-3);
|
|
279
171
|
align-items: center;
|
|
172
|
+
padding-block: var(--space-s);
|
|
173
|
+
padding-inline: var(--_card-pad, 0);
|
|
174
|
+
border-block-start: var(--border-width) solid var(--color-border);
|
|
280
175
|
}
|
|
281
176
|
|
|
282
|
-
|
|
283
|
-
.card__footer[data-align="
|
|
284
|
-
justify-content: flex-end;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
.card__footer[data-align="between"] {
|
|
288
|
-
justify-content: space-between;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
/* ========================================
|
|
293
|
-
SIZE VARIANTS
|
|
294
|
-
Compact for lists, spacious for features
|
|
295
|
-
======================================== */
|
|
296
|
-
|
|
297
|
-
.card[data-size="sm"] .card__content {
|
|
298
|
-
padding: var(--space-4);
|
|
299
|
-
gap: var(--space-2);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
.card[data-size="sm"] .card__title {
|
|
303
|
-
font-size: var(--font-size-base);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.card[data-size="sm"] .card__footer {
|
|
307
|
-
padding: var(--space-3) var(--space-4);
|
|
308
|
-
}
|
|
177
|
+
.card__footer[data-align="end"] { justify-content: flex-end; }
|
|
178
|
+
.card__footer[data-align="between"] { justify-content: space-between; }
|
|
309
179
|
|
|
310
|
-
.card[data-size="
|
|
311
|
-
|
|
312
|
-
gap: var(--space-4);
|
|
313
|
-
}
|
|
180
|
+
.card[data-size="sm"] .card__title { font-size: var(--step-0); }
|
|
181
|
+
.card[data-size="lg"] .card__title { font-size: var(--step-2); }
|
|
314
182
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
.card[data-size="lg"] .card__footer {
|
|
320
|
-
padding: var(--space-5) var(--space-6);
|
|
183
|
+
@container card (min-width: 30rem) {
|
|
184
|
+
.card[data-layout="horizontal"] { flex-direction: row; gap: var(--space-m); }
|
|
185
|
+
.card[data-layout="horizontal"] .card__media { inline-size: 40%; max-inline-size: 16rem; }
|
|
186
|
+
.card[data-layout="horizontal"] .card__media + :is(.card__content, .card__body) { margin-block-start: 0; }
|
|
321
187
|
}
|
|
322
188
|
|
|
323
189
|
|
|
324
190
|
/* ========================================
|
|
325
|
-
|
|
326
|
-
Cards adapt to their container, not viewport
|
|
191
|
+
DUOTONE (opt-in): the hue comes from --accent
|
|
327
192
|
======================================== */
|
|
328
193
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
padding: var(--space-4);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
.card__title {
|
|
336
|
-
font-size: var(--font-size-base);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
.card__footer {
|
|
340
|
-
padding: var(--space-3) var(--space-4);
|
|
341
|
-
flex-direction: column;
|
|
342
|
-
align-items: stretch;
|
|
343
|
-
}
|
|
194
|
+
.card__media-wrap {
|
|
195
|
+
position: relative;
|
|
196
|
+
overflow: hidden;
|
|
344
197
|
}
|
|
345
198
|
|
|
346
|
-
|
|
347
|
-
@container card (min-width: 30rem) {
|
|
348
|
-
.card[data-layout="horizontal"] {
|
|
349
|
-
flex-direction: row;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
.card[data-layout="horizontal"] .card__media {
|
|
353
|
-
inline-size: 40%;
|
|
354
|
-
max-inline-size: 16rem;
|
|
355
|
-
block-size: auto;
|
|
356
|
-
}
|
|
199
|
+
.card[data-treatment="duotone"] .card__media { filter: grayscale(100%) contrast(1.1); }
|
|
357
200
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
201
|
+
.card[data-treatment="duotone"] .card__media-wrap::after {
|
|
202
|
+
content: "";
|
|
203
|
+
position: absolute;
|
|
204
|
+
inset: 0;
|
|
205
|
+
background: linear-gradient(
|
|
206
|
+
135deg,
|
|
207
|
+
var(--duotone-dark, oklch(from var(--accent) 0.3 c h)) 0%,
|
|
208
|
+
var(--duotone-light, oklch(from var(--accent) 0.8 calc(c * 0.5) h)) 100%
|
|
209
|
+
);
|
|
210
|
+
mix-blend-mode: multiply;
|
|
211
|
+
opacity: 0.85;
|
|
212
|
+
pointer-events: none;
|
|
361
213
|
}
|
|
362
214
|
|
|
363
215
|
|
|
364
216
|
/* ========================================
|
|
365
217
|
SPECIAL CARD TYPES
|
|
366
|
-
Common card patterns
|
|
367
218
|
======================================== */
|
|
368
219
|
|
|
369
|
-
/* Profile card */
|
|
370
|
-
.card[data-type="profile"] {
|
|
371
|
-
text-align: center;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
220
|
.card[data-type="profile"] .card__media {
|
|
375
221
|
inline-size: 6rem;
|
|
376
222
|
block-size: 6rem;
|
|
377
223
|
border-radius: var(--radius-full);
|
|
378
|
-
margin: var(--space-5) auto 0;
|
|
379
224
|
}
|
|
380
225
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
.card[data-type="stat"] .card__value {
|
|
388
|
-
font-size: var(--font-size-3xl);
|
|
389
|
-
font-weight: var(--weight-bold);
|
|
390
|
-
line-height: var(--leading-none);
|
|
391
|
-
color: var(--accent);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
.card[data-type="stat"] .card__title {
|
|
395
|
-
font-size: var(--font-size-sm);
|
|
396
|
-
font-weight: var(--weight-normal);
|
|
397
|
-
color: var(--color-text-muted);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/* Feature card - emphasized */
|
|
401
|
-
.card[data-type="feature"] {
|
|
402
|
-
text-align: center;
|
|
403
|
-
padding: var(--space-6);
|
|
226
|
+
:is(.card[data-type="stat"] .card__value, .card[data-type="pricing"] .card__price) {
|
|
227
|
+
font-family: var(--font-heading);
|
|
228
|
+
font-size: var(--step-4);
|
|
229
|
+
font-weight: calc(var(--weight-display) + var(--_dark-weight));
|
|
230
|
+
line-height: 1;
|
|
231
|
+
font-variant-numeric: lining-nums tabular-nums;
|
|
404
232
|
}
|
|
405
233
|
|
|
406
234
|
.card[data-type="feature"] .card__icon {
|
|
407
|
-
inline-size:
|
|
408
|
-
block-size:
|
|
409
|
-
margin-
|
|
410
|
-
|
|
411
|
-
color: var(--accent);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/* Testimonial card - quote with attribution */
|
|
415
|
-
.card[data-type="testimonial"] .card__content {
|
|
416
|
-
gap: var(--space-4);
|
|
235
|
+
inline-size: 2.5rem;
|
|
236
|
+
block-size: 2.5rem;
|
|
237
|
+
margin-block-end: var(--space-s);
|
|
238
|
+
color: var(--accent-ink);
|
|
417
239
|
}
|
|
418
240
|
|
|
419
241
|
.card[data-type="testimonial"] .card__rating {
|
|
@@ -423,77 +245,45 @@
|
|
|
423
245
|
}
|
|
424
246
|
|
|
425
247
|
.card[data-type="testimonial"] .card__quote {
|
|
248
|
+
font-family: var(--font-heading);
|
|
249
|
+
font-size: var(--step-1);
|
|
426
250
|
font-style: italic;
|
|
427
|
-
line-height:
|
|
428
|
-
color: var(--color-text);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
.card[data-type="testimonial"] .card__quote::before {
|
|
432
|
-
content: "\201C";
|
|
433
|
-
font-size: var(--font-size-3xl);
|
|
434
|
-
font-style: normal;
|
|
435
|
-
line-height: 0;
|
|
436
|
-
vertical-align: -0.35em;
|
|
437
|
-
color: var(--accent);
|
|
438
|
-
margin-inline-end: var(--space-1);
|
|
251
|
+
line-height: 1.4;
|
|
439
252
|
}
|
|
440
253
|
|
|
441
254
|
.card[data-type="testimonial"] .card__attribution {
|
|
442
255
|
display: flex;
|
|
443
256
|
align-items: center;
|
|
444
257
|
gap: var(--space-3);
|
|
445
|
-
font-size: var(--
|
|
258
|
+
font-size: var(--step--1);
|
|
446
259
|
}
|
|
447
260
|
|
|
448
|
-
.card[data-type="testimonial"] .card__author {
|
|
449
|
-
|
|
450
|
-
font-style: normal;
|
|
451
|
-
color: var(--color-text);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
.card[data-type="testimonial"] .card__role {
|
|
455
|
-
color: var(--color-text-muted);
|
|
456
|
-
}
|
|
261
|
+
.card[data-type="testimonial"] .card__author { font-weight: 600; font-style: normal; }
|
|
262
|
+
.card[data-type="testimonial"] .card__role { color: var(--color-text-muted); }
|
|
457
263
|
|
|
458
|
-
|
|
459
|
-
.card[data-type="pricing"] {
|
|
460
|
-
text-align: center;
|
|
461
|
-
overflow: visible;
|
|
462
|
-
position: relative;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
.card[data-type="pricing"] .card__price {
|
|
466
|
-
font-size: var(--font-size-4xl);
|
|
467
|
-
font-weight: var(--weight-bold);
|
|
468
|
-
line-height: var(--leading-none);
|
|
469
|
-
margin-block-end: var(--space-1);
|
|
470
|
-
}
|
|
264
|
+
.card[data-type="pricing"] { overflow: visible; }
|
|
471
265
|
|
|
472
266
|
.card[data-type="pricing"] .card__price-period {
|
|
473
|
-
font-
|
|
267
|
+
font-family: var(--font-body);
|
|
268
|
+
font-size: var(--step--1);
|
|
474
269
|
color: var(--color-text-muted);
|
|
475
|
-
font-weight: var(--weight-normal);
|
|
476
270
|
}
|
|
477
271
|
|
|
478
|
-
|
|
479
|
-
.card[data-type="pricing"][data-featured] {
|
|
480
|
-
border: 2px solid var(--accent);
|
|
481
|
-
transform: scale(1.03);
|
|
482
|
-
}
|
|
272
|
+
.card[data-type="pricing"][data-featured] { --_card-border: var(--color-border-strong); border-width: var(--border-width-thick); }
|
|
483
273
|
|
|
484
274
|
.card[data-type="pricing"][data-featured] > .badge {
|
|
485
275
|
position: absolute;
|
|
486
276
|
inset-block-start: 0;
|
|
487
|
-
inset-inline
|
|
488
|
-
|
|
277
|
+
inset-inline: 0;
|
|
278
|
+
margin-inline: auto;
|
|
279
|
+
inline-size: fit-content;
|
|
280
|
+
translate: 0 -50%;
|
|
489
281
|
}
|
|
490
282
|
|
|
491
|
-
/* Pricing feature list */
|
|
492
283
|
.card[data-type="pricing"] .card__features {
|
|
493
284
|
list-style: none;
|
|
494
285
|
padding: 0;
|
|
495
286
|
margin: 0;
|
|
496
|
-
text-align: start;
|
|
497
287
|
}
|
|
498
288
|
|
|
499
289
|
.card[data-type="pricing"] .card__features li {
|
|
@@ -501,11 +291,8 @@
|
|
|
501
291
|
align-items: center;
|
|
502
292
|
gap: var(--space-2);
|
|
503
293
|
padding-block: var(--space-2);
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
.card[data-type="pricing"] .card__features li:last-child {
|
|
508
|
-
border-block-end: none;
|
|
294
|
+
margin: 0;
|
|
295
|
+
border-block-end: var(--border-width) solid var(--color-border);
|
|
509
296
|
}
|
|
510
297
|
|
|
511
298
|
.card[data-type="pricing"] .card__features .check {
|
|
@@ -516,135 +303,13 @@
|
|
|
516
303
|
|
|
517
304
|
/* ========================================
|
|
518
305
|
CARD GROUPS
|
|
519
|
-
Multiple cards together
|
|
520
306
|
======================================== */
|
|
521
307
|
|
|
522
308
|
.card-group {
|
|
523
309
|
display: grid;
|
|
524
|
-
gap: var(--space-
|
|
525
|
-
grid-template-columns: repeat(
|
|
526
|
-
auto-fit,
|
|
527
|
-
minmax(min(100%, var(--card-min-width, 18rem)), 1fr)
|
|
528
|
-
);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
/* Equal height cards */
|
|
532
|
-
.card-group[data-equal-height] > .card {
|
|
533
|
-
block-size: 100%;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
.card-group[data-equal-height] > .card .card__content {
|
|
537
|
-
flex: 1;
|
|
310
|
+
gap: var(--space-l) var(--space-m);
|
|
311
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--card-min-width, 18rem)), 1fr));
|
|
538
312
|
}
|
|
539
313
|
|
|
540
|
-
|
|
541
|
-
/* ========================================
|
|
542
|
-
THEME-SPECIFIC CARD STYLES
|
|
543
|
-
Motion styles affect card appearance
|
|
544
|
-
======================================== */
|
|
545
|
-
|
|
546
|
-
/* Still: Crisp, no-nonsense borders */
|
|
547
|
-
[data-motion="still"] .card {
|
|
548
|
-
border-width: 1px;
|
|
549
|
-
border-color: var(--color-border);
|
|
550
|
-
box-shadow: none;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/* Serene: Extra soft, pillowy cards with gentle shadows */
|
|
554
|
-
[data-motion="serene"] .card {
|
|
555
|
-
box-shadow: var(--shadow-sm);
|
|
556
|
-
}
|
|
557
|
-
[data-motion="serene"] .card[data-variant="elevated"] {
|
|
558
|
-
box-shadow: var(--shadow-md);
|
|
559
|
-
}
|
|
560
|
-
[data-motion="serene"] .card:hover {
|
|
561
|
-
box-shadow: var(--shadow-md);
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
/* Cascade: Prominent layered shadows, bubbly elevated feel */
|
|
565
|
-
[data-motion="cascade"] .card {
|
|
566
|
-
box-shadow:
|
|
567
|
-
0 4px 12px oklch(0 0 0 / 0.06),
|
|
568
|
-
0 12px 28px oklch(0 0 0 / 0.1);
|
|
569
|
-
}
|
|
570
|
-
[data-motion="cascade"] .card:hover {
|
|
571
|
-
transform: translateY(-4px);
|
|
572
|
-
box-shadow:
|
|
573
|
-
0 8px 20px oklch(0 0 0 / 0.08),
|
|
574
|
-
0 20px 40px oklch(0 0 0 / 0.14);
|
|
575
|
-
}
|
|
576
|
-
[data-motion="cascade"] .card[data-variant="elevated"] {
|
|
577
|
-
box-shadow:
|
|
578
|
-
0 8px 20px oklch(0 0 0 / 0.08),
|
|
579
|
-
0 24px 48px oklch(0 0 0 / 0.12);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
/* Rapids: Hard offset shadows, energetic hover */
|
|
583
|
-
[data-motion="rapids"] .card {
|
|
584
|
-
box-shadow: var(--shadow-offset);
|
|
585
|
-
transition:
|
|
586
|
-
transform 150ms var(--ease-fluid),
|
|
587
|
-
box-shadow 150ms var(--ease-fluid);
|
|
588
|
-
}
|
|
589
|
-
[data-motion="rapids"] .card:hover {
|
|
590
|
-
transform: translate(-2px, -2px);
|
|
591
|
-
box-shadow: var(--shadow-offset-hover);
|
|
592
|
-
}
|
|
593
|
-
[data-motion="rapids"] .card:active {
|
|
594
|
-
transform: translate(1px, 1px);
|
|
595
|
-
box-shadow: 2px 2px 0 oklch(0 0 0 / 0.15);
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
/* Tsunami: 3D depth effect with dramatic shadows */
|
|
599
|
-
[data-motion="tsunami"] .card {
|
|
600
|
-
transform-style: preserve-3d;
|
|
601
|
-
transition: transform 0.4s var(--ease-fluid), box-shadow 0.4s var(--ease-fluid);
|
|
602
|
-
box-shadow:
|
|
603
|
-
0 15px 35px oklch(0 0 0 / 0.2),
|
|
604
|
-
0 5px 15px oklch(0 0 0 / 0.1);
|
|
605
|
-
}
|
|
606
|
-
[data-motion="tsunami"] .card:hover {
|
|
607
|
-
transform: translateY(-8px) scale(1.01);
|
|
608
|
-
box-shadow:
|
|
609
|
-
0 25px 50px oklch(0 0 0 / 0.25),
|
|
610
|
-
0 10px 20px oklch(0 0 0 / 0.15),
|
|
611
|
-
0 0 40px oklch(from var(--accent) l c h / 0.15);
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
/* ========================================
|
|
616
|
-
REDUCED MOTION
|
|
617
|
-
======================================== */
|
|
618
|
-
|
|
619
|
-
@media (prefers-reduced-motion: reduce) {
|
|
620
|
-
.card {
|
|
621
|
-
transition: none;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
.card[data-interactive]:active,
|
|
625
|
-
a.card:active {
|
|
626
|
-
transform: none;
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
[data-motion="cascade"] .card:hover,
|
|
630
|
-
[data-motion="rapids"] .card:hover,
|
|
631
|
-
[data-motion="rapids"] .card:active,
|
|
632
|
-
[data-motion="tsunami"] .card:hover {
|
|
633
|
-
transform: none;
|
|
634
|
-
transition: none;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
[data-motion="rapids"] .card {
|
|
638
|
-
transition: none;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
[data-motion="tsunami"] .card {
|
|
642
|
-
transition: none;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
.card__media,
|
|
646
|
-
.card__media-wrap::after {
|
|
647
|
-
transition: none;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
314
|
+
.card-group[data-equal-height] > .card { block-size: 100%; }
|
|
650
315
|
}
|