@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,12 +3,12 @@ version: alpha
3
3
  name: Percipio Design System
4
4
  description: Design tokens for the Skillsoft Percipio 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
6
+ # palette — raw swatches; set once on :root and then always reference by token name, never use hex values directly in code
7
7
  percipioTextPrimary: '#222325'
8
8
  percipioTextAccent: '#222325'
9
9
  percipioTextSecondary: 'rgba(34, 35, 37, 0.75)'
10
10
  percipioTextDisabled: '#AFB6C2'
11
- percipioActionPrimary: '#0073C4'
11
+ sapphire: '#1C50BB'
12
12
  percipioActionPrimaryHover: '#141C36'
13
13
  percipioActionSecondary: '#6A6E75'
14
14
  percipioActionSecondaryHover: 'rgba(106, 110, 117, 0.86)'
@@ -21,10 +21,10 @@ colors:
21
21
  percipioBgWarning: '#FFF7E0'
22
22
  percipioBgError: '#FFF1F5'
23
23
  navy-800: '#10162F'
24
- navy-400: '#8F919D'
25
- navy-300: '#BCBEC5'
26
- navy-200: '#E2E3E6'
27
- navy-100: '#F5F6F7'
24
+ navy-400: 'rgba(16, 22, 47, 0.47)'
25
+ navy-300: 'rgba(16, 22, 47, 0.28)'
26
+ navy-200: 'rgba(16, 22, 47, 0.12)'
27
+ navy-100: 'rgba(16, 22, 47, 0.04)'
28
28
  white: '#ffffff'
29
29
  # semantic aliases — use these in code, not palette swatches or hex values
30
30
  text: '{colors.percipioTextPrimary}'
@@ -39,13 +39,11 @@ colors:
39
39
  background-success: '{colors.percipioBgSuccess}'
40
40
  background-warning: '{colors.percipioBgWarning}'
41
41
  background-error: '{colors.percipioBgError}'
42
- primary: '{colors.percipioActionPrimary}'
42
+ primary: '{colors.sapphire}'
43
43
  primary-hover: '{colors.percipioActionPrimaryHover}'
44
44
  primary-inverse: '{colors.white}'
45
45
  secondary: '{colors.percipioActionSecondary}'
46
46
  secondary-hover: '{colors.percipioActionSecondaryHover}'
47
- interface: '{colors.percipioActionPrimary}'
48
- interface-hover: '{colors.percipioActionPrimaryHover}'
49
47
  danger: '{colors.percipioDanger}'
50
48
  danger-hover: '{colors.percipioActionDangerHover}'
51
49
  feedback-error: '{colors.percipioDanger}'
@@ -59,22 +57,42 @@ colors:
59
57
  shadow-secondary: '{colors.navy-400}'
60
58
  typography:
61
59
  base:
62
- fontFamily: '"Roboto", sans-serif'
60
+ fontFamily: '"Skillsoft Text", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
63
61
  fontSize: '1rem'
64
62
  fontWeight: '400'
65
63
  lineHeight: '1.5'
66
64
  accent:
67
- fontFamily: '"Roboto", sans-serif'
65
+ fontFamily: '"Skillsoft Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
68
66
  fontSize: '0.875rem'
69
67
  fontWeight: '400'
70
68
  lineHeight: '1.5'
71
69
  title:
72
- fontFamily: '"Roboto", sans-serif'
70
+ fontFamily: '"Skillsoft Text", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif'
73
71
  fontSize: '2.125rem'
74
72
  fontWeight: '500'
75
73
  lineHeight: '1.2'
76
74
  monospace:
77
75
  fontFamily: '"Roboto Mono", monospace'
76
+ system:
77
+ fontFamily: '"Roboto", sans-serif'
78
+ '14':
79
+ fontSize: '0.875rem'
80
+ '16':
81
+ fontSize: '1rem'
82
+ '18':
83
+ fontSize: '1.125rem'
84
+ '20':
85
+ fontSize: '1.25rem'
86
+ '22':
87
+ fontSize: '1.375rem'
88
+ '26':
89
+ fontSize: '1.625rem'
90
+ '34':
91
+ fontSize: '2.125rem'
92
+ '44':
93
+ fontSize: '2.75rem'
94
+ '64':
95
+ fontSize: '4rem'
78
96
  borderRadii:
79
97
  none: '0px'
80
98
  sm: '2px'
@@ -94,36 +112,66 @@ spacing:
94
112
  '48': '3rem'
95
113
  '64': '4rem'
96
114
  '96': '6rem'
97
-
98
115
  components:
99
116
  FillButton:
100
117
  backgroundColor: '{colors.primary}'
101
118
  textColor: '{colors.primary-inverse}'
102
- rounded: '{rounded.md}'
119
+ borderRadii: '{borderRadii.md}'
103
120
  FillButton-hover:
104
121
  backgroundColor: '{colors.primary-hover}'
105
122
  textColor: '{colors.primary-inverse}'
106
123
  FillButton-danger:
107
124
  backgroundColor: '{colors.danger}'
108
125
  textColor: '{colors.white}'
109
- rounded: '{rounded.md}'
126
+ borderRadii: '{borderRadii.md}'
110
127
  FillButton-danger-hover:
111
128
  backgroundColor: '{colors.danger-hover}'
112
129
  textColor: '{colors.white}'
113
130
  StrokeButton:
114
131
  backgroundColor: 'transparent'
115
132
  textColor: '{colors.secondary}'
116
- rounded: '{rounded.md}'
133
+ borderRadii: '{borderRadii.md}'
134
+ StrokeButton-hover:
135
+ textColor: '{colors.secondary-hover}'
136
+ TextButton:
137
+ backgroundColor: 'transparent'
138
+ textColor: '{colors.primary}'
139
+ TextButton-hover:
140
+ textColor: '{colors.primary-hover}'
141
+ IconButton:
142
+ backgroundColor: 'transparent'
143
+ textColor: '{colors.secondary}'
144
+ IconButton-hover:
145
+ textColor: '{colors.secondary-hover}'
117
146
  Input:
118
147
  backgroundColor: '{colors.background}'
119
148
  textColor: '{colors.text}'
120
- rounded: '{rounded.md}'
149
+ borderRadii: '{borderRadii.md}'
121
150
  borderColor: '{colors.border-primary}'
122
151
  Checkbox:
123
- backgroundColor: '{colors.interface}'
124
- rounded: '{rounded.sm}'
152
+ backgroundColor: '{colors.primary}'
153
+ borderRadii: '{borderRadii.sm}'
125
154
  Checkbox-hover:
126
- backgroundColor: '{colors.interface-hover}'
155
+ backgroundColor: '{colors.primary-hover}'
156
+ Card:
157
+ backgroundColor: '{colors.background}'
158
+ borderRadii: '{borderRadii.none}'
159
+ Card-interactive:
160
+ borderRadii: '{borderRadii.md}'
161
+ Card-elevated:
162
+ backgroundColor: '{colors.background-primary}'
163
+ borderRadii: '{borderRadii.lg}'
164
+ Headline:
165
+ textColor: '{colors.text-accent}'
166
+ typography: '{typography.title}'
167
+ Tag-success:
168
+ backgroundColor: '{colors.feedback-success}'
169
+ textColor: '{colors.white}'
170
+ borderRadii: '{borderRadii.sm}'
171
+ Tag-warning:
172
+ backgroundColor: '{colors.feedback-warning}'
173
+ textColor: '{colors.text}'
174
+ borderRadii: '{borderRadii.sm}'
127
175
  Alert-error:
128
176
  backgroundColor: '{colors.background-error}'
129
177
  textColor: '{colors.feedback-error}'
@@ -139,134 +187,120 @@ components:
139
187
 
140
188
  This file defines the visual design tokens for the Skillsoft Percipio platform, implemented using the Gamut design system (`@codecademy/gamut`, `@codecademy/gamut-styles`). Percipio uses a dedicated Gamut theme that applies its own colors and typography — all Gamut components work without modification.
141
189
 
142
- In handoffs and implementation, **default to semantic token names** (`primary`, `text`, `interface`, …) and Gamut system props — do not paste hex literals where a theme token exists. Hex in this file documents resolved light-mode values for designers and reviewers.
143
-
144
- **Storybook**: https://gamut.codecademy.com
190
+ Storybook: https://gamut.codecademy.com
145
191
 
146
192
  ---
147
193
 
148
- ## Visual Theme & Atmosphere
149
-
150
- Percipio communicates **professional clarity** — clean, trustworthy, and enterprise-ready. The design voice is more neutral and corporate than Codecademy: less playful, more functional. Primary blue drives interactive affordances; neutral grays define text and structure.
194
+ ## Overview
151
195
 
152
- **Density**: Medium. Consistent with Codecademy layouts but with softer shadows and a lighter overall feel due to the muted neutral palette.
196
+ Percipio communicates professional clarity clean, trustworthy, and enterprise-ready. The design voice is more neutral and corporate than Codecademy: less playful, more functional. Primary blue drives interactive affordances; neutral grays define text and structure.
153
197
 
154
- **Design philosophy**:
155
-
156
- - Extends **Core** — light and dark color modes are available; `percipioTheme` defines explicit **light** overrides and inherits **Core dark** where not overridden
157
- - Primary blue (`percipioActionPrimary`) replaces Codecademy's `hyper-500` for all interactive elements
158
- - Text is near-black dark gray rather than navy
159
- - Shadows are soft and minimal (navy at low opacity) rather than hard borders
160
- - Title font weight is 500 (medium) rather than 700 (bold) — Percipio headlines are less heavy
161
-
162
- ---
198
+ Density: Medium. Consistent with Codecademy layouts but with softer shadows and a lighter overall feel due to the muted neutral palette.
163
199
 
164
- ## Themes
200
+ ### Themes
165
201
 
166
- Percipio uses **`percipioTheme`**, which spreads **`coreTheme`** and adds explicit **light** semantic overrides (see `packages/gamut-styles/src/themes/percipio.ts`). Dark mode resolves through the same Core color-mode system.
202
+ Percipio uses a single Gamut theme that extends Core. Light mode applies Percipio-specific semantic overrides (sapphire primary, percipio neutrals). Dark mode inherits Core dark semantics — use `<ColorMode>` and semantic tokens the same way as Codecademy.
167
203
 
168
- | Theme | Use case | Base font | Dark mode |
169
- | ------------ | --------------------------- | --------- | ------------------------------------------------------- |
170
- | **Percipio** | Skillsoft Percipio platform | Roboto | yes (inherits Core dark; light overrides in theme file) |
204
+ | Theme | Use case | Base font | Dark mode |
205
+ | -------- | --------------------------- | --------------------- | -------------- |
206
+ | Percipio | Skillsoft Percipio platform | Skillsoft Sans / Text | light + dark |
171
207
 
172
- The active theme is set at the app root via `<GamutProvider theme={percipioTheme}>`.
208
+ Set the active theme via `<GamutProvider theme={percipioTheme}>`. Install in app repos: `gamut plugin install cursor --theme percipio` (copies to `./DESIGN.md`).
173
209
 
174
210
  ---
175
211
 
176
- ## Semantic Color Aliases
212
+ ## Colors
177
213
 
178
- Use **semantic token names** in specs and code. **`percipioTheme`** (`packages/gamut-styles/src/themes/percipio.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 Percipio does not override them. Hex or rgba in the **Value** column documents **light mode** for designers (`percipioColors` in `packages/gamut-styles/src/variables/colors.ts`). For raw vs semantic usage, see `guidelines/foundations/color.md` in this package.
214
+ Use semantic token names in code and designs. They resolve per color mode automatically. Never hardcode hex values for adaptive UI. Never hardcode core-theme values like `beige` use `background-primary` (`#FAFBFC` on Percipio).
179
215
 
180
- The YAML `components:` block at the top of this file is an **illustrative recipe set**—use semantic system props and Gamut primitives in application code.
216
+ For dark/light regions, use `<ColorMode>` or `<Background>` never swap colors manually with custom CSS.
181
217
 
182
218
  ### Text
183
219
 
184
- | Token | Value | Use for |
185
- | ---------------- | -------------------------------------------------- | ---------------------------------------------- |
186
- | `text` | `#222325` (`percipioTextPrimary`) | Default body and UI text |
187
- | `text-accent` | `#222325` (`percipioTextAccent`) | Emphasis text (same hex as `text` in Percipio) |
188
- | `text-secondary` | `rgba(34, 35, 37, 0.75)` (`percipioTextSecondary`) | Supporting / secondary copy |
189
- | `text-disabled` | `#AFB6C2` (`percipioTextDisabled`) | Disabled state labels |
220
+ | Token | Light | Dark | Use for |
221
+ | ---------------- | ------------------------ | --------------- | ------------------------------------------------ |
222
+ | `text` | `#222325` | white `#ffffff` | Default body and UI text |
223
+ | `text-accent` | `#222325` | beige `#FFF0E5` | Emphasis text (same as `text` in Percipio light) |
224
+ | `text-secondary` | `rgba(34, 35, 37, 0.75)` | white at 65% | Supporting / secondary copy |
225
+ | `text-disabled` | `#AFB6C2` | white at 50% | Disabled state labels |
190
226
 
191
227
  ### Background
192
228
 
193
- | Token | Value | Use for |
194
- | --------------------- | -------------------- | --------------------------------- |
195
- | `background` | `#ffffff` | Default page/component background |
196
- | `background-primary` | `#FAFBFC` | Slightly elevated surfaces |
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` | `#EEF7F3` | Success state container |
201
- | `background-warning` | `#FFF7E0` | Warning state container |
202
- | `background-error` | `#FFF1F5` | Error state container |
229
+ | Token | Light | Dark | Use for |
230
+ | --------------------- | --------------------------------- | -------------------- | --------------------------------- |
231
+ | `background` | white `#ffffff` | navy-800 `#10162F` | Default page/component background |
232
+ | `background-primary` | `#FAFBFC` | navy-900 `#0A0D1C` | Slightly elevated surfaces |
233
+ | `background-selected` | navy-100 `rgba(16, 22, 47, 0.04)` | white at 4% | Selected row / item |
234
+ | `background-hover` | navy-200 `rgba(16, 22, 47, 0.12)` | white at 9% | Hover state overlay |
235
+ | `background-disabled` | navy-200 `rgba(16, 22, 47, 0.12)` | white at 9% | Disabled surface |
236
+ | `background-success` | `#EEF7F3` | green-900 `#151C07` | Success state container |
237
+ | `background-warning` | `#FFF7E0` | yellow-900 `#211B00` | Warning state container |
238
+ | `background-error` | `#FFF1F5` | red-900 `#280503` | Error state container |
203
239
 
204
240
  ### Interactive
205
241
 
206
- | Token | Value | Use for |
207
- | ----------------- | ------------------------------------------------------------ | --------------------------------------------- |
208
- | `primary` | `#0073C4` | Primary CTA, links, focus rings |
209
- | `primary-hover` | `#141C36` | Hover state of primary interactive |
210
- | `primary-inverse` | `#ffffff` | Primary on a colored background |
211
- | `secondary` | `#6A6E75` | Secondary CTA, ghost buttons |
212
- | `secondary-hover` | `rgba(106, 110, 117, 0.86)` (`percipioActionSecondaryHover`) | Hover state of secondary interactive |
213
- | `interface` | `#0073C4` | UI affordances (checkboxes, toggles, sliders) |
214
- | `interface-hover` | `#141C36` | Hover on interface elements |
215
- | `danger` | `#B83C3C` | Destructive actions, error states |
216
- | `danger-hover` | `#A52020` | Hover on danger interactive |
242
+ | Token | Light | Dark | Use for |
243
+ | ----------------- | --------------------------- | -------------------- | ------------------------------------ |
244
+ | `primary` | sapphire `#1C50BB` | yellow-500 `#FFD300` | Primary CTA, links, focus rings |
245
+ | `primary-hover` | `#141C36` | yellow-400 `#CCA900` | Hover state of primary interactive |
246
+ | `primary-inverse` | white `#ffffff` | hyper-500 `#3A10E5` | Primary on a colored background |
247
+ | `secondary` | `#6A6E75` | white `#ffffff` | Secondary CTA, ghost buttons |
248
+ | `secondary-hover` | `rgba(106, 110, 117, 0.86)` | white at 80% | Hover state of secondary interactive |
249
+ | `danger` | `#B83C3C` | red-300 `#E85D7F` | Destructive actions, error states |
250
+ | `danger-hover` | `#A52020` | red-400 `#DC5879` | Hover on danger interactive |
217
251
 
218
252
  ### Border
219
253
 
220
254
  Percipio's border weights use a non-standard order: `primary` is mid-weight, `secondary` is very light, `tertiary` is the strongest (solid navy). Use them for their semantic intent, not their numeric rank.
221
255
 
222
- | Token | Value | Use for |
223
- | ------------------ | -------------------- | ----------------------------------- |
224
- | `border-primary` | `#8F919D` (navy-400) | Standard input and card borders |
225
- | `border-secondary` | `#E2E3E6` (navy-200) | Subtle dividers, section separators |
226
- | `border-tertiary` | `#10162F` (navy-800) | Strong structural borders |
227
- | `border-disabled` | `#BCBEC5` (navy-300) | Disabled input borders |
256
+ | Token | Light | Dark | Use for |
257
+ | ------------------ | --------------------------------- | --------------- | ----------------------------------- |
258
+ | `border-primary` | navy-400 `rgba(16, 22, 47, 0.47)` | white `#ffffff` | Standard input and card borders |
259
+ | `border-secondary` | navy-200 `rgba(16, 22, 47, 0.12)` | white at 65% | Subtle dividers, section separators |
260
+ | `border-tertiary` | navy-800 `#10162F` | white at 20% | Strong structural borders |
261
+ | `border-disabled` | navy-300 `rgba(16, 22, 47, 0.28)` | white at 50% | Disabled input borders |
228
262
 
229
263
  ### Feedback
230
264
 
231
- | Token | Value | Use for |
232
- | ------------------ | --------- | -------------------------------- |
233
- | `feedback-error` | `#B83C3C` | Error messages, validation |
234
- | `feedback-success` | `#1B8057` | Success messages, confirmations |
235
- | `feedback-warning` | `#EF5B0D` | Warning messages, caution states |
265
+ | Token | Light | Dark | Use for |
266
+ | ------------------ | --------- | ------------------- | -------------------------------- |
267
+ | `feedback-error` | `#B83C3C` | red-300 `#E85D7F` | Error messages, validation |
268
+ | `feedback-success` | `#1B8057` | green-400 `#AEE938` | Success messages, confirmations |
269
+ | `feedback-warning` | `#EF5B0D` | yellow-0 `#FFFAE5` | Warning messages, caution states |
236
270
 
237
271
  ### Shadow
238
272
 
239
- | Token | Value |
240
- | ------------------ | -------------------- |
241
- | `shadow-primary` | `#E2E3E6` (navy-200) |
242
- | `shadow-secondary` | `#8F919D` (navy-400) |
273
+ | Token | Light | Dark |
274
+ | ------------------ | --------------------------------- | ------------ |
275
+ | `shadow-primary` | navy-200 `rgba(16, 22, 47, 0.12)` | white |
276
+ | `shadow-secondary` | navy-400 `rgba(16, 22, 47, 0.47)` | white at 65% |
243
277
 
244
278
  Percipio shadows are softer than Codecademy's — use `shadow-primary` for standard elevated surfaces.
245
279
 
246
280
  ---
247
281
 
248
- ## Percipio Color Palette
282
+ ### Percipio color palette
249
283
 
250
284
  Percipio introduces its own named semantic colors. These are the source values behind the aliases above. Use the semantic aliases in designs, not the raw named colors.
251
285
 
252
- | Named color | Value | Mapped to |
253
- | ------------------------------ | --------------------------- | ---------------------------------- |
254
- | `percipioTextPrimary` | `#222325` | `text` |
255
- | `percipioTextAccent` | `#222325` | `text-accent` |
256
- | `percipioTextSecondary` | `rgba(34, 35, 37, 0.75)` | `text-secondary` |
257
- | `percipioTextDisabled` | `#AFB6C2` | `text-disabled` |
258
- | `percipioActionPrimary` | `#0073C4` | `primary`, `interface` |
259
- | `percipioActionPrimaryHover` | `#141C36` | `primary-hover`, `interface-hover` |
260
- | `percipioActionSecondary` | `#6A6E75` | `secondary` |
261
- | `percipioActionSecondaryHover` | `rgba(106, 110, 117, 0.86)` | `secondary-hover` |
262
- | `percipioActionDangerHover` | `#A52020` | `danger-hover` |
263
- | `percipioDanger` | `#B83C3C` | `danger`, `feedback-error` |
264
- | `percipioFeedbackSuccess` | `#1B8057` | `feedback-success` |
265
- | `percipioFeedbackWarning` | `#EF5B0D` | `feedback-warning` |
266
- | `percipioBgPrimary` | `#FAFBFC` | `background-primary` |
267
- | `percipioBgSuccess` | `#EEF7F3` | `background-success` |
268
- | `percipioBgWarning` | `#FFF7E0` | `background-warning` |
269
- | `percipioBgError` | `#FFF1F5` | `background-error` |
286
+ | Named color | Value | Mapped to |
287
+ | ------------------------------ | --------------------------- | -------------------------- |
288
+ | `percipioTextPrimary` | `#222325` | `text` |
289
+ | `percipioTextAccent` | `#222325` | `text-accent` |
290
+ | `percipioTextSecondary` | `rgba(34, 35, 37, 0.75)` | `text-secondary` |
291
+ | `percipioTextDisabled` | `#AFB6C2` | `text-disabled` |
292
+ | `sapphire` | `#1C50BB` | `primary` |
293
+ | `percipioActionPrimaryHover` | `#141C36` | `primary-hover` |
294
+ | `percipioActionSecondary` | `#6A6E75` | `secondary` |
295
+ | `percipioActionSecondaryHover` | `rgba(106, 110, 117, 0.86)` | `secondary-hover` |
296
+ | `percipioActionDangerHover` | `#A52020` | `danger-hover` |
297
+ | `percipioDanger` | `#B83C3C` | `danger`, `feedback-error` |
298
+ | `percipioFeedbackSuccess` | `#1B8057` | `feedback-success` |
299
+ | `percipioFeedbackWarning` | `#EF5B0D` | `feedback-warning` |
300
+ | `percipioBgPrimary` | `#FAFBFC` | `background-primary` |
301
+ | `percipioBgSuccess` | `#EEF7F3` | `background-success` |
302
+ | `percipioBgWarning` | `#FFF7E0` | `background-warning` |
303
+ | `percipioBgError` | `#FFF1F5` | `background-error` |
270
304
 
271
305
  The full core swatch palette (navy, blue, green, yellow, red, etc.) is also available, but the semantic aliases above are how Percipio maps them. Raw swatches should only be used for fixed colors that must not adapt (illustrations, data viz, etc.).
272
306
 
@@ -276,30 +310,30 @@ The full core swatch palette (navy, blue, green, yellow, red, etc.) is also avai
276
310
 
277
311
  ### Typefaces
278
312
 
279
- All font families in Percipio use **Roboto**. There is no separate accent or display typeface.
313
+ Percipio uses Skillsoft Text for body and Skillsoft Sans for accent/labels. Roboto is the `system` fallback; Roboto Mono is used for monospace.
280
314
 
281
- | Token | Font | Use for |
282
- | ----------- | -------------------------- | ------------------------------------------- |
283
- | `base` | `"Roboto", sans-serif` | All default UI text, headlines, body copy |
284
- | `accent` | `"Roboto", sans-serif` | Labels, captions (same as base in Percipio) |
285
- | `monospace` | `"Roboto Mono", monospace` | Code editor contexts |
286
- | `system` | `"Roboto", sans-serif` | Performance-critical surfaces |
315
+ | Token | Font | Use for |
316
+ | ----------- | -------------------------- | ----------------------------------------- |
317
+ | `base` | `"Skillsoft Text", …` | All default UI text, headlines, body copy |
318
+ | `accent` | `"Skillsoft Sans", …` | Labels, captions, technical context |
319
+ | `monospace` | `"Roboto Mono", monospace` | Code editor contexts |
320
+ | `system` | `"Roboto", sans-serif` | Performance-critical surfaces |
287
321
 
288
322
  ### Rules
289
323
 
290
- - **Roboto Medium (500)** for headlines, sub-headlines, CTAs, and buttons — not Bold (700).
291
- - **Roboto Regular (400)** for body text, UI labels, and menu items.
292
- - 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.
293
327
  - Do not adjust letter-spacing.
294
328
 
295
329
  ### Font weight scale
296
330
 
297
331
  Percipio overrides the title weight from Core's 700 to 500 (medium). This gives Percipio a lighter, less heavy headline style.
298
332
 
299
- | Token | Value | Use |
300
- | ------- | ------- | ---------------------------------------------------------- |
301
- | `base` | 400 | Body text, UI labels |
302
- | `title` | **500** | Headlines, CTAs, buttons _(differs from Codecademy's 700)_ |
333
+ | Token | Value | Use |
334
+ | ------- | ----- | ---------------------------------------------------------- |
335
+ | `base` | 400 | Body text, UI labels |
336
+ | `title` | 500 | Headlines, CTAs, buttons _(differs from Codecademy's 700)_ |
303
337
 
304
338
  ### Font size scale
305
339
 
@@ -333,7 +367,9 @@ Target 45–85 characters per line; 66 characters is ideal. Max 50 for multi-col
333
367
 
334
368
  ---
335
369
 
336
- ## Spacing Scale
370
+ ## Layout
371
+
372
+ ### Spacing scale
337
373
 
338
374
  Identical to Core. All spacing is multiples of 4px on an 8px grid.
339
375
 
@@ -351,26 +387,13 @@ Identical to Core. All spacing is multiples of 4px on an 8px grid.
351
387
  | `64` | 64px |
352
388
  | `96` | 96px |
353
389
 
354
- ---
390
+ ### System props
355
391
 
356
- ## Border Radius Scale
392
+ Never use inline `style` attributes. Use system props shorthand (`m`, `mb`, `p`, `px`, etc.) and Gamut tokens for `bg`, `color`, `borderColor`, `borderRadius`.
357
393
 
358
- Identical to Core.
394
+ ### Responsive behavior
359
395
 
360
- | Token | Value | Use |
361
- | ------ | ----- | ------------------------------------------ |
362
- | `none` | 0px | Square / non-interactive elements |
363
- | `sm` | 2px | Subtle rounding, tags |
364
- | `md` | 4px | Default buttons, inputs, interactive cards |
365
- | `lg` | 8px | Cards, panels |
366
- | `xl` | 16px | Large cards, modals |
367
- | `full` | 999px | Pills, avatars, circular elements |
368
-
369
- ---
370
-
371
- ## Responsive Behavior
372
-
373
- Identical to Core. Mobile-first, apply styles from the named breakpoint up.
396
+ Identical to Core. Mobile-first; 12-column grid. Minimum touch target 44×44px on mobile. Begin at 1440px (XL), then adapt down.
374
397
 
375
398
  | Token | Min-width | Max content |
376
399
  | -------- | --------- | ----------- |
@@ -381,29 +404,45 @@ Identical to Core. Mobile-first, apply styles from the named breakpoint up.
381
404
  | `lg` | 1200px | 1072px |
382
405
  | `xl` | 1440px | 1248px |
383
406
 
384
- 12-column grid at all breakpoints.
407
+ ---
408
+
409
+ ## Elevation & Depth
410
+
411
+ Percipio shadows are softer than Codecademy's — use `shadow-primary` (navy-200) for standard elevated surfaces. Card outline shadows use theme-resolved border/shadow tokens.
412
+
413
+ ---
414
+
415
+ ## Shapes
385
416
 
386
- | Usage | Recommended values |
387
- | --------------------- | ------------------------------------------------ |
388
- | Horizontal margins | 64px (lg+), 48px (md), 32px (sm/xs), 16px (base) |
389
- | Column gaps (gutters) | 32px (lg+), 24px (md), 16px (sm/xs), 8px (base) |
390
- | Row gaps | 32px (lg+), 24px (md), 16px (sm/xs), 8px (base) |
417
+ Identical to Core (`borderRadii` in YAML). No custom radius values.
391
418
 
392
- Minimum interactive touch target: **44×44px** on mobile breakpoints.
419
+ | Token | Value | Use |
420
+ | ------ | ----- | ------------------------------------------ |
421
+ | `none` | 0px | Square / non-interactive elements |
422
+ | `sm` | 2px | Subtle rounding, tags, checkboxes |
423
+ | `md` | 4px | Default buttons, inputs, interactive cards |
424
+ | `lg` | 8px | Cards, panels |
425
+ | `xl` | 16px | Large cards, modals |
426
+ | `full` | 999px | Pills, avatars, circular elements |
393
427
 
394
428
  ---
395
429
 
396
- ## Component Library
430
+ ## Components
397
431
 
398
432
  Same component library as Codecademy — all atoms, molecules, and organisms apply. Token values resolve differently per theme automatically.
399
433
 
400
- Key Percipio-specific visual differences:
434
+ ### Gamut implementation guardrails
401
435
 
402
- - `FillButton` uses **`primary`** (Percipio blue — `#0073C4` resolved in light) instead of Codecademy hyper-purple
403
- - `FillButton` hover uses **`primary-hover`** (near-black `#141C36` resolved in light) rather than a lighter purple
404
- - `Checkbox` / `Toggle` use **`interface`** (same Percipio blue ramp as primary affordances)
405
- - `Card` has softer shadows (navy-200 vs navy-800 in Codecademy light mode)
406
- - Card shadow patterns (`patternLeft`, `patternRight`) are available but rarely used in Percipio UIs
436
+ Same rules as Codecademy (`DESIGN.Codecademy.md` Components section), with Percipio-specific notes:
437
+
438
+ - Buttons: no generic `Button`; `IconButton` requires `tip`; never set `mode` on buttons.
439
+ - Forms: `GridForm` / `ConnectedForm` for submit flows; atoms only for standalone/live controls.
440
+ - Cards: valid variants `default`, `white`, `yellow`, `beige`, `navy`, `hyper`; defaults `shadow="none"`, `isInteractive={false}`; set `isInteractive` only for link/interactive cards.
441
+ - DataTable / DataList: `sortable` requires `query`, `onQueryChange`, and client-sorted rows.
442
+ - Menu: always `variant="fixed"` + `as="nav"` or `variant="popover"`.
443
+ - Color mode: `<ColorMode>` / `<Background>`; no manual rgba overrides.
444
+ - Accessibility: WCAG contrast, 44×44px touch targets, `FocusTrap` in modals/drawers.
445
+ - Assets: `@codecademy/gamut-icons`, `gamut-illustrations`, `gamut-patterns`.
407
446
 
408
447
  ---
409
448
 
@@ -411,52 +450,63 @@ Key Percipio-specific visual differences:
411
450
 
412
451
  ### Colors
413
452
 
414
- - **Do** use semantic color aliases (`primary`, `text`, `background`, etc.) — never hardcode hex values in product UI where a token exists.
415
- - **Do** use **`primary`** / **`interface`** (and their hover tokens) for all Percipio blues they resolve to the Percipio palette in the theme; do not duplicate those blues as literals.
416
- - **Don't** use Codecademy's hyper-purple or yellow in Percipio contexts.
417
- - **Don't** treat the semantic tables as exhaustive for dark modethey show resolved **light** values; use tokens and `colorMode` in code.
453
+ - Do use semantic color aliases (`primary`, `text`, `background`, etc.) — never hardcode hex values.
454
+ - Do use `sapphire` (`#1C50BB`) as the primary interactive color via semantic aliases in light mode.
455
+ - Do use `<ColorMode>` and `<Background>` for scoped light/dark — dark mode inherits from Core.
456
+ - Don't use Codecademy's hyper-purple or yellow directly in Percipio contextsuse semantic tokens.
418
457
 
419
458
  ### Typography
420
459
 
421
- - **Do** use title weight (500) for headlines, CTAs, and buttons — not 700.
422
- - **Do** keep body text at 150–175% line height for readability.
423
- - **Don't** use a separate accent typefaceRoboto is used uniformly for base and accent.
424
- - **Don't** right-align or center-align body paragraphs.
425
- - **Don't** adjust letter-spacing.
460
+ - Do use title weight (500) for headlines, CTAs, and buttons — not 700.
461
+ - Do keep body text at 150–175% line height for readability.
462
+ - Don't use Codecademy fonts (Apercu, Suisse)Percipio uses Skillsoft Text and Skillsoft Sans.
463
+ - Don't right-align or center-align body paragraphs.
464
+ - Don't adjust letter-spacing.
426
465
 
427
466
  ### Layout & Spacing
428
467
 
429
- - **Do** use multiples of 8px for block-element spacing (4px only for inline / typographic relationships).
430
- - **Do** begin design work at 1440px (XL), then adapt down.
431
- - **Do** align elements to the 12-column grid.
468
+ - Do use multiples of 8px for block-element spacing (4px only for inline / typographic relationships).
469
+ - Do begin design work at 1440px (XL), then adapt down.
470
+ - Do align elements to the 12-column grid.
471
+
472
+ ### Components
473
+
474
+ - Don't import a generic `Button` or use Codecademy hyper/yellow directly — use semantic tokens.
475
+ - Don't use bare form atoms for functional forms.
476
+
477
+ ### Pre-ship validation
478
+
479
+ 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 percipio`; Claude Code — `gamut plugin install claude --theme percipio`.
480
+
481
+ 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).
432
482
 
433
483
  ---
434
484
 
435
485
  ## Agent Prompt Guide
436
486
 
437
- Quick color/token reference for generating or specifying Percipio 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.
438
-
439
- | Scenario | Tokens |
440
- | ---------------- | ------------------------------------------------------------------------------------------------------------ |
441
- | Primary button | `bg: primary (#0073C4)`, `color: white`, `hover: primary-hover (#141C36)` |
442
- | Body text | `color: text (#222325)`, `font: Roboto`, `size: 16px`, `weight: 400`, `lineHeight: base (1.5)` |
443
- | Headline | `color: text (#222325)`, `font: Roboto`, `size: 34–64px`, `weight: title (500)`, `lineHeight: title (1.2)` |
444
- | Secondary text | `color: text-secondary` (`rgba(34, 35, 37, 0.75)`) |
445
- | Disabled text | `color: text-disabled (#AFB6C2)` |
446
- | Elevated surface | `bg: background-primary (#FAFBFC)` |
447
- | Card default | `bg: background (#ffffff)`, `borderRadius: none` — add `isInteractive` for hover shadow + `borderRadius: md` |
448
- | Error state | `color: feedback-error (#B83C3C)`, `bg: background-error (#FFF1F5)`, `border: danger` |
449
- | Success state | `color: feedback-success (#1B8057)`, `bg: background-success (#EEF7F3)` |
450
- | Warning state | `color: feedback-warning (#EF5B0D)`, `bg: background-warning (#FFF7E0)` |
451
- | Disabled state | `color: text-disabled (#AFB6C2)`, `bg: background-disabled (#E2E3E6, navy-200)`, `border: border-disabled` |
487
+ Quick color/token reference for generating or specifying Percipio UI:
488
+
489
+ | Scenario | Tokens |
490
+ | ---------------- | ------------------------------------------------------------------------------------------------------------------ |
491
+ | Primary button | `bg: primary (#1C50BB)`, `color: white`, `hover: primary-hover (#141C36)` |
492
+ | Body text | `color: text (#222325)`, `font: Skillsoft Text`, `size: 16px`, `weight: 400`, `lineHeight: base (1.5)` |
493
+ | Headline | `color: text (#222325)`, `font: Skillsoft Text`, `size: 34–64px`, `weight: title (500)`, `lineHeight: title (1.2)` |
494
+ | Secondary text | `color: text-secondary (rgba(34, 35, 37, 0.75))` |
495
+ | Disabled text | `color: text-disabled (#AFB6C2)` |
496
+ | Elevated surface | `bg: background-primary (#FAFBFC)` |
497
+ | Card default | `bg: background (#ffffff)`, `borderRadius: none` — add `isInteractive` for hover shadow + `borderRadius: md` |
498
+ | Error state | `color: feedback-error (#B83C3C)`, `bg: background-error (#FFF1F5)`, `border: danger` |
499
+ | Success state | `color: feedback-success (#1B8057)`, `bg: background-success (#EEF7F3)` |
500
+ | Warning state | `color: feedback-warning (#EF5B0D)`, `bg: background-warning (#FFF7E0)` |
501
+ | Disabled state | `color: text-disabled (#AFB6C2)`, `bg: background-disabled (navy-200)`, `border: border-disabled` |
452
502
 
453
503
  ### Component token cheatsheet
454
504
 
455
505
  ```
456
- FillButton → bg: primary (#0073C4), color: white, hover: primary-hover (#141C36)
506
+ FillButton → bg: primary (#1C50BB), color: white, hover: primary-hover (#141C36)
457
507
  StrokeButton → bg: transparent, border: secondary (#6A6E75)
458
- Checkbox/Toggle → interface (#0073C4), hover: interface-hover (#141C36)
459
- Card → bg: background, shadow: shadow-primary (#E2E3E6, navy-200, soft)
508
+ Checkbox/Toggle → primary (theme-resolved), hover: primary-hover
509
+ Card → bg: background, shadow: shadow-primary (navy-200, soft)
460
510
  Alert (error) → uses feedback-error + background-error
461
511
  Alert (success) → uses feedback-success + background-success
462
512
  Alert (warning) → uses feedback-warning + background-warning
@@ -1 +1 @@
1
- Use the appropriate DESIGN.\*.md based on your Gamut theme.
1
+ DEPRECATED. Use the appropriate DESIGN.*.md from https://github.com/Codecademy/gamut/pull/3329 instead.