figma-code-agent 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +133 -0
  2. package/bin/install.js +328 -0
  3. package/knowledge/README.md +62 -0
  4. package/knowledge/css-strategy.md +973 -0
  5. package/knowledge/design-to-code-assets.md +855 -0
  6. package/knowledge/design-to-code-layout.md +929 -0
  7. package/knowledge/design-to-code-semantic.md +1085 -0
  8. package/knowledge/design-to-code-typography.md +1003 -0
  9. package/knowledge/design-to-code-visual.md +1145 -0
  10. package/knowledge/design-tokens-variables.md +1261 -0
  11. package/knowledge/design-tokens.md +960 -0
  12. package/knowledge/figma-api-devmode.md +894 -0
  13. package/knowledge/figma-api-plugin.md +920 -0
  14. package/knowledge/figma-api-rest.md +742 -0
  15. package/knowledge/figma-api-variables.md +848 -0
  16. package/knowledge/figma-api-webhooks.md +876 -0
  17. package/knowledge/payload-blocks.md +1184 -0
  18. package/knowledge/payload-figma-mapping.md +1210 -0
  19. package/knowledge/payload-visual-builder.md +1004 -0
  20. package/knowledge/plugin-architecture.md +1176 -0
  21. package/knowledge/plugin-best-practices.md +1206 -0
  22. package/knowledge/plugin-codegen.md +1313 -0
  23. package/package.json +31 -0
  24. package/skills/README.md +103 -0
  25. package/skills/audit-plugin/SKILL.md +244 -0
  26. package/skills/build-codegen-plugin/SKILL.md +279 -0
  27. package/skills/build-importer/SKILL.md +320 -0
  28. package/skills/build-plugin/SKILL.md +199 -0
  29. package/skills/build-token-pipeline/SKILL.md +363 -0
  30. package/skills/ref-html/SKILL.md +290 -0
  31. package/skills/ref-layout/SKILL.md +150 -0
  32. package/skills/ref-payload-block/SKILL.md +415 -0
  33. package/skills/ref-react/SKILL.md +222 -0
  34. package/skills/ref-tokens/SKILL.md +347 -0
@@ -0,0 +1,973 @@
1
+ # Layered CSS Architecture
2
+
3
+ ## Purpose
4
+
5
+ Authoritative reference for the layered CSS strategy used in Figma design-to-code generation. Documents how generated CSS properties are distributed across three layers -- Tailwind CSS utilities for structural layout, CSS Custom Properties for design tokens, and CSS Modules for component-specific visual styling -- to produce maintainable, overridable, production-grade CSS output. Encodes production patterns for token extraction, CSS generation, token consumption, and CSS Modules isolation.
6
+
7
+ ## When to Use
8
+
9
+ Reference this module when you need to:
10
+
11
+ - Decide which CSS layer a generated property should belong to (Tailwind, Custom Property, or CSS Module)
12
+ - Understand how the three CSS layers compose without specificity conflicts
13
+ - Configure Tailwind to reference design tokens from CSS Custom Properties
14
+ - Structure CSS Module files for component-scoped visual styles
15
+ - Implement token consumption patterns with `var()` and fallback values
16
+ - Handle responsive CSS using mobile-first media queries with Tailwind prefixes
17
+ - Support light/dark themes through CSS Custom Properties and mode selectors
18
+ - Choose between separate CSS files (reset.css, tokens.css, styles.css) or merged output
19
+ - Understand how the five design-to-code modules feed into the CSS generation pipeline
20
+ - Implement Visual Builder token aliasing for plugin isolation
21
+
22
+ ---
23
+
24
+ ## Content
25
+
26
+ ### 1. Three-Layer Architecture Overview
27
+
28
+ Generated CSS is distributed across three layers, each with a distinct responsibility and specificity level. This separation ensures that layout structure, design tokens, and visual skin can be modified independently.
29
+
30
+ #### Layer Summary
31
+
32
+ | Layer | Technology | Responsibility | Specificity |
33
+ |-------|-----------|----------------|-------------|
34
+ | 1. Layout Bones | Tailwind CSS classes | Flexbox, gap, padding, margin, sizing, positioning, responsive breakpoints | Zero (utility classes at `@layer utilities`) |
35
+ | 2. Design Tokens | CSS Custom Properties | Colors, font sizes, font families, spacing values, radii, shadows, transitions | Defined on `:root` (zero selector specificity for the variables themselves) |
36
+ | 3. Visual Skin | CSS Modules | Component-specific backgrounds, borders, effects, color assignments, overrides | Scoped to component (hashed class names prevent leaking) |
37
+
38
+ #### Why Three Layers
39
+
40
+ The three-layer approach solves three problems that single-strategy CSS cannot:
41
+
42
+ 1. **Tailwind alone** cannot handle design-specific visual styles (exact color assignments, shadow compositions, gradient definitions) without excessive arbitrary values that defeat the utility-class purpose.
43
+
44
+ 2. **CSS Custom Properties alone** cannot provide structural layout utilities efficiently. Repeating `display: flex; flex-direction: column; gap: var(--spacing-md)` on every container is verbose when `flex flex-col gap-4` achieves the same result.
45
+
46
+ 3. **CSS Modules alone** cannot share design tokens across components without importing a shared file or duplicating values. Token changes would require editing every module file.
47
+
48
+ The three layers compose naturally: Tailwind handles the predictable structural patterns, Custom Properties provide the shared design language, and CSS Modules apply the unique visual identity per component.
49
+
50
+ #### How the Layers Compose
51
+
52
+ ```html
53
+ <!-- Layer 1: Tailwind classes handle layout -->
54
+ <div class="flex flex-col gap-4 p-6 w-full">
55
+ <!-- Layer 3: CSS Module class handles visual skin -->
56
+ <div class="card">
57
+ <h2 class="card__title">Welcome</h2>
58
+ <p class="card__body">Content here</p>
59
+ </div>
60
+ </div>
61
+ ```
62
+
63
+ ```css
64
+ /* Layer 2: tokens.css — design tokens at :root */
65
+ :root {
66
+ --color-neutral-100: #f5f5f5;
67
+ --color-neutral-800: #333333;
68
+ --color-primary: #1a73e8;
69
+ --radius-lg: 12px;
70
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
71
+ }
72
+
73
+ /* Layer 3: Card.module.css — visual skin consuming tokens */
74
+ .card {
75
+ background-color: var(--color-neutral-100);
76
+ border: 1px solid var(--color-neutral-300);
77
+ border-radius: var(--radius-lg);
78
+ box-shadow: var(--shadow-md);
79
+ }
80
+
81
+ .card__title {
82
+ color: var(--color-neutral-800);
83
+ font-size: var(--text-2xl);
84
+ font-weight: var(--font-bold);
85
+ }
86
+ ```
87
+
88
+ ---
89
+
90
+ ### 2. Layer 1: Tailwind CSS (Layout Bones)
91
+
92
+ Tailwind CSS handles all structural layout properties. These are the mechanical, pattern-based properties that determine how elements are arranged, sized, and spaced -- not how they look visually.
93
+
94
+ #### Properties That Belong in Tailwind
95
+
96
+ | CSS Property | Tailwind Class | Source in Figma |
97
+ |-------------|---------------|-----------------|
98
+ | `display: flex` | `flex` | Auto Layout container |
99
+ | `flex-direction: column` | `flex-col` | `layoutMode: VERTICAL` |
100
+ | `flex-direction: row` | `flex-row` | `layoutMode: HORIZONTAL` |
101
+ | `justify-content: center` | `justify-center` | `primaryAxisAlignItems: CENTER` |
102
+ | `justify-content: space-between` | `justify-between` | `primaryAxisAlignItems: SPACE_BETWEEN` |
103
+ | `align-items: center` | `items-center` | `counterAxisAlignItems: CENTER` |
104
+ | `align-items: flex-start` | `items-start` | `counterAxisAlignItems: MIN` |
105
+ | `gap: 16px` | `gap-4` | `itemSpacing: 16` |
106
+ | `padding: 24px` | `p-6` | `padding: { top: 24, right: 24, bottom: 24, left: 24 }` |
107
+ | `padding: 16px 24px` | `py-4 px-6` | Mixed padding values |
108
+ | `flex-grow: 1; flex-basis: 0` | `flex-1` | `layoutSizingHorizontal: FILL` (primary axis) |
109
+ | `flex-shrink: 0` | `shrink-0` | `layoutSizingHorizontal: FIXED` (primary axis) |
110
+ | `align-self: stretch` | `self-stretch` | `layoutSizingVertical: FILL` (counter axis) |
111
+ | `width: 100%` | `w-full` | FILL on counter axis |
112
+ | `flex-wrap: wrap` | `flex-wrap` | `layoutWrap: WRAP` |
113
+ | `position: relative` | `relative` | Parent of absolute children |
114
+ | `position: absolute` | `absolute` | `layoutPositioning: ABSOLUTE` |
115
+ | `overflow: hidden` | `overflow-hidden` | Clip content |
116
+ | `min-width: 200px` | `min-w-[200px]` | `minWidth: 200` |
117
+ | `max-width: 800px` | `max-w-[800px]` | `maxWidth: 800` |
118
+
119
+ #### When NOT to Use Tailwind
120
+
121
+ Tailwind should NOT be used for visual design properties:
122
+
123
+ - **Colors** -- `bg-blue-500` creates a tight coupling to Tailwind's color palette. Use CSS Custom Properties so colors can be changed via tokens without touching HTML.
124
+ - **Shadows** -- `shadow-lg` uses Tailwind's built-in shadow, not the design's specific shadow. Use token-referenced `box-shadow` in CSS Modules.
125
+ - **Border radius** -- Design-specific radii should reference tokens (`var(--radius-lg)`), not Tailwind's radius scale.
126
+ - **Font sizes** -- Use token-referenced `font-size` (`var(--text-lg)`) to maintain consistency with the design's type scale.
127
+ - **Specific spacing values** -- When a spacing value maps to a design token (from Figma Variables or threshold-promoted), use `var(--spacing-md)` instead of `gap-4`.
128
+
129
+ **Exception:** When Tailwind is configured to reference CSS Custom Properties in its theme (see Section 2.1), Tailwind classes like `gap-md` or `text-lg` can safely reference tokens.
130
+
131
+ #### 2.1 Tailwind Theme Integration with Design Tokens
132
+
133
+ Tailwind's theme can be configured to reference CSS Custom Properties, bridging Layer 1 and Layer 2:
134
+
135
+ ```js
136
+ // tailwind.config.js
137
+ export default {
138
+ theme: {
139
+ extend: {
140
+ colors: {
141
+ primary: 'var(--color-primary)',
142
+ secondary: 'var(--color-secondary)',
143
+ neutral: {
144
+ 100: 'var(--color-neutral-100)',
145
+ 300: 'var(--color-neutral-300)',
146
+ 800: 'var(--color-neutral-800)',
147
+ },
148
+ },
149
+ spacing: {
150
+ xs: 'var(--spacing-xs)',
151
+ sm: 'var(--spacing-sm)',
152
+ md: 'var(--spacing-md)',
153
+ lg: 'var(--spacing-lg)',
154
+ xl: 'var(--spacing-xl)',
155
+ },
156
+ borderRadius: {
157
+ sm: 'var(--radius-sm)',
158
+ md: 'var(--radius-md)',
159
+ lg: 'var(--radius-lg)',
160
+ full: 'var(--radius-full)',
161
+ },
162
+ fontSize: {
163
+ xs: 'var(--text-xs)',
164
+ sm: 'var(--text-sm)',
165
+ base: 'var(--text-base)',
166
+ lg: 'var(--text-lg)',
167
+ xl: 'var(--text-xl)',
168
+ '2xl': 'var(--text-2xl)',
169
+ },
170
+ boxShadow: {
171
+ sm: 'var(--shadow-sm)',
172
+ md: 'var(--shadow-md)',
173
+ lg: 'var(--shadow-lg)',
174
+ },
175
+ },
176
+ },
177
+ }
178
+ ```
179
+
180
+ With this configuration, `gap-md` resolves to `gap: var(--spacing-md)`, which in turn resolves to the actual pixel value defined in the `:root` tokens. This allows Tailwind classes to be token-aware without hardcoding values.
181
+
182
+ #### Tailwind v4 Configuration
183
+
184
+ The reference project uses Tailwind v4 via `@tailwindcss/postcss`:
185
+
186
+ ```js
187
+ // postcss.config.mjs
188
+ const config = {
189
+ plugins: {
190
+ '@tailwindcss/postcss': {},
191
+ },
192
+ }
193
+ export default config
194
+ ```
195
+
196
+ Tailwind v4 automatically detects CSS custom properties and can use them as utility values without explicit theme configuration, reducing the need for manual theme extension.
197
+
198
+ ---
199
+
200
+ ### 3. Layer 2: CSS Custom Properties (Design Tokens)
201
+
202
+ CSS Custom Properties serve as the design tokens bridge -- the shared vocabulary of colors, spacing, typography, radii, shadows, and transitions that all components reference. Tokens are defined once in `:root` and consumed everywhere via `var()`.
203
+
204
+ #### Token Placement at `:root`
205
+
206
+ All design tokens are defined on the `:root` selector, making them globally available:
207
+
208
+ ```css
209
+ :root {
210
+ /* Colors */
211
+ --color-primary: #1a73e8;
212
+ --color-secondary: #5f6368;
213
+ --color-neutral-100: #f5f5f5;
214
+ --color-neutral-800: #333333;
215
+ --color-success: #34a853;
216
+ --color-warning: #fbbc04;
217
+ --color-error: #ea4335;
218
+
219
+ /* Spacing */
220
+ --spacing-1: 4px;
221
+ --spacing-2: 8px;
222
+ --spacing-3: 12px;
223
+ --spacing-4: 16px;
224
+ --spacing-6: 24px;
225
+ --spacing-8: 32px;
226
+
227
+ /* Typography */
228
+ --font-primary: 'Inter', sans-serif;
229
+ --font-mono: 'Roboto Mono', monospace;
230
+ --text-sm: 14px;
231
+ --text-base: 16px;
232
+ --text-lg: 18px;
233
+ --text-xl: 24px;
234
+ --text-2xl: 32px;
235
+ --font-regular: 400;
236
+ --font-medium: 500;
237
+ --font-bold: 700;
238
+
239
+ /* Border Radii */
240
+ --radius-sm: 4px;
241
+ --radius-md: 8px;
242
+ --radius-lg: 12px;
243
+ --radius-full: 9999px;
244
+
245
+ /* Shadows */
246
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
247
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
248
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
249
+
250
+ /* Transitions */
251
+ --transition-fast: 150ms ease;
252
+ --transition-normal: 200ms ease;
253
+ --transition-slow: 300ms ease;
254
+ }
255
+ ```
256
+
257
+ #### Category Naming Conventions
258
+
259
+ The recommended category prefixes for auto-detected tokens:
260
+
261
+ | Category | Prefix | Examples |
262
+ |----------|--------|---------|
263
+ | Colors | `--color-*` | `--color-primary`, `--color-neutral-800`, `--color-error` |
264
+ | Spacing | `--spacing-*` | `--spacing-1`, `--spacing-4`, `--spacing-8` |
265
+ | Font sizes | `--text-*` | `--text-sm`, `--text-base`, `--text-2xl` |
266
+ | Font families | `--font-*` | `--font-primary`, `--font-mono` |
267
+ | Font weights | `--font-*` | `--font-bold`, `--font-medium`, `--font-regular` |
268
+ | Border radii | `--radius-*` | `--radius-sm`, `--radius-md`, `--radius-full` |
269
+ | Shadows | `--shadow-*` | `--shadow-sm`, `--shadow-md`, `--shadow-lg` |
270
+ | Transitions | `--transition-*` | `--transition-fast`, `--transition-normal` |
271
+
272
+ #### The `--token-*` Double-Prefix Pattern
273
+
274
+ Some projects add a `--token-` prefix to all design tokens. This serves two purposes: (1) clearly distinguishes design tokens from other CSS custom properties, and (2) enables the Visual Builder's token aliasing pattern.
275
+
276
+ ```css
277
+ /* tokens.css */
278
+ :root {
279
+ --token-color-primary: #3b82f6;
280
+ --token-spacing-md: 16px;
281
+ --token-radius-lg: 12px;
282
+ --token-font-size-base: 18px;
283
+ --token-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
284
+ }
285
+ ```
286
+
287
+ The `--token-` prefix is a project convention, not a requirement. Some projects use bare category prefixes (`--color-*`), others use `--token-color-*`. Both are valid approaches.
288
+
289
+ #### Token Fallback Pattern
290
+
291
+ When consuming tokens in CSS Module rules, always include a raw fallback value. This ensures the styles work even if the token definition is missing (e.g., during development, or when tokens are loaded asynchronously):
292
+
293
+ ```css
294
+ /* With fallback — safe for all environments */
295
+ background-color: var(--token-color-primary, #3b82f6);
296
+ border-radius: var(--token-radius-lg, 12px);
297
+ padding: var(--token-spacing-lg, 24px);
298
+
299
+ /* Without fallback — only safe when token is guaranteed to be defined */
300
+ background-color: var(--color-primary);
301
+ ```
302
+
303
+ **When to omit fallbacks:** For tokens defined in the same project's `tokens.css` that is guaranteed to be loaded before component styles. Fallbacks can be omitted for local Figma Variables (tokens defined in the same file). External library variables always include fallbacks.
304
+
305
+ > For details on token extraction, naming algorithms, and promotion thresholds, see `design-tokens.md`.
306
+
307
+ ---
308
+
309
+ ### 4. Layer 3: CSS Modules (Visual Skin)
310
+
311
+ CSS Modules provide component-scoped visual styles. These are the Figma-specific visual properties that give each component its unique appearance -- backgrounds, borders, shadows, color assignments, typography styling.
312
+
313
+ #### Component-Scoped Styles
314
+
315
+ Each component gets its own CSS Module file. Class names are locally scoped (hashed at build time), preventing style leaking between components:
316
+
317
+ ```css
318
+ /* Card.module.css */
319
+ .card {
320
+ background-color: var(--color-neutral-100);
321
+ border: 1px solid var(--color-neutral-300);
322
+ border-radius: var(--radius-lg);
323
+ box-shadow: var(--shadow-md);
324
+ }
325
+
326
+ .card__title {
327
+ color: var(--color-neutral-800);
328
+ font-size: var(--text-2xl);
329
+ font-weight: var(--font-bold);
330
+ }
331
+
332
+ .card__body {
333
+ color: var(--color-neutral-800);
334
+ font-size: var(--text-base);
335
+ line-height: 1.6;
336
+ }
337
+
338
+ .card__cta {
339
+ background-color: var(--color-primary);
340
+ color: var(--color-neutral-100);
341
+ border-radius: var(--radius-sm);
342
+ font-weight: var(--font-medium);
343
+ }
344
+ ```
345
+
346
+ #### BEM Naming Within Modules
347
+
348
+ CSS Module class names follow BEM conventions with flat hierarchy (no deeper than `block__element`):
349
+
350
+ ```css
351
+ /* Block */
352
+ .hero { }
353
+
354
+ /* Elements */
355
+ .hero__inner { }
356
+ .hero__content { }
357
+ .hero__title { }
358
+ .hero__buttons { }
359
+ .hero__button { }
360
+
361
+ /* Modifiers (via composes or separate classes) */
362
+ .heroContainerHigh { min-height: 400px; }
363
+ .heroContainerMedium { min-height: 300px; }
364
+ ```
365
+
366
+ > For BEM naming conventions and flat hierarchy rules, see `design-to-code-semantic.md`.
367
+
368
+ #### Token Consumption Pattern
369
+
370
+ CSS Module rules consume tokens via `var()` references. The module never defines its own token values -- it only references tokens from Layer 2:
371
+
372
+ ```css
373
+ /* CORRECT: Module consumes tokens */
374
+ .card {
375
+ background-color: var(--token-color-bg, #ffffff);
376
+ border-radius: var(--token-radius-lg, 12px);
377
+ box-shadow: var(--token-shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.1));
378
+ }
379
+
380
+ /* WRONG: Module defines its own values (bypasses token system) */
381
+ .card {
382
+ background-color: #ffffff;
383
+ border-radius: 12px;
384
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
385
+ }
386
+ ```
387
+
388
+ #### File Organization (Per-Block Modules)
389
+
390
+ The recommended approach organizes CSS Modules by block type, with each block in its own file under `src/styles/blocks/`:
391
+
392
+ ```
393
+ src/styles/
394
+ tokens.css # Layer 2: shared design tokens
395
+ blocks/
396
+ accordion.module.css # Layer 3: per-block visual skin
397
+ button.module.css
398
+ callToAction.module.css
399
+ card.module.css
400
+ container.module.css
401
+ hero.module.css
402
+ media.module.css
403
+ richText.module.css
404
+ stats.module.css
405
+ testimonial.module.css
406
+ video.module.css
407
+ ```
408
+
409
+ Each module imports `tokens.css` to ensure token definitions are available:
410
+
411
+ ```css
412
+ @import '../tokens.css';
413
+
414
+ .card {
415
+ background-color: var(--token-color-bg, #ffffff);
416
+ /* ... */
417
+ }
418
+ ```
419
+
420
+ #### Visual Builder Token Aliasing
421
+
422
+ The Visual Builder plugin creates a CSS isolation boundary using `contain: content` and `isolation: isolate`. Within this boundary, tokens are aliased from `--token-*` to `--vb-*` to prevent interference with the Payload CMS admin panel's styles:
423
+
424
+ ```css
425
+ /* visualCanvas.module.css */
426
+ .visualCanvas {
427
+ all: revert;
428
+ contain: content;
429
+ isolation: isolate;
430
+
431
+ /* Token aliasing: VB tokens reference project tokens with fallbacks */
432
+ --vb-color-primary: var(--token-color-primary, #3b82f6);
433
+ --vb-spacing-md: var(--token-spacing-md, 16px);
434
+ --vb-radius-md: var(--token-radius-md, 8px);
435
+ /* ... full aliasing for all token categories */
436
+ }
437
+ ```
438
+
439
+ This pattern enables:
440
+
441
+ 1. **Plugin portability** -- The Visual Builder works in any project regardless of whether `--token-*` variables are defined (fallbacks kick in)
442
+ 2. **Admin isolation** -- `contain: content` prevents Payload admin styles from bleeding into the visual canvas
443
+ 3. **Single source of truth** -- Projects define tokens once in `tokens.css`; the Visual Builder automatically picks them up via the alias chain
444
+
445
+ ---
446
+
447
+ ### 5. Property Placement Decision Tree
448
+
449
+ For any CSS property generated from a Figma node, this decision tree determines which layer it belongs to. This is the core routing logic for the CSS generation pipeline.
450
+
451
+ ```
452
+ For each CSS property on a GeneratedElement:
453
+
454
+ 1. IS IT A STRUCTURAL LAYOUT PROPERTY?
455
+ (display, flex-direction, justify-content, align-items, gap,
456
+ flex-grow, flex-basis, flex-shrink, flex-wrap, align-self,
457
+ align-content, position, width/height from sizing modes,
458
+ min-width, max-width, min-height, max-height, overflow)
459
+
460
+ YES → Layer 1: Tailwind utility class
461
+ Rationale: Layout is mechanical and pattern-based.
462
+ Tailwind's utility classes express these concisely.
463
+
464
+ 2. IS THE RAW VALUE A PROMOTED DESIGN TOKEN?
465
+ (color resolves to var(--color-*),
466
+ spacing resolves to var(--spacing-*),
467
+ font-size resolves to var(--text-*),
468
+ font-family resolves to var(--font-*),
469
+ font-weight resolves to var(--font-*),
470
+ border-radius resolves to var(--radius-*),
471
+ box-shadow resolves to var(--shadow-*))
472
+
473
+ YES → Layer 2: CSS Custom Property reference in the value
474
+ The token is DEFINED in :root, CONSUMED in the CSS Module rule.
475
+ Rationale: Tokens are the shared design language. Centralizing
476
+ them enables theme changes without touching component styles.
477
+
478
+ 3. IS IT A COMPONENT-SPECIFIC VISUAL STYLE?
479
+ (background-color, background-image, border, border-color,
480
+ border-radius, box-shadow, color, opacity, filter,
481
+ backdrop-filter, mix-blend-mode, text-decoration,
482
+ transition, transform)
483
+
484
+ YES → Layer 3: CSS Module rule
485
+ The property is placed in the component's .module.css file.
486
+ If the value is a token, the rule uses var(--token-*).
487
+ If the value is not a token, the raw value is used inline.
488
+
489
+ 4. IS IT PADDING OR GAP WITH A TOKEN VALUE?
490
+
491
+ YES → Layer 1 if using Tailwind theme integration:
492
+ class="gap-md p-lg" (where md/lg map to token vars)
493
+ YES → Layer 3 if not using Tailwind theme integration:
494
+ gap: var(--spacing-md); padding: var(--spacing-lg);
495
+ Rationale: Padding and gap are layout properties but can also
496
+ carry token values. The choice depends on Tailwind configuration.
497
+ ```
498
+
499
+ #### Property-to-Layer Reference Table
500
+
501
+ | Property Category | Example Properties | Layer | Method |
502
+ |------------------|--------------------|-------|--------|
503
+ | Flex container | `display`, `flex-direction`, `justify-content`, `align-items`, `flex-wrap`, `align-content` | 1 (Tailwind) | Utility classes |
504
+ | Flex child | `flex-grow`, `flex-basis`, `flex-shrink`, `align-self` | 1 (Tailwind) | Utility classes |
505
+ | Spacing | `gap`, `padding`, `margin` | 1 or 3 | Tailwind if standard; Module if token-bound |
506
+ | Sizing | `width`, `height`, `min-width`, `max-width` | 1 (Tailwind) | Utility classes |
507
+ | Positioning | `position`, `top`, `right`, `bottom`, `left`, `z-index` | 1 (Tailwind) | Utility classes |
508
+ | Overflow | `overflow`, `text-overflow` | 1 (Tailwind) | Utility classes |
509
+ | Background | `background-color`, `background-image`, `background-size` | 3 (Module) | CSS rule with `var()` |
510
+ | Border | `border`, `border-color`, `border-width` | 3 (Module) | CSS rule with `var()` |
511
+ | Border radius | `border-radius` | 3 (Module) | CSS rule with `var()` |
512
+ | Shadow | `box-shadow` | 3 (Module) | CSS rule with `var()` |
513
+ | Color | `color` | 3 (Module) | CSS rule with `var()` |
514
+ | Typography | `font-family`, `font-size`, `font-weight`, `line-height` | 3 (Module) | CSS rule with `var()` |
515
+ | Text | `text-align`, `text-transform`, `white-space`, `letter-spacing` | 3 (Module) | CSS rule |
516
+ | Opacity | `opacity` | 3 (Module) | CSS rule |
517
+ | Blend modes | `mix-blend-mode`, `background-blend-mode` | 3 (Module) | CSS rule |
518
+ | Filters | `filter`, `backdrop-filter` | 3 (Module) | CSS rule |
519
+ | Transitions | `transition` | 3 (Module) | CSS rule with `var()` |
520
+
521
+ ---
522
+
523
+ ### 6. Specificity Management
524
+
525
+ The three layers compose without specificity conflicts because each layer operates at a different specificity level.
526
+
527
+ #### Specificity by Layer
528
+
529
+ | Layer | Selector Type | Specificity | Example |
530
+ |-------|-------------|-------------|---------|
531
+ | 1. Tailwind | Utility class | `0-1-0` (single class) | `.flex` |
532
+ | 2. Tokens | `:root` pseudo-class | `0-1-0` (for definition) | `:root { --color-primary: #1a73e8 }` |
533
+ | 3. CSS Module | Hashed class | `0-1-0` (single class) | `.card_abc123` |
534
+
535
+ #### Why Conflicts Do Not Occur
536
+
537
+ 1. **Tailwind vs Modules** -- Tailwind handles layout properties. Modules handle visual properties. They target different CSS properties on the same element, so they do not compete.
538
+
539
+ 2. **Tokens vs Modules** -- Tokens define variables on `:root`. Modules consume those variables via `var()`. They do not target the same selectors or properties.
540
+
541
+ 3. **Tailwind vs Tokens** -- When Tailwind is configured with token references in its theme, Tailwind utilities resolve to `var()` values. This is composition, not conflict.
542
+
543
+ #### Potential Conflict: Padding and Gap
544
+
545
+ The one area where Layers 1 and 3 could conflict is spacing properties (padding, gap). If a Tailwind class sets `gap: 16px` and a CSS Module rule also sets `gap: var(--spacing-md)`, the Module rule wins due to source order (Modules are loaded after Tailwind utilities).
546
+
547
+ **Resolution:** Choose one layer for spacing. Either:
548
+ - Use Tailwind for all spacing (with token-aware theme configuration)
549
+ - Use CSS Module rules for all spacing (when token substitution is needed)
550
+
551
+ Do not mix both layers for the same spacing property on the same element.
552
+
553
+ #### Tailwind `@layer` Ordering
554
+
555
+ Tailwind v4 uses CSS `@layer` to establish baseline ordering:
556
+
557
+ ```
558
+ @layer base; /* Resets, element defaults */
559
+ @layer components; /* Component styles (CSS Modules go here) */
560
+ @layer utilities; /* Tailwind utilities (highest CSS layer priority) */
561
+ ```
562
+
563
+ By default, Tailwind utilities override component styles. This means a Tailwind class on an element will override the same property set by a CSS Module. This is generally desirable for layout overrides but requires awareness when both layers target the same property.
564
+
565
+ ---
566
+
567
+ ### 7. Responsive Strategy
568
+
569
+ #### Mobile-First Breakpoint Ordering
570
+
571
+ All responsive CSS uses a mobile-first approach: base styles target the smallest viewport, and larger viewports are handled through `min-width` media queries.
572
+
573
+ | Breakpoint | min-width | CSS |
574
+ |------------|-----------|-----|
575
+ | `mobile` | _(base)_ | No media query (base styles) |
576
+ | `tablet` | 768px | `@media (min-width: 768px)` |
577
+ | `desktop` | 1024px | `@media (min-width: 1024px)` |
578
+
579
+ This matches both responsive frame merging (see `design-to-code-layout.md` Section 8) and Figma Variables breakpoint mode detection.
580
+
581
+ #### Figma Variables Mode to Media Query Mapping
582
+
583
+ When Figma variable collections use breakpoint modes (detected by mode names like "mobile", "tablet", "desktop"), the pipeline renders mode-aware `:root` overrides inside media queries:
584
+
585
+ ```css
586
+ /* Base: mobile values (default mode) */
587
+ :root {
588
+ --spacing-lg: 16px;
589
+ --text-xl: 20px;
590
+ }
591
+
592
+ /* Tablet overrides */
593
+ @media (min-width: 768px) {
594
+ :root {
595
+ --spacing-lg: 24px;
596
+ --text-xl: 24px;
597
+ }
598
+ }
599
+
600
+ /* Desktop overrides */
601
+ @media (min-width: 1024px) {
602
+ :root {
603
+ --spacing-lg: 32px;
604
+ --text-xl: 28px;
605
+ }
606
+ }
607
+ ```
608
+
609
+ This approach means component styles automatically respond to viewport changes without any media queries of their own -- the token values change, and all `var()` references resolve to the new values.
610
+
611
+ #### Tailwind Responsive Prefixes
612
+
613
+ For layout properties in Layer 1, use Tailwind's responsive prefixes:
614
+
615
+ ```html
616
+ <div class="flex flex-col md:flex-row gap-3 md:gap-6 lg:gap-8 p-4 md:p-6 lg:p-8">
617
+ ```
618
+
619
+ | Prefix | Breakpoint | CSS |
620
+ |--------|-----------|-----|
621
+ | _(none)_ | All | Base styles |
622
+ | `sm:` | 640px | `@media (min-width: 640px)` |
623
+ | `md:` | 768px | `@media (min-width: 768px)` |
624
+ | `lg:` | 1024px | `@media (min-width: 1024px)` |
625
+ | `xl:` | 1280px | `@media (min-width: 1280px)` |
626
+
627
+ #### CSS Module Responsive Patterns
628
+
629
+ For visual properties in Layer 3 that need responsive behavior beyond what token media queries provide:
630
+
631
+ ```css
632
+ /* Card.module.css */
633
+ .card {
634
+ border-radius: var(--radius-md);
635
+ }
636
+
637
+ @media (min-width: 768px) {
638
+ .card {
639
+ border-radius: var(--radius-lg);
640
+ }
641
+ }
642
+ ```
643
+
644
+ This is less common because most responsive visual changes are handled through token mode overrides at the `:root` level. Module-level media queries are only needed for structural visual changes (e.g., adding/removing a border on desktop, changing an element's background pattern).
645
+
646
+ > For responsive frame matching and style diffing algorithms, see `design-to-code-layout.md` Section 8.
647
+
648
+ ---
649
+
650
+ ### 8. Theme Support
651
+
652
+ #### Light/Dark Theme via CSS Custom Properties
653
+
654
+ Themes are implemented by redefining token values under different selectors. The component styles remain unchanged -- they reference tokens via `var()`, and the resolved values change based on the active theme.
655
+
656
+ **Media query approach (automatic, based on OS preference):**
657
+
658
+ ```css
659
+ :root {
660
+ --color-bg: #ffffff;
661
+ --color-text: #1a1a1a;
662
+ --color-border: #e0e0e0;
663
+ }
664
+
665
+ @media (prefers-color-scheme: dark) {
666
+ :root {
667
+ --color-bg: #1a1a1a;
668
+ --color-text: #ffffff;
669
+ --color-border: #404040;
670
+ }
671
+ }
672
+ ```
673
+
674
+ **Data attribute approach (manual toggle, JavaScript-controlled):**
675
+
676
+ ```css
677
+ :root,
678
+ [data-theme="light"] {
679
+ --color-bg: #ffffff;
680
+ --color-text: #1a1a1a;
681
+ }
682
+
683
+ [data-theme="dark"] {
684
+ --color-bg: #1a1a1a;
685
+ --color-text: #ffffff;
686
+ }
687
+ ```
688
+
689
+ The pipeline generates both approaches when theme mode collections are detected: the `prefers-color-scheme` media query for automatic theme detection, and the `[data-theme]` selector for manual control.
690
+
691
+ #### Figma Variables Theme Mode Mapping
692
+
693
+ When a Figma variable collection has a "theme" mode type (detected by mode names containing "light" or "dark"), the pipeline maps the default mode (light) to `:root` and non-default modes to both `prefers-color-scheme` and `[data-theme]` selectors:
694
+
695
+ ```
696
+ Collection: "Theme"
697
+ Mode "Light" (default) → :root { }
698
+ Mode "Dark" → @media (prefers-color-scheme: dark) { :root { } }
699
+ [data-theme="dark"] { }
700
+ ```
701
+
702
+ > For the full Figma Variables multi-mode theming patterns, see `figma-api-variables.md`.
703
+
704
+ #### Brand Theming
705
+
706
+ For multi-brand themes, use class-based selectors:
707
+
708
+ ```css
709
+ .brand-a {
710
+ --color-primary: #0066ff;
711
+ --font-primary: 'Inter', sans-serif;
712
+ }
713
+
714
+ .brand-b {
715
+ --color-primary: #ff3366;
716
+ --font-primary: 'Poppins', sans-serif;
717
+ }
718
+ ```
719
+
720
+ Components reference `var(--color-primary)` and automatically adopt the active brand's values.
721
+
722
+ ---
723
+
724
+ ### 9. Export Formats
725
+
726
+ The generation pipeline supports multiple CSS export structures depending on the project's needs.
727
+
728
+ #### Separate Files (Recommended for Projects)
729
+
730
+ When `separateTokens: true`, the export produces three independent CSS files:
731
+
732
+ | File | Content | Layer |
733
+ |------|---------|-------|
734
+ | `reset.css` | Universal CSS reset (box-sizing, margin, padding, image defaults) | Pre-layer |
735
+ | `tokens.css` | `:root` block with CSS Custom Properties, media queries for modes | Layer 2 |
736
+ | `styles.css` | Component class rules (BEM-named) | Layer 3 |
737
+
738
+ Import order matters:
739
+
740
+ ```html
741
+ <link rel="stylesheet" href="reset.css">
742
+ <link rel="stylesheet" href="tokens.css">
743
+ <link rel="stylesheet" href="styles.css">
744
+ ```
745
+
746
+ #### Merged Output (Default for Preview)
747
+
748
+ When `separateTokens: false`, tokens are merged into `styles.css`:
749
+
750
+ | File | Content |
751
+ |------|---------|
752
+ | `reset.css` | Universal CSS reset |
753
+ | `styles.css` | Tokens (`:root` block) + component class rules |
754
+
755
+ #### SCSS Export
756
+
757
+ For SCSS consumers, the pipeline generates a parallel file structure using SCSS conventions:
758
+
759
+ | File | Content | Notes |
760
+ |------|---------|-------|
761
+ | `_reset.scss` | Reset rules | Underscore prefix = SCSS partial |
762
+ | `_variables.scss` | `$variable` declarations | `--color-primary` becomes `$color-primary` |
763
+ | `_mixins.scss` | Empty placeholder | For project-specific mixins |
764
+ | `styles.scss` | `@import` statements + component rules | Entry point with var() converted to $variable |
765
+
766
+ **SCSS variable conversion:**
767
+
768
+ ```scss
769
+ // _variables.scss (generated from tokens)
770
+ $color-primary: #1a73e8;
771
+ $spacing-4: 16px;
772
+ $text-lg: 18px;
773
+ $font-bold: 700;
774
+ $shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
775
+
776
+ // styles.scss (generated from component styles)
777
+ @import 'variables';
778
+ @import 'reset';
779
+ @import 'mixins';
780
+
781
+ .card {
782
+ background-color: $color-neutral-100;
783
+ border-radius: $radius-lg;
784
+ box-shadow: $shadow-md;
785
+ }
786
+ ```
787
+
788
+ The conversion replaces `var(--name)` with `$name` and `--name: value` with `$name: value`.
789
+
790
+ #### HTML Document Export
791
+
792
+ For standalone preview, the pipeline generates a complete HTML document with embedded CSS:
793
+
794
+ ```html
795
+ <!DOCTYPE html>
796
+ <html lang="en">
797
+ <head>
798
+ <style>
799
+ @import url('https://fonts.googleapis.com/css2?family=...');
800
+ /* CSS reset */
801
+ /* tokens :root block */
802
+ /* component styles */
803
+ </style>
804
+ </head>
805
+ <body>
806
+ <!-- generated HTML -->
807
+ </body>
808
+ </html>
809
+ ```
810
+
811
+ The ordering within the `<style>` block is: font imports, reset, tokens, component styles.
812
+
813
+ > For details on the SCSS rendering pipeline, see `design-tokens.md`.
814
+
815
+ ---
816
+
817
+ ### 10. Integration with Design-to-Code Pipeline
818
+
819
+ The five design-to-code modules feed into the CSS strategy at specific integration points.
820
+
821
+ #### Pipeline Flow
822
+
823
+ ```
824
+ Figma Node Tree
825
+
826
+ [Extraction Phase]
827
+
828
+ ExtractedNode tree
829
+
830
+ ┌─────────────────────────────┐
831
+ │ Token Collection & Promotion │ ← design-tokens.md
832
+ │ (colors, spacing, typography,│
833
+ │ effects, Figma Variables) │
834
+ └──────────────┬──────────────┘
835
+
836
+ TokenLookup map
837
+
838
+ ┌─────────────────────────────┐
839
+ │ Generation Phase │
840
+ │ ├─ layout.md → Layer 1 │ Flex container/child → Tailwind classes
841
+ │ ├─ visual.md → Layer 3 │ Fills, strokes, effects → CSS Module rules
842
+ │ ├─ typography.md → Layer 3 │ Font props → CSS Module rules with var()
843
+ │ ├─ assets.md → HTML │ Vector/image → <img> tags
844
+ │ └─ semantic.md → HTML │ Tags, BEM classes, ARIA attributes
845
+ └──────────────┬──────────────┘
846
+
847
+ GeneratedOutput
848
+ ┌──────┼──────┐
849
+ ↓ ↓ ↓
850
+ HTML CSS Tokens
851
+ ↓ ↓
852
+ Layer 3 Layer 2
853
+ (styles.css) (tokens.css)
854
+ ```
855
+
856
+ #### How Each Module Contributes
857
+
858
+ **`design-to-code-layout.md`** produces layout CSS that maps to Layer 1 (Tailwind classes):
859
+ - `display: flex` → `flex`
860
+ - `flex-direction: column` → `flex-col`
861
+ - `gap: 16px` → `gap-4` (or `gap: var(--spacing-4)` if token-bound)
862
+ - Responsive frame merging → `md:flex-row lg:gap-8`
863
+
864
+ **`design-to-code-visual.md`** produces visual CSS that maps to Layer 3 (CSS Module rules):
865
+ - `background-color: var(--color-primary)` (via token lookup)
866
+ - `box-shadow: var(--shadow-md)` (via token lookup)
867
+ - `border-radius: var(--radius-lg)` (via token lookup)
868
+ - Raw values when no token match: `border: 1px solid #e0e0e0`
869
+
870
+ **`design-to-code-typography.md`** produces typography CSS that maps to Layer 3:
871
+ - `font-family: var(--font-primary)` (via token lookup)
872
+ - `font-size: var(--text-lg)` (via token lookup)
873
+ - `font-weight: var(--font-bold)` (via token lookup)
874
+ - `line-height: 1.50` (always raw, not tokenized)
875
+
876
+ **`design-to-code-assets.md`** produces HTML elements (not CSS):
877
+ - Vector containers → `<img src="icon.svg">`
878
+ - Image fills → `<img>` or `background-image` CSS in Module
879
+
880
+ **`design-to-code-semantic.md`** produces HTML structure:
881
+ - Semantic tags → `<section>`, `<nav>`, `<h2>`, `<button>`
882
+ - BEM class names → `.card`, `.card__title`, `.card__body`
883
+ - ARIA attributes → `aria-label`, `role`
884
+
885
+ #### Token Lookup During Generation
886
+
887
+ The `TokenLookup` is built from promoted tokens before generation begins. During CSS generation, each raw value is checked against the lookup map. If a match is found, the `var()` reference is used instead of the raw value:
888
+
889
+ ```
890
+ Raw value: #1a73e8
891
+ → lookupColor(lookup, "#1a73e8")
892
+ → Returns: "var(--color-primary)" (if token exists)
893
+ → Returns: "#1a73e8" (if no token match)
894
+ ```
895
+
896
+ This substitution happens transparently during the generation of visual and typography styles. Layout properties are not token-substituted (they go to Tailwind).
897
+
898
+ > For the complete token lookup system, including Figma Variable priority over auto-detected tokens, see `design-tokens.md`.
899
+
900
+ #### Complete Example: All Three Layers
901
+
902
+ A card component with all three layers working together:
903
+
904
+ ```html
905
+ <!-- Layer 1: Tailwind for layout -->
906
+ <section class="flex flex-col gap-6 p-6 max-w-md">
907
+ <!-- Layer 3: CSS Module for visual skin -->
908
+ <div class="card">
909
+ <img class="card__image" src="./assets/photo.png" alt="Team photo">
910
+ <div class="flex flex-col gap-3 p-4">
911
+ <h3 class="card__title">Meet the Team</h3>
912
+ <p class="card__body">Our talented people make the difference.</p>
913
+ <a class="card__cta" href="#">Learn More</a>
914
+ </div>
915
+ </div>
916
+ </section>
917
+ ```
918
+
919
+ ```css
920
+ /* Layer 2: tokens.css */
921
+ :root {
922
+ --color-primary: #1a73e8;
923
+ --color-neutral-100: #f5f5f5;
924
+ --color-neutral-800: #333333;
925
+ --text-lg: 18px;
926
+ --text-2xl: 32px;
927
+ --font-bold: 700;
928
+ --radius-lg: 12px;
929
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
930
+ }
931
+
932
+ /* Layer 3: Card.module.css */
933
+ .card {
934
+ background-color: var(--color-neutral-100);
935
+ border-radius: var(--radius-lg);
936
+ box-shadow: var(--shadow-md);
937
+ overflow: hidden;
938
+ }
939
+
940
+ .card__title {
941
+ font-size: var(--text-2xl);
942
+ font-weight: var(--font-bold);
943
+ color: var(--color-neutral-800);
944
+ }
945
+
946
+ .card__body {
947
+ font-size: var(--text-lg);
948
+ color: var(--color-neutral-800);
949
+ line-height: 1.60;
950
+ }
951
+
952
+ .card__cta {
953
+ background-color: var(--color-primary);
954
+ color: var(--color-neutral-100);
955
+ border-radius: var(--radius-sm);
956
+ padding: 8px 16px;
957
+ font-weight: var(--font-bold);
958
+ }
959
+ ```
960
+
961
+ ---
962
+
963
+ ## Cross-References
964
+
965
+ - **`design-tokens.md`** -- Token extraction pipeline, threshold-based promotion, naming conventions, CSS/SCSS/Tailwind rendering. Defines the tokens consumed by Layer 2.
966
+ - **`design-tokens-variables.md`** -- Figma Variables deep dive: mode detection and classification, variable resolution chains, mode-aware CSS rendering, fallback strategies, scope-to-CSS-property mapping. The Variables-to-Token-to-CSS bridge.
967
+ - **`figma-api-variables.md`** -- Variables API endpoints, variable data model, multi-mode theming patterns. The source data for Figma Variable tokens.
968
+ - **`design-to-code-layout.md`** -- Auto Layout to Flexbox mapping that produces Layer 1 (Tailwind) output. Responsive multi-frame pattern with mobile-first media queries.
969
+ - **`design-to-code-visual.md`** -- Visual property extraction that produces Layer 3 (CSS Module) output. Color token integration with HSL naming, variable binding resolution.
970
+ - **`design-to-code-typography.md`** -- Typography extraction that produces Layer 3 output. Font family/size/weight token lookup during generation.
971
+ - **`design-to-code-assets.md`** -- Asset management for image and vector export. Asset references appear in HTML (`<img src>`) and CSS Module rules (`background-image`).
972
+ - **`design-to-code-semantic.md`** -- Semantic HTML generation that provides the element structure. BEM class naming used by Layer 3 CSS Modules. Three-layer architecture overview (Section 9).
973
+ - **`payload-blocks.md`** -- PayloadCMS block system that consumes all three CSS layers. Container blocks store Tailwind utility classes (Layer 1), block CSS Modules reference `--token-*` custom properties (Layer 2), and each block has a dedicated CSS Module for scoped visual styles (Layer 3). The three-layer architecture serves this block system directly.