@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.
Files changed (48) hide show
  1. package/AGENTS.md +32 -0
  2. package/CHANGELOG.md +159 -0
  3. package/CLAUDE.md +104 -0
  4. package/GEMINI.md +48 -0
  5. package/LICENSE +21 -0
  6. package/README.md +253 -0
  7. package/dist/fluid.min.css +2 -0
  8. package/fluid-agent-kit/README.md +57 -0
  9. package/fluid-agent-kit/skills/accessibility.md +41 -0
  10. package/fluid-agent-kit/skills/css-conventions.md +51 -0
  11. package/fluid-agent-kit/skills/image-optimization.md +115 -0
  12. package/fluid-agent-kit/skills/ux-rules.md +43 -0
  13. package/package.json +68 -0
  14. package/src/animations/scroll-reveal.css +224 -0
  15. package/src/components/accordion.css +250 -0
  16. package/src/components/alert.css +453 -0
  17. package/src/components/avatar.css +192 -0
  18. package/src/components/badge.css +182 -0
  19. package/src/components/button.css +387 -0
  20. package/src/components/card.css +650 -0
  21. package/src/components/chip.css +143 -0
  22. package/src/components/dropdown.css +335 -0
  23. package/src/components/empty-state.css +105 -0
  24. package/src/components/form.css +508 -0
  25. package/src/components/hero.css +293 -0
  26. package/src/components/indicator.css +455 -0
  27. package/src/components/loading.css +274 -0
  28. package/src/components/modal.css +364 -0
  29. package/src/components/nav.css +726 -0
  30. package/src/components/scroll-progress.css +104 -0
  31. package/src/components/search-input.css +125 -0
  32. package/src/components/settings-panel.css +603 -0
  33. package/src/components/step-indicator.css +188 -0
  34. package/src/components/table.css +350 -0
  35. package/src/components/themed-images.css +229 -0
  36. package/src/components/tooltip.css +247 -0
  37. package/src/components/version-badge.css +70 -0
  38. package/src/core/base.css +884 -0
  39. package/src/core/reset.css +159 -0
  40. package/src/core/tokens.css +2416 -0
  41. package/src/fluid.css +242 -0
  42. package/src/layouts/positioning.css +626 -0
  43. package/src/sections/cta.css +210 -0
  44. package/src/sections/features.css +356 -0
  45. package/src/sections/footer.css +283 -0
  46. package/src/sections/stats.css +234 -0
  47. package/src/sections/team.css +181 -0
  48. package/src/sections/testimonials.css +251 -0
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Fluid Framework - Footer Sections
3
+ * @layer components
4
+ *
5
+ * Page-level footer layouts. Three variants via data-type attribute.
6
+ * Uses <footer> element with <nav> for link groups.
7
+ *
8
+ * Usage:
9
+ * <!-- Simple (default) -->
10
+ * <footer class="site-footer">
11
+ * <div class="site-footer__inner">
12
+ * <p class="site-footer__copyright">&copy; 2026 Company</p>
13
+ * <nav class="site-footer__links" aria-label="Footer">
14
+ * <a href="#">Privacy</a>
15
+ * <a href="#">Terms</a>
16
+ * <a href="#">Contact</a>
17
+ * </nav>
18
+ * </div>
19
+ * </footer>
20
+ *
21
+ * <!-- Standard multi-column -->
22
+ * <footer class="site-footer" data-type="standard">
23
+ * <div class="site-footer__grid">
24
+ * <div class="site-footer__column">
25
+ * <h3 class="site-footer__title">Company</h3>
26
+ * <nav class="site-footer__links" aria-label="Company links">
27
+ * <a href="#">About</a>
28
+ * <a href="#">Careers</a>
29
+ * </nav>
30
+ * </div>
31
+ * <div class="site-footer__column">
32
+ * <h3 class="site-footer__title">Product</h3>
33
+ * <nav class="site-footer__links" aria-label="Product links">
34
+ * <a href="#">Features</a>
35
+ * <a href="#">Pricing</a>
36
+ * </nav>
37
+ * </div>
38
+ * </div>
39
+ * <div class="site-footer__bottom">
40
+ * <p class="site-footer__copyright">&copy; 2026 Company</p>
41
+ * </div>
42
+ * </footer>
43
+ *
44
+ * <!-- Mega footer -->
45
+ * <footer class="site-footer" data-type="mega">
46
+ * <div class="site-footer__brand">
47
+ * <h2>Brand Name</h2>
48
+ * <p>A short tagline about the company.</p>
49
+ * <div class="site-footer__social">
50
+ * <a href="#" aria-label="Twitter"><svg>...</svg></a>
51
+ * <a href="#" aria-label="GitHub"><svg>...</svg></a>
52
+ * </div>
53
+ * </div>
54
+ * <div class="site-footer__grid">
55
+ * <!-- columns -->
56
+ * </div>
57
+ * <div class="site-footer__bottom">
58
+ * <p class="site-footer__copyright">&copy; 2026 Company</p>
59
+ * </div>
60
+ * </footer>
61
+ */
62
+
63
+ @layer components {
64
+
65
+ /* ========================================
66
+ BASE FOOTER
67
+ ======================================== */
68
+
69
+ .site-footer {
70
+ --_footer-bg: var(--color-surface);
71
+ --_footer-text: var(--color-text-muted);
72
+ --_footer-border: var(--color-border-subtle);
73
+ --_footer-padding: var(--space-10);
74
+
75
+ background-color: var(--_footer-bg);
76
+ color: var(--_footer-text);
77
+ padding-block: var(--_footer-padding);
78
+ padding-inline: var(--space-5);
79
+ border-block-start: var(--border-width) solid var(--_footer-border);
80
+ }
81
+
82
+ .site-footer a {
83
+ color: var(--_footer-text);
84
+ text-decoration: none;
85
+ transition: color var(--duration-fast) var(--ease-fluid);
86
+ }
87
+
88
+ .site-footer a:hover {
89
+ color: var(--color-text);
90
+ }
91
+
92
+ .site-footer a:focus-visible {
93
+ outline: 2px solid var(--color-focus);
94
+ outline-offset: 2px;
95
+ border-radius: var(--radius-sm);
96
+ }
97
+
98
+
99
+ /* ========================================
100
+ SIMPLE (default)
101
+ Copyright + horizontal links
102
+ ======================================== */
103
+
104
+ .site-footer__inner {
105
+ display: flex;
106
+ flex-wrap: wrap;
107
+ justify-content: space-between;
108
+ align-items: center;
109
+ gap: var(--space-4);
110
+ max-inline-size: var(--container-xl);
111
+ margin-inline: auto;
112
+ }
113
+
114
+ .site-footer__copyright {
115
+ font-size: var(--font-size-sm);
116
+ margin: 0;
117
+ }
118
+
119
+ .site-footer:not([data-type]) .site-footer__links {
120
+ display: flex;
121
+ flex-wrap: wrap;
122
+ gap: var(--space-5);
123
+ font-size: var(--font-size-sm);
124
+ }
125
+
126
+
127
+ /* ========================================
128
+ STANDARD
129
+ Multi-column grid with bottom bar
130
+ ======================================== */
131
+
132
+ .site-footer[data-type="standard"],
133
+ .site-footer[data-type="mega"] {
134
+ --_footer-padding: var(--space-16);
135
+ }
136
+
137
+ .site-footer__grid {
138
+ display: grid;
139
+ gap: var(--space-8);
140
+ grid-template-columns: repeat(
141
+ auto-fit,
142
+ minmax(min(100%, 12rem), 1fr)
143
+ );
144
+ max-inline-size: var(--container-xl);
145
+ margin-inline: auto;
146
+ }
147
+
148
+ .site-footer__column {
149
+ display: flex;
150
+ flex-direction: column;
151
+ gap: var(--space-3);
152
+ }
153
+
154
+ .site-footer__title {
155
+ font-size: var(--font-size-sm);
156
+ font-weight: var(--weight-semibold, 600);
157
+ color: var(--color-text);
158
+ text-transform: uppercase;
159
+ letter-spacing: var(--tracking-wider);
160
+ margin: 0;
161
+ margin-block-end: var(--space-2);
162
+ }
163
+
164
+ .site-footer__column .site-footer__links {
165
+ display: flex;
166
+ flex-direction: column;
167
+ gap: var(--space-2);
168
+ font-size: var(--font-size-sm);
169
+ }
170
+
171
+ .site-footer__bottom {
172
+ display: flex;
173
+ flex-wrap: wrap;
174
+ justify-content: space-between;
175
+ align-items: center;
176
+ gap: var(--space-4);
177
+ max-inline-size: var(--container-xl);
178
+ margin-inline: auto;
179
+ margin-block-start: var(--space-10);
180
+ padding-block-start: var(--space-6);
181
+ border-block-start: var(--border-width) solid var(--_footer-border);
182
+ font-size: var(--font-size-sm);
183
+ }
184
+
185
+
186
+ /* ========================================
187
+ MEGA FOOTER
188
+ Brand section + columns + bottom bar
189
+ ======================================== */
190
+
191
+ .site-footer__brand {
192
+ max-inline-size: 20rem;
193
+ margin-inline: auto;
194
+ margin-block-end: var(--space-10);
195
+ }
196
+
197
+ .site-footer[data-type="mega"] .site-footer__brand {
198
+ max-inline-size: var(--container-xl);
199
+ margin-inline: auto;
200
+ margin-block-end: var(--space-10);
201
+ }
202
+
203
+ .site-footer__brand h2 {
204
+ font-size: var(--font-size-xl);
205
+ font-weight: var(--weight-bold);
206
+ color: var(--color-text);
207
+ margin: 0;
208
+ margin-block-end: var(--space-2);
209
+ }
210
+
211
+ .site-footer__brand p {
212
+ font-size: var(--font-size-sm);
213
+ color: var(--color-text-muted);
214
+ margin: 0;
215
+ margin-block-end: var(--space-4);
216
+ max-inline-size: 20rem;
217
+ }
218
+
219
+ .site-footer__social {
220
+ display: flex;
221
+ gap: var(--space-3);
222
+ }
223
+
224
+ .site-footer__social a {
225
+ display: flex;
226
+ align-items: center;
227
+ justify-content: center;
228
+ inline-size: 2.25rem;
229
+ block-size: 2.25rem;
230
+ border-radius: var(--radius-full);
231
+ color: var(--color-text-muted);
232
+ background-color: color-mix(in oklch, var(--color-text) 8%, transparent);
233
+ transition:
234
+ color var(--duration-fast) var(--ease-fluid),
235
+ background-color var(--duration-fast) var(--ease-fluid);
236
+ }
237
+
238
+ .site-footer__social a:hover {
239
+ color: var(--white);
240
+ background-color: var(--accent);
241
+ }
242
+
243
+ .site-footer__social svg {
244
+ inline-size: 1.125rem;
245
+ block-size: 1.125rem;
246
+ }
247
+
248
+
249
+ /* ========================================
250
+ DARK VARIANT
251
+ Darker background for contrast with page
252
+ ======================================== */
253
+
254
+ .site-footer[data-dark] {
255
+ --_footer-bg: var(--theme-dark, var(--gray-15));
256
+ --_footer-text: var(--gray-60);
257
+ --_footer-border: var(--gray-20);
258
+ }
259
+
260
+ .site-footer[data-dark] a:hover {
261
+ color: var(--white);
262
+ }
263
+
264
+ .site-footer[data-dark] .site-footer__title {
265
+ color: var(--gray-80);
266
+ }
267
+
268
+ .site-footer[data-dark] .site-footer__brand h2 {
269
+ color: var(--white);
270
+ }
271
+
272
+
273
+ /* ========================================
274
+ ACCESSIBILITY
275
+ ======================================== */
276
+
277
+ @media (prefers-reduced-motion: reduce) {
278
+ .site-footer a,
279
+ .site-footer__social a {
280
+ transition: none;
281
+ }
282
+ }
283
+ }
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Fluid Framework - Stats/Metrics Section
3
+ * @layer components
4
+ *
5
+ * Counter blocks for displaying key metrics, achievements, or numbers.
6
+ * Uses <dl> (description list) for semantic markup.
7
+ *
8
+ * Usage:
9
+ * <section class="stats" aria-label="Key metrics">
10
+ * <header class="stats__header">
11
+ * <h2>By the numbers</h2>
12
+ * </header>
13
+ * <dl class="stats__grid">
14
+ * <div class="stat">
15
+ * <dd class="stat__value">10K+</dd>
16
+ * <dt class="stat__label">Happy Users</dt>
17
+ * </div>
18
+ * <div class="stat">
19
+ * <dd class="stat__value">99.9%</dd>
20
+ * <dt class="stat__label">Uptime</dt>
21
+ * </div>
22
+ * <div class="stat">
23
+ * <dd class="stat__value">50M</dd>
24
+ * <dt class="stat__label">API Requests</dt>
25
+ * </div>
26
+ * <div class="stat">
27
+ * <dd class="stat__value">4.9</dd>
28
+ * <dt class="stat__label">Star Rating</dt>
29
+ * </div>
30
+ * </dl>
31
+ * </section>
32
+ */
33
+
34
+ @layer components {
35
+
36
+ /* ========================================
37
+ BASE STATS SECTION
38
+ ======================================== */
39
+
40
+ .stats {
41
+ padding-block: var(--space-16);
42
+ padding-inline: var(--space-5);
43
+ max-inline-size: var(--container-xl);
44
+ margin-inline: auto;
45
+ }
46
+
47
+ .stats__header {
48
+ text-align: center;
49
+ max-inline-size: var(--container-md);
50
+ margin-inline: auto;
51
+ margin-block-end: var(--space-12);
52
+ }
53
+
54
+ .stats__header h2 {
55
+ font-size: var(--font-size-3xl);
56
+ font-weight: var(--weight-bold);
57
+ color: var(--color-text);
58
+ margin-block-end: var(--space-3);
59
+ }
60
+
61
+ .stats__header p {
62
+ font-size: var(--font-size-lg);
63
+ color: var(--color-text-muted);
64
+ }
65
+
66
+
67
+ /* ========================================
68
+ STATS GRID
69
+ ======================================== */
70
+
71
+ .stats__grid {
72
+ display: grid;
73
+ gap: var(--space-6);
74
+ grid-template-columns: repeat(
75
+ auto-fit,
76
+ minmax(min(100%, 10rem), 1fr)
77
+ );
78
+ margin: 0;
79
+ padding: 0;
80
+ }
81
+
82
+
83
+ /* ========================================
84
+ INDIVIDUAL STAT
85
+ ======================================== */
86
+
87
+ .stat {
88
+ --_stat-padding: var(--space-6);
89
+ --_stat-bg: var(--color-surface);
90
+ --_stat-border: var(--color-border-subtle);
91
+ --_stat-radius: var(--radius-lg);
92
+
93
+ display: flex;
94
+ flex-direction: column;
95
+ align-items: center;
96
+ text-align: center;
97
+ gap: var(--space-2);
98
+ padding: var(--_stat-padding);
99
+ background-color: var(--_stat-bg);
100
+ border: var(--border-width) solid var(--_stat-border);
101
+ border-radius: var(--_stat-radius);
102
+ }
103
+
104
+ .stat__value {
105
+ font-size: var(--font-size-4xl);
106
+ font-weight: var(--weight-bold);
107
+ color: var(--accent);
108
+ line-height: 1.1;
109
+ margin: 0;
110
+ }
111
+
112
+ .stat__label {
113
+ font-size: var(--font-size-sm);
114
+ color: var(--color-text-muted);
115
+ font-weight: var(--weight-medium, 500);
116
+ }
117
+
118
+ .stat__icon {
119
+ display: flex;
120
+ align-items: center;
121
+ justify-content: center;
122
+ color: var(--accent);
123
+ font-size: var(--font-size-xl);
124
+ margin-block-end: var(--space-2);
125
+ }
126
+
127
+ .stat__icon svg {
128
+ inline-size: 1.5em;
129
+ block-size: 1.5em;
130
+ stroke: currentColor;
131
+ stroke-width: 2;
132
+ }
133
+
134
+
135
+ /* ========================================
136
+ BORDERLESS VARIANT
137
+ Minimal stat blocks without cards
138
+ ======================================== */
139
+
140
+ .stats[data-variant="borderless"] .stat {
141
+ --_stat-bg: transparent;
142
+ --_stat-border: transparent;
143
+ }
144
+
145
+ .stats[data-variant="borderless"] .stat__value {
146
+ font-size: var(--font-size-5xl);
147
+ }
148
+
149
+
150
+ /* ========================================
151
+ DIVIDER VARIANT
152
+ Stats separated by vertical lines
153
+ ======================================== */
154
+
155
+ .stats[data-variant="divider"] .stats__grid {
156
+ display: flex;
157
+ flex-wrap: wrap;
158
+ justify-content: center;
159
+ gap: 0;
160
+ }
161
+
162
+ .stats[data-variant="divider"] .stat {
163
+ --_stat-bg: transparent;
164
+ --_stat-border: transparent;
165
+ border-radius: 0;
166
+ padding-inline: var(--space-8);
167
+ border-inline-end: var(--border-width) solid var(--color-border-subtle);
168
+ }
169
+
170
+ .stats[data-variant="divider"] .stat:last-child {
171
+ border-inline-end: none;
172
+ }
173
+
174
+ @media (max-width: 40rem) {
175
+ .stats[data-variant="divider"] .stat {
176
+ border-inline-end: none;
177
+ border-block-end: var(--border-width) solid var(--color-border-subtle);
178
+ padding-inline: var(--space-6);
179
+ padding-block: var(--space-4);
180
+ }
181
+
182
+ .stats[data-variant="divider"] .stat:last-child {
183
+ border-block-end: none;
184
+ }
185
+ }
186
+
187
+
188
+ /* ========================================
189
+ COUNT-UP ANIMATION
190
+ Plays once when section enters viewport
191
+ ======================================== */
192
+
193
+ @keyframes stat-fade-up {
194
+ from {
195
+ opacity: 0;
196
+ transform: translateY(1rem);
197
+ }
198
+ to {
199
+ opacity: 1;
200
+ transform: translateY(0);
201
+ }
202
+ }
203
+
204
+ .stats[data-animate] .stat {
205
+ animation: stat-fade-up var(--duration-slow) var(--ease-settle) both;
206
+ }
207
+
208
+ .stats[data-animate] .stat:nth-child(2) {
209
+ animation-delay: 100ms;
210
+ }
211
+
212
+ .stats[data-animate] .stat:nth-child(3) {
213
+ animation-delay: 200ms;
214
+ }
215
+
216
+ .stats[data-animate] .stat:nth-child(4) {
217
+ animation-delay: 300ms;
218
+ }
219
+
220
+ .stats[data-animate] .stat:nth-child(5) {
221
+ animation-delay: 400ms;
222
+ }
223
+
224
+
225
+ /* ========================================
226
+ ACCESSIBILITY
227
+ ======================================== */
228
+
229
+ @media (prefers-reduced-motion: reduce) {
230
+ .stats[data-animate] .stat {
231
+ animation: none;
232
+ }
233
+ }
234
+ }
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Fluid Framework - Team Section
3
+ * @layer components
4
+ *
5
+ * Grid of team member cards with avatar, name, role, and optional bio.
6
+ * Integrates with the existing avatar component.
7
+ *
8
+ * Usage:
9
+ * <section class="team">
10
+ * <header class="team__header">
11
+ * <h2>Our Team</h2>
12
+ * <p>The people behind the product.</p>
13
+ * </header>
14
+ * <div class="team__grid">
15
+ * <article class="team-member">
16
+ * <img class="avatar avatar--xl" src="..." alt="Jane Doe">
17
+ * <h3 class="team-member__name">Jane Doe</h3>
18
+ * <p class="team-member__role">CEO & Co-founder</p>
19
+ * <p class="team-member__bio">Short bio about Jane.</p>
20
+ * <nav class="team-member__social" aria-label="Jane's social links">
21
+ * <a href="#" aria-label="Twitter"><svg>...</svg></a>
22
+ * <a href="#" aria-label="LinkedIn"><svg>...</svg></a>
23
+ * </nav>
24
+ * </article>
25
+ * </div>
26
+ * </section>
27
+ */
28
+
29
+ @layer components {
30
+
31
+ /* ========================================
32
+ BASE TEAM SECTION
33
+ ======================================== */
34
+
35
+ .team {
36
+ padding-block: var(--space-16);
37
+ padding-inline: var(--space-5);
38
+ max-inline-size: var(--container-xl);
39
+ margin-inline: auto;
40
+ }
41
+
42
+ .team__header {
43
+ text-align: center;
44
+ max-inline-size: var(--container-md);
45
+ margin-inline: auto;
46
+ margin-block-end: var(--space-12);
47
+ }
48
+
49
+ .team__header h2 {
50
+ font-size: var(--font-size-3xl);
51
+ font-weight: var(--weight-bold);
52
+ color: var(--color-text);
53
+ margin-block-end: var(--space-3);
54
+ }
55
+
56
+ .team__header p {
57
+ font-size: var(--font-size-lg);
58
+ color: var(--color-text-muted);
59
+ }
60
+
61
+
62
+ /* ========================================
63
+ TEAM GRID
64
+ ======================================== */
65
+
66
+ .team__grid {
67
+ display: grid;
68
+ gap: var(--space-8);
69
+ grid-template-columns: repeat(
70
+ auto-fit,
71
+ minmax(min(100%, 14rem), 1fr)
72
+ );
73
+ }
74
+
75
+
76
+ /* ========================================
77
+ TEAM MEMBER CARD
78
+ ======================================== */
79
+
80
+ .team-member {
81
+ --_member-bg: var(--color-surface);
82
+ --_member-border: var(--color-border-subtle);
83
+ --_member-radius: var(--radius-xl);
84
+ --_member-padding: var(--space-6);
85
+
86
+ display: flex;
87
+ flex-direction: column;
88
+ align-items: center;
89
+ text-align: center;
90
+ gap: var(--space-2);
91
+ padding: var(--_member-padding);
92
+ background-color: var(--_member-bg);
93
+ border: var(--border-width) solid var(--_member-border);
94
+ border-radius: var(--_member-radius);
95
+ transition:
96
+ box-shadow var(--duration-normal) var(--ease-fluid),
97
+ transform var(--duration-normal) var(--ease-settle);
98
+ }
99
+
100
+ .team-member:hover {
101
+ box-shadow: var(--shadow-md);
102
+ transform: translateY(-2px);
103
+ }
104
+
105
+ .team-member .avatar {
106
+ margin-block-end: var(--space-2);
107
+ }
108
+
109
+ .team-member__name {
110
+ font-size: var(--font-size-lg);
111
+ font-weight: var(--weight-semibold, 600);
112
+ color: var(--color-text);
113
+ margin: 0;
114
+ }
115
+
116
+ .team-member__role {
117
+ font-size: var(--font-size-sm);
118
+ color: var(--accent);
119
+ margin: 0;
120
+ }
121
+
122
+ .team-member__bio {
123
+ font-size: var(--font-size-sm);
124
+ color: var(--color-text-muted);
125
+ line-height: var(--leading-relaxed);
126
+ margin: 0;
127
+ margin-block-start: var(--space-2);
128
+ }
129
+
130
+
131
+ /* ========================================
132
+ SOCIAL LINKS
133
+ ======================================== */
134
+
135
+ .team-member__social {
136
+ display: flex;
137
+ gap: var(--space-2);
138
+ margin-block-start: var(--space-3);
139
+ }
140
+
141
+ .team-member__social a {
142
+ display: flex;
143
+ align-items: center;
144
+ justify-content: center;
145
+ inline-size: 2rem;
146
+ block-size: 2rem;
147
+ border-radius: var(--radius-full);
148
+ color: var(--color-text-muted);
149
+ transition: color var(--duration-fast) var(--ease-fluid);
150
+ }
151
+
152
+ .team-member__social a:hover {
153
+ color: var(--accent);
154
+ }
155
+
156
+ .team-member__social a:focus-visible {
157
+ outline: 2px solid var(--color-focus);
158
+ outline-offset: 2px;
159
+ }
160
+
161
+ .team-member__social svg {
162
+ inline-size: 1rem;
163
+ block-size: 1rem;
164
+ }
165
+
166
+
167
+ /* ========================================
168
+ ACCESSIBILITY
169
+ ======================================== */
170
+
171
+ @media (prefers-reduced-motion: reduce) {
172
+ .team-member,
173
+ .team-member__social a {
174
+ transition: none;
175
+ }
176
+
177
+ .team-member:hover {
178
+ transform: none;
179
+ }
180
+ }
181
+ }