@codecademy/gamut 68.6.1-alpha.e6c390.0 → 68.6.1-alpha.f6b2ce.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 (47) hide show
  1. package/agent-tools/.cursor-plugin/plugin.json +1 -1
  2. package/agent-tools/DESIGN.Codecademy.md +239 -191
  3. package/agent-tools/DESIGN.LXStudio.md +236 -184
  4. package/agent-tools/DESIGN.Percipio.md +232 -182
  5. package/agent-tools/DESIGN.md +1 -1
  6. package/agent-tools/commands/gamut-review.md +176 -87
  7. package/agent-tools/guidelines/components/animations.md +74 -0
  8. package/agent-tools/guidelines/components/buttons.md +74 -23
  9. package/agent-tools/guidelines/components/card.md +19 -0
  10. package/agent-tools/guidelines/components/coachmark.md +21 -0
  11. package/agent-tools/guidelines/components/data-table.md +79 -0
  12. package/agent-tools/guidelines/components/forms.md +106 -0
  13. package/agent-tools/guidelines/components/loading-states.md +17 -0
  14. package/agent-tools/guidelines/components/menu.md +58 -0
  15. package/agent-tools/guidelines/components/overview.md +97 -17
  16. package/agent-tools/guidelines/components/radial-progress.md +13 -0
  17. package/agent-tools/guidelines/components/select.md +23 -0
  18. package/agent-tools/guidelines/components/tooltips.md +22 -0
  19. package/agent-tools/guidelines/components/video.md +29 -0
  20. package/agent-tools/guidelines/foundations/color.md +140 -58
  21. package/agent-tools/guidelines/foundations/modes.md +39 -17
  22. package/agent-tools/guidelines/foundations/spacing.md +78 -37
  23. package/agent-tools/guidelines/foundations/typography.md +69 -37
  24. package/agent-tools/guidelines/overview-icons.md +19 -0
  25. package/agent-tools/guidelines/overview-illustrations.md +7 -0
  26. package/agent-tools/guidelines/overview-patterns.md +7 -0
  27. package/agent-tools/guidelines/overview.md +69 -23
  28. package/agent-tools/guidelines/setup.md +59 -18
  29. package/agent-tools/rules/accessibility.mdc +22 -13
  30. package/agent-tools/skills/gamut-accessibility/SKILL.md +97 -112
  31. package/agent-tools/skills/gamut-color-mode/SKILL.md +79 -29
  32. package/agent-tools/skills/gamut-components/SKILL.md +46 -0
  33. package/agent-tools/skills/gamut-forms/SKILL.md +101 -0
  34. package/agent-tools/skills/gamut-style-utilities/SKILL.md +111 -0
  35. package/agent-tools/skills/gamut-system-props/SKILL.md +70 -26
  36. package/agent-tools/skills/gamut-testing/SKILL.md +106 -62
  37. package/agent-tools/skills/gamut-theming/SKILL.md +34 -86
  38. package/agent-tools/skills/gamut-typography/SKILL.md +36 -80
  39. package/bin/commands/plugin/install.mjs +96 -56
  40. package/bin/commands/plugin/list.mjs +11 -43
  41. package/bin/commands/plugin/remove.mjs +30 -38
  42. package/bin/commands/plugin/update.mjs +15 -5
  43. package/bin/gamut.mjs +17 -13
  44. package/bin/lib/design.mjs +71 -0
  45. package/bin/lib/io.mjs +14 -0
  46. package/package.json +6 -6
  47. package/bin/lib/figma.mjs +0 -49
@@ -3,10 +3,8 @@ version: alpha
3
3
  name: LX Studio Design System
4
4
  description: Design tokens for the Skillsoft LX Studio authoring platform.
5
5
  colors:
6
- # palette — reference hex for docs/tools; in product UI use semantic colors via Gamut theme (Emotion) / system props or Figma tokens—never paste these literals into code
7
6
  # LX Studio additions — custom brand tokens
8
- lxStudioPurple: '#5628FE'
9
- lxStudioPurpleHover: '#7955FC'
7
+ sapphire: '#1C50BB'
10
8
  lxStudioSuccess: '#06844F'
11
9
  lxStudioBgPrimary: '#FAFBFC'
12
10
  # core palette — referenced by semantic aliases below
@@ -14,13 +12,13 @@ colors:
14
12
  hyper-400: '#5533FF'
15
13
  navy-900: '#0A0D1C'
16
14
  navy-800: '#10162F'
17
- navy-700: '#31374C'
18
- navy-600: '#4C5063'
19
- navy-500: '#686C7C'
20
- navy-400: '#8F919D'
21
- navy-300: '#BCBEC5'
22
- navy-200: '#E2E3E6'
23
- navy-100: '#F5F6F7'
15
+ navy-700: 'rgba(16, 22, 47, 0.86)'
16
+ navy-600: 'rgba(16, 22, 47, 0.75)'
17
+ navy-500: 'rgba(16, 22, 47, 0.63)'
18
+ navy-400: 'rgba(16, 22, 47, 0.47)'
19
+ navy-300: 'rgba(16, 22, 47, 0.28)'
20
+ navy-200: 'rgba(16, 22, 47, 0.12)'
21
+ navy-100: 'rgba(16, 22, 47, 0.04)'
24
22
  yellow-500: '#FFD300'
25
23
  yellow-0: '#FFFAE5'
26
24
  green-700: '#008A27'
@@ -43,13 +41,11 @@ colors:
43
41
  background-success: '{colors.green-0}'
44
42
  background-warning: '{colors.yellow-0}'
45
43
  background-error: '{colors.red-0}'
46
- primary: '{colors.lxStudioPurple}'
47
- primary-hover: '{colors.lxStudioPurpleHover}'
44
+ primary: '{colors.sapphire}'
45
+ primary-hover: '{colors.navy-800}'
48
46
  primary-inverse: '{colors.yellow-500}'
49
47
  secondary: '{colors.navy-800}'
50
48
  secondary-hover: '{colors.navy-700}'
51
- interface: '{colors.hyper-500}'
52
- interface-hover: '{colors.hyper-400}'
53
49
  danger: '{colors.red-500}'
54
50
  danger-hover: '{colors.red-600}'
55
51
  feedback-error: '{colors.red-600}'
@@ -63,22 +59,42 @@ colors:
63
59
  shadow-secondary: '{colors.navy-600}'
64
60
  typography:
65
61
  base:
66
- fontFamily: '"Hanken Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
62
+ fontFamily: '"Skillsoft Text", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
67
63
  fontSize: '1rem'
68
64
  fontWeight: '400'
69
65
  lineHeight: '1.5'
70
66
  accent:
71
- fontFamily: '"Hanken Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
67
+ fontFamily: '"Skillsoft Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
72
68
  fontSize: '0.875rem'
73
69
  fontWeight: '400'
74
70
  lineHeight: '1.5'
75
71
  title:
76
- fontFamily: '"Hanken Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
72
+ fontFamily: '"Skillsoft Text", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
77
73
  fontSize: '2.125rem'
78
- fontWeight: '700'
74
+ fontWeight: '500'
79
75
  lineHeight: '1.2'
80
76
  monospace:
81
77
  fontFamily: 'Monaco, Menlo, "Ubuntu Mono", "Droid Sans Mono", Consolas, monospace'
78
+ system:
79
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
80
+ '14':
81
+ fontSize: '0.875rem'
82
+ '16':
83
+ fontSize: '1rem'
84
+ '18':
85
+ fontSize: '1.125rem'
86
+ '20':
87
+ fontSize: '1.25rem'
88
+ '22':
89
+ fontSize: '1.375rem'
90
+ '26':
91
+ fontSize: '1.625rem'
92
+ '34':
93
+ fontSize: '2.125rem'
94
+ '44':
95
+ fontSize: '2.75rem'
96
+ '64':
97
+ fontSize: '4rem'
82
98
  borderRadii:
83
99
  none: '0px'
84
100
  sm: '4px'
@@ -102,31 +118,62 @@ components:
102
118
  FillButton:
103
119
  backgroundColor: '{colors.primary}'
104
120
  textColor: '{colors.white}'
105
- rounded: '{rounded.md}'
121
+ borderRadii: '{borderRadii.md}'
106
122
  FillButton-hover:
107
123
  backgroundColor: '{colors.primary-hover}'
108
124
  textColor: '{colors.white}'
109
125
  FillButton-danger:
110
126
  backgroundColor: '{colors.danger}'
111
127
  textColor: '{colors.white}'
112
- rounded: '{rounded.md}'
128
+ borderRadii: '{borderRadii.md}'
113
129
  FillButton-danger-hover:
114
130
  backgroundColor: '{colors.danger-hover}'
115
131
  textColor: '{colors.white}'
116
132
  StrokeButton:
117
133
  backgroundColor: 'transparent'
118
134
  textColor: '{colors.secondary}'
119
- rounded: '{rounded.md}'
135
+ borderRadii: '{borderRadii.md}'
136
+ StrokeButton-hover:
137
+ textColor: '{colors.secondary-hover}'
138
+ TextButton:
139
+ backgroundColor: 'transparent'
140
+ textColor: '{colors.primary}'
141
+ TextButton-hover:
142
+ textColor: '{colors.primary-hover}'
143
+ IconButton:
144
+ backgroundColor: 'transparent'
145
+ textColor: '{colors.secondary}'
146
+ IconButton-hover:
147
+ textColor: '{colors.secondary-hover}'
120
148
  Input:
121
149
  backgroundColor: '{colors.background}'
122
150
  textColor: '{colors.text}'
123
- rounded: '{rounded.md}'
151
+ borderRadii: '{borderRadii.md}'
124
152
  borderColor: '{colors.border-primary}'
125
153
  Checkbox:
126
- backgroundColor: '{colors.interface}'
127
- rounded: '{rounded.sm}'
154
+ backgroundColor: '{colors.primary}'
155
+ borderRadii: '{borderRadii.sm}'
128
156
  Checkbox-hover:
129
- backgroundColor: '{colors.interface-hover}'
157
+ backgroundColor: '{colors.primary-hover}'
158
+ Card:
159
+ backgroundColor: '{colors.background}'
160
+ borderRadii: '{borderRadii.none}'
161
+ Card-interactive:
162
+ borderRadii: '{borderRadii.md}'
163
+ Card-elevated:
164
+ backgroundColor: '{colors.background-primary}'
165
+ borderRadii: '{borderRadii.lg}'
166
+ Headline:
167
+ textColor: '{colors.text-accent}'
168
+ typography: '{typography.title}'
169
+ Tag-success:
170
+ backgroundColor: '{colors.feedback-success}'
171
+ textColor: '{colors.white}'
172
+ borderRadii: '{borderRadii.sm}'
173
+ Tag-warning:
174
+ backgroundColor: '{colors.feedback-warning}'
175
+ textColor: '{colors.text}'
176
+ borderRadii: '{borderRadii.sm}'
130
177
  Alert-error:
131
178
  backgroundColor: '{colors.background-error}'
132
179
  textColor: '{colors.feedback-error}'
@@ -140,123 +187,118 @@ components:
140
187
 
141
188
  # LX Studio
142
189
 
143
- This file defines the visual design tokens for the Skillsoft LX Studio authoring platform, implemented using the Gamut design system (`@codecademy/gamut`, `@codecademy/gamut-styles`). LX Studio uses a dedicated Gamut theme that extends Core with its own brand colors, typography, and border radii — all Gamut components work without modification. **Spacing uses the same token scale as Core**; only border radii are larger in this theme (see Border Radius Scale below).
190
+ This file defines the visual design tokens for the Skillsoft LX Studio authoring platform, implemented using the Gamut design system (`@codecademy/gamut`, `@codecademy/gamut-styles`). LX Studio uses a dedicated Gamut theme that extends Core with its own brand colors, typography, and border radii — all Gamut components work without modification.
144
191
 
145
- **Storybook**: https://gamut.codecademy.com
192
+ Storybook: https://gamut.codecademy.com
146
193
 
147
194
  ---
148
195
 
149
- ## Visual Theme & Atmosphere
196
+ ## Overview
150
197
 
151
- LX Studio communicates **modern professional craft** — clean, precise, and tool-like. As an authoring environment for learning content creators, the interface must feel capable and unobtrusive. The design voice prioritizes clarity and control over personality.
198
+ LX Studio communicates modern professional craft — clean, precise, and tool-like. As an authoring environment for learning content creators, the interface must feel capable and unobtrusive. The design voice prioritizes clarity and control over personality.
152
199
 
153
- **Density**: Medium. Layouts are information-dense but well-spaced; generous border radii and soft shadows reduce visual weight.
200
+ Density: Medium. Layouts are information-dense but well-spaced; generous border radii and soft shadows reduce visual weight.
154
201
 
155
- **Design philosophy**:
202
+ Design philosophy:
156
203
 
157
- - Extends **Core** — light and dark color modes are available; `lxStudioTheme` defines explicit **light** overrides and inherits **Core dark** where not overridden
158
204
  - Larger border radii than Core give the UI a softer, more modern feel
159
- - Brand purple (`lxStudioPurple`) drives primary CTAs; `hyper-500` drives interface affordances (checkboxes, toggles)
205
+ - Sapphire (`#1C50BB`) drives primary CTAs and interactive controls in light mode
160
206
  - Shadows are soft (navy-200) rather than hard (navy-800 in Core light mode)
161
- - Hanken Grotesk replaces Apercu and Suisse across all font roles
207
+ - Skillsoft Text and Skillsoft Sans replace Apercu and Suisse across `base` and `accent`
208
+ - Use semantic `background-primary` (`#FAFBFC`) — not Core `beige`
162
209
 
163
- ---
210
+ ### Themes
164
211
 
165
- ## Themes
212
+ LX Studio uses a single Gamut theme that extends Core. Light mode applies LX-specific semantic overrides (sapphire primary, softer borders, larger radii). Dark mode inherits Core dark semantics — use `<ColorMode>` and semantic tokens the same way as Codecademy.
166
213
 
167
- LX Studio uses **`lxStudioTheme`**, which spreads **`coreTheme`** and adds explicit **light** semantic overrides (see `packages/gamut-styles/src/themes/lxStudio.ts`). Dark mode resolves through the same Core color-mode system.
214
+ | Theme | Use case | Base font | Dark mode |
215
+ | --------- | -------------------------------------- | --------------------- | -------------- |
216
+ | LX Studio | Skillsoft LX Studio authoring platform | Skillsoft Sans / Text | ✓ light + dark |
168
217
 
169
- | Theme | Use case | Base font | Dark mode |
170
- | ------------- | -------------------------------------- | -------------- | ------------------------------------------------------- |
171
- | **LX Studio** | Skillsoft LX Studio authoring platform | Hanken Grotesk | yes (inherits Core dark; light overrides in theme file) |
172
-
173
- The active theme is set at the app root via `<GamutProvider theme={lxStudioTheme}>`.
218
+ Set the active theme via `<GamutProvider theme={lxStudioTheme}>`. For new LX Studio apps, default to `lxStudioTheme` unless another theme is explicitly requested. Install in app repos: `gamut plugin install cursor --theme lxstudio` (copies to `./DESIGN.md`).
174
219
 
175
220
  ---
176
221
 
177
- ## Semantic Color Aliases
222
+ ## Colors
223
+
224
+ Use semantic token names in code and designs. They resolve per color mode automatically. Never hardcode hex values for adaptive UI. Never hardcode `beige` — LX maps `background-primary` to `lxStudioBgPrimary` (`#FAFBFC`).
178
225
 
179
- Use these token names when specifying colors. **`lxStudioTheme`** (`packages/gamut-styles/src/themes/lxStudio.ts`) extends **`coreTheme`**, so **light and dark** color modes behave like Codecademy: the theme file lists explicit **light** overrides, and **dark** uses **Core dark** semantics anywhere LX does not override them (`packages/gamut-styles/src/themes/core.ts`). Hex values in the tables below document **light mode** for designer handoff. The YAML `components:` block at the top of this file is an **illustrative recipe set** for handoff tools—use semantic system props in application code.
226
+ For dark/light regions, use `<ColorMode>` or `<Background>` never swap colors manually with custom CSS.
180
227
 
181
228
  ### Text
182
229
 
183
- | Token | Value | Use for |
184
- | ---------------- | -------------------- | --------------------------- |
185
- | `text` | `#10162F` (navy-800) | Default body and UI text |
186
- | `text-accent` | `#0A0D1C` (navy-900) | Stronger emphasis text |
187
- | `text-secondary` | `#4C5063` (navy-600) | Supporting / secondary copy |
188
- | `text-disabled` | `#686C7C` (navy-500) | Disabled state labels |
230
+ | Token | Light | Dark | Use for |
231
+ | ---------------- | --------------------------------- | --------------- | --------------------------- |
232
+ | `text` | navy-800 `#10162F` | white `#ffffff` | Default body and UI text |
233
+ | `text-accent` | navy-900 `#0A0D1C` | beige `#FFF0E5` | Stronger emphasis text |
234
+ | `text-secondary` | navy-600 `rgba(16, 22, 47, 0.75)` | white at 65% | Supporting / secondary copy |
235
+ | `text-disabled` | navy-500 `rgba(16, 22, 47, 0.63)` | white at 50% | Disabled state labels |
189
236
 
190
237
  ### Background
191
238
 
192
- | Token | Value | Use for |
193
- | --------------------- | ----------------------------- | --------------------------------- |
194
- | `background` | `#ffffff` | Default page/component background |
195
- | `background-primary` | `#FAFBFC` (lxStudioBgPrimary) | Slightly elevated surfaces |
196
- | `background-contrast` | `#ffffff` | Maximum contrast surface |
197
- | `background-selected` | `#F5F6F7` (navy-100) | Selected row / item |
198
- | `background-hover` | `#E2E3E6` (navy-200) | Hover state overlay |
199
- | `background-disabled` | `#E2E3E6` (navy-200) | Disabled surface |
200
- | `background-success` | `#F5FFE3` (green-0) | Success state container |
201
- | `background-warning` | `#FFFAE5` (yellow-0) | Warning state container |
202
- | `background-error` | `#FBF1F0` (red-0) | Error state container |
239
+ | Token | Light | Dark | Use for |
240
+ | --------------------- | --------------------------------- | -------------------- | --------------------------------- |
241
+ | `background` | white `#ffffff` | navy-800 `#10162F` | Default page/component background |
242
+ | `background-primary` | `#FAFBFC` (lxStudioBgPrimary) | navy-900 `#0A0D1C` | Slightly elevated surfaces |
243
+ | `background-contrast` | white `#ffffff` | black `#000000` | Maximum contrast surface |
244
+ | `background-selected` | navy-100 `rgba(16, 22, 47, 0.04)` | white at 4% | Selected row / item |
245
+ | `background-hover` | navy-200 `rgba(16, 22, 47, 0.12)` | white at 9% | Hover state overlay |
246
+ | `background-disabled` | navy-200 `rgba(16, 22, 47, 0.12)` | white at 9% | Disabled surface |
247
+ | `background-success` | green-0 `#F5FFE3` | green-900 `#151C07` | Success state container |
248
+ | `background-warning` | yellow-0 `#FFFAE5` | yellow-900 `#211B00` | Warning state container |
249
+ | `background-error` | red-0 `#FBF1F0` | red-900 `#280503` | Error state container |
203
250
 
204
251
  ### Interactive
205
252
 
206
- | Token | Value | Use for |
207
- | ----------------- | ------------------------------- | --------------------------------------------- |
208
- | `primary` | `#5628FE` (lxStudioPurple) | Primary CTA, links, focus rings |
209
- | `primary-hover` | `#7955FC` (lxStudioPurpleHover) | Hover state of primary interactive |
210
- | `primary-inverse` | `#FFD300` (yellow-500) | Primary on a colored background |
211
- | `secondary` | `#10162F` (navy-800) | Secondary CTA, ghost buttons |
212
- | `secondary-hover` | `#31374C` (navy-700) | Hover state of secondary interactive |
213
- | `interface` | `#3A10E5` (hyper-500) | UI affordances (checkboxes, toggles, sliders) |
214
- | `interface-hover` | `#5533FF` (hyper-400) | Hover on interface elements |
215
- | `danger` | `#E91C11` (red-500) | Destructive actions, error states |
216
- | `danger-hover` | `#BE1809` (red-600) | Hover on danger interactive |
217
-
218
- **Key distinction**: `primary` (lxStudioPurple `#5628FE`) differs from `interface` (hyper-500 `#3A10E5`). Buttons and links use the lighter LX Studio purple; checkboxes, toggles, and sliders use the deeper hyper purple.
253
+ | Token | Light | Dark | Use for |
254
+ | ----------------- | --------------------------------- | -------------------- | ---------------------------------- |
255
+ | `primary` | sapphire `#1C50BB` | yellow-500 `#FFD300` | Primary CTA, links, focus rings |
256
+ | `primary-hover` | navy-800 `#10162F` | yellow-400 `#CCA900` | Hover state of primary interactive |
257
+ | `primary-inverse` | yellow-500 `#FFD300` | hyper-500 `#3A10E5` | Primary on a colored background |
258
+ | `secondary` | navy-800 `#10162F` | white `#ffffff` | Secondary CTA, ghost buttons |
259
+ | `secondary-hover` | navy-700 `rgba(16, 22, 47, 0.86)` | white at 80% | Hover state of secondary |
260
+ | `danger` | red-500 `#E91C11` | red-300 `#E85D7F` | Destructive actions, error states |
261
+ | `danger-hover` | red-600 `#BE1809` | red-400 `#DC5879` | Hover on danger interactive |
219
262
 
220
263
  ### Border
221
264
 
222
- | Token | Value | Use for |
223
- | ------------------ | -------------------- | ------------------------------- |
224
- | `border-primary` | `#8F919D` (navy-400) | Standard input and card borders |
225
- | `border-secondary` | `#4C5063` (navy-600) | Medium-weight borders |
226
- | `border-tertiary` | `#10162F` (navy-800) | Strong structural borders |
227
- | `border-disabled` | `#BCBEC5` (navy-300) | Disabled input borders |
265
+ | Token | Light | Dark | Use for |
266
+ | ------------------ | --------------------------------- | --------------- | ------------------------------- |
267
+ | `border-primary` | navy-400 `rgba(16, 22, 47, 0.47)` | white `#ffffff` | Standard input and card borders |
268
+ | `border-secondary` | navy-600 `rgba(16, 22, 47, 0.75)` | white at 65% | Medium-weight borders |
269
+ | `border-tertiary` | navy-800 `#10162F` | white at 20% | Strong structural borders |
270
+ | `border-disabled` | navy-300 `rgba(16, 22, 47, 0.28)` | white at 50% | Disabled input borders |
228
271
 
229
272
  LX Studio's `border-primary` is mid-gray (navy-400) rather than Core's near-black navy-800 — borders are softer and less prominent.
230
273
 
231
274
  ### Feedback
232
275
 
233
- | Token | Value | Use for |
234
- | ------------------ | --------------------------- | -------------------------------- |
235
- | `feedback-error` | `#BE1809` (red-600) | Error messages, validation |
236
- | `feedback-success` | `#06844F` (lxStudioSuccess) | Success messages, confirmations |
237
- | `feedback-warning` | `#FFD300` (yellow-500) | Warning messages, caution states |
276
+ | Token | Light | Dark | Use for |
277
+ | ------------------ | --------------------------- | ------------------- | -------------------------------- |
278
+ | `feedback-error` | red-600 `#BE1809` | red-300 `#E85D7F` | Error messages, validation |
279
+ | `feedback-success` | `#06844F` (lxStudioSuccess) | green-400 `#AEE938` | Success messages, confirmations |
280
+ | `feedback-warning` | yellow-500 `#FFD300` | yellow-0 `#FFFAE5` | Warning messages, caution states |
238
281
 
239
282
  ### Shadow
240
283
 
241
- | Token | Value |
242
- | ------------------ | -------------------- |
243
- | `shadow-primary` | `#E2E3E6` (navy-200) |
244
- | `shadow-secondary` | `#4C5063` (navy-600) |
284
+ | Token | Light | Dark |
285
+ | ------------------ | --------------------------------- | ------------ |
286
+ | `shadow-primary` | navy-200 `rgba(16, 22, 47, 0.12)` | white |
287
+ | `shadow-secondary` | navy-600 `rgba(16, 22, 47, 0.75)` | white at 65% |
245
288
 
246
289
  LX Studio shadows are soft — use `shadow-primary` for standard elevated surfaces. This matches Percipio's shadow weight, not Core's hard navy-800 shadow.
247
290
 
248
291
  ---
249
292
 
250
- ## LX Studio Color Palette
293
+ ### LX Studio color palette
251
294
 
252
- LX Studio adds four named colors to the core palette. Use semantic aliases in code, not these raw names.
295
+ LX Studio adds named colors to the core palette. Use semantic aliases in code, not these raw names.
253
296
 
254
- | Named color | Value | Mapped to |
255
- | --------------------- | --------- | -------------------- |
256
- | `lxStudioPurple` | `#5628FE` | `primary` |
257
- | `lxStudioPurpleHover` | `#7955FC` | `primary-hover` |
258
- | `lxStudioSuccess` | `#06844F` | `feedback-success` |
259
- | `lxStudioBgPrimary` | `#FAFBFC` | `background-primary` |
297
+ | Named color | Value | Mapped to |
298
+ | ------------------- | --------- | -------------------------------- |
299
+ | `sapphire` | `#1C50BB` | `primary` (shared with Percipio) |
300
+ | `lxStudioSuccess` | `#06844F` | `feedback-success` |
301
+ | `lxStudioBgPrimary` | `#FAFBFC` | `background-primary` |
260
302
 
261
303
  The full core swatch palette (navy, hyper, blue, green, yellow, red, etc.) is also available. Raw swatches should only be used for fixed colors that must not adapt (illustrations, data viz, etc.).
262
304
 
@@ -266,31 +308,31 @@ The full core swatch palette (navy, hyper, blue, green, yellow, red, etc.) is al
266
308
 
267
309
  ### Typefaces
268
310
 
269
- LX Studio uses **Hanken Grotesk** for all font roles. There is no Apercu and no Suisse.
311
+ LX Studio uses Skillsoft Text for `base` and Skillsoft Sans for `accent`. There is no Apercu and no Suisse.
270
312
 
271
- | Token | Font | Use for |
272
- | ----------- | ----------------------------------------------------- | --------------------------------------------------------------- |
273
- | `base` | `"Hanken Grotesk"`, sans-serif fallback | All default UI text, headlines, body copy |
274
- | `accent` | `"Hanken Grotesk"`, sans-serif fallback | Labels, captions, technical context (same as base in LX Studio) |
275
- | `monospace` | Monaco, Menlo, Ubuntu Mono, Droid Sans Mono, Consolas | Code editor contexts |
276
- | `system` | System UI fonts | Performance-critical surfaces |
313
+ | Token | Font | Use for |
314
+ | ----------- | ----------------------------------------------------- | ----------------------------------------- |
315
+ | `base` | `"Skillsoft Text", …` | All default UI text, headlines, body copy |
316
+ | `accent` | `"Skillsoft Sans", …` | Labels, captions, technical context |
317
+ | `monospace` | Monaco, Menlo, Ubuntu Mono, Droid Sans Mono, Consolas | Code editor contexts |
318
+ | `system` | System UI fonts | Performance-critical surfaces |
277
319
 
278
- Hanken Grotesk is served from `https://www.codecademy.com/gamut/` in four variants: regular, italic, bold, bold-italic.
320
+ Skillsoft fonts are loaded via `GamutProvider` asset configuration (see `@codecademy/gamut-styles` remote font assets).
279
321
 
280
322
  ### Rules
281
323
 
282
- - **Hanken Grotesk Bold (700)** for headlines, sub-headlines, CTAs, and buttons.
283
- - **Hanken Grotesk Regular (400)** for body text, UI labels, and menu items.
284
- - Text is **left-aligned** by default. Center-align only for short marketing headlines. Never right-align.
324
+ - Skillsoft Medium (500) for headlines, sub-headlines, CTAs, and buttons — not Bold (700).
325
+ - Skillsoft Regular (400) for body text, UI labels, and menu items.
326
+ - Text is left-aligned by default. Center-align only for short marketing headlines. Never right-align.
285
327
  - Do not adjust letter-spacing.
286
- - No separate accent typeface Hanken Grotesk is used uniformly for `base` and `accent`.
328
+ - `accent` uses Skillsoft Sans; `base` uses Skillsoft Text they are intentionally different families.
287
329
 
288
330
  ### Font weight scale
289
331
 
290
- | Token | Value | Use |
291
- | ------- | ----- | ------------------------ |
292
- | `base` | 400 | Body text, UI labels |
293
- | `title` | 700 | Headlines, CTAs, buttons |
332
+ | Token | Value | Use |
333
+ | ------- | ----- | ------------------------------------------------------------- |
334
+ | `base` | 400 | Body text, UI labels |
335
+ | `title` | 500 | Headlines, CTAs, buttons _(matches Percipio, not Core's 700)_ |
294
336
 
295
337
  ### Font size scale
296
338
 
@@ -324,7 +366,9 @@ Target 45–85 characters per line; 66 characters is ideal. Max 50 for multi-col
324
366
 
325
367
  ---
326
368
 
327
- ## Spacing Scale
369
+ ## Layout
370
+
371
+ ### Spacing scale
328
372
 
329
373
  Identical to Core. All spacing is multiples of 4px on an 8px grid.
330
374
 
@@ -342,60 +386,61 @@ Identical to Core. All spacing is multiples of 4px on an 8px grid.
342
386
  | `64` | 64px |
343
387
  | `96` | 96px |
344
388
 
345
- ---
389
+ ### System props
346
390
 
347
- ## Border Radius Scale
391
+ Never use inline `style` attributes. Use system props shorthand (`m`, `mb`, `p`, etc.) and Gamut tokens for colors and borders.
348
392
 
349
- LX Studio uses larger border radii than Core — everything is one step softer.
393
+ ### Responsive behavior
350
394
 
351
- | Token | LX Studio | Core | Use |
352
- | ------ | --------- | ----- | ------------------------------------------ |
353
- | `none` | 0px | 0px | Square / non-interactive elements |
354
- | `sm` | **4px** | 2px | Subtle rounding, tags, checkboxes |
355
- | `md` | **8px** | 4px | Default buttons, inputs, interactive cards |
356
- | `lg` | **12px** | 8px | Cards, panels |
357
- | `xl` | 16px | 16px | Large cards, modals |
358
- | `full` | 999px | 999px | Pills, avatars, circular elements |
395
+ Identical to Core. Mobile-first; 12-column grid; 44×44px minimum touch targets on mobile.
359
396
 
360
397
  ---
361
398
 
362
- ## Responsive Behavior
399
+ ## Elevation & Depth
363
400
 
364
- Identical to Core. Mobile-first, apply styles from the named breakpoint up.
401
+ LX Studio shadows are soft — use `shadow-primary` (navy-200) for elevated surfaces, not Core's hard navy-800 shadow in light mode.
365
402
 
366
- | Token | Min-width | Max content |
367
- | -------- | --------- | ----------- |
368
- | _(base)_ | 0 | 288px |
369
- | `xs` | 480px | 448px |
370
- | `sm` | 768px | 704px |
371
- | `md` | 1024px | 896px |
372
- | `lg` | 1200px | 1072px |
373
- | `xl` | 1440px | 1248px |
403
+ ---
374
404
 
375
- 12-column grid at all breakpoints.
405
+ ## Shapes
376
406
 
377
- | Usage | Recommended values |
378
- | --------------------- | ------------------------------------------------ |
379
- | Horizontal margins | 64px (lg+), 48px (md), 32px (sm/xs), 16px (base) |
380
- | Column gaps (gutters) | 32px (lg+), 24px (md), 16px (sm/xs), 8px (base) |
381
- | Row gaps | 32px (lg+), 24px (md), 16px (sm/xs), 8px (base) |
407
+ LX Studio uses larger border radii than Core — defined in `lxStudioBorderRadii`. No custom radius values.
382
408
 
383
- Minimum interactive touch target: **44×44px** on mobile breakpoints.
409
+ | Token | LX Studio | Core | Use |
410
+ | ------ | --------- | ----- | ------------------------------------------ |
411
+ | `none` | 0px | 0px | Square / non-interactive elements |
412
+ | `sm` | 4px | 2px | Subtle rounding, tags, checkboxes |
413
+ | `md` | 8px | 4px | Default buttons, inputs, interactive cards |
414
+ | `lg` | 12px | 8px | Cards, panels |
415
+ | `xl` | 16px | 16px | Large cards, modals |
416
+ | `full` | 999px | 999px | Pills, avatars, circular elements |
384
417
 
385
418
  ---
386
419
 
387
- ## Component Library
420
+ ## Components
388
421
 
389
422
  Same component library as Codecademy — all atoms, molecules, and organisms apply. Token values resolve differently per theme automatically.
390
423
 
391
- Key LX Studio-specific visual differences:
424
+ ### LX Studio visual differences
392
425
 
393
- - `FillButton` uses `#5628FE` (lxStudioPurple) instead of hyper-500
394
- - `FillButton` hover shifts to `#7955FC` (lxStudioPurpleHover) lighter, not darker, on hover
395
- - `Checkbox` / `Toggle` use `hyper-500` (`#3A10E5`) not the brand purple
396
- - All interactive elements have `borderRadius: md` (8px) instead of Core's 4px
426
+ - `FillButton` uses sapphire `#1C50BB` in light mode instead of hyper-500
427
+ - `FillButton` hover shifts to navy-800 `#10162F` in light mode
428
+ - Interactive elements use `borderRadius: md` (8px, not Core's 4px)
397
429
  - `Card` shadows use navy-200 (soft) rather than navy-800 (hard)
398
- - No `Card-beige` variant — LX Studio `background-primary` is off-white, not beige
430
+ - Prefer `background-primary` over beige for elevated surfaces
431
+
432
+ ### Gamut implementation guardrails
433
+
434
+ Same rules as Codecademy (`DESIGN.Codecademy.md` Components section), with LX-specific notes:
435
+
436
+ - Buttons: no generic `Button`; `IconButton` requires `tip`; never set `mode` on buttons; use `borderRadii.md` (8px) on buttons/inputs.
437
+ - Forms: `GridForm` / `ConnectedForm` for submit flows.
438
+ - Cards: valid variants `default`, `white`, `yellow`, `beige`, `navy`, `hyper`; defaults `shadow="none"`, `isInteractive={false}`.
439
+ - DataTable / DataList: `sortable` requires `query`, `onQueryChange`, and client-sorted rows.
440
+ - Menu: always explicit `variant` (`fixed` + `as="nav"` or `popover`).
441
+ - Color mode: `<ColorMode>` / `<Background>` only.
442
+ - Accessibility: WCAG, `FocusTrap` in modals/drawers.
443
+ - Assets: `@codecademy/gamut-icons`, `gamut-illustrations`, `gamut-patterns`.
399
444
 
400
445
  ---
401
446
 
@@ -403,57 +448,64 @@ Key LX Studio-specific visual differences:
403
448
 
404
449
  ### Colors
405
450
 
406
- - **Do** use semantic color aliases (`primary`, `text`, `background`, etc.) — never hardcode hex values.
407
- - **Do** use `lxStudioPurple` (`#5628FE`) via `primary` for buttons and links.
408
- - **Do** use `hyper-500` (`#3A10E5`) via `interface` for checkboxes, toggles, and sliders.
409
- - **Don't** use `primary` and `interface` interchangeably — they are intentionally different purples.
410
- - **Don't** treat the semantic tables as exhaustive for dark mode — they show resolved **light** values; use tokens and `colorMode` in code.
411
- - **Don't** use the Percipio or Codecademy primary blue/hyper colors directly; go through semantic aliases.
451
+ - Do use semantic color aliases (`primary`, `text`, `background`, etc.) — never hardcode hex values.
452
+ - Do use `<ColorMode>` and `<Background>` for scoped light/dark — dark mode inherits from Core.
453
+ - Don't use the Percipio or Codecademy palette swatches directly; go through semantic aliases.
412
454
 
413
455
  ### Typography
414
456
 
415
- - **Do** use Hanken Grotesk Bold (700) for headlines, CTAs, and buttons.
416
- - **Do** keep body text at 150–175% line height for readability.
417
- - **Don't** use Apercu or Suisse — those fonts are not available in LX Studio.
418
- - **Don't** right-align or center-align body paragraphs.
419
- - **Don't** adjust letter-spacing.
457
+ - Do use title weight (500) for headlines, CTAs, and buttons — not 700.
458
+ - Do keep body text at 150–175% line height for readability.
459
+ - Don't use Apercu or Suisse — LX Studio uses Skillsoft Text and Skillsoft Sans.
460
+ - Don't right-align or center-align body paragraphs.
461
+ - Don't adjust letter-spacing.
420
462
 
421
463
  ### Layout & Spacing
422
464
 
423
- - **Do** use the shared Core **spacing** token scale (`4`–`96`) — LX Studio does not define a separate spacing ramp; only **border radii** differ from Core.
424
- - **Do** use multiples of 8px for block-element spacing (4px only for inline / typographic relationships).
425
- - **Do** begin design work at 1440px (XL), then adapt down.
426
- - **Do** align elements to the 12-column grid.
427
- - **Do** apply the larger `md` border radius (8px) to buttons and inputs — it defines the LX Studio feel.
465
+ - Do use multiples of 8px for block-element spacing (4px only for inline / typographic relationships).
466
+ - Do begin design work at 1440px (XL), then adapt down.
467
+ - Do align elements to the 12-column grid.
468
+ - Do apply the larger `md` border radius (8px) to buttons and inputs — it defines the LX Studio feel.
469
+
470
+ ### Components
471
+
472
+ - Don't import a generic `Button` or use Apercu / Suisse.
473
+ - Don't use bare form atoms for functional forms.
474
+
475
+ ### Pre-ship validation
476
+
477
+ Before considering UI output final, run `/gamut-review` from the app repository root (the directory that contains `DESIGN.md`). Install the plugin first if needed: Cursor — `gamut plugin install cursor --theme lxstudio`; Claude Code — `gamut plugin install claude --theme lxstudio`.
478
+
479
+ The command performs automated checks (dependencies, `GamutProvider`, imports, hex colors, tests, component guardrails) and prints a manual pre-ship checklist keyed to this product's theme. Fix all errors before shipping. Full procedure: [`commands/gamut-review.md`](commands/gamut-review.md) in `@codecademy/gamut` agent-tools (installed as a slash command with the Gamut plugin).
428
480
 
429
481
  ---
430
482
 
431
483
  ## Agent Prompt Guide
432
484
 
433
- Quick color/token reference for generating or specifying LX Studio UI. **Token names are the contract**; parenthetical hex is reference only. Implement with `@codecademy/gamut-styles` theme keys and system props, not raw color strings.
434
-
435
- | Scenario | Tokens |
436
- | ----------------- | ------------------------------------------------------------------------------------------------------------------ |
437
- | Primary button | `bg: primary (#5628FE)`, `color: white`, `hover: primary-hover (#7955FC)`, `borderRadius: md (8px)` |
438
- | Body text | `color: text (#10162F)`, `font: Hanken Grotesk`, `size: 16px`, `weight: 400`, `lineHeight: base (1.5)` |
439
- | Headline | `color: text-accent (#0A0D1C)`, `font: Hanken Grotesk`, `size: 34–64px`, `weight: 700`, `lineHeight: title (1.2)` |
440
- | Secondary text | `color: text-secondary (#4C5063)` |
441
- | Disabled text | `color: text-disabled (#686C7C)` |
442
- | Elevated surface | `bg: background-primary (#FAFBFC)` |
443
- | Card default | `bg: background (#ffffff)`, `borderRadius: none` — add `isInteractive` for hover shadow + `borderRadius: md (8px)` |
444
- | Checkbox / toggle | `interface (#3A10E5)`, `hover: interface-hover (#5533FF)` |
445
- | Error state | `color: feedback-error (#BE1809)`, `bg: background-error (#FBF1F0)`, `border: danger` |
446
- | Success state | `color: feedback-success (#06844F)`, `bg: background-success (#F5FFE3)` |
447
- | Warning state | `color: feedback-warning (#FFD300)`, `bg: background-warning (#FFFAE5)` |
448
- | Disabled state | `color: text-disabled (#686C7C)`, `bg: background-disabled (#E2E3E6, navy-200)`, `border: border-disabled` |
485
+ Quick color/token reference for generating or specifying LX Studio UI:
486
+
487
+ | Scenario | Tokens |
488
+ | ----------------- | ------------------------------------------------------------------------------------------------------------------------- |
489
+ | Primary button | `bg: primary (#1C50BB)`, `color: white`, `hover: primary-hover (#10162F)`, `borderRadius: md (8px)` |
490
+ | Body text | `color: text (#10162F)`, `font: Skillsoft Text`, `size: 16px`, `weight: 400`, `lineHeight: base (1.5)` |
491
+ | Headline | `color: text-accent (#0A0D1C)`, `font: Skillsoft Text`, `size: 34–64px`, `weight: title (500)`, `lineHeight: title (1.2)` |
492
+ | Secondary text | `color: text-secondary (navy-600)` |
493
+ | Disabled text | `color: text-disabled (navy-500)` |
494
+ | Elevated surface | `bg: background-primary (#FAFBFC)` |
495
+ | Card default | `bg: background (#ffffff)`, `borderRadius: none` — add `isInteractive` for hover shadow + `borderRadius: md (8px)` |
496
+ | Checkbox / toggle | `primary` / `primary-hover` (theme-resolved via Gamut Checkbox) |
497
+ | Error state | `color: feedback-error (#BE1809)`, `bg: background-error (#FBF1F0)`, `border: danger` |
498
+ | Success state | `color: feedback-success (#06844F)`, `bg: background-success (#F5FFE3)` |
499
+ | Warning state | `color: feedback-warning (#FFD300)`, `bg: background-warning (#FFFAE5)` |
500
+ | Disabled state | `color: text-disabled (navy-500)`, `bg: background-disabled (navy-200)`, `border: border-disabled` |
449
501
 
450
502
  ### Component token cheatsheet
451
503
 
452
504
  ```
453
- FillButton → bg: primary (#5628FE), color: white, hover: primary-hover (#7955FC), radius: 8px
505
+ FillButton → bg: primary (#1C50BB), color: white, hover: primary-hover (#10162F), radius: 8px
454
506
  StrokeButton → bg: transparent, border: secondary (#10162F)
455
- Checkbox/Toggle → interface (#3A10E5), hover: interface-hover (#5533FF), radius: 4px
456
- Card → bg: background, shadow: shadow-primary (#E2E3E6, navy-200, soft), radius: none
507
+ Checkbox/Toggle → primary (theme-resolved), hover: primary-hover, radius: 4px
508
+ Card → bg: background, shadow: shadow-primary (navy-200, soft), radius: none
457
509
  Alert (error) → uses feedback-error + background-error
458
510
  Alert (success) → uses feedback-success + background-success
459
511
  Alert (warning) → uses feedback-warning + background-warning