@crisp-ui-kit/crisp 0.57.0 → 0.57.1

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 (96) hide show
  1. package/dist/accentpicker.css +5 -0
  2. package/dist/accentpicker.d.ts +7 -0
  3. package/dist/accentpicker.layered.css +7 -0
  4. package/dist/avatar.css +1 -1
  5. package/dist/avatar.layered.css +1 -1
  6. package/dist/badge.css +2 -2
  7. package/dist/badge.layered.css +2 -2
  8. package/dist/button.css +3 -3
  9. package/dist/button.layered.css +3 -3
  10. package/dist/cjs/components/accentpicker/accentpicker.js +66 -0
  11. package/dist/cjs/components/accentpicker/accentpicker.recipe.js +25 -0
  12. package/dist/cjs/components/accentpicker/index.js +7 -0
  13. package/dist/cjs/components/avatar/avatar.recipe.js +4 -1
  14. package/dist/cjs/components/badge/badge.recipe.js +16 -2
  15. package/dist/cjs/components/button/button.recipe.js +16 -6
  16. package/dist/cjs/components/input/input.js +2 -2
  17. package/dist/cjs/components/input/input.recipe.js +8 -0
  18. package/dist/cjs/components/multiselect/multiselect.js +1 -1
  19. package/dist/cjs/components/multiselect/multiselect.recipe.js +12 -3
  20. package/dist/cjs/components/progress/progress.js +21 -4
  21. package/dist/cjs/components/progress/progress.recipe.js +30 -0
  22. package/dist/cjs/components/select/select.js +2 -2
  23. package/dist/cjs/components/select/select.recipe.js +32 -5
  24. package/dist/cjs/components/text/text.recipe.js +8 -7
  25. package/dist/cjs/components/textarea/textarea.js +3 -2
  26. package/dist/cjs/components/textarea/textarea.recipe.js +2 -1
  27. package/dist/cjs/components/textlink/textlink.recipe.js +6 -3
  28. package/dist/cjs/index.js +1 -0
  29. package/dist/cjs/product/recordpage/recordpage.js +46 -5
  30. package/dist/cjs/tokens/palette.js +79 -25
  31. package/dist/cjs/tokens/scale.js +1 -0
  32. package/dist/cjs/tokens/semantic.js +24 -0
  33. package/dist/esm/components/accentpicker/accentpicker.js +30 -0
  34. package/dist/esm/components/accentpicker/accentpicker.recipe.js +22 -0
  35. package/dist/esm/components/accentpicker/index.js +2 -0
  36. package/dist/esm/components/avatar/avatar.recipe.js +4 -1
  37. package/dist/esm/components/badge/badge.recipe.js +16 -2
  38. package/dist/esm/components/button/button.recipe.js +16 -6
  39. package/dist/esm/components/input/input.js +3 -3
  40. package/dist/esm/components/input/input.recipe.js +8 -0
  41. package/dist/esm/components/multiselect/multiselect.js +1 -1
  42. package/dist/esm/components/multiselect/multiselect.recipe.js +12 -3
  43. package/dist/esm/components/progress/progress.js +22 -5
  44. package/dist/esm/components/progress/progress.recipe.js +30 -0
  45. package/dist/esm/components/select/select.js +2 -2
  46. package/dist/esm/components/select/select.recipe.js +32 -5
  47. package/dist/esm/components/text/text.recipe.js +8 -7
  48. package/dist/esm/components/textarea/textarea.js +3 -2
  49. package/dist/esm/components/textarea/textarea.recipe.js +2 -1
  50. package/dist/esm/components/textlink/textlink.recipe.js +6 -3
  51. package/dist/esm/index.js +1 -0
  52. package/dist/esm/product/recordpage/recordpage.js +47 -6
  53. package/dist/esm/tokens/palette.js +79 -25
  54. package/dist/esm/tokens/scale.js +1 -0
  55. package/dist/esm/tokens/semantic.js +24 -0
  56. package/dist/input.css +7 -0
  57. package/dist/input.layered.css +7 -0
  58. package/dist/multiselect.css +4 -0
  59. package/dist/multiselect.d.ts +2 -2
  60. package/dist/multiselect.layered.css +4 -0
  61. package/dist/native/tokens.d.ts +1 -1
  62. package/dist/native/tokens.js +33 -22
  63. package/dist/progress.css +3 -0
  64. package/dist/progress.layered.css +3 -0
  65. package/dist/select.css +22 -2
  66. package/dist/select.d.ts +2 -2
  67. package/dist/select.layered.css +22 -2
  68. package/dist/styles.css +71 -23
  69. package/dist/styles.layered.css +71 -23
  70. package/dist/text.css +1 -1
  71. package/dist/text.layered.css +1 -1
  72. package/dist/textarea.css +2 -1
  73. package/dist/textarea.layered.css +2 -1
  74. package/dist/textlink.css +2 -2
  75. package/dist/textlink.layered.css +2 -2
  76. package/dist/tokens.css +18 -11
  77. package/dist/tokens.json +33 -22
  78. package/dist/types/components/accentpicker/accentpicker.d.ts +23 -0
  79. package/dist/types/components/accentpicker/accentpicker.recipe.d.ts +3 -0
  80. package/dist/types/components/accentpicker/index.d.ts +2 -0
  81. package/dist/types/components/button/button.recipe.d.ts +2 -2
  82. package/dist/types/components/input/input.d.ts +12 -0
  83. package/dist/types/components/multiselect/multiselect.d.ts +4 -3
  84. package/dist/types/components/multiselect/multiselect.recipe.d.ts +3 -0
  85. package/dist/types/components/progress/progress.d.ts +16 -4
  86. package/dist/types/components/progress/progress.recipe.d.ts +22 -0
  87. package/dist/types/components/select/select.d.ts +6 -5
  88. package/dist/types/components/select/select.recipe.d.ts +3 -0
  89. package/dist/types/components/textarea/textarea.d.ts +16 -0
  90. package/dist/types/index.d.ts +1 -0
  91. package/dist/types/product/recordpage/recordpage.d.ts +37 -1
  92. package/dist/types/tokens/contract.d.ts +4 -1
  93. package/dist/types/tokens/palette.d.ts +19 -11
  94. package/dist/types/tokens/scale.d.ts +1 -0
  95. package/dist/types/tokens/semantic.d.ts +15 -0
  96. package/package.json +6 -1
@@ -7,6 +7,13 @@
7
7
  & .crisp-input-value::placeholder { color: var(--crisp-fg-muted); }
8
8
  & .crisp-input-value:disabled { opacity: 0.5; cursor: not-allowed; }
9
9
  &:has(.crisp-input-value:disabled) { opacity: 1; }
10
+ /* crisp#634: measured live on Attio's own Settings > Profile read-only
11
+ primary-email field -- a tinted field, not just muted text, driven off
12
+ the native `readOnly` attribute. `ringField` (rgba(0,0,0,.06)) is an
13
+ exact match for the measured ring; the 2%-fgPrimary tint reuses the
14
+ same color-mix idiom every other soft crisp surface already uses. */
15
+ &[data-readonly] { background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-ring-field); }
16
+ & .crisp-input-suffix { flex-shrink: 0; margin-inline-start: var(--crisp-space-1); }
10
17
  }
11
18
  .crisp-input--size_sm {
12
19
  height: var(--crisp-size-row); border-radius: var(--crisp-radius-md);
@@ -61,6 +61,10 @@
61
61
  & .crisp-multiselect-chevron { flex-shrink: 0; color: var(--crisp-fg-neutral-muted); transition: transform .1s cubic-bezier(.35,0,.35,1); }
62
62
  & .crisp-multiselect-trigger[data-open] .crisp-multiselect-chevron { transform: rotate(180deg); transition-duration: .15s; }
63
63
  }
64
+ .crisp-multiselect--size_small {
65
+ & .crisp-multiselect-trigger { min-height: var(--crisp-size-menuRow); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-1); padding: var(--crisp-space-0-5) var(--crisp-space-1-5) var(--crisp-space-0-5) var(--crisp-space-2); }
66
+ & .crisp-multiselect-chevron { width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
67
+ }
64
68
  .crisp-multiselect--size_medium {
65
69
  & .crisp-multiselect-trigger { min-height: var(--crisp-size-selectTriggerMd); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-2); padding: var(--crisp-space-1) var(--crisp-space-3-5); }
66
70
  & .crisp-multiselect-chevron { width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
@@ -1,9 +1,9 @@
1
1
  import type { RecipeFn } from "../core/types";
2
2
 
3
3
  export interface MultiselectVariants {
4
- size?: "medium" | "large";
4
+ size?: "small" | "medium" | "large";
5
5
  invalid?: boolean;
6
6
  variant?: "default" | "ghost";
7
7
  }
8
8
 
9
- export declare const multiselectRecipe: RecipeFn<{ size: { medium: string; large: string }; invalid: { true: string; false: string }; variant: { default: string; ghost: string } }>;
9
+ export declare const multiselectRecipe: RecipeFn<{ size: { small: string; medium: string; large: string }; invalid: { true: string; false: string }; variant: { default: string; ghost: string } }>;
@@ -62,6 +62,10 @@
62
62
  & .crisp-multiselect-chevron { flex-shrink: 0; color: var(--crisp-fg-neutral-muted); transition: transform .1s cubic-bezier(.35,0,.35,1); }
63
63
  & .crisp-multiselect-trigger[data-open] .crisp-multiselect-chevron { transform: rotate(180deg); transition-duration: .15s; }
64
64
  }
65
+ .crisp-multiselect--size_small {
66
+ & .crisp-multiselect-trigger { min-height: var(--crisp-size-menuRow); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-1); padding: var(--crisp-space-0-5) var(--crisp-space-1-5) var(--crisp-space-0-5) var(--crisp-space-2); }
67
+ & .crisp-multiselect-chevron { width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
68
+ }
65
69
  .crisp-multiselect--size_medium {
66
70
  & .crisp-multiselect-trigger { min-height: var(--crisp-size-selectTriggerMd); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-2); padding: var(--crisp-space-1) var(--crisp-space-3-5); }
67
71
  & .crisp-multiselect-chevron { width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
@@ -2,7 +2,7 @@
2
2
  // The same tokens the CSS custom properties carry, resolved per theme, with
3
3
  // dimensions as numbers for React Native and Lynx style objects.
4
4
  export type Theme = "light" | "dark";
5
- export type ColorTokens = Record<"bgBrandSolid" | "bgBrandSolidPressed" | "fgOnBrand" | "fgOnTone" | "bgSurface" | "bgRaised" | "bgSurfaceMuted" | "borderDefault" | "borderSubtle" | "borderDropzone" | "borderDivider" | "ringNeutral" | "ringField" | "ringSwitch" | "bgTileActive" | "shadowTileActive" | "bgScrim" | "fgAlertDescription" | "bgOverlayFrost" | "shadowOverlay1" | "shadowOverlay2" | "shadowOverlay3" | "bgPopover" | "ringPopover" | "shadowPopover1" | "shadowPopover2" | "shadowPopover3" | "fgPrimary" | "fgMuted" | "bgDanger" | "bgDangerSolid" | "fgDanger" | "strokeFieldFocus" | "fgDisabled" | "bgNeutralWeak" | "bgNeutralInverted" | "fgOnNeutralInverted" | "fgNeutralSubtle" | "fgNeutralMuted" | "strokeFocusRing" | "bgSuccess" | "bgWarning" | "bgOrange" | "bgCyan" | "bgPurple" | "bgSidebar" | "bgSubtle" | "fgBrandSoft" | "fgSuccessSoft" | "fgWarningSoft" | "fgDangerSoft" | "fgNeutralSoft" | "bgPurpleSoft" | "fgPurpleSoft" | "ringPurpleSoft" | "ringBrandSoft" | "fgSelectNeutral" | "bgSelectListbox" | "strokeSelectTrigger" | "bgSelectPressed" | "bgSelectDisabled" | "strokeSelectInvalid" | "strokeSelectDivider" | "fgSelectPlaceholder" | "shadowSelect", string>;
5
+ export type ColorTokens = Record<"bgBrandSolid" | "bgBrandSolidPressed" | "bgBrandContrast" | "fgBrandContrast" | "fgOnBrand" | "fgOnTone" | "bgSurface" | "bgRaised" | "bgSurfaceMuted" | "borderDefault" | "borderSubtle" | "borderDropzone" | "borderDivider" | "ringNeutral" | "ringField" | "ringSwitch" | "bgTileActive" | "shadowTileActive" | "bgScrim" | "fgAlertDescription" | "bgOverlayFrost" | "shadowOverlay1" | "shadowOverlay2" | "shadowOverlay3" | "bgPopover" | "ringPopover" | "shadowPopover1" | "shadowPopover2" | "shadowPopover3" | "fgPrimary" | "fgMuted" | "bgDanger" | "bgDangerSolid" | "fgDanger" | "strokeFieldFocus" | "fgDisabled" | "bgNeutralWeak" | "bgNeutralInverted" | "fgOnNeutralInverted" | "fgNeutralSubtle" | "fgNeutralMuted" | "strokeFocusRing" | "bgSuccess" | "bgWarning" | "bgWarningSolid" | "bgOrange" | "bgCyan" | "bgPurple" | "bgSidebar" | "bgSubtle" | "fgBrandSoft" | "fgSuccessSoft" | "fgWarningSoft" | "fgDangerSoft" | "fgNeutralSoft" | "bgPurpleSoft" | "fgPurpleSoft" | "ringPurpleSoft" | "ringBrandSoft" | "fgSelectNeutral" | "bgSelectListbox" | "strokeSelectTrigger" | "bgSelectPressed" | "bgSelectDisabled" | "strokeSelectInvalid" | "strokeSelectDivider" | "fgSelectPlaceholder" | "shadowSelect", string>;
6
6
  export declare const tokens: {
7
7
  color: Record<Theme, ColorTokens>;
8
8
  palette: Record<Theme, Record<string, string>>;
@@ -4,14 +4,16 @@
4
4
  export const tokens = {
5
5
  "color": {
6
6
  "light": {
7
- "bgBrandSolid": "#266df0",
8
- "bgBrandSolidPressed": "#1f5fd6",
7
+ "bgBrandSolid": "#0298d9",
8
+ "bgBrandSolidPressed": "#0283bb",
9
+ "bgBrandContrast": "#0278ac",
10
+ "fgBrandContrast": "#0278ac",
9
11
  "fgOnBrand": "#ffffff",
10
12
  "fgOnTone": "#101112",
11
13
  "bgSurface": "#ffffff",
12
- "bgRaised": "#f4f4f5",
14
+ "bgRaised": "#f7f8f9",
13
15
  "bgSurfaceMuted": "#f6f7f7",
14
- "borderDefault": "#e4e4e7",
16
+ "borderDefault": "#dcdee3",
15
17
  "borderSubtle": "#eeeff1",
16
18
  "borderDropzone": "#e6e7ea",
17
19
  "borderDivider": "#e6e7ea",
@@ -33,9 +35,9 @@ export const tokens = {
33
35
  "shadowPopover3": "rgba(24,41,75,0.16)",
34
36
  "fgPrimary": "#101112",
35
37
  "fgMuted": "#71717a",
36
- "bgDanger": "#e5484d",
37
- "bgDangerSolid": "#ba2525",
38
- "fgDanger": "#eb3b3b",
38
+ "bgDanger": "#fa342c",
39
+ "bgDangerSolid": "#ca1d13",
40
+ "fgDanger": "#fa342c",
39
41
  "strokeFieldFocus": "#1a1c20",
40
42
  "fgDisabled": "#d1d3d8",
41
43
  "bgNeutralWeak": "#f3f4f5",
@@ -44,8 +46,9 @@ export const tokens = {
44
46
  "fgNeutralSubtle": "#868b94",
45
47
  "fgNeutralMuted": "#555d6d",
46
48
  "strokeFocusRing": "#1e82eb",
47
- "bgSuccess": "#1f9d57",
48
- "bgWarning": "#b5730f",
49
+ "bgSuccess": "#079171",
50
+ "bgWarning": "#9b7821",
51
+ "bgWarningSolid": "#fbdc65",
49
52
  "bgOrange": "#f97514",
50
53
  "bgCyan": "#00b9eb",
51
54
  "bgPurple": "#9b69ff",
@@ -71,8 +74,10 @@ export const tokens = {
71
74
  "shadowSelect": "#0000001f"
72
75
  },
73
76
  "dark": {
74
- "bgBrandSolid": "#266df0",
75
- "bgBrandSolidPressed": "#1f5fd6",
77
+ "bgBrandSolid": "#0298d9",
78
+ "bgBrandSolidPressed": "#0283bb",
79
+ "bgBrandContrast": "#0278ac",
80
+ "fgBrandContrast": "#0278ac",
76
81
  "fgOnBrand": "#ffffff",
77
82
  "fgOnTone": "#101112",
78
83
  "bgSurface": "#0a0a0a",
@@ -113,6 +118,7 @@ export const tokens = {
113
118
  "strokeFocusRing": "#5e98fe",
114
119
  "bgSuccess": "#2ea968",
115
120
  "bgWarning": "#e0982a",
121
+ "bgWarningSolid": "#e0982a",
116
122
  "bgOrange": "#f97514",
117
123
  "bgCyan": "#00b9eb",
118
124
  "bgPurple": "#9b69ff",
@@ -143,9 +149,9 @@ export const tokens = {
143
149
  "gray00": "#ffffff",
144
150
  "white": "#ffffff",
145
151
  "ink": "#101112",
146
- "gray50": "#f4f4f5",
152
+ "gray50": "#f7f8f9",
147
153
  "gray900": "#101112",
148
- "line200": "#e4e4e7",
154
+ "line200": "#dcdee3",
149
155
  "line100": "#eeeff1",
150
156
  "line150": "#e6e7ea",
151
157
  "gray25": "#f6f7f7",
@@ -167,11 +173,12 @@ export const tokens = {
167
173
  "shadowPopover2": "rgba(28,40,64,0.12)",
168
174
  "shadowPopover3": "rgba(24,41,75,0.16)",
169
175
  "gray400": "#71717a",
170
- "brand600": "#266df0",
171
- "brand700": "#1f5fd6",
172
- "red600": "#e5484d",
173
- "red700": "#ba2525",
174
- "red500": "#eb3b3b",
176
+ "brand600": "#0298d9",
177
+ "brand700": "#0283bb",
178
+ "brandContrast": "#0278ac",
179
+ "red600": "#fa342c",
180
+ "red700": "#ca1d13",
181
+ "red500": "#fa342c",
175
182
  "fieldFocus": "#1a1c20",
176
183
  "disabledFg": "#d1d3d8",
177
184
  "neutralWeak": "#f3f4f5",
@@ -180,8 +187,9 @@ export const tokens = {
180
187
  "neutralSubtle": "#868b94",
181
188
  "neutralMuted": "#555d6d",
182
189
  "focusRing": "#1e82eb",
183
- "green600": "#1f9d57",
184
- "amber600": "#b5730f",
190
+ "green600": "#079171",
191
+ "amber600": "#9b7821",
192
+ "amberSolid": "#fbdc65",
185
193
  "orange600": "#f97514",
186
194
  "cyan600": "#00b9eb",
187
195
  "purple600": "#9b69ff",
@@ -231,8 +239,9 @@ export const tokens = {
231
239
  "shadowPopover2": "rgba(0,0,0,0.24)",
232
240
  "shadowPopover3": "rgba(0,0,0,0.32)",
233
241
  "gray400": "#9a9aa2",
234
- "brand600": "#266df0",
235
- "brand700": "#1f5fd6",
242
+ "brand600": "#0298d9",
243
+ "brand700": "#0283bb",
244
+ "brandContrast": "#0278ac",
236
245
  "red600": "#ff5a5f",
237
246
  "red700": "#ba2525",
238
247
  "red500": "#ff5a5f",
@@ -246,6 +255,7 @@ export const tokens = {
246
255
  "focusRing": "#5e98fe",
247
256
  "green600": "#2ea968",
248
257
  "amber600": "#e0982a",
258
+ "amberSolid": "#e0982a",
249
259
  "orange600": "#f97514",
250
260
  "cyan600": "#00b9eb",
251
261
  "purple600": "#9b69ff",
@@ -283,6 +293,7 @@ export const tokens = {
283
293
  "3.5": 14
284
294
  },
285
295
  "radius": {
296
+ "xs": 4,
286
297
  "chip": 7,
287
298
  "sm": 6,
288
299
  "md": 8,
package/dist/progress.css CHANGED
@@ -4,6 +4,9 @@
4
4
  &[data-segmented] { display: flex; gap: var(--crisp-space-1); background: transparent; overflow: visible; }
5
5
  &[data-segmented] .crisp-progress-seg { flex: 1; height: 100%; border-radius: var(--crisp-radius-full); background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); transition: background 0.2s; }
6
6
  &[data-segmented] .crisp-progress-seg[data-filled] { background: var(--crisp-bg-brand-solid); }
7
+ &[data-variant="circular"] { display: inline-flex; height: auto; border-radius: 0; background: transparent; overflow: visible; }
8
+ & .crisp-progress-circle-track { stroke: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); }
9
+ & .crisp-progress-circle-fill { stroke: var(--crisp-bg-brand-solid); transition: stroke-dashoffset 0.25s ease; }
7
10
  }
8
11
 
9
12
  @media (prefers-reduced-motion: reduce) {
@@ -5,6 +5,9 @@
5
5
  &[data-segmented] { display: flex; gap: var(--crisp-space-1); background: transparent; overflow: visible; }
6
6
  &[data-segmented] .crisp-progress-seg { flex: 1; height: 100%; border-radius: var(--crisp-radius-full); background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); transition: background 0.2s; }
7
7
  &[data-segmented] .crisp-progress-seg[data-filled] { background: var(--crisp-bg-brand-solid); }
8
+ &[data-variant="circular"] { display: inline-flex; height: auto; border-radius: 0; background: transparent; overflow: visible; }
9
+ & .crisp-progress-circle-track { stroke: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); }
10
+ & .crisp-progress-circle-fill { stroke: var(--crisp-bg-brand-solid); transition: stroke-dashoffset 0.25s ease; }
8
11
  }
9
12
 
10
13
  @media (prefers-reduced-motion: reduce) {
package/dist/select.css CHANGED
@@ -13,9 +13,19 @@
13
13
  }
14
14
  .crisp-select-listbox[data-up] { transform-origin: bottom left; }
15
15
  .crisp-select-listbox { @starting-style { opacity: 0; transform: scale(0.95); } }
16
- .crisp-select-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 34px; flex-shrink: 0; margin: calc(-1 * var(--crisp-space-2)) calc(-1 * var(--crisp-space-2)) var(--crisp-space-2); padding: 0 var(--crisp-space-2-5); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-neutral-muted); }
16
+ /* Composed from @seed-design/rootage's text-input.yaml
17
+ (variant=outline,size=medium) -- seed's Select has no search field of
18
+ its own to resolve this from (see the file header), so this reuses
19
+ the SAME tokens #867 already resolved for the trigger at this size:
20
+ minHeight x10 (var(--crisp-size-selectTriggerMd)), paddingX x3_5
21
+ (var(--crisp-space-3-5)), gap x2 (var(--crisp-space-2)), cornerRadius r2
22
+ (var(--crisp-radius-md)), strokeColor stroke.neutral-weak
23
+ (var(--crisp-stroke-select-trigger)) -- a real bordered field sitting flush
24
+ inside the listbox's own 8px padding, replacing the old bare
25
+ 34px/no-border/bleeds-to-the-edge strip (crisp/#904). */
26
+ .crisp-select-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: var(--crisp-size-selectTriggerMd); flex-shrink: 0; padding: 0 var(--crisp-space-3-5); border: 1px solid var(--crisp-stroke-select-trigger); border-radius: var(--crisp-radius-md); color: var(--crisp-fg-neutral-muted); }
17
27
  .crisp-select-search svg { flex-shrink: 0; }
18
- .crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-select-neutral); }
28
+ .crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; color: var(--crisp-fg-select-neutral); }
19
29
  .crisp-select-search input::placeholder { color: var(--crisp-fg-select-placeholder); }
20
30
  .crisp-select-empty { padding: var(--crisp-space-3) var(--crisp-space-4); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-neutral-subtle); }
21
31
  /* select.yaml's groupLabel -- font-size/line-height/weight are the same
@@ -70,6 +80,16 @@
70
80
  .crisp-select--width_auto {
71
81
  width: auto;
72
82
  }
83
+ .crisp-select--size_small {
84
+ & .crisp-select-trigger { height: var(--crisp-size-menuRow); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-1-5); padding-inline: var(--crisp-space-2-5); }
85
+ & .crisp-select-value, & .crisp-select-placeholder { font-size: var(--crisp-text-lg); line-height: 20px; }
86
+ & .crisp-select-chevron { width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
87
+ .crisp-select-option { gap: var(--crisp-space-2); }
88
+ .crisp-select-option-label { font-size: var(--crisp-text-lg); line-height: 19px; }
89
+ .crisp-select-option-description { font-size: var(--crisp-text-sm); line-height: 16px; }
90
+ .crisp-select-option-check { width: var(--crisp-space-3); height: var(--crisp-space-3); }
91
+ .crisp-select-label { padding-top: var(--crisp-space-2); }
92
+ }
73
93
  .crisp-select--size_medium {
74
94
  & .crisp-select-trigger { height: var(--crisp-size-selectTriggerMd); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-2); padding-inline: var(--crisp-space-3-5); }
75
95
  & .crisp-select-value, & .crisp-select-placeholder { font-size: var(--crisp-text-lg); line-height: 19px; }
package/dist/select.d.ts CHANGED
@@ -2,9 +2,9 @@ import type { RecipeFn } from "../core/types";
2
2
 
3
3
  export interface SelectVariants {
4
4
  width?: "full" | "auto";
5
- size?: "medium" | "large";
5
+ size?: "small" | "medium" | "large";
6
6
  invalid?: boolean;
7
7
  variant?: "default" | "ghost";
8
8
  }
9
9
 
10
- export declare const selectRecipe: RecipeFn<{ width: { full: string; auto: string }; size: { medium: string; large: string }; invalid: { true: string; false: string }; variant: { default: string; ghost: string } }>;
10
+ export declare const selectRecipe: RecipeFn<{ width: { full: string; auto: string }; size: { small: string; medium: string; large: string }; invalid: { true: string; false: string }; variant: { default: string; ghost: string } }>;
@@ -14,9 +14,19 @@
14
14
  }
15
15
  .crisp-select-listbox[data-up] { transform-origin: bottom left; }
16
16
  .crisp-select-listbox { @starting-style { opacity: 0; transform: scale(0.95); } }
17
- .crisp-select-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 34px; flex-shrink: 0; margin: calc(-1 * var(--crisp-space-2)) calc(-1 * var(--crisp-space-2)) var(--crisp-space-2); padding: 0 var(--crisp-space-2-5); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-neutral-muted); }
17
+ /* Composed from @seed-design/rootage's text-input.yaml
18
+ (variant=outline,size=medium) -- seed's Select has no search field of
19
+ its own to resolve this from (see the file header), so this reuses
20
+ the SAME tokens #867 already resolved for the trigger at this size:
21
+ minHeight x10 (var(--crisp-size-selectTriggerMd)), paddingX x3_5
22
+ (var(--crisp-space-3-5)), gap x2 (var(--crisp-space-2)), cornerRadius r2
23
+ (var(--crisp-radius-md)), strokeColor stroke.neutral-weak
24
+ (var(--crisp-stroke-select-trigger)) -- a real bordered field sitting flush
25
+ inside the listbox's own 8px padding, replacing the old bare
26
+ 34px/no-border/bleeds-to-the-edge strip (crisp/#904). */
27
+ .crisp-select-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: var(--crisp-size-selectTriggerMd); flex-shrink: 0; padding: 0 var(--crisp-space-3-5); border: 1px solid var(--crisp-stroke-select-trigger); border-radius: var(--crisp-radius-md); color: var(--crisp-fg-neutral-muted); }
18
28
  .crisp-select-search svg { flex-shrink: 0; }
19
- .crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-select-neutral); }
29
+ .crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; color: var(--crisp-fg-select-neutral); }
20
30
  .crisp-select-search input::placeholder { color: var(--crisp-fg-select-placeholder); }
21
31
  .crisp-select-empty { padding: var(--crisp-space-3) var(--crisp-space-4); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-neutral-subtle); }
22
32
  /* select.yaml's groupLabel -- font-size/line-height/weight are the same
@@ -71,6 +81,16 @@
71
81
  .crisp-select--width_auto {
72
82
  width: auto;
73
83
  }
84
+ .crisp-select--size_small {
85
+ & .crisp-select-trigger { height: var(--crisp-size-menuRow); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-1-5); padding-inline: var(--crisp-space-2-5); }
86
+ & .crisp-select-value, & .crisp-select-placeholder { font-size: var(--crisp-text-lg); line-height: 20px; }
87
+ & .crisp-select-chevron { width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
88
+ .crisp-select-option { gap: var(--crisp-space-2); }
89
+ .crisp-select-option-label { font-size: var(--crisp-text-lg); line-height: 19px; }
90
+ .crisp-select-option-description { font-size: var(--crisp-text-sm); line-height: 16px; }
91
+ .crisp-select-option-check { width: var(--crisp-space-3); height: var(--crisp-space-3); }
92
+ .crisp-select-label { padding-top: var(--crisp-space-2); }
93
+ }
74
94
  .crisp-select--size_medium {
75
95
  & .crisp-select-trigger { height: var(--crisp-size-selectTriggerMd); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-2); padding-inline: var(--crisp-space-3-5); }
76
96
  & .crisp-select-value, & .crisp-select-placeholder { font-size: var(--crisp-text-lg); line-height: 19px; }
package/dist/styles.css CHANGED
@@ -27,14 +27,16 @@
27
27
  font-display: swap;
28
28
  }
29
29
  :root {
30
- --crisp-bg-brand-solid: #266df0;
31
- --crisp-bg-brand-solid-pressed: #1f5fd6;
30
+ --crisp-bg-brand-solid: #0298d9;
31
+ --crisp-bg-brand-solid-pressed: #0283bb;
32
+ --crisp-bg-brand-contrast: #0278ac;
33
+ --crisp-fg-brand-contrast: #0278ac;
32
34
  --crisp-fg-on-brand: #ffffff;
33
35
  --crisp-fg-on-tone: #101112;
34
36
  --crisp-bg-surface: #ffffff;
35
- --crisp-bg-raised: #f4f4f5;
37
+ --crisp-bg-raised: #f7f8f9;
36
38
  --crisp-bg-surface-muted: #f6f7f7;
37
- --crisp-border-default: #e4e4e7;
39
+ --crisp-border-default: #dcdee3;
38
40
  --crisp-border-subtle: #eeeff1;
39
41
  --crisp-border-dropzone: #e6e7ea;
40
42
  --crisp-border-divider: #e6e7ea;
@@ -56,9 +58,9 @@
56
58
  --crisp-shadow-popover3: rgba(24,41,75,0.16);
57
59
  --crisp-fg-primary: #101112;
58
60
  --crisp-fg-muted: #71717a;
59
- --crisp-bg-danger: #e5484d;
60
- --crisp-bg-danger-solid: #ba2525;
61
- --crisp-fg-danger: #eb3b3b;
61
+ --crisp-bg-danger: #fa342c;
62
+ --crisp-bg-danger-solid: #ca1d13;
63
+ --crisp-fg-danger: #fa342c;
62
64
  --crisp-stroke-field-focus: #1a1c20;
63
65
  --crisp-fg-disabled: #d1d3d8;
64
66
  --crisp-bg-neutral-weak: #f3f4f5;
@@ -67,8 +69,9 @@
67
69
  --crisp-fg-neutral-subtle: #868b94;
68
70
  --crisp-fg-neutral-muted: #555d6d;
69
71
  --crisp-stroke-focus-ring: #1e82eb;
70
- --crisp-bg-success: #1f9d57;
71
- --crisp-bg-warning: #b5730f;
72
+ --crisp-bg-success: #079171;
73
+ --crisp-bg-warning: #9b7821;
74
+ --crisp-bg-warning-solid: #fbdc65;
72
75
  --crisp-bg-orange: #f97514;
73
76
  --crisp-bg-cyan: #00b9eb;
74
77
  --crisp-bg-purple: #9b69ff;
@@ -95,8 +98,10 @@
95
98
  }
96
99
 
97
100
  [data-theme="dark"] {
98
- --crisp-bg-brand-solid: #266df0;
99
- --crisp-bg-brand-solid-pressed: #1f5fd6;
101
+ --crisp-bg-brand-solid: #0298d9;
102
+ --crisp-bg-brand-solid-pressed: #0283bb;
103
+ --crisp-bg-brand-contrast: #0278ac;
104
+ --crisp-fg-brand-contrast: #0278ac;
100
105
  --crisp-fg-on-brand: #ffffff;
101
106
  --crisp-fg-on-tone: #101112;
102
107
  --crisp-bg-surface: #0a0a0a;
@@ -137,6 +142,7 @@
137
142
  --crisp-stroke-focus-ring: #5e98fe;
138
143
  --crisp-bg-success: #2ea968;
139
144
  --crisp-bg-warning: #e0982a;
145
+ --crisp-bg-warning-solid: #e0982a;
140
146
  --crisp-bg-orange: #f97514;
141
147
  --crisp-bg-cyan: #00b9eb;
142
148
  --crisp-bg-purple: #9b69ff;
@@ -175,6 +181,7 @@
175
181
  --crisp-space-1-5: 6px;
176
182
  --crisp-space-2-5: 10px;
177
183
  --crisp-space-3-5: 14px;
184
+ --crisp-radius-xs: 4px;
178
185
  --crisp-radius-chip: 7px;
179
186
  --crisp-radius-sm: 6px;
180
187
  --crisp-radius-md: 8px;
@@ -207,6 +214,12 @@
207
214
  --crisp-font-sans: "VK Sans Display", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
208
215
  }
209
216
 
217
+ .crisp-accentpicker {
218
+ display: flex; gap: var(--crisp-space-2);
219
+ & .crisp-accentpicker-swatch { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; margin: 0; border-radius: var(--crisp-radius-full); border: 1px solid transparent; background: none; font-family: inherit; cursor: pointer; }
220
+ & .crisp-accentpicker-swatch:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 2px; }
221
+ }
222
+
210
223
  .crisp-accordion {
211
224
  display: flex; flex-direction: column; font-family: var(--crisp-font-sans);
212
225
  & .crisp-accordion-item { border-bottom: 1px solid var(--crisp-border-subtle); }
@@ -255,7 +268,7 @@
255
268
  background: var(--crisp-bg-raised); color: var(--crisp-fg-neutral-muted); box-shadow: inset 0 0 0 1px var(--crisp-border-default);
256
269
  }
257
270
  .crisp-avatar--tone_brand {
258
- background: var(--crisp-bg-brand-solid); color: #fff;
271
+ background: var(--crisp-bg-brand-contrast); color: #fff;
259
272
  }
260
273
  .crisp-avatar--tone_orange {
261
274
  background: var(--crisp-bg-orange); color: #fff;
@@ -314,13 +327,13 @@
314
327
 
315
328
  }
316
329
  .crisp-badge--compound_0 {
317
- background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); box-shadow: none;
330
+ background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); box-shadow: none;
318
331
  }
319
332
  .crisp-badge--compound_1 {
320
333
  background: var(--crisp-bg-success); color: var(--crisp-fg-on-tone); box-shadow: none;
321
334
  }
322
335
  .crisp-badge--compound_2 {
323
- background: var(--crisp-bg-warning); color: var(--crisp-fg-on-tone); box-shadow: none;
336
+ background: var(--crisp-bg-warning-solid); color: var(--crisp-fg-on-tone); box-shadow: none;
324
337
  }
325
338
  .crisp-badge--compound_3 {
326
339
  background: var(--crisp-bg-danger); color: var(--crisp-fg-on-tone); box-shadow: none;
@@ -395,9 +408,9 @@
395
408
  &:disabled { opacity: 0.5; cursor: not-allowed; }
396
409
  }
397
410
  .crisp-button--intent_primary {
398
- background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08);
399
- &:hover { background: var(--crisp-bg-brand-solid-pressed); }
400
- &:active { background: var(--crisp-bg-brand-solid-pressed); }
411
+ background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08);
412
+ &:hover { filter: brightness(0.96); }
413
+ &:active { filter: brightness(0.92); }
401
414
  }
402
415
  .crisp-button--intent_neutral {
403
416
  background: var(--crisp-bg-surface); color: var(--crisp-fg-primary); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04);
@@ -1385,6 +1398,13 @@
1385
1398
  & .crisp-input-value::placeholder { color: var(--crisp-fg-muted); }
1386
1399
  & .crisp-input-value:disabled { opacity: 0.5; cursor: not-allowed; }
1387
1400
  &:has(.crisp-input-value:disabled) { opacity: 1; }
1401
+ /* crisp#634: measured live on Attio's own Settings > Profile read-only
1402
+ primary-email field -- a tinted field, not just muted text, driven off
1403
+ the native `readOnly` attribute. `ringField` (rgba(0,0,0,.06)) is an
1404
+ exact match for the measured ring; the 2%-fgPrimary tint reuses the
1405
+ same color-mix idiom every other soft crisp surface already uses. */
1406
+ &[data-readonly] { background: color-mix(in srgb, var(--crisp-fg-primary) 2%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-ring-field); }
1407
+ & .crisp-input-suffix { flex-shrink: 0; margin-inline-start: var(--crisp-space-1); }
1388
1408
  }
1389
1409
  .crisp-input--size_sm {
1390
1410
  height: var(--crisp-size-row); border-radius: var(--crisp-radius-md);
@@ -1560,6 +1580,10 @@
1560
1580
  & .crisp-multiselect-chevron { flex-shrink: 0; color: var(--crisp-fg-neutral-muted); transition: transform .1s cubic-bezier(.35,0,.35,1); }
1561
1581
  & .crisp-multiselect-trigger[data-open] .crisp-multiselect-chevron { transform: rotate(180deg); transition-duration: .15s; }
1562
1582
  }
1583
+ .crisp-multiselect--size_small {
1584
+ & .crisp-multiselect-trigger { min-height: var(--crisp-size-menuRow); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-1); padding: var(--crisp-space-0-5) var(--crisp-space-1-5) var(--crisp-space-0-5) var(--crisp-space-2); }
1585
+ & .crisp-multiselect-chevron { width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
1586
+ }
1563
1587
  .crisp-multiselect--size_medium {
1564
1588
  & .crisp-multiselect-trigger { min-height: var(--crisp-size-selectTriggerMd); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-2); padding: var(--crisp-space-1) var(--crisp-space-3-5); }
1565
1589
  & .crisp-multiselect-chevron { width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
@@ -1618,6 +1642,9 @@
1618
1642
  &[data-segmented] { display: flex; gap: var(--crisp-space-1); background: transparent; overflow: visible; }
1619
1643
  &[data-segmented] .crisp-progress-seg { flex: 1; height: 100%; border-radius: var(--crisp-radius-full); background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); transition: background 0.2s; }
1620
1644
  &[data-segmented] .crisp-progress-seg[data-filled] { background: var(--crisp-bg-brand-solid); }
1645
+ &[data-variant="circular"] { display: inline-flex; height: auto; border-radius: 0; background: transparent; overflow: visible; }
1646
+ & .crisp-progress-circle-track { stroke: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); }
1647
+ & .crisp-progress-circle-fill { stroke: var(--crisp-bg-brand-solid); transition: stroke-dashoffset 0.25s ease; }
1621
1648
  }
1622
1649
 
1623
1650
  @media (prefers-reduced-motion: reduce) {
@@ -1776,9 +1803,19 @@
1776
1803
  }
1777
1804
  .crisp-select-listbox[data-up] { transform-origin: bottom left; }
1778
1805
  .crisp-select-listbox { @starting-style { opacity: 0; transform: scale(0.95); } }
1779
- .crisp-select-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 34px; flex-shrink: 0; margin: calc(-1 * var(--crisp-space-2)) calc(-1 * var(--crisp-space-2)) var(--crisp-space-2); padding: 0 var(--crisp-space-2-5); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-neutral-muted); }
1806
+ /* Composed from @seed-design/rootage's text-input.yaml
1807
+ (variant=outline,size=medium) -- seed's Select has no search field of
1808
+ its own to resolve this from (see the file header), so this reuses
1809
+ the SAME tokens #867 already resolved for the trigger at this size:
1810
+ minHeight x10 (var(--crisp-size-selectTriggerMd)), paddingX x3_5
1811
+ (var(--crisp-space-3-5)), gap x2 (var(--crisp-space-2)), cornerRadius r2
1812
+ (var(--crisp-radius-md)), strokeColor stroke.neutral-weak
1813
+ (var(--crisp-stroke-select-trigger)) -- a real bordered field sitting flush
1814
+ inside the listbox's own 8px padding, replacing the old bare
1815
+ 34px/no-border/bleeds-to-the-edge strip (crisp/#904). */
1816
+ .crisp-select-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: var(--crisp-size-selectTriggerMd); flex-shrink: 0; padding: 0 var(--crisp-space-3-5); border: 1px solid var(--crisp-stroke-select-trigger); border-radius: var(--crisp-radius-md); color: var(--crisp-fg-neutral-muted); }
1780
1817
  .crisp-select-search svg { flex-shrink: 0; }
1781
- .crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-select-neutral); }
1818
+ .crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; color: var(--crisp-fg-select-neutral); }
1782
1819
  .crisp-select-search input::placeholder { color: var(--crisp-fg-select-placeholder); }
1783
1820
  .crisp-select-empty { padding: var(--crisp-space-3) var(--crisp-space-4); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-neutral-subtle); }
1784
1821
  /* select.yaml's groupLabel -- font-size/line-height/weight are the same
@@ -1833,6 +1870,16 @@
1833
1870
  .crisp-select--width_auto {
1834
1871
  width: auto;
1835
1872
  }
1873
+ .crisp-select--size_small {
1874
+ & .crisp-select-trigger { height: var(--crisp-size-menuRow); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-1-5); padding-inline: var(--crisp-space-2-5); }
1875
+ & .crisp-select-value, & .crisp-select-placeholder { font-size: var(--crisp-text-lg); line-height: 20px; }
1876
+ & .crisp-select-chevron { width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
1877
+ .crisp-select-option { gap: var(--crisp-space-2); }
1878
+ .crisp-select-option-label { font-size: var(--crisp-text-lg); line-height: 19px; }
1879
+ .crisp-select-option-description { font-size: var(--crisp-text-sm); line-height: 16px; }
1880
+ .crisp-select-option-check { width: var(--crisp-space-3); height: var(--crisp-space-3); }
1881
+ .crisp-select-label { padding-top: var(--crisp-space-2); }
1882
+ }
1836
1883
  .crisp-select--size_medium {
1837
1884
  & .crisp-select-trigger { height: var(--crisp-size-selectTriggerMd); border-radius: var(--crisp-radius-md); gap: var(--crisp-space-2); padding-inline: var(--crisp-space-3-5); }
1838
1885
  & .crisp-select-value, & .crisp-select-placeholder { font-size: var(--crisp-text-lg); line-height: 19px; }
@@ -2321,7 +2368,7 @@
2321
2368
  color: var(--crisp-fg-neutral-muted);
2322
2369
  }
2323
2370
  .crisp-text--tone_brand {
2324
- color: var(--crisp-bg-brand-solid);
2371
+ color: var(--crisp-fg-brand-contrast);
2325
2372
  }
2326
2373
  .crisp-text--tone_danger {
2327
2374
  color: var(--crisp-fg-danger);
@@ -2345,8 +2392,9 @@
2345
2392
  &[data-invalid] .crisp-textarea-wrap::after { border-color: var(--crisp-bg-danger); }
2346
2393
  &[data-invalid] .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-bg-danger); }
2347
2394
  &[data-counted] .crisp-textarea-field { padding-bottom: var(--crisp-space-5); }
2348
- & .crisp-textarea-count { position: absolute; inset-inline-end: 14px; bottom: var(--crisp-space-2-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
2395
+ & .crisp-textarea-count { position: absolute; inset-inline-end: 14px; bottom: var(--crisp-space-2-5); display: flex; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); pointer-events: none; }
2349
2396
  & .crisp-textarea-count[data-over] { color: var(--crisp-bg-danger); }
2397
+ & .crisp-textarea-progress { flex-shrink: 0; }
2350
2398
  }
2351
2399
 
2352
2400
  @media (prefers-reduced-motion: reduce) {
@@ -2362,11 +2410,11 @@
2362
2410
  &:hover { text-decoration: underline; }
2363
2411
  }
2364
2412
  .crisp-textlink--tone_brand {
2365
- font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-bg-brand-solid);
2413
+ font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-brand-contrast);
2366
2414
  }
2367
2415
  .crisp-textlink--tone_muted {
2368
2416
  font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-regular); color: var(--crisp-fg-muted);
2369
- &:hover { color: var(--crisp-bg-brand-solid); }
2417
+ &:hover { color: var(--crisp-fg-brand-contrast); }
2370
2418
  }
2371
2419
  .crisp-textlink--size_sm {
2372
2420
  font-size: var(--crisp-text-sm);