trdr-ds-install 1.8.1 β†’ 1.9.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trdr-ds-install",
3
- "version": "1.8.1",
3
+ "version": "1.9.0",
4
4
  "description": "Installs the TRDR Design System skill for Claude Code",
5
5
  "bin": {
6
6
  "trdr-ds-install": "./bin/install.js"
@@ -6,7 +6,7 @@ argument-hint: "[analyze|apply|foundation|violations|components|final|resume|sta
6
6
  allowed-tools: [Read, Glob, Grep, Edit, Write, Bash, WebFetch]
7
7
  ---
8
8
 
9
- **Skill version:** 1.8.1
9
+ **Skill version:** 1.9.0
10
10
  **npm package:** trdr-ds-install
11
11
 
12
12
  You are implementing the **TRDR Design System** in a developer's project. The Design Hub is the single source of truth and lives at **https://trdr.mrocontent.com.br**.
@@ -60,7 +60,7 @@ Compare the result with the **Skill version** constant at the top of this file.
60
60
  - If registry version == local version: skip silently, continue.
61
61
  - If registry version > local version:
62
62
  ```
63
- πŸ”„ Nova versΓ£o da skill disponΓ­vel: trdr-ds-install@[registry-version] (instalada: 1.8.1)
63
+ πŸ”„ Nova versΓ£o da skill disponΓ­vel: trdr-ds-install@[registry-version] (instalada: 1.9.0)
64
64
 
65
65
  Responda:
66
66
  - `"atualizar"` / `"update"` β€” instalar a nova versΓ£o agora (requer reiniciar /trdr-ds apΓ³s)
@@ -111,10 +111,26 @@ Read `package.json` at the project root. Identify:
111
111
  | `plain-css` | No `tailwind.config.*`, no `*.module.css`, no CSS-in-JS dep | `class="trdr-btn"` in HTML attributes |
112
112
  | `css-modules` | `*.module.css` files present | `composes: trdr-btn from global` in module file, `className={styles.btn}` in JSX |
113
113
  | `tailwind` | `tailwind.config.*` present | `className="trdr-btn"` alongside Tailwind utilities |
114
- | `css-in-js` | `styled-components` or `@emotion/*` in package.json | Insert token vars inside template literals / `theme` objects |
114
+ | `css-in-js` | `styled-components` or `@emotion/*` in package.json (WITHOUT `@mui/material`) | Insert token vars inside template literals / `theme` objects |
115
+ | `mui` | `@mui/material` in package.json (v5+) | Theme-level integration: `createTheme()` palette/typography/shape use `var(--token)`, component `styleOverrides` use DS tokens, `sx` props migrated to token values |
115
116
 
116
117
  Save `stylingMode` β€” it must be referenced throughout Phase 2 wherever the output format differs by framework.
117
118
 
119
+ **MUI detection priority:**
120
+ If `package.json` contains `@mui/material` (any version >= 5):
121
+ - Set `stylingMode: 'mui'` β€” do NOT fall through to `css-in-js` even if `@emotion/react` or `@emotion/styled` are present (they are MUI transitive dependencies, not direct CSS-in-JS usage)
122
+ - Record `muiVersion` from package.json (e.g., `7.3.9`)
123
+ - Detect MUI theme file: Glob for `**/theme.ts`, `**/theme.js`, `**/theme/index.ts`, `**/theme/index.js`, `**/theme/*.ts`, `**/createTheme*`, `**/muiTheme*` (exclude node_modules)
124
+ - Record `themeFilePath` β€” the primary theme entry point (the file containing `createTheme()`)
125
+ - Detect if project uses `ThemeProvider` in the app root: Grep for `<ThemeProvider` or `<MuiThemeProvider` in layout/app entry files
126
+ - Record `hasThemeProvider: boolean`
127
+
128
+ **MUI + Tailwind simultaneously:**
129
+ If `package.json` contains BOTH `@mui/material` AND `tailwindcss`:
130
+ - Set `stylingMode: 'mui'` (MUI dominant for component styling)
131
+ - Set `hasTailwind: true` β€” Tailwind utilities may coexist for layout
132
+ - In Step 3, scan BOTH theme files AND `tailwind.config.*` for violations
133
+
118
134
  **Dual stylingMode β€” tailwind + styled-components simultaneously:**
119
135
  If `package.json` contains BOTH `tailwindcss` AND `styled-components` (or `@emotion/*`):
120
136
  - Set `stylingMode: 'tailwind'` (dominant β€” utility classes in className)
@@ -154,6 +170,20 @@ Read `tailwind.config.js` (or `tailwind.config.ts`) and check `theme.colors` and
154
170
  - Example: `brand: '#00A8CC'` β†’ `brand: 'var(--content-brand)'`
155
171
  - This allows Tailwind classes like `text-brand` to use the DS token automatically
156
172
 
173
+ **For `mui` stylingMode β€” additional scan:**
174
+ Read all theme files found during detection. Identify:
175
+ - `createTheme()` call location and structure
176
+ - `palette` object: list all hardcoded `#hex` values and their semantic role (primary, secondary, error, warning, success, info, background, text)
177
+ - `typography` object: list all hardcoded `font-family`, `fontSize`, `fontWeight` values
178
+ - `shape` object: list all hardcoded `borderRadius` values
179
+ - `components` object: list all component `styleOverrides` with hardcoded values
180
+ - Whether `cssVariables: true` is already passed to `createTheme()` (MUI v6+ CSS variables mode)
181
+ - Whether project uses MUI's `sx` prop extensively: Grep for `sx=\{\{` in `*.tsx, *.jsx` β€” count distinct files
182
+ - `styled(MuiComponent)` calls: Grep for `styled\([A-Z]\w+\)` in `*.tsx, *.ts, *.jsx, *.js` β€” count distinct files
183
+ - Custom theme augmentation: `declare module '@mui/material/styles'` in `*.d.ts` files
184
+
185
+ Add theme files and all files with `sx` / `styled(Mui*)` to "FILES TO MODIFY" in the plan.
186
+
157
187
  ### Step 3 β€” Find violations
158
188
 
159
189
  Search for TRDR rule violations across all source files (*.css, *.scss, *.tsx, *.jsx, *.ts, *.js, *.vue, *.html):
@@ -307,8 +337,41 @@ Do NOT flag: `logo-trdr.svg` references β€” those are correct.
307
337
 
308
338
  **Note:** The pattern `<span[^>]*>[^<]*TRDR[^<]*</span>` is known to fail in ripgrep β€” do NOT use it.
309
339
 
340
+ **L β€” Hardcoded values in MUI theme** (only when `stylingMode === 'mui'`):
341
+ Search in theme files (`**/theme/**/*.ts`, `**/theme/**/*.js`, `**/theme.ts`, `**/theme.js`, `**/createTheme*`, `**/muiTheme*`):
342
+
343
+ L.1 β€” palette hardcoded colors:
344
+ - Pattern: `(?:main|light|dark|contrastText|paper|default):\s*['"]#[0-9A-Fa-f]{3,8}['"]`
345
+ - Also: `primary:|secondary:|error:|warning:|success:|info:|background:|text:` objects with nested hex values
346
+ - Fix: replace with `'var(--semantic-token)'` using the color mapping table
347
+
348
+ L.2 β€” typography hardcoded values:
349
+ - Pattern: `fontFamily:\s*['"][^'"]*Inter|fontFamily:\s*['"][^'"]*JetBrains|fontSize:\s*\d+` inside typography object
350
+ - Fix: replace with `'var(--font-*)'` tokens
351
+
352
+ L.3 β€” shape hardcoded radius:
353
+ - Pattern: `borderRadius:\s*\d+` inside shape object or component styleOverrides
354
+ - Fix: replace with numeric value from DS radius mapping
355
+
356
+ L.4 β€” component styleOverrides hardcoded values:
357
+ - Search inside `components:` > `Mui*` > `styleOverrides` for any `#hex`, `Npx` (spacing/radius), `font-family`
358
+ - Fix: replace with appropriate `var(--token)`
359
+
360
+ **M β€” Hardcoded values in MUI sx props** (only when `stylingMode === 'mui'`):
361
+ Search in all component files (`*.tsx, *.jsx`):
362
+ - Pattern: `sx=\{\{` then scan content for `#[0-9A-Fa-f]{3,8}`, `(?:padding|margin|gap):\s*['"]?\d+(?:px)?`, `fontFamily:`, `fontSize:\s*\d+`, `borderRadius:\s*\d+`
363
+ - Also detect hardcoded values inside nested pseudo-selectors (`'&:hover'`, `'& .MuiXxx'`)
364
+ - Fix: replace hardcoded values with `'var(--token)'`
365
+
366
+ **N β€” Hardcoded values in styled(MuiComponent) calls** (only when `stylingMode === 'mui'`):
367
+ Search in all component files (`*.tsx, *.jsx, *.ts, *.js`):
368
+ - Pattern: `styled\([A-Z]\w+\)` β€” then scan the styled block for `#hex`, hardcoded `fontFamily`, `fontSize`, `borderRadius`, spacing px values
369
+ - Fix: replace hardcoded values with `'var(--token)'`
370
+
371
+ **MUI violation categories L, M, N are ONLY scanned when `stylingMode === 'mui'`** β€” they do not apply to other modes.
372
+
310
373
  Track:
311
- - `total_violations` = sum of all A–H occurrences
374
+ - `total_violations` = sum of all A–K occurrences (+ L, M, N when MUI)
312
375
  - `total_files_with_violations` = count of unique files with β‰₯ 1 violation
313
376
  - `violations_by_folder` = map of `{ folder: string, files: string[], count: number }[]` grouped by first-level folder inside `src/` (or project root if no `src/`)
314
377
 
@@ -362,6 +425,29 @@ Use Grep (not Bash grep) to search for the patterns below. Group patterns from t
362
425
 
363
426
  For each match, add to `replacementCandidates[]` with a `customCssClass` field noting the project's class name, so Phase 2 Step 6 can add DS classes to those elements.
364
427
 
428
+ **MUI component detection (only when `stylingMode === 'mui'`):**
429
+
430
+ When `stylingMode === 'mui'`, the component candidate scan shifts focus. Instead of searching for HTML tags to replace with DS classes, search for MUI components that need theme-level DS token integration:
431
+
432
+ | DS Slug | MUI Component patterns |
433
+ |---------|----------------------|
434
+ | `button` | `<Button`, `<IconButton`, `<LoadingButton`, `<Fab` |
435
+ | `text-input` | `<TextField`, `<Input`, `<OutlinedInput`, `<FilledInput` |
436
+ | `checkbox` | `<Checkbox`, `<FormControlLabel` with checkbox |
437
+ | `radio-button` | `<Radio`, `<RadioGroup` |
438
+ | `switch` | `<Switch` (MUI) |
439
+ | `dropdown` | `<Select`, `<Autocomplete`, `<NativeSelect` |
440
+ | `tooltip` | `<Tooltip` (MUI) |
441
+ | `abas` | `<Tabs`, `<Tab` (MUI) |
442
+ | `card` | `<Card`, `<CardContent`, `<CardActions`, `<CardMedia` |
443
+ | `badge` | `<Badge`, `<Chip` (MUI) |
444
+ | `header` | `<AppBar`, `<Toolbar` |
445
+ | `modal` | `<Dialog`, `<Modal`, `<DialogTitle`, `<DialogContent` |
446
+
447
+ For MUI projects, the purpose of detecting these components is NOT to replace them (they stay as MUI components), but to know WHICH MUI theme `components.MuiXxx.styleOverrides` entries to generate in Sub-fase C.
448
+
449
+ Store results in the same `replacementCandidates[]` structure β€” the `slug` and `files` fields are used, but classification follows MUI-specific rules (see Step 3.5b).
450
+
365
451
  **Output:** `replacementCandidates[]` β€” passed to Step 3.5b, Step 5 template and Phase 2 Step 6.
366
452
 
367
453
  ### Step 3.5b β€” Capture structural context for each candidate
@@ -374,6 +460,19 @@ For each file:line match found in Step 3.5, read the surrounding context (10 lin
374
460
  | `complex-preservable` | Element has event handlers, data bindings (`value={state}`, `checked={state}`), refs, or conditional rendering, BUT the DOM structure maps cleanly to a DS component | Apply DS structure + classes, preserving ALL handlers, bindings, and conditional logic |
375
461
  | `complex-manual` | Element has deeply nested custom logic, multiple conditional branches affecting structure, dynamically generated children, or domain-specific behavior that doesn't map to any DS component pattern | Flag for manual review in DS_MIGRATION.md β€” do NOT auto-modify |
376
462
 
463
+ **MUI classification rules (only when `stylingMode === 'mui'`):**
464
+
465
+ When `stylingMode === 'mui'`, use these classifications instead of the table above:
466
+
467
+ | Classification | Criteria | Phase 2 action |
468
+ |---|---|---|
469
+ | `theme-override` | Standard MUI component usage β€” the component should receive DS tokens via theme `components.MuiXxx.styleOverrides` | Generate/update styleOverrides in theme file (Sub-fase C) |
470
+ | `sx-migration` | Component has `sx={{...}}` with hardcoded design values (colors, fonts, radius) | Replace hardcoded sx values with `'var(--token)'` (Sub-fase B/C) |
471
+ | `styled-migration` | Component uses `styled(MuiComponent)` with hardcoded values | Replace values inside styled() call with `'var(--token)'` (Sub-fase B/C) |
472
+ | `complex-manual` | Deeply customized MUI component with renderProp, slots API, complex theme augmentation, or `sx` with dynamic calculations | Flag for manual review in DS_MIGRATION.md |
473
+
474
+ All detected MUI components default to `theme-override`. Add `sx-migration` or `styled-migration` only for individual instances that also have inline hardcoded values.
475
+
377
476
  **For each candidate, store:**
378
477
  ```json
379
478
  {
@@ -574,6 +673,25 @@ All projects use the same checkpointed 4-sub-phase execution regardless of size.
574
673
  > **Implementados:** o CSS estarΓ‘ em `components.css` apΓ³s a Fase 2, **E** as classes DS serΓ£o aplicadas diretamente nos elementos HTML/JSX/Vue durante o Step 6 β€” nΓ£o Γ© necessΓ‘ria nenhuma aΓ§Γ£o manual.
575
674
  > **Stubs:** receberΓ£o banner comment com tokens recomendados + entrada em `MISSING_COMPONENTS.md`.
576
675
 
676
+ [If `stylingMode === 'mui'`:]
677
+
678
+ ### MUI THEME INTEGRATION PLAN:
679
+ | Area | Current state | Action |
680
+ |------|--------------|--------|
681
+ | palette | [N] hardcoded hex values | Replace with `var(--token)` references |
682
+ | typography | [N] hardcoded font values | Map to DS font tokens |
683
+ | shape | borderRadius: [value] | Map to DS radius token |
684
+ | components | [N] MUI components detected | Generate/update styleOverrides with DS tokens |
685
+ | sx props | [N] files with hardcoded sx values | Migrate to token references |
686
+ | styled() | [N] styled(MuiComponent) calls | Migrate to token references |
687
+
688
+ **Theme file:** `[themeFilePath]`
689
+ **MUI version:** [muiVersion]
690
+ **CSS Variables mode:** [yes/no β€” if no, will be recommended for MUI v6+]
691
+ **ThemeProvider:** [found at file:line / not found β€” will need manual setup]
692
+
693
+ > **Note:** MUI projects receive DS tokens via the theme object. Sub-fase A creates `tokens.css` AND updates the MUI theme to reference those tokens via `var()`. Sub-fase C generates `styleOverrides` for each detected MUI component instead of swapping HTML tags.
694
+
577
695
  ### SCOPE ESTIMATE: [Small / Medium / Large]
578
696
  Small = <10 violations | Medium = 10–50 | Large = 50+
579
697
 
@@ -632,9 +750,16 @@ Skill version: [X.Y.Z]
632
750
  ## Project
633
751
  Framework: [next.js|react|vue|html]
634
752
  Language: [ts|js]
635
- Styling: [css-modules|tailwind|plain-css|css-in-js]
753
+ Styling: [css-modules|tailwind|plain-css|css-in-js|mui]
636
754
  Global CSS file: [path]
637
755
  Styles dir: [detected-styles-dir]
756
+ [If stylingMode === 'mui':]
757
+ MUI version: [muiVersion]
758
+ Theme file: [themeFilePath]
759
+ Has ThemeProvider: [yes/no]
760
+ MUI CSS Variables mode: [yes/no]
761
+ Files with sx props: [count]
762
+ Files with styled(Mui*): [count]
638
763
 
639
764
  ## Violations Summary
640
765
  Total violations: [total_violations]
@@ -654,6 +779,10 @@ Total files with violations: [total_files_with_violations]
654
779
  | I | Inline styles | N | ... |
655
780
  | J | SVG icons inline | N | ... |
656
781
  | K | Logo incorrect/missing | N | ... |
782
+ [If stylingMode === 'mui':]
783
+ | L | MUI theme hardcoded values | N | theme.ts |
784
+ | M | MUI sx prop hardcoded values | N | Component1.tsx, Component2.tsx |
785
+ | N | styled(MuiComponent) hardcoded values | N | StyledButton.tsx |
657
786
 
658
787
  ### By File
659
788
  [For each file with violations:]
@@ -736,9 +865,15 @@ Estimated context windows: [N] (one per sprint + one for this analysis)
736
865
  ---
737
866
 
738
867
  ## Sprint 1 β€” Foundation
868
+ [If stylingMode !== 'mui':]
739
869
  **Scope:** Create tokens.css, components.css, CLAUDE.md, @import in global CSS
870
+ [If stylingMode === 'mui':]
871
+ **Scope:** Create tokens.css, components.css, CLAUDE.md, @import in global CSS, AND generate/update MUI theme with DS token references (palette, typography, shape)
740
872
  **Sub-fase:** A
741
873
  **Files to create:** 3 (tokens.css, components.css, CLAUDE.md)
874
+ [If stylingMode === 'mui':]
875
+ **Files to modify:** 2 (global CSS, [themeFilePath])
876
+ [else:]
742
877
  **Files to modify:** 1 (global CSS)
743
878
  **Status:** PENDING
744
879
 
@@ -767,10 +902,14 @@ Estimated context windows: [N] (one per sprint + one for this analysis)
767
902
  ---
768
903
 
769
904
  ## Sprint [N-1] β€” Components
905
+ [If stylingMode !== 'mui':]
770
906
  **Scope:** Implement DS components ([S] simple, [P] complex-preservable, [M] manual review)
771
- **Sub-fase:** C
772
907
  **Candidates:** [total]
773
908
  **Install order:** [topological order from dependency graph β€” atomics first, then compounds]
909
+ [If stylingMode === 'mui':]
910
+ **Scope:** Generate MUI theme component styleOverrides for [N] detected MUI components, migrate [M] sx prop violations
911
+ **Candidates:** [total MUI components]
912
+ **Sub-fase:** C
774
913
  **Status:** PENDING
775
914
 
776
915
  ---
@@ -1163,6 +1302,20 @@ bg.primary (base) β†’ bg.secondary/tertiary (content areas) β†’ surface.* (cards
1163
1302
  - Inline SVG: usar o conteΓΊdo de `references/logo-trdr.svg` (viewBox="0 0 105 41", fill="#00D4FF")
1164
1303
  - **NUNCA** usar texto ("TRDR" em `<span>`) como logo
1165
1304
  - **NUNCA** usar outro arquivo SVG que nΓ£o seja logo-trdr.svg
1305
+
1306
+ [If `stylingMode === 'mui'`, add this section to CLAUDE.md:]
1307
+
1308
+ ## MUI Theme Integration
1309
+ This project uses Material UI with TRDR DS tokens integrated via the theme.
1310
+
1311
+ ### Rules
1312
+ 1. NEVER hardcode colors in palette, sx props, or styleOverrides β€” always use `var(--token)`
1313
+ 2. Theme file (`[themeFilePath]`) is the single source for MUI component styling β€” do not override via individual sx props unless necessary for one-off layout adjustments
1314
+ 3. When adding new MUI components: check if a styleOverride exists in the theme's `components` section. If not, add one using DS tokens.
1315
+ 4. sx props: acceptable for layout (padding, margin, display, flex) using DS spacing tokens. NOT acceptable for colors, fonts, or borders with hardcoded values.
1316
+ 5. styled(MuiComponent): use `'var(--token)'` for all design values
1317
+ 6. Typography: use MUI variants (h1-h6, body1, body2, etc.) β€” they are mapped to TRDR DS text styles in the theme
1318
+ 7. tokens.css is the source of truth β€” the MUI theme references tokens via `var(--token)` strings
1166
1319
  ```
1167
1320
 
1168
1321
  Update `DS_PROGRESS.md`:
@@ -1170,10 +1323,163 @@ Update `DS_PROGRESS.md`:
1170
1323
  - [x] CLAUDE.md β€” CLAUDE.md
1171
1324
  ```
1172
1325
 
1326
+ ### Step 5 β€” Generate/update MUI theme with DS tokens (only when `stylingMode === 'mui'`)
1327
+
1328
+ This step creates the bridge between `tokens.css` (CSS variables source of truth) and MUI's theme system. MUI components read from the theme object, so tokens must be explicitly referenced there via `var()`.
1329
+
1330
+ **Step 5a β€” Ensure tokens.css is imported:**
1331
+ The `@import './tokens.css'` added in Step 3 makes CSS variables available to MUI's Emotion runtime. This is sufficient β€” Emotion styles CAN reference `var(--token)` in string values.
1332
+
1333
+ **Step 5b β€” Create or update the MUI theme file:**
1334
+
1335
+ If `themeFilePath` exists: READ the entire existing theme file. Preserve all non-DS customizations (breakpoints, transitions, zIndex, custom component logic, defaultProps, variants).
1336
+
1337
+ If `themeFilePath` does NOT exist: Create a new theme file at `src/theme.ts` (or `src/theme/index.ts` if a `theme/` directory exists).
1338
+
1339
+ Generate/update the theme with DS token references:
1340
+
1341
+ ```typescript
1342
+ import { createTheme } from '@mui/material/styles';
1343
+
1344
+ const theme = createTheme({
1345
+ // cssVariables: true, β€” recommended for MUI v6+ (enables native CSS variable support)
1346
+ palette: {
1347
+ mode: 'dark',
1348
+ primary: {
1349
+ main: 'var(--action-brand-default)', // #00D4FF
1350
+ dark: 'var(--action-brand-active)', // #007D99
1351
+ contrastText: 'var(--content-inverse)', // #1A1A1A
1352
+ },
1353
+ secondary: {
1354
+ main: 'var(--action-secondary-default)', // #4A4A4A
1355
+ dark: 'var(--action-secondary-active)', // #A4A4A4
1356
+ contrastText: 'var(--content-primary)', // #FFFFFF
1357
+ },
1358
+ error: {
1359
+ main: 'var(--content-error)', // #F34F45
1360
+ },
1361
+ warning: {
1362
+ main: 'var(--content-warning)', // #FFCC40
1363
+ },
1364
+ success: {
1365
+ main: 'var(--content-success)', // #4FE290
1366
+ },
1367
+ info: {
1368
+ main: 'var(--content-info)', // #CCFDFF
1369
+ },
1370
+ background: {
1371
+ default: 'var(--bg-primary)', // #0E0E0E
1372
+ paper: 'var(--bg-secondary)', // #141519
1373
+ },
1374
+ text: {
1375
+ primary: 'var(--content-primary)', // #FFFFFF
1376
+ secondary: 'var(--content-secondary)', // #E8E8E8
1377
+ disabled: 'var(--content-disabled)', // #4A4A4A
1378
+ },
1379
+ divider: 'var(--border-default)', // #4A4A4A
1380
+ action: {
1381
+ hover: 'var(--surface-hover, rgba(255,255,255,0.08))',
1382
+ selected: 'var(--surface-brand)',
1383
+ disabled: 'var(--content-disabled)',
1384
+ disabledBackground: 'var(--surface-disabled)',
1385
+ },
1386
+ },
1387
+ typography: {
1388
+ fontFamily: 'var(--font-secondary)', // Inter
1389
+ h1: { fontFamily: 'var(--font-primary)', fontSize: 80, fontWeight: 500, lineHeight: 1.1 },
1390
+ h2: { fontFamily: 'var(--font-primary)', fontSize: 56, fontWeight: 500, lineHeight: 1.1 },
1391
+ h3: { fontFamily: 'var(--font-primary)', fontSize: 46, fontWeight: 700, lineHeight: 1.15 },
1392
+ h4: { fontFamily: 'var(--font-primary)', fontSize: 38, fontWeight: 500, lineHeight: 1.15 },
1393
+ h5: { fontFamily: 'var(--font-primary)', fontSize: 32, fontWeight: 500, lineHeight: 1.2 },
1394
+ h6: { fontFamily: 'var(--font-primary)', fontSize: 26, fontWeight: 500, lineHeight: 1.2 },
1395
+ subtitle1: { fontFamily: 'var(--font-secondary)', fontSize: 22, fontWeight: 600, lineHeight: 1.3 },
1396
+ body1: { fontFamily: 'var(--font-secondary)', fontSize: 16, fontWeight: 400, lineHeight: 1.5 },
1397
+ body2: { fontFamily: 'var(--font-secondary)', fontSize: 14, fontWeight: 400, lineHeight: 1.5 },
1398
+ caption: { fontFamily: 'var(--font-secondary)', fontSize: 12, fontWeight: 400, lineHeight: 1.4 },
1399
+ overline: { fontFamily: 'var(--font-secondary)', fontSize: 10, fontWeight: 400, lineHeight: 1.4 },
1400
+ button: { fontFamily: 'var(--font-secondary)', fontWeight: 600, textTransform: 'none' as const },
1401
+ },
1402
+ shape: {
1403
+ borderRadius: 8, // --radius-md = 8px β€” MUI shape.borderRadius must be numeric
1404
+ },
1405
+ components: {
1406
+ // styleOverrides are generated in Sub-fase C
1407
+ },
1408
+ });
1409
+
1410
+ export default theme;
1411
+ ```
1412
+
1413
+ **MUI palette role β†’ DS token mapping table:**
1414
+
1415
+ | MUI palette key | DS token | Hex reference |
1416
+ |---|---|---|
1417
+ | `palette.primary.main` | `var(--action-brand-default)` | #00D4FF |
1418
+ | `palette.primary.dark` | `var(--action-brand-active)` | #007D99 |
1419
+ | `palette.primary.contrastText` | `var(--content-inverse)` | #1A1A1A |
1420
+ | `palette.secondary.main` | `var(--action-secondary-default)` | #4A4A4A |
1421
+ | `palette.secondary.dark` | `var(--action-secondary-active)` | #A4A4A4 |
1422
+ | `palette.error.main` | `var(--content-error)` | #F34F45 |
1423
+ | `palette.warning.main` | `var(--content-warning)` | #FFCC40 |
1424
+ | `palette.success.main` | `var(--content-success)` | #4FE290 |
1425
+ | `palette.info.main` | `var(--content-info)` | #CCFDFF |
1426
+ | `palette.background.default` | `var(--bg-primary)` | #0E0E0E |
1427
+ | `palette.background.paper` | `var(--bg-secondary)` | #141519 |
1428
+ | `palette.text.primary` | `var(--content-primary)` | #FFFFFF |
1429
+ | `palette.text.secondary` | `var(--content-secondary)` | #E8E8E8 |
1430
+ | `palette.text.disabled` | `var(--content-disabled)` | #4A4A4A |
1431
+ | `palette.divider` | `var(--border-default)` | #4A4A4A |
1432
+
1433
+ **MUI typography variant β†’ DS token mapping table:**
1434
+
1435
+ | MUI variant | DS equivalent | Font family token |
1436
+ |---|---|---|
1437
+ | `h1` | `.trdr-h1` | `var(--font-primary)` β€” 80px/500 |
1438
+ | `h2` | `.trdr-h2` | `var(--font-primary)` β€” 56px/500 |
1439
+ | `h3` | `.trdr-h3` | `var(--font-primary)` β€” 46px/700 |
1440
+ | `h4` | `.trdr-h4` | `var(--font-primary)` β€” 38px/500 |
1441
+ | `h5` | `.trdr-h5` | `var(--font-primary)` β€” 32px/500 |
1442
+ | `h6` | `.trdr-h6` | `var(--font-primary)` β€” 26px/500 |
1443
+ | `subtitle1` | `.trdr-h7` | `var(--font-secondary)` β€” 22px/600 |
1444
+ | `body1` | `.trdr-body-b2` | `var(--font-secondary)` β€” 16px/500 |
1445
+ | `body2` | `.trdr-body-b3` | `var(--font-secondary)` β€” 14px/400 |
1446
+ | `caption` | `.trdr-body-b4` | `var(--font-secondary)` β€” 12px/500 |
1447
+ | `overline` | `.trdr-body-b5` | `var(--font-secondary)` β€” 10px/400 |
1448
+ | `button` | `.trdr-label-l3` | `var(--font-secondary)` β€” 14px/600 |
1449
+
1450
+ **MUI shape/radius β†’ DS token mapping table:**
1451
+
1452
+ | Value (px) | DS token (for CSS) | MUI shape (numeric) |
1453
+ |---|---|---|
1454
+ | `0` | `var(--radius-none)` | `0` |
1455
+ | `2` | `var(--radius-xs)` | `2` |
1456
+ | `4` | `var(--radius-sm)` | `4` |
1457
+ | `8` | `var(--radius-md)` | `8` |
1458
+ | `12` | β€” (no DS token) | `12` |
1459
+ | `16` | `var(--radius-lg)` | `16` |
1460
+ | `20` | `var(--radius-xl)` | `20` |
1461
+ | `9999` | `var(--radius-full)` | `9999` |
1462
+
1463
+ **Important MUI + CSS var() caveat:**
1464
+ MUI accepts string values for palette colors. `'var(--token)'` works for rendering in MUI v5+. However, MUI internally uses `palette.primary.main` for color calculations (alpha, lighten, darken). When `main` is a `var()` string, those calculations produce invalid CSS.
1465
+
1466
+ **Solution by MUI version:**
1467
+ - **MUI v6+**: Add `cssVariables: true` to `createTheme()` β€” MUI handles CSS variables natively, calculations work
1468
+ - **MUI v5 / v7 without cssVariables mode**: Provide `main`, `light`, `dark`, and `contrastText` ALL explicitly using DS tokens. Do NOT rely on MUI's auto-generated `light`/`dark` variants. Document this caveat in `CLAUDE.md` and `DS_MIGRATION.md`.
1469
+
1470
+ **Step 5c β€” Update DS_PROGRESS.md:**
1471
+ ```
1472
+ - [x] MUI theme β€” [themeFilePath] (palette, typography, shape with DS tokens)
1473
+ ```
1474
+
1173
1475
  Update `DS_PROGRESS.md`: set `Sub-fase A: Foundation β€” βœ… COMPLETE`.
1174
1476
 
1175
1477
  Output:
1176
1478
  ```
1479
+ [If stylingMode === 'mui':]
1480
+ βœ… Sub-fase A completa β€” tokens.css, components.css, CLAUDE.md, @import e MUI theme criados/atualizados.
1481
+
1482
+ [else:]
1177
1483
  βœ… Sub-fase A completa β€” tokens.css, components.css, CLAUDE.md e @import criados.
1178
1484
 
1179
1485
  PrΓ³ximo: Sub-fase B β€” Violations ([total_files_with_violations] arquivos em [N] lotes de atΓ© [batch_size] cada)
@@ -1298,6 +1604,32 @@ For each batch listed as PENDING in `DS_PROGRESS.md` Β§ Sub-fase B:
1298
1604
  - Example: `margin: 12px 0 8px` β†’ `margin: var(--spacing-md) 0 var(--spacing-sm)`
1299
1605
  - If one value has no token: replace only the mappable ones; keep the others as-is and flag
1300
1606
 
1607
+ **MUI sx spacing shorthand mapping** (only when `stylingMode === 'mui'`):
1608
+
1609
+ When fixing violations in MUI `sx` props, MUI uses a numeric spacing multiplier (default 8px base). Use this mapping:
1610
+
1611
+ | sx prop | MUI value | Pixels | DS token (for string replacement) |
1612
+ |---|---|---|---|
1613
+ | `p`, `m`, `gap`, etc. | `0.5` | 4px | `'var(--spacing-xs)'` |
1614
+ | `p`, `m`, `gap`, etc. | `1` | 8px | `'var(--spacing-sm)'` |
1615
+ | `p`, `m`, `gap`, etc. | `1.5` | 12px | `'var(--spacing-md)'` |
1616
+ | `p`, `m`, `gap`, etc. | `2` | 16px | `'var(--spacing-lg)'` |
1617
+ | `p`, `m`, `gap`, etc. | `2.5` | 20px | `'var(--spacing-xl)'` |
1618
+ | `p`, `m`, `gap`, etc. | `3` | 24px | `'var(--spacing-2xl)'` |
1619
+ | `p`, `m`, `gap`, etc. | `4` | 32px | `'var(--spacing-3xl)'` |
1620
+
1621
+ Prefer keeping MUI numeric scale when the project consistently uses it (`p: 2`, `m: 1`). Only use `'var(--spacing-*)'` string replacement when the sx value uses hardcoded px string (e.g., `padding: '16px'` instead of `p: 2`).
1622
+
1623
+ **MUI-specific violation processing** (only when `stylingMode === 'mui'`):
1624
+
1625
+ In addition to standard A-K violations in CSS/JSX files, process these MUI-specific violations during batch processing:
1626
+
1627
+ - **Category L** (theme file): Read the theme file. For each hardcoded `#hex`, font-family, fontSize, or borderRadius value, look up in the mapping tables and replace with `'var(--token)'`. If no DS token match exists, flag in DS_MIGRATION.md.
1628
+ - **Category M** (sx props): For each file with `sx={{}}` containing hardcoded values, replace colors with `'var(--token)'`, spacing with token or MUI scale, fonts with `'var(--font-*)'`, radius with `'var(--radius-*)'`.
1629
+ - **Category N** (styled() calls): For each `styled(MuiComponent)()` call with hardcoded values, replace with `'var(--token)'` in the style object.
1630
+
1631
+ Theme files (Category L) should be processed in the FIRST violation batch, before component files, so that theme-level tokens are in place before scanning individual components.
1632
+
1301
1633
  **Ambiguous colors:** Use property context to decide β€” `background-color` β†’ bg/surface token, `color` β†’ content token, `border-color` β†’ border token, `accent-color` β†’ action token.
1302
1634
 
1303
1635
  **Tailwind arbitrary value colors** (only when `stylingMode: tailwind`):
@@ -1442,6 +1774,290 @@ When a CSS class has a `font-size` that maps to a DS text style, the fix is **tw
1442
1774
 
1443
1775
  Update `DS_PROGRESS.md`: set `Sub-fase C: Components β€” IN_PROGRESS`.
1444
1776
 
1777
+ **If `stylingMode === 'mui'`: skip directly to Step 6-MUI below.** MUI projects do NOT use Pass 1/2/3 (HTML tag replacement). All visual changes come from MUI theme styleOverrides + sx prop migration.
1778
+
1779
+ ### Step 6-MUI β€” Generate MUI component styleOverrides (only when `stylingMode === 'mui'`)
1780
+
1781
+ #### Step 6-MUI.0 β€” DS slug to MUI component mapping
1782
+
1783
+ | DS Component (slug) | MUI Component | Theme key |
1784
+ |---|---|---|
1785
+ | `button` | Button, IconButton, LoadingButton | `MuiButton`, `MuiIconButton`, `MuiLoadingButton` |
1786
+ | `text-input` | TextField, OutlinedInput, FilledInput | `MuiTextField`, `MuiOutlinedInput` |
1787
+ | `checkbox` | Checkbox | `MuiCheckbox` |
1788
+ | `radio-button` | Radio | `MuiRadio` |
1789
+ | `switch` | Switch | `MuiSwitch` |
1790
+ | `dropdown` | Select, Autocomplete | `MuiSelect`, `MuiAutocomplete` |
1791
+ | `tooltip` | Tooltip | `MuiTooltip` |
1792
+ | `abas` | Tabs, Tab | `MuiTabs`, `MuiTab` |
1793
+ | `card` | Card, CardContent, CardActions | `MuiCard`, `MuiCardContent` |
1794
+ | `badge` | Badge, Chip | `MuiBadge`, `MuiChip` |
1795
+ | `header` | AppBar, Toolbar | `MuiAppBar`, `MuiToolbar` |
1796
+ | `modal` | Dialog, DialogTitle, DialogContent | `MuiDialog`, `MuiDialogTitle`, `MuiDialogContent` |
1797
+
1798
+ #### Step 6-MUI.1 β€” Generate styleOverrides block
1799
+
1800
+ For each MUI component detected in `replacementCandidates[]`:
1801
+
1802
+ 1. Read the corresponding DS component from `data/components.json` β€” look up by slug.
1803
+ 2. Extract the visual properties (colors, spacing, typography, border-radius) from its `code.css` block.
1804
+ 3. Translate each CSS property into a MUI `styleOverrides` entry using DS tokens.
1805
+
1806
+ **Reference template for common MUI components:**
1807
+
1808
+ ```typescript
1809
+ components: {
1810
+ MuiButton: {
1811
+ styleOverrides: {
1812
+ root: {
1813
+ fontFamily: 'var(--font-secondary)',
1814
+ fontWeight: 600,
1815
+ textTransform: 'none' as const,
1816
+ borderRadius: 'var(--radius-sm)',
1817
+ transition: 'all 0.15s ease',
1818
+ '&:focus-visible': {
1819
+ outline: '2px solid var(--border-focus)',
1820
+ outlineOffset: '2px',
1821
+ },
1822
+ },
1823
+ containedPrimary: {
1824
+ backgroundColor: 'var(--action-brand-inverse-default)',
1825
+ color: 'var(--content-primary)',
1826
+ '&:hover': { backgroundColor: 'var(--action-brand-inverse-hover)' },
1827
+ '&:active': { backgroundColor: 'var(--action-brand-inverse-active)' },
1828
+ '&.Mui-disabled': {
1829
+ backgroundColor: 'var(--action-brand-inverse-disabled)',
1830
+ color: 'var(--content-disabled)',
1831
+ },
1832
+ },
1833
+ outlinedPrimary: {
1834
+ borderColor: 'var(--action-brand-default)',
1835
+ color: 'var(--action-brand-default)',
1836
+ '&:hover': {
1837
+ borderColor: 'var(--action-brand-hover)',
1838
+ backgroundColor: 'var(--action-brand-alpha)',
1839
+ },
1840
+ },
1841
+ textPrimary: {
1842
+ color: 'var(--action-brand-default)',
1843
+ '&:hover': { backgroundColor: 'var(--action-brand-alpha)' },
1844
+ },
1845
+ },
1846
+ },
1847
+ MuiTextField: {
1848
+ styleOverrides: {
1849
+ root: {
1850
+ '& .MuiOutlinedInput-root': {
1851
+ fontFamily: 'var(--font-secondary)',
1852
+ fontSize: 14,
1853
+ color: 'var(--content-primary)',
1854
+ '& fieldset': { borderColor: 'var(--border-default)' },
1855
+ '&:hover fieldset': { borderColor: 'var(--border-strong)' },
1856
+ '&.Mui-focused fieldset': { borderColor: 'var(--border-focus)' },
1857
+ '&.Mui-error fieldset': { borderColor: 'var(--content-error)' },
1858
+ },
1859
+ '& .MuiInputLabel-root': {
1860
+ color: 'var(--content-tertiary)',
1861
+ fontFamily: 'var(--font-secondary)',
1862
+ '&.Mui-focused': { color: 'var(--content-brand)' },
1863
+ },
1864
+ },
1865
+ },
1866
+ },
1867
+ MuiCard: {
1868
+ styleOverrides: {
1869
+ root: {
1870
+ backgroundColor: 'var(--bg-secondary)',
1871
+ borderRadius: 'var(--radius-md)',
1872
+ border: '1px solid var(--border-subtle)',
1873
+ },
1874
+ },
1875
+ },
1876
+ MuiTooltip: {
1877
+ styleOverrides: {
1878
+ tooltip: {
1879
+ backgroundColor: 'var(--bg-inverse)',
1880
+ color: 'var(--content-inverse)',
1881
+ fontFamily: 'var(--font-secondary)',
1882
+ fontSize: 12,
1883
+ borderRadius: 'var(--radius-sm)',
1884
+ },
1885
+ arrow: { color: 'var(--bg-inverse)' },
1886
+ },
1887
+ },
1888
+ MuiSwitch: {
1889
+ styleOverrides: {
1890
+ root: { width: 44, height: 24, padding: 0 },
1891
+ switchBase: {
1892
+ padding: 4,
1893
+ '&.Mui-checked': {
1894
+ color: 'var(--content-primary)',
1895
+ '& + .MuiSwitch-track': {
1896
+ backgroundColor: 'var(--action-brand-default)',
1897
+ opacity: 1,
1898
+ },
1899
+ },
1900
+ },
1901
+ track: {
1902
+ borderRadius: 'var(--radius-full)',
1903
+ backgroundColor: 'var(--surface-primary)',
1904
+ opacity: 1,
1905
+ },
1906
+ thumb: { width: 16, height: 16 },
1907
+ },
1908
+ },
1909
+ MuiCheckbox: {
1910
+ styleOverrides: {
1911
+ root: {
1912
+ color: 'var(--border-default)',
1913
+ '&.Mui-checked': { color: 'var(--action-brand-default)' },
1914
+ '&.Mui-disabled': { color: 'var(--content-disabled)' },
1915
+ },
1916
+ },
1917
+ },
1918
+ MuiRadio: {
1919
+ styleOverrides: {
1920
+ root: {
1921
+ color: 'var(--border-default)',
1922
+ '&.Mui-checked': { color: 'var(--action-brand-default)' },
1923
+ },
1924
+ },
1925
+ },
1926
+ MuiTabs: {
1927
+ styleOverrides: {
1928
+ indicator: { backgroundColor: 'var(--action-brand-default)' },
1929
+ },
1930
+ },
1931
+ MuiTab: {
1932
+ styleOverrides: {
1933
+ root: {
1934
+ fontFamily: 'var(--font-secondary)',
1935
+ fontWeight: 600,
1936
+ textTransform: 'none',
1937
+ color: 'var(--content-tertiary)',
1938
+ '&.Mui-selected': { color: 'var(--content-brand)' },
1939
+ },
1940
+ },
1941
+ },
1942
+ MuiChip: {
1943
+ styleOverrides: {
1944
+ root: {
1945
+ fontFamily: 'var(--font-secondary)',
1946
+ borderRadius: 'var(--radius-sm)',
1947
+ },
1948
+ colorPrimary: {
1949
+ backgroundColor: 'var(--surface-brand)',
1950
+ color: 'var(--content-brand)',
1951
+ },
1952
+ colorSuccess: {
1953
+ backgroundColor: 'var(--surface-success)',
1954
+ color: 'var(--content-success)',
1955
+ },
1956
+ colorWarning: {
1957
+ backgroundColor: 'var(--surface-warning)',
1958
+ color: 'var(--content-warning)',
1959
+ },
1960
+ colorError: {
1961
+ backgroundColor: 'var(--surface-error)',
1962
+ color: 'var(--content-error)',
1963
+ },
1964
+ },
1965
+ },
1966
+ MuiDialog: {
1967
+ styleOverrides: {
1968
+ paper: {
1969
+ backgroundColor: 'var(--bg-secondary)',
1970
+ borderRadius: 'var(--radius-md)',
1971
+ border: '1px solid var(--border-subtle)',
1972
+ },
1973
+ },
1974
+ },
1975
+ MuiAppBar: {
1976
+ styleOverrides: {
1977
+ root: {
1978
+ backgroundColor: 'var(--bg-secondary)',
1979
+ borderBottom: '1px solid var(--border-subtle)',
1980
+ boxShadow: 'none',
1981
+ },
1982
+ },
1983
+ },
1984
+ MuiSelect: {
1985
+ styleOverrides: {
1986
+ root: {
1987
+ fontFamily: 'var(--font-secondary)',
1988
+ fontSize: 14,
1989
+ },
1990
+ },
1991
+ },
1992
+ },
1993
+ ```
1994
+
1995
+ **IMPORTANT:** This template is a REFERENCE. For each project:
1996
+ 1. Only include `MuiXxx` entries for components actually detected in `replacementCandidates[]`
1997
+ 2. Read the DS component's `code.css` for accurate token values β€” the template above covers the most common tokens, but individual components may have specific values
1998
+ 3. If the DS component has variants (e.g., button primary/secondary/ghost), map each to the appropriate MUI variant prop or className
1999
+
2000
+ #### Step 6-MUI.2 β€” Insert styleOverrides into theme file
2001
+
2002
+ Read the existing theme file (`themeFilePath`). Find the `components: {}` block (or create it if absent). Merge the generated styleOverrides:
2003
+
2004
+ - If a `MuiXxx` key already exists in the theme: **MERGE** the DS overrides into the existing overrides, preserving any project-specific customizations that do not conflict with DS tokens
2005
+ - If a `MuiXxx` key does NOT exist: ADD the DS override block
2006
+ - **NEVER** overwrite project-specific `defaultProps`, `variants`, or slot customizations
2007
+
2008
+ #### Step 6-MUI.3 β€” Process individual sx prop violations
2009
+
2010
+ For components with `sx-migration` classification in `replacementCandidates[]`:
2011
+
2012
+ 1. Read each sx prop with hardcoded values
2013
+ 2. Replace with token references:
2014
+ ```tsx
2015
+ // Before
2016
+ <Box sx={{ backgroundColor: '#141519', padding: '16px', borderRadius: '8px' }}>
2017
+ // After
2018
+ <Box sx={{ backgroundColor: 'var(--bg-secondary)', padding: 'var(--spacing-lg)', borderRadius: 'var(--radius-md)' }}>
2019
+ ```
2020
+ 3. If the sx prop becomes empty after migration (all values now come from theme), consider removing it
2021
+ 4. Preserve all layout-related sx values (display, flex, grid, position) as-is
2022
+
2023
+ #### Step 6-MUI.4 β€” Process styled(MuiComponent) violations
2024
+
2025
+ For components with `styled-migration` classification:
2026
+
2027
+ 1. Replace hardcoded values inside `styled()` calls with `'var(--token)'`
2028
+ 2. Preserve all theme-based logic (`theme.breakpoints`, `theme.palette.*` references, `theme.spacing()`)
2029
+ 3. If the styled() call uses `({ theme }) =>` destructuring: theme references will now pull from the updated theme with DS tokens β€” this is correct and expected
2030
+
2031
+ #### Step 6-MUI.5 β€” Skip HTML tag replacement
2032
+
2033
+ Do NOT run Pass 1/2/3 (HTML tag replacement) for MUI projects. Jump directly to updating DS_PROGRESS.md after completing Steps 6-MUI.1 through 6-MUI.4.
2034
+
2035
+ Document in `DS_PROGRESS.md` each styleOverride generated and each sx prop migrated:
2036
+ ```
2037
+ ## Sub-fase C: Components β€” βœ… COMPLETE
2038
+ - [x] MuiButton β€” styleOverrides (containedPrimary, outlinedPrimary, textPrimary)
2039
+ - [x] MuiTextField β€” styleOverrides (root, label, fieldset states)
2040
+ - [x] MuiCard β€” styleOverrides (root)
2041
+ - [x] sx migrations: [N] files, [M] values replaced
2042
+ - [x] styled() migrations: [N] files
2043
+ ```
2044
+
2045
+ Output:
2046
+ ```
2047
+ βœ… Sub-fase C completa β€” [N] MUI component styleOverrides gerados, [M] sx props migrados.
2048
+
2049
+ PrΓ³ximo: Sub-fase D β€” Final (logos, Γ­cones, DS_MIGRATION.md)
2050
+ Responda:
2051
+ - "continuar" / "continue" β€” iniciar Sub-fase D
2052
+ - "parar" / "stop" β€” salvar progresso e parar aqui
2053
+ ```
2054
+
2055
+ **STOP HERE. Wait for developer reply before starting Sub-fase D.**
2056
+
2057
+ ---
2058
+
2059
+ **For non-MUI projects (`stylingMode !== 'mui'`), continue with the standard Step 6 below:**
2060
+
1445
2061
  ### Step 6 β€” Implement DS components in project files
1446
2062
 
1447
2063
  #### Step 6.0 β€” Resolve dependency order
@@ -2082,6 +2698,52 @@ Group new classes in a clearly labelled block at the bottom of the project's CSS
2082
2698
  /* ... */
2083
2699
  ```
2084
2700
 
2701
+ **MUI sx prop migration (only when `stylingMode === 'mui'`):**
2702
+
2703
+ MUI's `sx` prop is the idiomatic way to style MUI components. Unlike inline `style={{}}`, `sx` props should NOT be eliminated β€” they should be migrated to use DS tokens.
2704
+
2705
+ **Decision tree for MUI `sx` props:**
2706
+
2707
+ 1. **Value already uses theme reference** (`theme.palette.primary.main`, `theme.spacing(2)`) β†’ keep as-is (theme was updated with DS tokens in Sub-fase A)
2708
+
2709
+ 2. **Hardcoded color** β†’ replace with token:
2710
+ ```tsx
2711
+ // Before
2712
+ sx={{ color: '#00A8CC' }}
2713
+ // After
2714
+ sx={{ color: 'var(--content-brand)' }}
2715
+ ```
2716
+
2717
+ 3. **Hardcoded spacing with string px** β†’ replace with token:
2718
+ ```tsx
2719
+ // Before
2720
+ sx={{ padding: '16px', gap: '8px' }}
2721
+ // After
2722
+ sx={{ padding: 'var(--spacing-lg)', gap: 'var(--spacing-sm)' }}
2723
+ ```
2724
+
2725
+ 4. **Hardcoded fontFamily** β†’ remove (theme typography handles this globally)
2726
+
2727
+ 5. **Hardcoded borderRadius** β†’ replace with token:
2728
+ ```tsx
2729
+ // Before
2730
+ sx={{ borderRadius: '12px' }}
2731
+ // After
2732
+ sx={{ borderRadius: 'var(--radius-md)' }}
2733
+ ```
2734
+
2735
+ 6. **Conditional sx values** β†’ replace both branches:
2736
+ ```tsx
2737
+ // Before
2738
+ sx={{ color: isActive ? '#00D4FF' : '#A4A4A4' }}
2739
+ // After
2740
+ sx={{ color: isActive ? 'var(--content-brand)' : 'var(--content-tertiary)' }}
2741
+ ```
2742
+
2743
+ 7. **Layout-only sx** (display, flex, grid, position, width, height) β†’ keep as-is (not DS concern)
2744
+
2745
+ Do NOT convert `sx` props to CSS classes β€” `sx` is idiomatic MUI and is acceptable when using DS tokens.
2746
+
2085
2747
  ---
2086
2748
 
2087
2749
  ### Step 7 β€” Generate DS_MIGRATION.md
@@ -2118,6 +2780,13 @@ Hub: https://trdr.mrocontent.com.br
2118
2780
  - [ ] **Stubs**: Review MISSING_COMPONENTS.md and decide whether to wait for canonical implementation in the Hub or hand-roll using the listed tokens
2119
2781
  - [ ] **Skipped files**: [list any files excluded from migration]
2120
2782
 
2783
+ [If `stylingMode === 'mui'`, add these additional manual steps:]
2784
+ - [ ] **MUI CSS Variables mode**: If MUI version >= 6, add `cssVariables: true` to `createTheme()` for native CSS variable support. Without it, MUI's internal color calculations (alpha, lighten, darken) may produce invalid CSS when palette values are `var()` strings.
2785
+ - [ ] **MUI palette auto-generation**: Verify that `primary.light`, `primary.dark`, and `primary.contrastText` are all explicitly set with DS tokens. MUI auto-generates these from `main`, which fails when `main` is a `var()` string.
2786
+ - [ ] **MUI theme composition**: If the project composes themes across multiple files (`createTheme()` + `deepmerge`), verify that DS token references are preserved in the final merged theme.
2787
+ - [ ] **MUI component slots**: Complex MUI components (DataGrid, DatePicker, Autocomplete) have many internal slots not covered by the standard styleOverrides. Review these manually if used in the project.
2788
+ - [ ] **sx props audit**: Run a quick grep for `sx=\{\{.*#[0-9A-Fa-f]` to verify no hardcoded hex values remain in sx props.
2789
+
2121
2790
  ## Missing DS tokens (flagged β€” no semantic token available)
2122
2791
  | Pattern | File | Suggestion |
2123
2792
  |---------|------|-----------|