@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.
Files changed (107) hide show
  1. package/AGENTS.md +6 -29
  2. package/CHANGELOG.md +564 -2
  3. package/CLAUDE.md +201 -14
  4. package/GEMINI.md +6 -45
  5. package/README.md +17 -8
  6. package/assets/js/compare.js +77 -0
  7. package/assets/js/fit-text.js +103 -0
  8. package/assets/js/lightbox.js +153 -0
  9. package/assets/js/scroll-reveal.js +72 -0
  10. package/assets/js/toc-build.mjs +86 -0
  11. package/assets/js/toc.js +384 -0
  12. package/dist/fluid-1x.min.css +4 -0
  13. package/dist/fluid-fonts-archivo.min.css +2 -0
  14. package/dist/fluid-fonts-bodoni.min.css +2 -0
  15. package/dist/fluid-fonts.min.css +2 -0
  16. package/dist/fluid-legacy-1x.css +3 -0
  17. package/dist/fluid-nav.min.css +3 -0
  18. package/dist/fluid-toc.min.css +3 -0
  19. package/dist/fluid-zero.min.css +3 -0
  20. package/dist/fluid.min.css +3 -2
  21. package/dist/fonts/OFL-archivo.txt +93 -0
  22. package/dist/fonts/OFL-bodoni-moda.txt +93 -0
  23. package/dist/fonts/OFL-hanken-grotesk.txt +93 -0
  24. package/dist/fonts/OFL-newsreader.txt +93 -0
  25. package/dist/fonts/OFL-schibsted-grotesk.txt +93 -0
  26. package/dist/fonts/archivo-latin-wdth-italic.woff2 +0 -0
  27. package/dist/fonts/archivo-latin-wdth-normal.woff2 +0 -0
  28. package/dist/fonts/bodoni-moda-latin-opsz-italic.woff2 +0 -0
  29. package/dist/fonts/bodoni-moda-latin-opsz-normal.woff2 +0 -0
  30. package/dist/fonts/hanken-grotesk-latin-wght-italic.woff2 +0 -0
  31. package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
  32. package/dist/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
  33. package/dist/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
  34. package/dist/fonts/schibsted-grotesk-latin-wght-italic.woff2 +0 -0
  35. package/dist/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
  36. package/fluid-agent-kit/README.md +1 -0
  37. package/fluid-agent-kit/skills/accessibility.md +3 -1
  38. package/fluid-agent-kit/skills/css-conventions.md +22 -5
  39. package/fluid-agent-kit/skills/image-optimization.md +2 -0
  40. package/fluid-agent-kit/skills/preset-composition.md +108 -0
  41. package/package.json +36 -11
  42. package/src/animations/scroll-reveal.css +75 -193
  43. package/src/components/accordion.css +6 -47
  44. package/src/components/alert.css +47 -88
  45. package/src/components/avatar.css +4 -20
  46. package/src/components/badge.css +25 -48
  47. package/src/components/button.css +69 -175
  48. package/src/components/card.css +146 -481
  49. package/src/components/chip.css +46 -12
  50. package/src/components/compare.css +234 -0
  51. package/src/components/dropdown.css +10 -67
  52. package/src/components/empty-state.css +4 -0
  53. package/src/components/form.css +113 -81
  54. package/src/components/gallery.css +252 -0
  55. package/src/components/hero.css +203 -88
  56. package/src/components/indicator.css +23 -117
  57. package/src/components/loading.css +7 -29
  58. package/src/components/modal.css +12 -65
  59. package/src/components/nav-modes.css +261 -0
  60. package/src/components/nav.css +324 -392
  61. package/src/components/search-input.css +4 -2
  62. package/src/components/step-indicator.css +26 -27
  63. package/src/components/table.css +64 -171
  64. package/src/components/toc.css +254 -0
  65. package/src/components/tooltip.css +5 -46
  66. package/src/core/base.css +393 -547
  67. package/src/core/reset.css +17 -5
  68. package/src/core/tokens.css +426 -2276
  69. package/src/fluid.css +258 -17
  70. package/src/fonts/OFL-newsreader.txt +93 -0
  71. package/src/fonts/OFL-schibsted-grotesk.txt +93 -0
  72. package/src/fonts/fluid-fonts.css +55 -0
  73. package/src/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
  74. package/src/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
  75. package/src/fonts/schibsted-grotesk-latin-wght-italic.woff2 +0 -0
  76. package/src/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
  77. package/src/layouts/positioning.css +6 -3
  78. package/src/legacy-1x.css +61 -0
  79. package/src/sections/cta.css +33 -101
  80. package/src/sections/features.css +42 -219
  81. package/src/sections/footer.css +53 -134
  82. package/src/sections/stats.css +40 -153
  83. package/src/sections/team.css +24 -113
  84. package/src/sections/testimonials.css +34 -148
  85. package/src/zero/base.css +166 -0
  86. package/src/zero/tokens.css +64 -0
  87. package/src/zero.css +20 -0
  88. package/starters/workflows/README.md +40 -0
  89. package/starters/workflows/dependabot.yml +21 -0
  90. package/starters/workflows/update-fluid-theme.yml +296 -0
  91. package/themes/fonts/OFL-archivo.txt +93 -0
  92. package/themes/fonts/OFL-bodoni-moda.txt +93 -0
  93. package/themes/fonts/OFL-hanken-grotesk.txt +93 -0
  94. package/themes/fonts/archivo-latin-wdth-italic.woff2 +0 -0
  95. package/themes/fonts/archivo-latin-wdth-normal.woff2 +0 -0
  96. package/themes/fonts/archivo.css +20 -0
  97. package/themes/fonts/bodoni-moda-latin-opsz-italic.woff2 +0 -0
  98. package/themes/fonts/bodoni-moda-latin-opsz-normal.woff2 +0 -0
  99. package/themes/fonts/bodoni.css +35 -0
  100. package/themes/fonts/hanken-grotesk-latin-wght-italic.woff2 +0 -0
  101. package/themes/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
  102. package/themes/gallery.css +105 -0
  103. package/themes/swiss.css +53 -0
  104. package/src/components/scroll-progress.css +0 -104
  105. package/src/components/settings-panel.css +0 -603
  106. package/src/components/themed-images.css +0 -229
  107. package/src/components/version-badge.css +0 -70
@@ -22,6 +22,11 @@
22
22
  * <button class="chip-group__clear" data-variant="ghost" data-size="sm">Clear All</button>
23
23
  * </div>
24
24
  *
25
+ * <!-- Selectable chip: a checkbox or radio inside the label. The chip shows
26
+ * the checked state, wraps a long label and is 44px tall for a thumb. -->
27
+ * <label class="chip"><input type="checkbox" name="cuisine" value="Mexican"> Mexican</label>
28
+ * <label class="chip"><input type="radio" name="size" value="m"> Medium</label>
29
+ *
25
30
  * Variants: data-variant="filled|outline"
26
31
  */
27
32
 
@@ -36,7 +41,7 @@
36
41
  color: var(--color-text);
37
42
  background: var(--color-surface);
38
43
  border: var(--border-width) solid var(--color-border);
39
- border-radius: var(--radius-full);
44
+ border-radius: var(--radius-pill);
40
45
  white-space: nowrap;
41
46
  transition: background-color var(--duration-fast) var(--ease-fluid);
42
47
  }
@@ -51,7 +56,7 @@
51
56
 
52
57
  .chip__remove {
53
58
  --_btn-bg: transparent;
54
- --_btn-shadow: none;
59
+ --_btn-bg-hover: var(--color-error-subtle);
55
60
 
56
61
  position: relative;
57
62
  display: inline-flex;
@@ -76,7 +81,8 @@
76
81
 
77
82
  .chip__remove:focus-visible {
78
83
  color: var(--color-error);
79
- box-shadow: var(--shadow-glow);
84
+ outline: var(--focus-ring-width) solid var(--color-focus);
85
+ outline-offset: 1px;
80
86
  }
81
87
 
82
88
  /* Extend touch target to 44px minimum */
@@ -94,16 +100,16 @@
94
100
  .chip[data-variant="filled"] {
95
101
  background: var(--accent-subtle);
96
102
  border-color: transparent;
97
- color: var(--accent);
103
+ color: var(--accent-ink);
98
104
  }
99
105
 
100
106
  .chip[data-variant="filled"]:hover {
101
107
  background: var(--accent);
102
- color: var(--white);
108
+ color: var(--on-accent);
103
109
  }
104
110
 
105
111
  .chip[data-variant="filled"]:hover .chip__remove:hover {
106
- color: var(--white);
112
+ color: var(--on-accent);
107
113
  background: oklch(from var(--accent) calc(l - 0.1) c h);
108
114
  }
109
115
 
@@ -112,6 +118,38 @@
112
118
  }
113
119
 
114
120
 
121
+ /* ========================================
122
+ SELECTABLE CHIP
123
+ <label class="chip"><input type="checkbox"> Text</label>
124
+ ======================================== */
125
+
126
+ .chip:has(> input:is([type="checkbox"], [type="radio"])) {
127
+ min-block-size: 2.75rem;
128
+ padding-block: var(--space-2);
129
+ white-space: normal;
130
+ cursor: pointer;
131
+ transition:
132
+ background-color var(--duration-fast) var(--ease-fluid),
133
+ border-color var(--duration-fast) var(--ease-fluid);
134
+ }
135
+
136
+ /* Tint and border only: the ticked box already says checked. */
137
+ .chip:has(> input:checked) {
138
+ background: var(--accent-subtle);
139
+ border-color: var(--accent);
140
+ }
141
+
142
+ .chip:has(> input:focus-visible) {
143
+ outline: var(--focus-ring-width) solid var(--color-focus);
144
+ outline-offset: 2px;
145
+ }
146
+
147
+ .chip:has(> input:disabled) {
148
+ opacity: 0.6;
149
+ cursor: not-allowed;
150
+ }
151
+
152
+
115
153
  /* ========================================
116
154
  CHIP GROUP
117
155
  Container for active filter chips
@@ -130,14 +168,10 @@
130
168
  }
131
169
 
132
170
 
171
+
133
172
  /* ========================================
134
173
  REDUCED MOTION
135
174
  ======================================== */
136
175
 
137
- @media (prefers-reduced-motion: reduce) {
138
- .chip,
139
- .chip__remove {
140
- transition: none;
141
- }
142
- }
176
+ /* Reduced motion: the reset shortens every transition. */
143
177
  }
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Fluid Framework - Before / After compare
3
+ * @layer components
4
+ *
5
+ * Two photos of the same view with a divider you drag: a driveway before and
6
+ * after cleaning, a kitchen before and after a renovation, a garden through
7
+ * the seasons.
8
+ *
9
+ * Progressive enhancement: without JavaScript the two photos sit side by side
10
+ * (stacked on a phone), each with its label. With assets/js/compare.js they
11
+ * overlap and a slider moves the divider: drag or tap anywhere on the photo,
12
+ * or focus it and use the arrow keys (Page Up / Page Down for big steps).
13
+ * Printing shows both photos side by side again.
14
+ *
15
+ * Usage:
16
+ * <figure class="compare" data-compare>
17
+ * <div class="compare__stage">
18
+ * <div class="compare__before">
19
+ * <img src="driveway-before.jpg" alt="Driveway before cleaning, black mould along the joints"
20
+ * width="1200" height="800" loading="lazy">
21
+ * <span class="compare__label">Before</span>
22
+ * </div>
23
+ * <div class="compare__after">
24
+ * <img src="driveway-after.jpg" alt="The same driveway after cleaning"
25
+ * width="1200" height="800" loading="lazy">
26
+ * <span class="compare__label">After</span>
27
+ * </div>
28
+ * </div>
29
+ * <figcaption class="compare__caption">Driveway · Photos: the pro's own</figcaption>
30
+ * </figure>
31
+ * <script src="assets/js/compare.js" defer></script>
32
+ *
33
+ * Options on .compare:
34
+ * data-start="30" where the divider starts, 0–100 (default 50)
35
+ * data-compare-label="…" the slider's accessible name (default "Compare before and after")
36
+ * style="--compare-aspect: 4 / 3" crop both photos to one shape (default: the photos' own)
37
+ * Both photos should show the same view at the same size.
38
+ */
39
+
40
+ @layer components {
41
+ .compare {
42
+ margin: 0;
43
+ display: flex;
44
+ flex-direction: column;
45
+ gap: var(--space-2);
46
+ min-inline-size: 0;
47
+ }
48
+
49
+ /* Without the script: side by side, stacked when narrow */
50
+ .compare__stage {
51
+ display: grid;
52
+ grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
53
+ gap: var(--space-3);
54
+ }
55
+
56
+ .compare__before,
57
+ .compare__after {
58
+ position: relative;
59
+ margin: 0;
60
+ min-inline-size: 0;
61
+ border-radius: var(--radius-md);
62
+ overflow: hidden;
63
+ background: var(--color-surface);
64
+ }
65
+
66
+ .compare__before img,
67
+ .compare__after img {
68
+ display: block;
69
+ inline-size: 100%;
70
+ block-size: auto;
71
+ aspect-ratio: var(--compare-aspect, auto);
72
+ object-fit: cover;
73
+ }
74
+
75
+ /* Photos vary, so labels carry their own dark backing: readable on any image */
76
+ .compare__label {
77
+ position: absolute;
78
+ inset-block-start: var(--space-2);
79
+ inset-inline-start: var(--space-2);
80
+ z-index: 1;
81
+ padding: var(--space-1) var(--space-2);
82
+ border-radius: var(--radius-sm);
83
+ background: oklch(0% 0 0 / 0.65);
84
+ color: oklch(100% 0 0);
85
+ font-size: var(--font-size-xs);
86
+ font-weight: 600;
87
+ line-height: 1.2;
88
+ letter-spacing: 0.04em;
89
+ text-transform: uppercase;
90
+ pointer-events: none;
91
+ }
92
+
93
+ .compare__caption {
94
+ font-size: var(--font-size-sm);
95
+ color: var(--color-text-muted);
96
+ line-height: var(--leading-snug);
97
+ overflow-wrap: anywhere;
98
+ }
99
+
100
+
101
+ /* ========================================
102
+ WITH THE SCRIPT: one frame, a divider
103
+ ======================================== */
104
+
105
+ .compare[data-compare-ready] .compare__stage {
106
+ display: block;
107
+ position: relative;
108
+ border-radius: var(--radius-md);
109
+ overflow: hidden;
110
+ isolation: isolate;
111
+ }
112
+
113
+ .compare[data-compare-ready] .compare__before,
114
+ .compare[data-compare-ready] .compare__after {
115
+ border-radius: 0;
116
+ }
117
+
118
+ .compare[data-compare-ready] .compare__after {
119
+ position: absolute;
120
+ inset: 0;
121
+ /* clip-path has no logical form: the after photo shows on the inline-end side */
122
+ clip-path: inset(0 0 0 var(--compare-pos, 50%));
123
+ }
124
+
125
+ .compare[data-compare-ready]:dir(rtl) .compare__after {
126
+ clip-path: inset(0 var(--compare-pos, 50%) 0 0);
127
+ }
128
+
129
+ .compare[data-compare-ready] .compare__after img {
130
+ block-size: 100%;
131
+ }
132
+
133
+ .compare[data-compare-ready] .compare__after .compare__label {
134
+ inset-inline-start: auto;
135
+ inset-inline-end: var(--space-2);
136
+ }
137
+
138
+ .compare__handle {
139
+ position: absolute;
140
+ inset-block: 0;
141
+ inset-inline-start: var(--compare-pos, 50%);
142
+ z-index: 2;
143
+ inline-size: 2px;
144
+ margin-inline-start: -1px;
145
+ display: flex;
146
+ align-items: center;
147
+ justify-content: center; /* the knob is wider than the line and overflows both sides equally */
148
+ background: oklch(100% 0 0);
149
+ box-shadow: 0 0 0 1px oklch(0% 0 0 / 0.35);
150
+ pointer-events: none;
151
+ }
152
+
153
+ .compare__knob {
154
+ flex: none;
155
+ display: grid;
156
+ place-items: center;
157
+ inline-size: 2.75rem;
158
+ block-size: 2.75rem;
159
+ border: var(--border-width-thick) solid oklch(100% 0 0);
160
+ border-radius: var(--radius-full);
161
+ background: oklch(0% 0 0 / 0.55);
162
+ color: oklch(100% 0 0);
163
+ font-size: var(--font-size-sm);
164
+ font-weight: 700;
165
+ line-height: 1;
166
+ box-shadow: var(--shadow-md);
167
+ }
168
+
169
+ /* The real control: a native range input over the whole photo, invisible */
170
+ .compare .compare__range {
171
+ position: absolute;
172
+ inset: 0;
173
+ z-index: 3;
174
+ inline-size: 100%;
175
+ block-size: 100%;
176
+ margin: 0;
177
+ padding: 0;
178
+ opacity: 0;
179
+ cursor: ew-resize;
180
+ touch-action: pan-y; /* a vertical swipe still scrolls the page */
181
+ }
182
+
183
+ .compare:has(.compare__range:hover) .compare__knob {
184
+ background: oklch(0% 0 0 / 0.8);
185
+ }
186
+
187
+ /* White ring with a dark halo: visible on light and dark photos alike */
188
+ .compare:has(.compare__range:focus-visible) .compare__knob {
189
+ outline: 3px solid oklch(100% 0 0);
190
+ outline-offset: 2px;
191
+ box-shadow: 0 0 0 7px oklch(0% 0 0 / 0.6);
192
+ }
193
+
194
+ @media (forced-colors: active) {
195
+ .compare__handle {
196
+ background: CanvasText;
197
+ }
198
+
199
+ .compare__knob,
200
+ .compare__label {
201
+ border: var(--border-width-thick) solid CanvasText;
202
+ background: Canvas;
203
+ color: CanvasText;
204
+ }
205
+
206
+ .compare:has(.compare__range:focus-visible) .compare__knob {
207
+ outline-color: Highlight;
208
+ }
209
+ }
210
+
211
+ @media print {
212
+ .compare[data-compare-ready] .compare__stage {
213
+ display: grid;
214
+ grid-template-columns: 1fr 1fr;
215
+ gap: var(--space-3);
216
+ overflow: visible;
217
+ }
218
+
219
+ .compare[data-compare-ready] .compare__after {
220
+ position: relative;
221
+ clip-path: none;
222
+ }
223
+
224
+ .compare[data-compare-ready] .compare__after .compare__label {
225
+ inset-inline-start: var(--space-2);
226
+ inset-inline-end: auto;
227
+ }
228
+
229
+ .compare__handle,
230
+ .compare .compare__range {
231
+ display: none;
232
+ }
233
+ }
234
+ }
@@ -76,22 +76,19 @@
76
76
  overflow-y: auto;
77
77
 
78
78
  /* Visual */
79
- background: var(--color-surface-raised);
80
- border: var(--border-width) solid var(--color-border-subtle);
81
- border-radius: var(--radius-lg);
82
- box-shadow: var(--shadow-lg);
79
+ background: var(--color-background);
80
+ border: var(--border-width) solid var(--color-border-strong);
81
+ border-radius: var(--radius-card);
83
82
  padding: var(--space-1);
84
83
 
85
84
  /* Hidden by default */
86
85
  opacity: 0;
87
86
  visibility: hidden;
88
- transform: translateY(-4px) scale(0.98);
89
87
  pointer-events: none;
90
88
 
91
89
  /* Transitions */
92
90
  transition:
93
91
  opacity var(--duration-fast) var(--ease-fluid),
94
- transform var(--duration-fast) var(--ease-settle),
95
92
  visibility var(--duration-fast) var(--ease-fluid);
96
93
  }
97
94
 
@@ -102,7 +99,6 @@
102
99
  .dropdown[data-open] > .dropdown__menu {
103
100
  opacity: 1;
104
101
  visibility: visible;
105
- transform: translateY(0) scale(1);
106
102
  pointer-events: auto;
107
103
  }
108
104
 
@@ -131,14 +127,12 @@
131
127
  .dropdown[data-position="top"] .dropdown__menu {
132
128
  inset-block-start: auto;
133
129
  inset-block-end: calc(100% + var(--space-1));
134
- transform: translateY(4px) scale(0.98);
135
130
  }
136
131
 
137
132
  .dropdown[data-position="top"]:hover > .dropdown__menu,
138
133
  .dropdown[data-position="top"]:focus-within > .dropdown__menu,
139
134
  .dropdown[data-position="top"][open] > .dropdown__menu,
140
135
  .dropdown[data-position="top"][data-open] > .dropdown__menu {
141
- transform: translateY(0) scale(1);
142
136
  }
143
137
 
144
138
  /* Top-end */
@@ -147,14 +141,12 @@
147
141
  inset-block-end: calc(100% + var(--space-1));
148
142
  inset-inline-start: auto;
149
143
  inset-inline-end: 0;
150
- transform: translateY(4px) scale(0.98);
151
144
  }
152
145
 
153
146
  .dropdown[data-position="top-end"]:hover > .dropdown__menu,
154
147
  .dropdown[data-position="top-end"]:focus-within > .dropdown__menu,
155
148
  .dropdown[data-position="top-end"][open] > .dropdown__menu,
156
149
  .dropdown[data-position="top-end"][data-open] > .dropdown__menu {
157
- transform: translateY(0) scale(1);
158
150
  }
159
151
 
160
152
 
@@ -181,7 +173,7 @@
181
173
  align-items: center;
182
174
  gap: var(--space-3);
183
175
  padding: var(--space-2) var(--space-3);
184
- border-radius: var(--radius-md);
176
+ border-radius: var(--radius-control);
185
177
  font-size: var(--font-size-sm);
186
178
  color: var(--color-text);
187
179
  text-decoration: none;
@@ -193,20 +185,20 @@
193
185
  }
194
186
 
195
187
  .dropdown__item:hover {
196
- background: color-mix(in oklch, var(--accent) 10%, var(--color-background));
197
- color: var(--accent);
188
+ background: color-mix(in oklab, var(--accent) 10%, var(--color-background));
189
+ color: var(--accent-ink);
198
190
  }
199
191
 
200
192
  .dropdown__item:focus-visible {
201
- outline: 2px solid var(--color-focus);
193
+ outline: var(--focus-ring-width) solid var(--color-focus);
202
194
  outline-offset: -2px;
203
195
  }
204
196
 
205
197
  /* Active/selected item */
206
198
  .dropdown__item[aria-selected="true"],
207
199
  .dropdown__item[data-active] {
208
- background: color-mix(in oklch, var(--accent) 12%, var(--color-background));
209
- color: var(--accent);
200
+ background: color-mix(in oklab, var(--accent) 12%, var(--color-background));
201
+ color: var(--accent-ink);
210
202
  font-weight: var(--weight-medium);
211
203
  }
212
204
 
@@ -277,59 +269,10 @@
277
269
  }
278
270
 
279
271
 
280
- /* ========================================
281
- THEME-SPECIFIC STYLES
282
- ======================================== */
283
-
284
- /* Still: no animation */
285
- [data-motion="still"] .dropdown__menu {
286
- transition: none;
287
- }
288
-
289
- [data-motion="still"] .dropdown__chevron {
290
- transition: none;
291
- }
292
-
293
- /* Serene: extra rounded */
294
- [data-motion="serene"] .dropdown__menu {
295
- border-radius: var(--radius-xl);
296
- }
297
-
298
- [data-motion="serene"] .dropdown__item {
299
- border-radius: var(--radius-lg);
300
- }
301
-
302
- /* Cascade: bouncy */
303
- [data-motion="cascade"] .dropdown__menu {
304
- border-radius: var(--radius-xl);
305
- }
306
-
307
- /* Rapids: offset shadow */
308
- [data-motion="rapids"] .dropdown__menu {
309
- box-shadow: var(--shadow-offset);
310
- }
311
-
312
- /* Tsunami: asymmetric */
313
- [data-motion="tsunami"] .dropdown__menu {
314
- border-radius: var(--radius-asymmetric, 0 24px 0 0);
315
- }
316
-
317
272
 
318
273
  /* ========================================
319
274
  REDUCED MOTION
320
275
  ======================================== */
321
276
 
322
- @media (prefers-reduced-motion: reduce) {
323
- .dropdown__menu {
324
- transition: none;
325
- }
326
-
327
- .dropdown__chevron {
328
- transition: none;
329
- }
330
-
331
- .dropdown__item {
332
- transition: none;
333
- }
334
- }
277
+ /* Reduced motion: the reset shortens every transition. */
335
278
  }
@@ -49,6 +49,7 @@
49
49
  }
50
50
 
51
51
  .empty-state__title {
52
+ font-family: var(--font-heading);
52
53
  font-size: var(--font-size-lg);
53
54
  font-weight: var(--weight-semibold);
54
55
  color: var(--color-text);
@@ -102,4 +103,7 @@
102
103
  .empty-state[data-size="lg"] .empty-state__title {
103
104
  font-size: var(--font-size-xl);
104
105
  }
106
+
107
+
108
+
105
109
  }