@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.
Files changed (80) hide show
  1. package/AGENTS.md +6 -29
  2. package/CHANGELOG.md +543 -2
  3. package/CLAUDE.md +193 -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.min.css +2 -0
  14. package/dist/fluid-legacy-1x.css +3 -0
  15. package/dist/fluid-nav.min.css +3 -0
  16. package/dist/fluid-toc.min.css +3 -0
  17. package/dist/fluid-zero.min.css +3 -0
  18. package/dist/fluid.min.css +3 -2
  19. package/dist/fonts/OFL-newsreader.txt +93 -0
  20. package/dist/fonts/OFL-schibsted-grotesk.txt +93 -0
  21. package/dist/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
  22. package/dist/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
  23. package/dist/fonts/schibsted-grotesk-latin-wght-italic.woff2 +0 -0
  24. package/dist/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
  25. package/fluid-agent-kit/README.md +1 -0
  26. package/fluid-agent-kit/skills/accessibility.md +3 -1
  27. package/fluid-agent-kit/skills/css-conventions.md +22 -5
  28. package/fluid-agent-kit/skills/image-optimization.md +2 -0
  29. package/fluid-agent-kit/skills/preset-composition.md +108 -0
  30. package/package.json +29 -3
  31. package/src/animations/scroll-reveal.css +75 -193
  32. package/src/components/accordion.css +6 -47
  33. package/src/components/alert.css +47 -88
  34. package/src/components/avatar.css +4 -20
  35. package/src/components/badge.css +25 -48
  36. package/src/components/button.css +69 -175
  37. package/src/components/card.css +146 -481
  38. package/src/components/chip.css +46 -12
  39. package/src/components/compare.css +234 -0
  40. package/src/components/dropdown.css +10 -67
  41. package/src/components/empty-state.css +4 -0
  42. package/src/components/form.css +113 -81
  43. package/src/components/gallery.css +252 -0
  44. package/src/components/hero.css +203 -88
  45. package/src/components/indicator.css +23 -117
  46. package/src/components/loading.css +7 -29
  47. package/src/components/modal.css +12 -65
  48. package/src/components/nav-modes.css +261 -0
  49. package/src/components/nav.css +324 -392
  50. package/src/components/search-input.css +4 -2
  51. package/src/components/step-indicator.css +26 -27
  52. package/src/components/table.css +64 -171
  53. package/src/components/toc.css +254 -0
  54. package/src/components/tooltip.css +5 -46
  55. package/src/core/base.css +393 -547
  56. package/src/core/reset.css +17 -5
  57. package/src/core/tokens.css +426 -2276
  58. package/src/fluid.css +258 -17
  59. package/src/fonts/OFL-newsreader.txt +93 -0
  60. package/src/fonts/OFL-schibsted-grotesk.txt +93 -0
  61. package/src/fonts/fluid-fonts.css +55 -0
  62. package/src/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
  63. package/src/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
  64. package/src/fonts/schibsted-grotesk-latin-wght-italic.woff2 +0 -0
  65. package/src/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
  66. package/src/layouts/positioning.css +6 -3
  67. package/src/legacy-1x.css +61 -0
  68. package/src/sections/cta.css +33 -101
  69. package/src/sections/features.css +42 -219
  70. package/src/sections/footer.css +53 -134
  71. package/src/sections/stats.css +40 -153
  72. package/src/sections/team.css +24 -113
  73. package/src/sections/testimonials.css +34 -148
  74. package/src/zero/base.css +166 -0
  75. package/src/zero/tokens.css +64 -0
  76. package/src/zero.css +20 -0
  77. package/src/components/scroll-progress.css +0 -104
  78. package/src/components/settings-panel.css +0 -603
  79. package/src/components/themed-images.css +0 -229
  80. package/src/components/version-badge.css +0 -70
@@ -39,8 +39,8 @@
39
39
  inline-size: var(--_avatar-size);
40
40
  block-size: var(--_avatar-size);
41
41
  border-radius: var(--radius-full);
42
- background: color-mix(in oklch, var(--accent) 20%, var(--color-surface));
43
- color: var(--accent);
42
+ background: color-mix(in oklab, var(--accent) 20%, var(--color-surface));
43
+ color: var(--accent-ink);
44
44
  font-weight: var(--weight-semibold);
45
45
  font-size: calc(var(--_avatar-size) * 0.4);
46
46
  line-height: 1;
@@ -106,7 +106,7 @@
106
106
  inline-size: calc(var(--_avatar-size) * 0.3);
107
107
  block-size: calc(var(--_avatar-size) * 0.3);
108
108
  border-radius: var(--radius-full);
109
- border: 2px solid var(--color-background);
109
+ border: var(--border-width-thick) solid var(--color-background);
110
110
  background: var(--color-text-subtle);
111
111
  }
112
112
 
@@ -144,17 +144,13 @@
144
144
 
145
145
  .avatar-group .avatar {
146
146
  box-shadow: 0 0 0 2px var(--color-background);
147
- transition: transform var(--duration-fast) var(--ease-settle);
148
147
  }
149
148
 
150
149
  .avatar-group .avatar + .avatar {
151
150
  margin-inline-start: calc(var(--_avatar-size) * -0.3);
152
151
  }
153
152
 
154
- .avatar-group .avatar:hover {
155
- z-index: var(--z-raised);
156
- transform: scale(1.1);
157
- }
153
+ .avatar-group .avatar:hover { z-index: var(--z-raised); }
158
154
 
159
155
  /* Overflow counter: +5 more */
160
156
  .avatar-group__overflow {
@@ -176,17 +172,5 @@
176
172
  }
177
173
 
178
174
 
179
- /* ========================================
180
- THEME-SPECIFIC STYLES
181
- ======================================== */
182
-
183
- /* Tsunami: asymmetric corners on square */
184
- [data-motion="tsunami"] .avatar[data-shape="square"] {
185
- border-radius: var(--radius-asymmetric, 0 12px 0 0);
186
- }
187
175
 
188
- /* Rapids: hard shadow on group */
189
- [data-motion="rapids"] .avatar-group .avatar {
190
- box-shadow: 2px 2px 0 oklch(0 0 0 / 0.1), 0 0 0 2px var(--color-background);
191
- }
192
176
  }
@@ -21,23 +21,21 @@
21
21
  BASE BADGE
22
22
  ======================================== */
23
23
 
24
+ /* The label voice in a 1px box: square (--radius-control), transparent. */
24
25
  .badge {
25
26
  display: inline-flex;
26
27
  align-items: center;
27
28
  gap: var(--space-1);
28
- padding: var(--space-1) var(--space-3);
29
- font-size: var(--font-size-xs);
30
- font-weight: var(--weight-semibold);
31
- line-height: var(--leading-tight);
32
- letter-spacing: var(--tracking-wide);
29
+ padding: 0.35em 0.6em;
30
+ font: calc(600 + var(--_dark-weight)) var(--step--2) / 1.2 var(--font-body);
31
+ letter-spacing: var(--tracking-caps);
33
32
  text-transform: uppercase;
34
- border-radius: var(--radius-full);
33
+ border: var(--border-width) solid currentColor;
34
+ border-radius: var(--radius-control);
35
35
  white-space: nowrap;
36
36
  vertical-align: middle;
37
-
38
- /* Default: accent-tinted */
39
- color: var(--accent);
40
- background: var(--accent-subtle);
37
+ color: var(--color-text);
38
+ background: transparent;
41
39
  }
42
40
 
43
41
 
@@ -47,8 +45,9 @@
47
45
 
48
46
  /* Filled - solid accent background */
49
47
  .badge[data-variant="filled"] {
50
- color: var(--white);
48
+ color: var(--on-accent);
51
49
  background: var(--accent);
50
+ border-color: transparent;
52
51
  }
53
52
 
54
53
  /* Outline - border only */
@@ -61,6 +60,7 @@
61
60
  .badge[data-variant="muted"] {
62
61
  color: var(--color-text-muted);
63
62
  background: var(--color-surface);
63
+ border-color: transparent;
64
64
  }
65
65
 
66
66
 
@@ -69,6 +69,8 @@
69
69
  Semantic states for indicators
70
70
  ======================================== */
71
71
 
72
+ /* The status colours are text colours (4.5:1 on their own tint in light
73
+ and dark); filled badges use the status fill and its on-colour. */
72
74
  .badge[data-status="good"] {
73
75
  color: var(--color-success);
74
76
  background: var(--color-success-subtle);
@@ -89,25 +91,24 @@
89
91
  background: var(--color-info-subtle);
90
92
  }
91
93
 
92
- /* Status + filled combo */
93
94
  .badge[data-status="good"][data-variant="filled"] {
94
- color: var(--white);
95
- background: var(--color-success);
95
+ color: var(--color-success-on);
96
+ background: var(--color-success-fill);
96
97
  }
97
98
 
98
99
  .badge[data-status="warning"][data-variant="filled"] {
99
- color: var(--white);
100
- background: var(--color-warning);
100
+ color: var(--color-warning-on);
101
+ background: var(--color-warning-fill);
101
102
  }
102
103
 
103
104
  .badge[data-status="error"][data-variant="filled"] {
104
- color: var(--white);
105
- background: var(--color-error);
105
+ color: var(--color-error-on);
106
+ background: var(--color-error-fill);
106
107
  }
107
108
 
108
109
  .badge[data-status="info"][data-variant="filled"] {
109
- color: var(--white);
110
- background: var(--color-info);
110
+ color: var(--color-info-on);
111
+ background: var(--color-info-fill);
111
112
  }
112
113
 
113
114
 
@@ -116,14 +117,13 @@
116
117
  ======================================== */
117
118
 
118
119
  .badge[data-size="sm"] {
119
- padding: var(--space-0-5) var(--space-2);
120
- font-size: var(--font-size-2xs, 0.6875rem);
121
- letter-spacing: var(--tracking-wider);
120
+ padding: 0.2em 0.45em;
121
+ font-size: 0.6875rem;
122
122
  }
123
123
 
124
124
  .badge[data-size="lg"] {
125
- padding: var(--space-2) var(--space-4);
126
- font-size: var(--font-size-sm);
125
+ padding: 0.5em 0.8em;
126
+ font-size: var(--step--1);
127
127
  }
128
128
 
129
129
 
@@ -151,32 +151,9 @@
151
151
  min-inline-size: 1.5rem;
152
152
  justify-content: center;
153
153
  padding: var(--space-1);
154
- border-radius: var(--radius-full);
155
154
  font-variant-numeric: tabular-nums;
156
155
  }
157
156
 
158
157
 
159
- /* ========================================
160
- THEME-SPECIFIC STYLES
161
- ======================================== */
162
-
163
- /* Still: square badges */
164
- [data-motion="still"] .badge {
165
- border-radius: 0;
166
- letter-spacing: var(--tracking-wider);
167
- }
168
-
169
- /* Brutalist: hard edges, bold */
170
- [data-motion="brutalist"] .badge {
171
- border-radius: 0;
172
- text-transform: uppercase;
173
- font-weight: var(--weight-bold);
174
- border: 2px solid currentColor;
175
- background: transparent;
176
- }
177
158
 
178
- /* Tsunami: asymmetric corners */
179
- [data-motion="tsunami"] .badge {
180
- border-radius: var(--radius-asymmetric, 0 12px 0 0);
181
- }
182
159
  }
@@ -15,79 +15,51 @@
15
15
  */
16
16
 
17
17
  @layer components {
18
- /* Base button - the foundation */
18
+ /* Base button: sans 600, square, no shadow, no transform. Colour comes
19
+ through the --_btn-* hooks, so a band (data-bg="inverse|accent-strong",
20
+ a themed hero) re-points <button> and .button alike. */
19
21
  button,
20
22
  [role="button"],
21
23
  .button {
22
- /* Reset */
23
24
  appearance: none;
24
- border: none;
25
- background: none;
26
-
27
- /* Layout */
28
25
  display: inline-flex;
29
26
  align-items: center;
30
27
  justify-content: center;
31
28
  gap: var(--space-2);
32
-
33
- /* Sizing */
34
- padding-block: var(--_btn-padding-block, var(--space-3));
35
- padding-inline: var(--_btn-padding-inline, var(--space-5));
36
- min-block-size: var(--_btn-min-height, 2.75rem);
37
-
38
- /* Typography */
39
- font-family: inherit;
40
- font-size: var(--_btn-font-size, var(--font-size-base));
41
- font-weight: var(--weight-medium);
29
+ padding-block: var(--_btn-padding-block, 0.9em);
30
+ padding-inline: var(--_btn-padding-inline, 1.6em);
31
+ min-block-size: var(--_btn-min-height, 3rem);
32
+ font-family: var(--font-body);
33
+ font-size: var(--_btn-font-size, var(--step-0));
34
+ font-weight: calc(var(--weight-semibold) + var(--_dark-weight));
35
+ letter-spacing: 0.01em;
42
36
  line-height: var(--leading-none);
43
37
  text-decoration: none;
44
38
  white-space: nowrap;
45
-
46
- /* Visual */
47
- color: var(--_btn-color, var(--white));
48
- background-color: var(--_btn-bg, var(--accent));
39
+ color: var(--_btn-color, var(--on-accent-fill));
40
+ background-color: var(--_btn-bg, var(--accent-fill));
49
41
  border: var(--border-width) solid var(--_btn-border, transparent);
50
- border-radius: var(--radius-button, var(--radius-md));
51
- box-shadow: var(--_btn-shadow, var(--shadow-xs)); /* Subtle depth at rest */
42
+ border-radius: var(--radius-control);
52
43
  cursor: pointer;
53
-
54
- /* Transitions - smooth like flowing water */
55
44
  transition:
56
- background-color var(--duration-normal) var(--ease-fluid),
57
- border-color var(--duration-normal) var(--ease-fluid),
58
- color var(--duration-normal) var(--ease-fluid),
59
- box-shadow var(--duration-normal) var(--ease-fluid),
60
- transform var(--duration-fast) var(--ease-settle);
45
+ background-color var(--duration-fast) var(--ease-fluid),
46
+ border-color var(--duration-fast) var(--ease-fluid),
47
+ color var(--duration-fast) var(--ease-fluid),
48
+ text-decoration-color var(--duration-fast) var(--ease-fluid);
61
49
  }
62
50
 
63
- /* Hover state - gentle lift */
64
- button:hover:not(:disabled),
65
- [role="button"]:hover:not(:disabled),
66
- .button:hover:not(:disabled) {
67
- background-color: var(--_btn-bg-hover, var(--accent-hover));
68
- box-shadow: var(--shadow-sm);
51
+ :is(button, [role="button"], .button):hover:not(:disabled) {
52
+ color: var(--_btn-color-hover, var(--_btn-color, var(--on-accent-fill)));
53
+ background-color: var(--_btn-bg-hover, var(--accent-fill-hover));
69
54
  }
70
55
 
71
- /* Active state - subtle press */
72
- button:active:not(:disabled),
73
- [role="button"]:active:not(:disabled),
74
- .button:active:not(:disabled) {
75
- transform: scale(0.98);
76
- box-shadow: none;
56
+ /* Focus: a real outline, so no shadow a site adds can hide it (#50),
57
+ and it survives forced-colors mode. */
58
+ :is(button, [role="button"], .button):focus-visible {
59
+ outline: var(--focus-ring-width) solid var(--color-focus);
60
+ outline-offset: 2px;
77
61
  }
78
62
 
79
- /* Focus state - clear ring */
80
- button:focus-visible,
81
- [role="button"]:focus-visible,
82
- .button:focus-visible {
83
- outline: 2px solid transparent;
84
- box-shadow:
85
- var(--shadow-glow),
86
- 0 0 0 2px var(--color-background),
87
- 0 0 0 4px var(--accent);
88
- }
89
-
90
- /* Disabled state */
91
63
  button:disabled,
92
64
  [role="button"][aria-disabled="true"],
93
65
  .button:disabled {
@@ -99,54 +71,60 @@
99
71
 
100
72
  /* ========================================
101
73
  VARIANTS
102
- Each with its own personality
103
74
  ======================================== */
104
75
 
105
- /* Secondary - understated, supportive */
106
- button[data-variant="secondary"],
107
- .button[data-variant="secondary"] {
76
+ :is(button, .button)[data-variant="secondary"] {
108
77
  --_btn-color: var(--color-text);
109
78
  --_btn-bg: var(--color-surface);
110
79
  --_btn-bg-hover: var(--color-surface-raised);
111
80
  --_btn-border: var(--color-border);
112
81
  }
113
82
 
114
- button[data-variant="secondary"]:hover:not(:disabled),
115
- .button[data-variant="secondary"]:hover:not(:disabled) {
116
- --_btn-border: var(--color-text-subtle);
83
+ /* Outline: an ink edge; hover inverts to an ink fill. */
84
+ :is(button, .button)[data-variant="outline"] {
85
+ --_btn-color: var(--color-text);
86
+ --_btn-bg: transparent;
87
+ --_btn-border: var(--color-border-strong);
88
+ --_btn-bg-hover: var(--color-text);
89
+ --_btn-color-hover: var(--color-background);
117
90
  }
118
91
 
119
- /* Ghost - minimal, text-like */
120
- button[data-variant="ghost"],
121
- .button[data-variant="ghost"] {
92
+ /* Ghost: underlined text and an arrow that steps forward on hover.
93
+ data-arrow="none" drops the arrow. */
94
+ :is(button, .button)[data-variant="ghost"] {
122
95
  --_btn-color: var(--color-text);
123
96
  --_btn-bg: transparent;
124
- --_btn-bg-hover: var(--color-surface);
125
- --_btn-border: transparent;
126
- --_btn-shadow: none; /* No shadow for ghost buttons */
97
+ --_btn-bg-hover: transparent;
98
+ --_btn-padding-inline: 0;
99
+ text-decoration-line: underline;
100
+ text-decoration-color: color-mix(in oklch, var(--accent-ink) 55%, transparent);
101
+ text-decoration-thickness: 0.06em;
102
+ text-underline-offset: 0.22em;
127
103
  }
128
104
 
129
- /* Outline - bordered, no fill */
130
- button[data-variant="outline"],
131
- .button[data-variant="outline"] {
132
- --_btn-color: var(--accent);
133
- --_btn-bg: transparent;
134
- --_btn-bg-hover: var(--accent-subtle);
135
- --_btn-border: var(--accent);
136
- --_btn-shadow: none; /* Border provides visual boundary */
105
+ :is(button, .button)[data-variant="ghost"]:hover {
106
+ text-decoration-color: var(--accent-ink);
137
107
  }
138
108
 
139
- /* Danger - for destructive actions */
140
- button[data-variant="danger"],
141
- .button[data-variant="danger"] {
142
- --_btn-color: var(--white);
143
- --_btn-bg: var(--color-error);
144
- --_btn-bg-hover: color-mix(in oklch, var(--color-error) 85%, var(--black));
109
+ :is(button, .button)[data-variant="ghost"]:not([data-icon], [data-arrow="none"], [aria-current], [aria-disabled="true"])::after {
110
+ content: "→";
111
+ transition: translate var(--duration-fast) var(--ease-settle);
145
112
  }
146
113
 
147
- /* Subtle danger - less alarming */
148
- button[data-variant="danger-subtle"],
149
- .button[data-variant="danger-subtle"] {
114
+ :is(button, .button)[data-variant="ghost"]:dir(rtl)::after { content: "←"; }
115
+
116
+ @media (prefers-reduced-motion: no-preference) {
117
+ :is(button, .button)[data-variant="ghost"]:hover::after { translate: 0.2em; }
118
+ :is(button, .button)[data-variant="ghost"]:dir(rtl):hover::after { translate: -0.2em; }
119
+ }
120
+
121
+ :is(button, .button)[data-variant="danger"] {
122
+ --_btn-color: var(--color-error-on);
123
+ --_btn-bg: var(--color-error-fill);
124
+ --_btn-bg-hover: color-mix(in oklch, var(--color-error-fill) 85%, var(--black));
125
+ }
126
+
127
+ :is(button, .button)[data-variant="danger-subtle"] {
150
128
  --_btn-color: var(--color-error);
151
129
  --_btn-bg: var(--color-error-subtle);
152
130
  --_btn-bg-hover: color-mix(in oklch, var(--color-error-subtle) 80%, var(--color-error));
@@ -165,7 +143,6 @@
165
143
  --_btn-padding-inline: var(--space-2);
166
144
  --_btn-font-size: var(--font-size-xs);
167
145
  --_btn-min-height: 1.75rem;
168
- border-radius: var(--radius-sm);
169
146
  }
170
147
 
171
148
  /* Small */
@@ -184,7 +161,6 @@
184
161
  --_btn-padding-inline: var(--space-6);
185
162
  --_btn-font-size: var(--font-size-lg);
186
163
  --_btn-min-height: 3.25rem;
187
- border-radius: var(--radius-lg);
188
164
  }
189
165
 
190
166
  /* Extra large */
@@ -194,7 +170,6 @@
194
170
  --_btn-padding-inline: var(--space-8);
195
171
  --_btn-font-size: var(--font-size-xl);
196
172
  --_btn-min-height: 4rem;
197
- border-radius: var(--radius-lg);
198
173
  }
199
174
 
200
175
 
@@ -219,7 +194,7 @@
219
194
  /* Pill shape */
220
195
  button[data-pill],
221
196
  .button[data-pill] {
222
- border-radius: var(--radius-full);
197
+ border-radius: var(--radius-pill);
223
198
  }
224
199
 
225
200
  /* Loading state */
@@ -240,11 +215,11 @@
240
215
  block-size: 1.25em;
241
216
  margin-inline-start: -0.625em;
242
217
  margin-block-start: -0.625em;
243
- border: 2px solid currentColor;
218
+ border: var(--border-width-thick) solid currentColor;
244
219
  border-inline-end-color: transparent;
245
220
  border-radius: var(--radius-full);
246
221
  animation: button-spin 0.6s linear infinite;
247
- color: var(--_btn-color, var(--white));
222
+ color: var(--_btn-color, var(--on-accent));
248
223
  opacity: 0.8;
249
224
  }
250
225
 
@@ -255,50 +230,6 @@
255
230
  }
256
231
 
257
232
 
258
- /* ========================================
259
- TSUNAMI MOTION EFFECTS
260
- Bold, wave-like interactions
261
- Uses transform only to avoid CLS
262
- ======================================== */
263
-
264
- /* Tsunami button hover - noticeable growth like a wave rising */
265
- [data-motion="tsunami"] button:hover:not(:disabled),
266
- [data-motion="tsunami"] [role="button"]:hover:not(:disabled),
267
- [data-motion="tsunami"] .button:hover:not(:disabled) {
268
- transform: scale(1.08);
269
- box-shadow: var(--shadow-lg);
270
- transition:
271
- transform var(--duration-normal) var(--ease-fluid),
272
- box-shadow var(--duration-normal) var(--ease-fluid),
273
- background-color var(--duration-normal) var(--ease-fluid);
274
- }
275
-
276
- /* Tsunami button active/click - crash down effect */
277
- [data-motion="tsunami"] button:active:not(:disabled),
278
- [data-motion="tsunami"] [role="button"]:active:not(:disabled),
279
- [data-motion="tsunami"] .button:active:not(:disabled) {
280
- transform: scale(0.92) translateY(4px);
281
- box-shadow: var(--shadow-xs);
282
- transition:
283
- transform 150ms var(--ease-settle),
284
- box-shadow 150ms var(--ease-settle);
285
- }
286
-
287
- /* Tsunami button leave - wave crash with bounce settle */
288
- @keyframes tsunami-button-settle {
289
- 0% { transform: scale(1.08); }
290
- 40% { transform: scale(0.95) translateY(3px); }
291
- 70% { transform: scale(1.02) translateY(-1px); }
292
- 100% { transform: scale(1) translateY(0); }
293
- }
294
-
295
- [data-motion="tsunami"] button:not(:hover):not(:active):not(:disabled),
296
- [data-motion="tsunami"] [role="button"]:not(:hover):not(:active):not([aria-disabled="true"]),
297
- [data-motion="tsunami"] .button:not(:hover):not(:active):not(:disabled) {
298
- animation: tsunami-button-settle var(--duration-normal) var(--ease-settle);
299
- }
300
-
301
-
302
233
  /* ========================================
303
234
  BUTTON GROUPS
304
235
  Multiple buttons together
@@ -317,14 +248,14 @@
317
248
 
318
249
  .button-group > button:first-child,
319
250
  .button-group > .button:first-child {
320
- border-start-start-radius: var(--radius-md);
321
- border-end-start-radius: var(--radius-md);
251
+ border-start-start-radius: var(--radius-control);
252
+ border-end-start-radius: var(--radius-control);
322
253
  }
323
254
 
324
255
  .button-group > button:last-child,
325
256
  .button-group > .button:last-child {
326
- border-start-end-radius: var(--radius-md);
327
- border-end-end-radius: var(--radius-md);
257
+ border-start-end-radius: var(--radius-control);
258
+ border-end-end-radius: var(--radius-control);
328
259
  }
329
260
 
330
261
  .button-group > button:not(:first-child),
@@ -345,43 +276,6 @@
345
276
  ======================================== */
346
277
 
347
278
  @media (prefers-reduced-motion: reduce) {
348
- button,
349
- [role="button"],
350
- .button {
351
- transition: none;
352
- }
353
-
354
- button:active:not(:disabled),
355
- [role="button"]:active:not(:disabled),
356
- .button:active:not(:disabled) {
357
- transform: none;
358
- }
359
-
360
- button[data-loading]::after,
361
- .button[data-loading]::after {
362
- animation: none;
363
- /* Static indicator instead of spinning */
364
- opacity: 0.6;
365
- }
366
-
367
- [data-motion="tsunami"] button:hover:not(:disabled),
368
- [data-motion="tsunami"] [role="button"]:hover:not(:disabled),
369
- [data-motion="tsunami"] .button:hover:not(:disabled) {
370
- transform: none;
371
- transition: none;
372
- }
373
-
374
- [data-motion="tsunami"] button:active:not(:disabled),
375
- [data-motion="tsunami"] [role="button"]:active:not(:disabled),
376
- [data-motion="tsunami"] .button:active:not(:disabled) {
377
- transform: none;
378
- transition: none;
379
- }
380
-
381
- [data-motion="tsunami"] button:not(:hover):not(:active):not(:disabled),
382
- [data-motion="tsunami"] [role="button"]:not(:hover):not(:active):not([aria-disabled="true"]),
383
- [data-motion="tsunami"] .button:not(:hover):not(:active):not(:disabled) {
384
- animation: none;
385
- }
279
+ :is(button, .button)[data-loading]::after { animation: none; opacity: 0.6; }
386
280
  }
387
281
  }