@nadicodeai/design-system 0.10.2 → 0.11.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 (51) hide show
  1. package/AGENTS.md +30 -101
  2. package/CONTEXT.md +75 -0
  3. package/DESIGN.md +180 -345
  4. package/README.md +27 -54
  5. package/dist/assets/logo-mark.svg +6 -0
  6. package/dist/assets/logo-wordmark.svg +4 -0
  7. package/dist/assets/nadia-canonical-face.png +0 -0
  8. package/dist/css/chat-autoplay.js +18 -27
  9. package/dist/css/index.css +2540 -56
  10. package/dist/favicon/apple-touch-icon.png +0 -0
  11. package/dist/favicon/favicon.ico +0 -0
  12. package/dist/favicon/favicon.svg +6 -16
  13. package/dist/favicon/icon-192.png +0 -0
  14. package/dist/favicon/icon-512.png +0 -0
  15. package/dist/favicon/site.webmanifest +2 -2
  16. package/dist/tailwind/nadicode.tailwind.json +98 -143
  17. package/dist/tokens/nadicode.dtcg.json +413 -908
  18. package/package.json +19 -11
  19. package/src/assets/logo-geometry.d.ts +27 -0
  20. package/src/assets/logo-geometry.js +204 -0
  21. package/src/assets/nadia-canonical-face.d.ts +2 -0
  22. package/dist/css/components/.gitkeep +0 -0
  23. package/dist/css/components/agent-avatar.css +0 -52
  24. package/dist/css/components/approval-gate.css +0 -145
  25. package/dist/css/components/artifact-preview.css +0 -81
  26. package/dist/css/components/chat-bubble-agent.css +0 -63
  27. package/dist/css/components/chat-bubble-user.css +0 -28
  28. package/dist/css/components/chat-thread.css +0 -159
  29. package/dist/css/components/handoff-banner.css +0 -37
  30. package/dist/css/components/image.css +0 -87
  31. package/dist/css/components/memory-item.css +0 -36
  32. package/dist/css/components/run-timeline.css +0 -160
  33. package/dist/css/components/state-row.css +0 -64
  34. package/dist/css/components/state-tag.css +0 -67
  35. package/dist/css/components/status-tag.css +0 -101
  36. package/dist/css/components/tool-call-trace.css +0 -36
  37. package/dist/css/components/typing-dots.css +0 -54
  38. package/dist/css/components/usage-meter.css +0 -63
  39. package/dist/css/foundation.css +0 -177
  40. package/dist/css/layout.css +0 -657
  41. package/dist/css/motion.css +0 -225
  42. package/dist/css/primitives.css +0 -333
  43. package/dist/css/reset.css +0 -22
  44. package/dist/css/tokens.generated.css +0 -349
  45. package/dist/css/tokens.local.css +0 -11
  46. package/dist/tailwind/nadicode.theme.css +0 -596
  47. package/src/assets/favicon.svg +0 -17
  48. package/src/assets/logo-mark.svg +0 -15
  49. package/src/assets/logo-wordmark.svg +0 -26
  50. package/src/assets/nadia.d.ts +0 -9
  51. package/src/assets/nadia.png +0 -0
package/DESIGN.md CHANGED
@@ -8,107 +8,59 @@ description: >-
8
8
  shared by every NadicodeAI interface.
9
9
 
10
10
  colors:
11
- primary: "#008c45"
12
- on-primary: "#ffffff"
13
- action: "#007a3c"
14
- action-foreground: "#ffffff"
15
- action-hover: "#00602f"
16
- action-active: "#00301a"
17
- ink: "#171717"
18
- body: "#4d4d4d"
19
- muted: "#888888"
11
+ primary: "#00a85a"
12
+ on-primary: "#0f0e0b"
13
+ action: "#00a85a"
14
+ action-foreground: "#0f0e0b"
15
+ action-hover: "#009d54"
16
+ action-active: "#009550"
17
+ ink: "#0f0e0b"
18
+ body: "#3d3c38"
19
+ muted: "#74726b"
20
20
  canvas: "#ffffff"
21
- canvas-soft: "#fafafa"
22
- canvas-soft-2: "#f5f5f5"
23
- line: "#e5e5e5"
24
- input: "#8f8f8f"
25
- seam: "#e4e7ec"
26
- cross: "#a1a1a1"
27
- focus-ring: "#007a3c"
28
- scrim: "#171717"
29
- link: "#007a3c"
30
- link-deep: "#00602f"
31
- link-bg-soft: "#d9f6e4"
32
- accent: "#cd212a"
33
- info: "#2743d8"
34
- success: "#008c45"
35
- error: "#b80022"
36
- error-soft: "#fce4e4"
37
- error-deep: "#9c001d"
38
- warning: "#f5a623"
39
- warning-soft: "#fff1cf"
40
- warning-deep: "#8f4a06"
41
- flag-red: "#cd212a"
42
- selection-bg: "#171717"
43
- selection-fg: "#f2f2f2"
44
- state-ready: "#4d4d4d"
45
- state-running: "#2743d8"
46
- state-review: "#f5a623"
47
- state-blocked: "#b80022"
48
- state-complete: "#008c45"
21
+ canvas-soft: "#f7f7f4"
22
+ canvas-soft-2: "#efefe9"
23
+ line: "#e6e6e0"
24
+ input: "#74726d"
25
+ seam: "#d8d8d0"
26
+ cross: "#97958b"
27
+ focus-ring: "#00713d"
28
+ scrim: "#0f0e0b"
29
+ link: "#00713d"
30
+ link-deep: "#00522c"
31
+ link-bg-soft: "#c6efd9"
32
+ accent: "#ff5a1f"
33
+ info: "#1e3cff"
34
+ info-soft: "#e8ecff"
35
+ info-deep: "#0e1d8a"
36
+ success: "#00a85a"
37
+ error: "#d3302f"
38
+ error-soft: "#fdeaea"
39
+ error-deep: "#8f1a19"
40
+ warning: "#ffc220"
41
+ warning-soft: "#fff3d1"
42
+ warning-deep: "#7a5800"
43
+ flag-red: "#d3302f"
44
+ selection-bg: "#0f0e0b"
45
+ selection-fg: "#f7f7f4"
46
+ state-ready: "#74726b"
47
+ state-running: "#1e3cff"
48
+ state-review: "#ffc220"
49
+ state-blocked: "#d3302f"
50
+ state-complete: "#00a85a"
49
51
  background-100: "#ffffff"
50
- background-200: "#fafafa"
51
- gray-100: "#f2f2f2"
52
- gray-200: "#ebebeb"
53
- gray-300: "#e6e6e6"
54
- gray-400: "#eaeaea"
55
- gray-500: "#c9c9c9"
56
- gray-600: "#a8a8a8"
57
- gray-700: "#8f8f8f"
58
- gray-800: "#7d7d7d"
59
- gray-900: "#4d4d4d"
60
- gray-1000: "#171717"
61
- green-italia-100: "#e8faef"
62
- green-italia-200: "#d9f6e4"
63
- green-italia-300: "#c3f0d4"
64
- green-italia-400: "#9fe6bc"
65
- green-italia-500: "#62d494"
66
- green-italia-600: "#17b568"
67
- green-italia-700: "#008c45"
68
- green-italia-800: "#007a3c"
69
- green-italia-900: "#00602f"
70
- green-italia-1000: "#00301a"
71
- red-italia-100: "#fdeeee"
72
- red-italia-200: "#fce4e4"
73
- red-italia-300: "#fad3d4"
74
- red-italia-400: "#f7b3b5"
75
- red-italia-500: "#f28085"
76
- red-italia-600: "#e84e57"
77
- red-italia-700: "#cd212a"
78
- red-italia-800: "#b80022"
79
- red-italia-900: "#9c001d"
80
- red-italia-1000: "#4a000e"
81
- blue-cobalto-100: "#eef2ff"
82
- blue-cobalto-200: "#e2e9fe"
83
- blue-cobalto-300: "#cdd9fd"
84
- blue-cobalto-400: "#a9befa"
85
- blue-cobalto-500: "#7d99f2"
86
- blue-cobalto-600: "#4f6ae6"
87
- blue-cobalto-700: "#2743d8"
88
- blue-cobalto-800: "#1d33ad"
89
- blue-cobalto-900: "#16277f"
90
- blue-cobalto-1000: "#0a1240"
91
- amber-100: "#fff6e1"
92
- amber-200: "#fff1cf"
93
- amber-300: "#ffe9b3"
94
- amber-400: "#ffd97d"
95
- amber-500: "#ffc933"
96
- amber-600: "#f5a623"
97
- amber-700: "#d98800"
98
- amber-800: "#b36b00"
99
- amber-900: "#8f4a06"
100
- amber-1000: "#452301"
101
- campo-verde: "#008c45"
102
- campo-rosso: "#cd212a"
103
- campo-arancio: "#e4530b"
104
- campo-giallo: "#f2b705"
105
- campo-cobalto: "#2743d8"
106
- campo-inchiostro: "#171717"
52
+ background-200: "#f7f7f4"
53
+ campo-verde: "#00a85a"
54
+ campo-rosso: "#d3302f"
55
+ campo-arancio: "#ff5a1f"
56
+ campo-giallo: "#ffc220"
57
+ campo-cobalto: "#1e3cff"
58
+ campo-inchiostro: "#0f0e0b"
107
59
  campo-bianco: "#ffffff"
108
- chart-1: "#2743d8"
109
- chart-2: "#008c45"
110
- chart-3: "#f5a623"
111
- chart-4: "#cd212a"
60
+ chart-1: "#1e3cff"
61
+ chart-2: "#00a85a"
62
+ chart-3: "#ffc220"
63
+ chart-4: "#d3302f"
112
64
  chart-5: "#00838f"
113
65
  chart-6: "#6f42c1"
114
66
  chart-seq-1: "#7d99f2"
@@ -116,51 +68,54 @@ colors:
116
68
  chart-seq-3: "#2743d8"
117
69
  chart-seq-4: "#1d33ad"
118
70
  chart-seq-5: "#16277f"
119
- chart-div-warm: "#d98800"
120
- chart-div-mid: "#8f8f8f"
121
- chart-div-cool: "#7d99f2"
122
- dark-canvas: "#0a0a0a"
123
- dark-canvas-soft: "#171717"
124
- dark-canvas-soft-2: "#262626"
125
- dark-ink: "#f5f5f5"
126
- dark-body: "#d4d4d4"
127
- dark-muted: "#a3a3a3"
128
- dark-line: "#2e2e2e"
129
- dark-input: "#5d5d5d"
130
- dark-seam: "#1f1f1f"
131
- dark-primary: "#ededed"
132
- dark-on-primary: "#0a0a0a"
133
- dark-action: "#ededed"
134
- dark-action-foreground: "#0a0a0a"
135
- dark-action-hover: "#d4d4d4"
136
- dark-action-active: "#a3a3a3"
137
- dark-link: "#9fe6bc"
138
- dark-link-deep: "#c3f0d4"
139
- dark-link-bg-soft: "#00301a"
140
- dark-focus-ring: "#9fe6bc"
141
- dark-scrim: "#f5f5f5"
142
- dark-error: "#f7b3b5"
143
- dark-error-soft: "#4a000e"
144
- dark-error-deep: "#fad3d4"
145
- dark-warning: "#ffd97d"
146
- dark-warning-soft: "#452301"
147
- dark-warning-deep: "#ffe9b3"
71
+ chart-div-warm: "#e0a600"
72
+ chart-div-mid: "#74726b"
73
+ chart-div-cool: "#4d6bff"
74
+ dark-canvas: "#0f0f0d"
75
+ dark-canvas-soft: "#171714"
76
+ dark-canvas-soft-2: "#20201b"
77
+ dark-ink: "#f2f2ee"
78
+ dark-body: "#cac9c3"
79
+ dark-muted: "#8f8d84"
80
+ dark-line: "#2a2a26"
81
+ dark-input: "#696863"
82
+ dark-seam: "#20201b"
83
+ dark-primary: "#2fd584"
84
+ dark-on-primary: "#0f0f0d"
85
+ dark-action: "#2fd584"
86
+ dark-action-foreground: "#0f0f0d"
87
+ dark-action-hover: "#4ecf8c"
88
+ dark-action-active: "#17bd68"
89
+ dark-link: "#4ecf8c"
90
+ dark-link-deep: "#93e3b8"
91
+ dark-link-bg-soft: "#00351c"
92
+ dark-focus-ring: "#4ecf8c"
93
+ dark-scrim: "#f2f2ee"
94
+ dark-error: "#f5a3a1"
95
+ dark-error-soft: "#380a09"
96
+ dark-error-deep: "#fbcccb"
97
+ dark-warning: "#ffd866"
98
+ dark-warning-soft: "#402e00"
99
+ dark-warning-deep: "#ffe7a3"
100
+ dark-info: "#8098ff"
101
+ dark-info-soft: "#070f47"
102
+ dark-info-deep: "#b3c1ff"
148
103
  dark-cyan: "#33d1cb"
149
104
  dark-cyan-soft: "#7ee8de"
150
105
  dark-cyan-deep: "#1f9e9a"
151
- dark-success: "#62d494"
152
- dark-state-ready: "#8f8f8f"
153
- dark-state-running: "#4f6ae6"
154
- dark-state-review: "#f5a623"
155
- dark-state-blocked: "#cd212a"
156
- dark-state-complete: "#008c45"
157
- dark-selection-bg: "#ededed"
158
- dark-selection-fg: "#0a0a0a"
159
- dark-cross: "#6e6e6e"
160
- dark-chart-1: "#7d99f2"
161
- dark-chart-2: "#17b568"
162
- dark-chart-3: "#ffd97d"
163
- dark-chart-4: "#f28085"
106
+ dark-success: "#17bd68"
107
+ dark-state-ready: "#74726b"
108
+ dark-state-running: "#4d6bff"
109
+ dark-state-review: "#ffc220"
110
+ dark-state-blocked: "#d3302f"
111
+ dark-state-complete: "#00a85a"
112
+ dark-selection-bg: "#f2f2ee"
113
+ dark-selection-fg: "#0f0f0d"
114
+ dark-cross: "#565349"
115
+ dark-chart-1: "#4d6bff"
116
+ dark-chart-2: "#00a85a"
117
+ dark-chart-3: "#ffd866"
118
+ dark-chart-4: "#e8615f"
164
119
  dark-chart-5: "#33d1cb"
165
120
  dark-chart-6: "#9575cd"
166
121
  dark-chart-seq-1: "#4f6ae6"
@@ -168,9 +123,9 @@ colors:
168
123
  dark-chart-seq-3: "#a9befa"
169
124
  dark-chart-seq-4: "#cdd9fd"
170
125
  dark-chart-seq-5: "#eef2ff"
171
- dark-chart-div-warm: "#ffd97d"
172
- dark-chart-div-mid: "#e6e6e6"
173
- dark-chart-div-cool: "#cdd9fd"
126
+ dark-chart-div-warm: "#ffd866"
127
+ dark-chart-div-mid: "#e6e6e0"
128
+ dark-chart-div-cool: "#b3c1ff"
174
129
 
175
130
  typography:
176
131
  display-xl:
@@ -361,164 +316,6 @@ spacing:
361
316
  filter-chip-height: 28px
362
317
  filter-chip-icon: 14px
363
318
 
364
- components:
365
- label-mono:
366
- textColor: "{colors.muted}"
367
- typography: "{typography.caption-mono}"
368
- padding: "0px"
369
- artifact-surface:
370
- backgroundColor: "{colors.canvas}"
371
- textColor: "{colors.ink}"
372
- padding: "{spacing.lg}"
373
- status-tag-gray:
374
- backgroundColor: "{colors.gray-200}"
375
- textColor: "{colors.gray-900}"
376
- typography: "{typography.caption-strong}"
377
- rounded: "{rounded.md}"
378
- padding: "0px 10px"
379
- height: 24px
380
- status-tag-green:
381
- backgroundColor: "{colors.green-italia-200}"
382
- textColor: "{colors.green-italia-900}"
383
- typography: "{typography.caption-strong}"
384
- rounded: "{rounded.md}"
385
- padding: "0px 10px"
386
- height: 24px
387
- status-tag-red:
388
- backgroundColor: "{colors.red-italia-200}"
389
- textColor: "{colors.red-italia-900}"
390
- typography: "{typography.caption-strong}"
391
- rounded: "{rounded.md}"
392
- padding: "0px 10px"
393
- height: 24px
394
- status-tag-amber:
395
- backgroundColor: "{colors.amber-200}"
396
- textColor: "{colors.amber-900}"
397
- typography: "{typography.caption-strong}"
398
- rounded: "{rounded.md}"
399
- padding: "0px 10px"
400
- height: 24px
401
- status-tag-blue:
402
- backgroundColor: "{colors.blue-cobalto-200}"
403
- textColor: "{colors.blue-cobalto-900}"
404
- typography: "{typography.caption-strong}"
405
- rounded: "{rounded.md}"
406
- padding: "0px 10px"
407
- height: 24px
408
- image:
409
- backgroundColor: "{colors.canvas-soft}"
410
- textColor: "{colors.body}"
411
- typography: "{typography.caption}"
412
- rounded: "{rounded.none}"
413
- padding: 0px
414
- badge-secondary:
415
- backgroundColor: "{colors.canvas-soft}"
416
- textColor: "{colors.body}"
417
- typography: "{typography.caption}"
418
- rounded: "{rounded.md}"
419
- padding: "0px {spacing.xs}"
420
- filter-chip:
421
- backgroundColor: "{colors.canvas-soft}"
422
- textColor: "{colors.body}"
423
- typography: "{typography.caption}"
424
- rounded: "{rounded.sm}"
425
- padding: "0px {spacing.xs}"
426
- height: "{spacing.filter-chip-height}"
427
- state-tag-ready:
428
- backgroundColor: "{colors.canvas}"
429
- textColor: "{colors.ink}"
430
- typography: "{typography.caption-mono}"
431
- rounded: "{rounded.sm}"
432
- padding: "0px {spacing.xs}"
433
- height: 26px
434
- state-tag-running:
435
- backgroundColor: "{colors.canvas}"
436
- textColor: "{colors.ink}"
437
- typography: "{typography.caption-mono}"
438
- rounded: "{rounded.sm}"
439
- padding: "0px {spacing.xs}"
440
- height: 26px
441
- state-tag-review:
442
- backgroundColor: "{colors.canvas}"
443
- textColor: "{colors.ink}"
444
- typography: "{typography.caption-mono}"
445
- rounded: "{rounded.sm}"
446
- padding: "0px {spacing.xs}"
447
- height: 26px
448
- state-tag-blocked:
449
- backgroundColor: "{colors.canvas}"
450
- textColor: "{colors.ink}"
451
- typography: "{typography.caption-mono}"
452
- rounded: "{rounded.sm}"
453
- padding: "0px {spacing.xs}"
454
- height: 26px
455
- state-tag-complete:
456
- backgroundColor: "{colors.canvas}"
457
- textColor: "{colors.ink}"
458
- typography: "{typography.caption-mono}"
459
- rounded: "{rounded.sm}"
460
- padding: "0px {spacing.xs}"
461
- height: 26px
462
- approval-gate:
463
- backgroundColor: "{colors.warning-soft}"
464
- textColor: "{colors.ink}"
465
- typography: "{typography.body-sm}"
466
- rounded: "{rounded.md}"
467
- padding: "{spacing.md}"
468
- agent-avatar:
469
- backgroundColor: "{colors.canvas-soft}"
470
- rounded: "{rounded.full}"
471
- padding: "0px"
472
- usage-meter:
473
- backgroundColor: "{colors.canvas}"
474
- textColor: "{colors.body}"
475
- typography: "{typography.caption-mono}"
476
- rounded: "{rounded.sm}"
477
- padding: "{spacing.xxs} {spacing.xs}"
478
- run-timeline:
479
- backgroundColor: "{colors.canvas}"
480
- textColor: "{colors.ink}"
481
- typography: "{typography.body-sm}"
482
- padding: "0px"
483
- memory-item:
484
- backgroundColor: "{colors.canvas-soft}"
485
- textColor: "{colors.ink}"
486
- typography: "{typography.body-sm}"
487
- rounded: "{rounded.sm}"
488
- padding: "{spacing.xs} {spacing.sm}"
489
- handoff-banner:
490
- backgroundColor: "{colors.link-bg-soft}"
491
- textColor: "{colors.link-deep}"
492
- typography: "{typography.body-sm-strong}"
493
- rounded: "{rounded.md}"
494
- padding: "{spacing.sm} {spacing.md}"
495
- chat-thread:
496
- backgroundColor: "{colors.canvas}"
497
- textColor: "{colors.ink}"
498
- padding: "{spacing.lg}"
499
- chat-bubble-user:
500
- backgroundColor: "{colors.primary}"
501
- textColor: "{colors.on-primary}"
502
- typography: "{typography.body-sm}"
503
- rounded: "{rounded.md}"
504
- padding: "{spacing.sm} {spacing.md}"
505
- chat-bubble-agent:
506
- backgroundColor: "{colors.canvas}"
507
- textColor: "{colors.ink}"
508
- typography: "{typography.body-sm}"
509
- rounded: "{rounded.md}"
510
- padding: "{spacing.sm} {spacing.md}"
511
- tool-call-trace:
512
- backgroundColor: "{colors.canvas-soft-2}"
513
- textColor: "{colors.ink}"
514
- typography: "{typography.code}"
515
- rounded: "{rounded.sm}"
516
- padding: "{spacing.xs} {spacing.sm}"
517
- link-inline:
518
- backgroundColor: "{colors.canvas}"
519
- textColor: "{colors.link}"
520
- typography: "{typography.body-md}"
521
- padding: "0px"
522
319
  ---
523
320
 
524
321
  ## Overview
@@ -531,60 +328,49 @@ The kernel is the reusable implementation layer. `DESIGN.md` defines the reusabl
531
328
 
532
329
  ## Colors
533
330
 
534
- The Italia color system runs on two tiers that never mix. The **functional tier** (scales + semantic roles + charts) drives every product and interface state; the **brand tier** (the seven campi) paints marketing and identity surfaces. A scale step is never a poster field, and a campo is never a UI state.
331
+ The colour system is two families that never mix. The **functional tier** the semantic role tokens plus the chart series — drives every product and interface state. The **brand tier** the campi paints marketing and identity surfaces only. A functional role is never a poster field, and a campo is never a UI state.
535
332
 
536
- ### Architecture step semantics
537
-
538
- Colour is organised as two page backgrounds plus five ten-step scales (`gray`, `green-italia`, `red-italia`, `blue-cobalto`, `amber`). Every scale reads the same way, so a step number carries a fixed job across all five families:
539
-
540
- - **100–300** — component backgrounds: default, hover, active.
541
- - **400–600** — borders: default, hover, active.
542
- - **700** — the high-contrast solid, the star anchor of the scale (the flag/cobalt tone).
543
- - **800** — solid hover.
544
- - **900** — text and icons (AA body weight on white).
545
- - **1000** — high-contrast text, and the darkest ground for dark-mode tinted panels.
546
-
547
- Backgrounds are `{colors.background-100}` (page default, white) and `{colors.background-200}` (soft, used sparingly). `gray` is adopted verbatim as the neutral spine: the existing `{colors.ink}` (= `gray-1000`), `{colors.body}` (= `gray-900`), `{colors.canvas}`, `{colors.canvas-soft}`, `{colors.canvas-soft-2}`, and `{colors.line}` names stay as consumed aliases over the scale — do not rename them. `green-italia` is the brand primary (anchor `{colors.green-italia-700}`, flag green); `red-italia` carries accent and danger (anchor `{colors.red-italia-700}`, flag red); `blue-cobalto` carries info and the cobalt world of the imagery (anchor `{colors.blue-cobalto-700}`); `amber` carries warning and chrome-yellow energy (`{colors.amber-600}` is the operational warning tone).
333
+ Every value a role needs is carried by the role token itself; there are no ten-step scale families to reference. Two neutral page grounds sit under the roles below: `{colors.background-100}` (page default, white) and `{colors.background-200}` (soft, used sparingly). The neutral spine — `{colors.ink}`, `{colors.body}`, `{colors.muted}`, `{colors.canvas}`, `{colors.canvas-soft}`, `{colors.canvas-soft-2}`, `{colors.line}`, `{colors.seam}` — is warm and low-chroma (OKLCH chroma ≤ 0.01), not equal-channel gray, so surfaces read as paper rather than cold screen while staying achromatic enough that no hue paints an app surface. Colours are authored as sRGB hex here and emitted as `oklch()` in the generated CSS.
548
334
 
549
335
  ### Semantic roles (functional tier)
550
336
 
551
- - **Primary brand anchor** (`{colors.primary}` = `green-italia-700`): identity marks and non-text brand accents. It is not the text-bearing action surface; normal-size white text on this green does not clear AA.
552
- - **Action** (`{colors.action}`, `{colors.action-foreground}`, `{colors.action-hover}`, `{colors.action-active}`): the text-bearing primary-control family. Shadcn `primary` roles map here rather than to the brand anchor. Dark mode uses the corresponding `dark-action-*` roles.
553
- - **Canvas / Line / Input / Cross / Seam** (`{colors.canvas}`, `{colors.line}`, `{colors.input}`, `{colors.cross}`, `{colors.seam}`): white content cells, the universal decorative 1 px divider, the stronger resting-control boundary, the stronger gray for marks and crosshair markers, and the dashed connector guide. `{colors.line}` owns ordinary seams; `{colors.input}` owns fields and other interactive boundaries that must clear the 3:1 non-text contrast floor. Never darken a decorative border locally to make it behave like a control.
554
- - **Body / Muted** (`{colors.body}`, `{colors.muted}`): `{colors.body}` is readable supporting copy; `{colors.muted}` is restricted to disabled, inactive, and placeholder content. Do not use muted text for ordinary descriptions, labels, or help text.
555
- - **Focus ring** (`{colors.focus-ring}` / `{colors.dark-focus-ring}`): the full-opacity `{spacing.focus-ring-width}` keyboard-focus indicator with no offset. It is independent of the resting border and clears the 3:1 non-text contrast floor against the adjacent canvas.
337
+ - **Primary brand anchor** (`{colors.primary}` = verde `#00a85a`): identity marks and brand accents. Text on the verde field is ink (`{colors.on-primary}`), never white normal-size white does not clear AA on the brighter verde, ink clears it comfortably.
338
+ - **Action** (`{colors.action}` = verde, `{colors.action-foreground}` = ink, `{colors.action-hover}`, `{colors.action-active}`): the primary-control family — an ink label on the verde field. The shadcn `primary` roles map here. Dark mode uses the `dark-action-*` roles, a brightened verde that clears the dark canvas, still ink-labelled.
339
+ - **Canvas / Line / Input / Cross / Seam** (`{colors.canvas}`, `{colors.line}`, `{colors.input}`, `{colors.cross}`, `{colors.seam}`): white content cells, the universal decorative 1 px divider, the resting-control boundary, the stronger mark/crosshair gray, and the dashed connector guide. `{colors.line}` owns ordinary seams and is deliberately quiet — a decorative hairline, not held to a non-text contrast floor. `{colors.input}` owns fields and other interactive boundaries and clears the 3:1 non-text floor against its canvas. Never darken a decorative border locally to make it behave like a control.
340
+ - **Body / Muted** (`{colors.body}`, `{colors.muted}`): `{colors.body}` is readable supporting copy and clears AA on canvas; `{colors.muted}` is restricted to disabled, inactive, and placeholder content. Do not use muted text for ordinary descriptions, labels, or help text.
341
+ - **Focus ring** (`{colors.focus-ring}` / `{colors.dark-focus-ring}`): the full-opacity `{spacing.focus-ring-width}` keyboard-focus indicator with no offset. It is independent of the resting border and clears the 3:1 non-text floor against the adjacent canvas.
556
342
  - **Scrim** (`{colors.scrim}` / `{colors.dark-scrim}`): the semantic modal-overlay foreground. Its opacity is the generated material token declared in `Elevation & Depth`; it is never combined with backdrop blur.
557
- - **Link** (`{colors.link}` = `green-italia-800`, `{colors.link-deep}` = `green-italia-900`, `{colors.link-bg-soft}` = `green-italia-200`): inline links, navigational accents, and approved/example proof states. Intentionally green, keeping the Italian signal without turning the interface into flag decoration.
558
- - **Semantic feedback** (`{colors.success}`, `{colors.error}` + `{colors.error-soft}`/`{colors.error-deep}`, `{colors.warning}` + `{colors.warning-soft}`/`{colors.warning-deep}`, `{colors.info}`): validation, caution, approval, and operational feedback. `success` uses `green-italia-700`; `error` uses `red-italia-800` with soft/deep on `red-italia-200`/`red-italia-900`; `warning` uses `amber-600` with soft/deep on `amber-200`/`amber-900`; `info` (`blue-cobalto-700`) is the new informational role.
559
- - **Accent** (`{colors.accent}` = `red-italia-700`): UI highlights, badges, and selected markers. Flag red is now an active accent — the former "decoration-only" restriction on flag red is retired. Do not conflate this functional Italia `accent` with the identically-named shadcn surface role `accent`: the latter is a neutral (mapped to `{colors.canvas-soft-2}` in light and `{colors.dark-canvas-soft-2}` in dark) and carries no flag-red hue despite the shared word.
560
- - **Flag Red** (`{colors.flag-red}`): kept as a stable alias at the same value as `{colors.accent}` (`red-italia-700`, `#cd212a`). `accent` and `flag-red` are two roles at one hex: `accent` is the interface-highlight role, `flag-red` is the identity-mark alias. `error` (`red-italia-800`) stays a distinct, deeper red; never use it as an accent.
561
- - **Workflow States** (`{colors.state-ready}`, `{colors.state-running}`, `{colors.state-review}`, `{colors.state-blocked}`, `{colors.state-complete}`): the left-border/state vocabulary for agentic work surfaces. `state-running` is `blue-cobalto-700` and `state-complete` is `green-italia-700` — blue means in motion, green means done; `state-ready` is `gray-900`. The dark counterparts (`{colors.dark-state-ready}`, `{colors.dark-state-running}`, `{colors.dark-state-review}`, `{colors.dark-state-blocked}`, `{colors.dark-state-complete}`) preserve the same functional identity instead of shifting to pastel labels: ready uses `gray-700`, running uses `blue-cobalto-600`, review reuses `amber-600`, blocked uses `red-italia-700`, and complete reuses `green-italia-700`. These state colors are carried only by the `state-tag` 3 px `border-left` rail and related non-text state accents; label text stays on the neutral foreground roles for contrast in both light and dark. The `{colors.state-*}` tokens stay rail-only for run-state surfaces; entity status is a separate vocabulary carried by the `status-tag` family's background+text ramp pairs (see `## Components`), and the two token sets never cross.
343
+ - **Link** (`{colors.link}`, `{colors.link-deep}`, `{colors.link-bg-soft}`): inline links, navigational accents, approved/example proof states, and the green entity-status tone. Green, keeping the Italian signal without turning the interface into flag decoration; `link` and `link-deep` clear AA as text on canvas, and `link-bg-soft` is the tinted green tag ground.
344
+ - **Semantic feedback** (`{colors.success}` = verde; `{colors.error}` = rosso funzionale `#d3302f` with `{colors.error-soft}`/`{colors.error-deep}`; `{colors.warning}` = giallo `#ffc220` with `{colors.warning-soft}`/`{colors.warning-deep}`; `{colors.info}` = cobalto `#1e3cff` with `{colors.info-soft}`/`{colors.info-deep}`): validation, caution, approval, and operational feedback. In each pair the `-soft` value is the tinted tag/banner ground and the `-deep` value is the AA-clearing text on it. On a solid `error` fill (the shadcn `destructive` role) text is white; on a solid `warning` or `success` fill text is ink.
345
+ - **Accent** (`{colors.accent}` = arancio `#ff5a1f`): the attention accent for highlights, exception flags, and emphasis marks. It is an accent only never a fill, background, or body-text colour, and it never carries text. Do not conflate this functional `accent` with the identically-named shadcn surface role: that role is a neutral (`{colors.canvas-soft-2}` in light, `{colors.dark-canvas-soft-2}` in dark) and carries no hue despite the shared word.
346
+ - **Flag Red** (`{colors.flag-red}` = `#d3302f`): the identity-mark red alias. It shares its hex with `{colors.error}` but stays a distinct role name `flag-red` is identity, `error` is validation feedback. The attention accent is arancio, not flag red.
347
+ - **Workflow States** (`{colors.state-ready}` neutral, `{colors.state-running}` cobalto, `{colors.state-review}` giallo, `{colors.state-blocked}` rosso, `{colors.state-complete}` verde): the left-border/state vocabulary for agentic work surfaces cobalto means in motion, verde means done. The dark counterparts (`{colors.dark-state-ready}`, `{colors.dark-state-running}`, `{colors.dark-state-review}`, `{colors.dark-state-blocked}`, `{colors.dark-state-complete}`) keep the same functional identity. These colours are carried only by the `state-tag` 3 px `border-left` rail and related non-text state accents; label text stays on the neutral foreground roles for contrast in both themes. The `{colors.state-*}` tokens stay rail-only for run-state surfaces; entity status is a separate vocabulary carried by the `status-tag` family's background+text pairs (see `## Components`), and the two token sets never cross.
562
348
 
563
349
  ### Chart categoricals (functional tier)
564
350
 
565
- - **Charts** (`{colors.chart-1}`…`{colors.chart-6}`): the categorical series palette — cobalto, verde, ambra, rosso, plus a functional-only teal and viola. Functional only: never place chart colours on marketing surfaces, campi, or generated imagery. On the dark canvas all six series carry dark-tuned steps, remapped in the `.dark` scope so any consumer reading the semantic token gets the right hue in both modes: `{colors.dark-chart-1}` on `blue-cobalto-500`, `{colors.dark-chart-2}` on `green-italia-600`, `{colors.dark-chart-3}` on `amber-400`, `{colors.dark-chart-4}` on `red-italia-500`, `{colors.dark-chart-5}` on the `dark-cyan` value, `{colors.dark-chart-6}` a lighter viola. Clearing the 3:1 WCAG 1.4.11 data-mark floor is necessary but not sufficient on the near-black canvas: the full-saturation light hues read as loud saturated blocks there, so each dark step lightens or desaturates its hue while keeping series identity, and all six clear 3:1 against `{colors.dark-canvas}`. Verde takes the one-step move to `green-italia-600` (not the mint `green-italia-500`) so the verde/teal separation survives in normal vision.
566
- - **Categorical distinguishability**: the same-family neighbours are held apart — `chart-3`/`chart-4` (ambra/rosso) and `chart-2`/`chart-5` (verde/teal) each clear a CIEDE2000 ≥ 20 normal / ≥ 15 deuteranopia-simulated floor, in the light set and in the dark-tuned set alike. Two proximities are brand-locked and exempt from the numeric floor: `chart-2`/`chart-4` (verde/rosso, the flag pair, which collapses under red-green deficiency by identity) and `chart-1`/`chart-6` (cobalto/viola, adjacent blue-violet). Charts using the full six must carry redundant encoding (direct labels, position, or pattern), never hue alone, so these two pairs stay readable under colour-vision deficiency.
351
+ - **Charts** (`{colors.chart-1}`…`{colors.chart-6}`): the categorical series palette — cobalto, verde, giallo, rosso, plus a functional-only teal and viola. Functional only: never place chart colours on marketing surfaces, campi, or generated imagery. On the dark canvas all six series carry dark-tuned steps (`{colors.dark-chart-1}`…`{colors.dark-chart-6}`), remapped in the `.dark` scope so any consumer reading the semantic token gets the right hue in both modes. Clearing the 3:1 WCAG 1.4.11 data-mark floor is necessary but not sufficient on the near-black canvas: the full-strength light hues read as loud blocks there, so each dark step lightens or desaturates while keeping series identity, and all six clear 3:1 against `{colors.dark-canvas}`.
352
+ - **Categorical distinguishability**: the same-family neighbours are held apart — `chart-3`/`chart-4` (giallo/rosso) and `chart-2`/`chart-5` (verde/teal) each clear a CIEDE2000 ≥ 20 normal / ≥ 15 deuteranopia-simulated floor, in the light set and the dark-tuned set alike. Two proximities are brand-locked and exempt from the numeric floor: `chart-2`/`chart-4` (verde/rosso, the flag pair, which collapses under red-green deficiency by identity) and `chart-1`/`chart-6` (cobalto/viola, adjacent blue-violet). Charts using the full six carry redundant encoding (direct labels, position, or pattern), never hue alone, so these two pairs stay readable under colour-vision deficiency.
567
353
 
568
354
  ### Brand tier — i campi
569
355
 
570
- The seven campi are full-strength named brand fields. They carry NO tints, NO steps, and NO hover variants; UI states always come from the scales, never from a campo.
356
+ The campi are full-strength named brand fields. They carry NO tints, NO steps, and NO hover variants; UI states always come from the functional roles, never from a campo.
571
357
 
572
358
  - `{colors.campo-verde}` (Verde Bandiera), `{colors.campo-rosso}` (Rosso Bandiera), and `{colors.campo-cobalto}` pair with `{colors.campo-bianco}` (white) type.
573
- - `{colors.campo-arancio}` (vermilion) and `{colors.campo-giallo}` (mustard) pair with `{colors.campo-inchiostro}` (ink) type.
359
+ - `{colors.campo-arancio}` (vermilion) and `{colors.campo-giallo}` (giallo) pair with `{colors.campo-inchiostro}` (ink) type.
574
360
  - `{colors.campo-inchiostro}` pairs with white type; `{colors.campo-bianco}` pairs with ink type.
575
361
 
576
362
  Four campo rules govern their use:
577
363
 
578
364
  1. **One campo per room.** A section owns exactly one field; adjacent sections must jump in luminance, so two mid-tone rooms never touch.
579
365
  2. **Type on a campo is bianco or inchiostro only.** Arancio and Giallo carry ink; Verde, Rosso, Cobalto, and Inchiostro carry white. No tinted text on fields.
580
- 3. **Campi are planes, not chips.** The minimum duty of a campo is a section ground, poster field, or full media mount. UI states come from the scales, never campi.
581
- 4. **One paint box.** Generated imagery draws its flat fields from these seven values; the Visual Law's private palette retires and points at these tokens.
366
+ 3. **Campi are planes, not chips.** The minimum duty of a campo is a section ground, poster field, or full media mount. UI states come from the functional roles, never campi.
367
+ 4. **One paint box.** Generated imagery draws its flat fields from these values; the Visual Law's private palette retires and points at these tokens.
582
368
 
583
369
  ### Dark primitives
584
370
 
585
- **Dark Primitives** (`{colors.dark-canvas}`, `{colors.dark-ink}`, `{colors.dark-line}`, and siblings) are the source tokens for the generated shadcn `.dark` role map — mode-bearing primitives, not a separate palette; consuming apps opt in by applying a `.dark` ancestor through their runtime theme provider. The dark neutrals (`dark-canvas`, `dark-canvas-soft`, `dark-canvas-soft-2`, `dark-ink`, `dark-body`, `dark-muted`, `dark-line`, `dark-input`, `dark-seam`, `dark-primary`, `dark-on-primary`, `dark-action`, `dark-action-foreground`, `dark-action-hover`, `dark-action-active`, and `dark-scrim`) are true neutrals: each is a pure gray (equal channels) so the interface carries no ambient tint, and they step in clear elevation planes (`dark-canvas` → `dark-canvas-soft` → `dark-canvas-soft-2`). `dark-input` is the resting-control boundary, held one gray brighter than the decorative `dark-line` border so a field edge clears non-text contrast before `{colors.dark-focus-ring}` appears. Chroma lives only in the intentional accents: the dark semantic ramps ride the same Italia scales as their light counterparts, moved to lighter steps where they are text-bearing — `dark-link`/`dark-link-deep` on `green-italia-400`/`green-italia-300`, `dark-error`/`dark-error-deep` on `red-italia-400`/`red-italia-300`, `dark-warning`/`dark-warning-deep` on `amber-400`/`amber-300`, with the `*-soft` tinted grounds on each scale's `1000` step, plus `dark-success` on `green-italia-500` for the positive-feedback green. The `dark-state-*` workflow family is not a text role; it preserves the matching ready/running/review/blocked/complete rail colors for 3 px state accents while text stays on neutral foreground roles. The remaining dark-ramp members stay true-neutral: `dark-selection-bg`/`dark-selection-fg` invert the light selection, `dark-scrim` supplies the modal foreground, and `dark-cross` is the visible mark gray, brighter than the decorative `dark-line`. Never reintroduce hue into the neutral set.
371
+ **Dark Primitives** (`{colors.dark-canvas}`, `{colors.dark-ink}`, `{colors.dark-line}`, and siblings) are the source tokens for the generated shadcn `.dark` role map — mode-bearing primitives, not a separate palette; consuming apps opt in by applying a `.dark` ancestor through their runtime theme provider. The dark neutrals (`dark-canvas`, `dark-canvas-soft`, `dark-canvas-soft-2`, `dark-ink`, `dark-body`, `dark-muted`, `dark-line`, `dark-input`, `dark-seam`, `dark-on-primary`, `dark-scrim`, and the neutral `dark-selection`/`dark-cross` marks) are warm low-chroma greys (OKLCH chroma 0.01), not equal-channel gray, so the night console reads as warm ground rather than cold screen while staying achromatic enough that no hue paints a surface. They step in clear elevation planes (`dark-canvas` → `dark-canvas-soft` → `dark-canvas-soft-2`). `dark-input` is the resting-control boundary, held brighter than the decorative `dark-line` border so a field edge clears the non-text floor before `{colors.dark-focus-ring}` appears. Chroma lives only in the intentional accents: `dark-primary`/`dark-action`/`dark-action-hover`/`dark-action-active` are a brightened verde for the primary control (ink-labelled), `dark-link`/`dark-link-deep` a lighter verde for links, and `dark-error`/`dark-error-deep`, `dark-warning`/`dark-warning-deep`, `dark-info`/`dark-info-deep`, `dark-success` the brightened feedback hues, each `*-soft` a deep tinted ground. The `dark-state-*` workflow family is not a text role; it preserves the matching ready/running/review/blocked/complete rail colours for 3 px state accents while text stays on neutral foreground roles. `dark-selection-bg`/`dark-selection-fg` invert the light selection, `dark-scrim` supplies the modal foreground, and `dark-cross` is the visible mark gray, brighter than the decorative `dark-line`. Never reintroduce chroma into the neutral set.
586
372
 
587
- This grayscale-only discipline is not dark-specific: it governs the whole generated shadcn surface-role bridge in both the light `:root` and dark `.dark` maps. The surface-role family — `background`, `card`, `popover`, `muted`, `secondary`, the `sidebar` roles and their `-foreground`/`-border` variants, plus `border` and `input` — resolves only to pure grays (equal channels) in both themes; hue in the role bridge is reserved for `primary`, `destructive`, and the focus rings (`ring`/`sidebar-ring`). In dark product shells, `background`, `card`, `popover`, and `sidebar` share `{colors.dark-canvas}` so page chrome, cards, tables, overlays, and nav rails read as one black console. `muted`, `secondary`, and `accent` retain the `dark-canvas-soft` steps for small interaction states such as hover, selected rows, keycaps, and inline controls. Large product surfaces never take a tinted or soft-panel fill by default.
373
+ This low-chroma-neutral discipline is not dark-specific: it governs the whole generated shadcn surface-role bridge in both the light `:root` and dark `.dark` maps. The surface-role family — `background`, `card`, `popover`, `muted`, `secondary`, the `sidebar` roles and their `-foreground`/`-border` variants, plus `border` and `input` — resolves only to warm low-chroma greys (OKLCH chroma ≤ 0.01) in both themes; hue in the role bridge is reserved for `primary`, `destructive`, `success`, `warning`, and the focus rings (`ring`/`sidebar-ring`). In dark product shells, `background`, `card`, `popover`, and `sidebar` share `{colors.dark-canvas}` so page chrome, cards, tables, overlays, and nav rails read as one console. `muted`, `secondary`, and `accent` retain the `dark-canvas-soft` steps for small interaction states such as hover, selected rows, keycaps, and inline controls. Large product surfaces never take a tinted or soft-panel fill by default.
588
374
 
589
375
  Do not delete a color because the current website kernel does not consume it. Prototype usage is not palette authority; removals require an explicit palette migration decision.
590
376
 
@@ -596,8 +382,8 @@ Do not delete a color because the current website kernel does not consume it. Pr
596
382
 
597
383
  ### Sequential ramp and diverging pair
598
384
 
599
- - **Sequential ramp** (`{colors.chart-seq-1}`…`{colors.chart-seq-5}`, light→dark on the `blue-cobalto` scale: `chart-seq-1` on `blue-cobalto-500`, `chart-seq-2` on `blue-cobalto-600`, `chart-seq-3` on `blue-cobalto-700`, `chart-seq-4` on `blue-cobalto-800`, `chart-seq-5` on `blue-cobalto-900`): ordered magnitude on one hue, never nominal categories, never a rainbow. `{colors.dark-chart-seq-1}`…`{colors.dark-chart-seq-5}` remap in the `.dark` scope like the categorical set, anchor flipped so `dark-chart-seq-1` is the dimmest step (`blue-cobalto-600`) and `dark-chart-seq-5` the brightest (`blue-cobalto-100`), each clearing the 3:1 WCAG 1.4.11 data-mark floor against `{colors.dark-canvas}`.
600
- - **Diverging pair** (`{colors.chart-div-warm}` on `amber-700`, `{colors.chart-div-mid}` on `gray-700`, `{colors.chart-div-cool}` on `blue-cobalto-500`; dark counterparts `{colors.dark-chart-div-warm}` on `amber-400`, `{colors.dark-chart-div-mid}` on `gray-300`, `{colors.dark-chart-div-cool}` on `blue-cobalto-300`, remapped in the `.dark` scope the same way): the warm and cool poles carry the sign, the neutral midpoint never carries hue. Meter tracks use a lighter step of the same ramp as their fill.
385
+ - **Sequential ramp** (`{colors.chart-seq-1}`…`{colors.chart-seq-5}`, a single cobalto hue running light→dark): ordered magnitude on one hue, never nominal categories, never a rainbow. `{colors.dark-chart-seq-1}`…`{colors.dark-chart-seq-5}` remap in the `.dark` scope like the categorical set, anchor flipped so `dark-chart-seq-1` is the dimmest step and `dark-chart-seq-5` the brightest, each clearing the 3:1 WCAG 1.4.11 data-mark floor against `{colors.dark-canvas}`.
386
+ - **Diverging pair** (`{colors.chart-div-warm}` giallo/amber, `{colors.chart-div-mid}` a neutral mid, `{colors.chart-div-cool}` cobalto; dark counterparts `{colors.dark-chart-div-warm}`, `{colors.dark-chart-div-mid}`, `{colors.dark-chart-div-cool}` remapped in the `.dark` scope the same way): the warm and cool poles carry the sign, the neutral midpoint never carries hue. Meter tracks use a lighter step of the same ramp as their fill.
601
387
 
602
388
  ### Meter and bullet grammar
603
389
 
@@ -684,8 +470,8 @@ Kernel compositions arrange approved primitives for a content role. They must no
684
470
  Each reusable concern has one home and one authoring surface, so a member is documented and shipped in exactly one place:
685
471
 
686
472
  - **Tokens** — exact reusable values live in this contract's `colors`, `spacing`, `rounded`, and `typography`; they export to the generated token layer (with a hand-authored local token layer beside it). No component or section may re-encode a token value.
687
- - **Framework-agnostic CSS components** — the brand/display CSS components that remain in this package (the agent-chat family, the run-state `state-tag` family, the entity-status `status-tag` family, `image`, and the small label/badge/link metadata components). Contracted CSS components are paired between `components:` YAML entries and `## Components` Markdown entries, and are realised by design-system CSS. The named CSS-internal components (`artifact-preview`, `typing-dots`, `state-row`) are documented exceptions: they realise brand display structure but carry no exported component token.
688
- - **Reusable compositions and sections** — patterns that arrange the page grammar and lower tiers for a content role. They ship as React shadcn compositions from `@nadicodeai/ui`, composed over the kept page grammar; they are not a pure-CSS section layer and carry no `components:` YAML entry or exported component token.
473
+ - **Framework-agnostic CSS components** — the brand/display CSS components that remain in this package (the agent-chat family, the run-state `state-tag` family, the entity-status `status-tag` family, `image`, and the small label/badge/link metadata components). Their names and semantics live once in `## Components`; design-system CSS realises that catalog without a second recipe or component-token hierarchy.
474
+ - **Reusable compositions and sections** — patterns that arrange the page grammar and lower tiers for a content role. They ship as React shadcn compositions from `@nadicodeai/ui`, composed over the kept page grammar; they are not a pure-CSS section layer and do not add a second component catalog here.
689
475
  - **Layout grammar** — the page-frame, row, lane, seam, stage, and marker system documented across this `## Layout` section, carried by the layout CSS layer.
690
476
  - **Specimens** — static demonstrations of already-defined primitives. They invent no geometry, seams, heights, or responsive behavior; they only assemble shipped tiers for inspection.
691
477
 
@@ -693,7 +479,7 @@ The page grammar below is the `## Layout` home for the structural names; the sec
693
479
 
694
480
  ### Page Grammar
695
481
 
696
- Page grammar is the NadicodeAI structural system. It defines how pages are built before any content surface appears. These names do not live in YAML `components:`. Exact reusable values are exported through `colors`, `spacing`, `rounded`, and `typography`; the structural semantics live here as layout doctrine, not as interface components.
482
+ Page grammar is the NadicodeAI structural system. It defines how pages are built before any content surface appears. These names live in this layout section, not in the component catalog. Exact reusable values are exported through `colors`, `spacing`, `rounded`, and `typography`; the structural semantics live here as layout doctrine, not as interface components.
697
483
 
698
484
  **`page-frame`** (`nc-page-frame`) — centered bordered frame capped by `{spacing.frame-max}`. Owns the outer left/right/top seams.
699
485
 
@@ -717,11 +503,11 @@ Page grammar is the NadicodeAI structural system. It defines how pages are built
717
503
 
718
504
  **`rule-svg`** — bounded dashed connector rule. Uses `{colors.seam}` and never overlaps a cell seam.
719
505
 
720
- The generic marketing/SaaS section patterns (hero, bento stage, action/CTA band, split, card grid, pricing, testimonials, stats, FAQ, logo/integration walls, contact, newsletter, banner, article index, team) ship as React shadcn compositions from `@nadicodeai/ui`, composed over the kept page grammar above. This contract no longer documents them as a pure-CSS section layer; the page grammar is the framework-agnostic foundation those compositions assemble.
506
+ The generic marketing/SaaS section patterns (Nav, Hero, Logo cloud, Statement, Texture strip, Feature grid, Feature rows, Bento, Steps, Integrations, Live demo, Stats, Testimonial, Security/data, Pricing, FAQ, Team, Contact, CTA band, Footer) ship as React shadcn compositions from `@nadicodeai/ui`, composed over the kept page grammar above. This contract no longer documents them as a pure-CSS section layer; the page grammar is the framework-agnostic foundation those compositions assemble.
721
507
 
722
508
  ### Related Layout Helpers
723
509
 
724
- These live helpers are part of the kept page-grammar layout layer. They are not YAML components: they support index/long-form page assemblies rather than naming an interface component.
510
+ These live helpers are part of the kept page-grammar layout layer. They support index/long-form page assemblies rather than naming an interface component.
725
511
 
726
512
  **`index-grid`** — layout helper for index-style page assemblies (blog, learn, and case-study rows whose guide layer owns the dividers).
727
513
 
@@ -774,7 +560,7 @@ Public page-grammar cells are not cards and remain square because their parent f
774
560
 
775
561
  ## Components
776
562
 
777
- Component entries are grouped by design-system family so the decision model stays small while the exported token surface remains available. YAML `components:` is reserved for reusable UI, content, and agentic-work surfaces with component-style token hooks. Page grammar and composition semantics live in `## Layout` and must not be duplicated in YAML `components:`.
563
+ This section is the semantic catalog for framework-agnostic components. Exact reusable values stay in the token maps above; CSS owns component composition. Page grammar and composition semantics live in `## Layout`, while React components and reusable sections live in `@nadicodeai/ui`.
778
564
 
779
565
  ### Interface Atoms
780
566
 
@@ -802,6 +588,8 @@ Agentic work surfaces are the NadicodeAI-specific layer. They show people and ag
802
588
 
803
589
  **`artifact-surface`** — inspectable output area. Use for proposal previews, reports, plans, spreadsheets, schedules, approval states, source traces, run logs, workflow maps, and conversation artifacts.
804
590
 
591
+ **`artifact-preview`** — compact inspectable artifact card for an agent-produced document, sheet, report, or code excerpt. The header identifies the artifact kind and the body carries the preview; use `artifact-surface` for a larger work area.
592
+
805
593
  Status-tag variants share the same compact sans rectangle at `{typography.caption-strong}`, `{rounded.md}` — a small subtle-tinted rectangle, never a capsule — and differentiate by tone: a paired background+text ramp step, not a border-left rail. Tone is `[data-tone]`, not BEM modifiers. Gray is the default tone; color is reserved for marking health and exceptions, so every terminal or no-action entity status (inactive, archived, rejected, canceled, expired, revoked, denied) renders gray. Subtle-only (no solid/filled variant), no icons inside the badge, no text-transform; labels render verbatim from the source's own i18n dictionary. `status-tag` is the entity-status vocabulary — agent, credential, activation, customer, invitation, subscription, and health values that live on a record — and stays a sibling of `state-tag`: the two families never blend, and `status-tag` never touches the `{colors.state-*}` tokens.
806
594
 
807
595
  **`status-tag-gray`** — default and terminal entity status: no action pending, nothing to watch (inactive, archived, rejected, canceled, expired, revoked, denied).
@@ -814,7 +602,7 @@ Status-tag variants share the same compact sans rectangle at `{typography.captio
814
602
 
815
603
  **`status-tag-blue`** — an in-progress, pending, or trial entity status still moving toward a resolution.
816
604
 
817
- **`chat-thread`** — conversation container showing how people instruct, correct, review, or approve agents. Autoplaying threads carry an enhancer-injected pause/resume control (WCAG 2.2.2); the control is never authored in static markup.
605
+ **`chat-thread`** — conversation container showing how people instruct, correct, review, or approve agents. Static markup always renders the complete conversation. The package's optional `chat-autoplay.js` progressive enhancer activates only on `data-nc-autoplay`, reveals messages in order while keeping the newest turn visible, loops while the thread is in view, and injects its own pause/resume control. It shows the complete thread immediately when reduced motion is requested. Consumers never author the enhancer control in static markup.
818
606
 
819
607
  **`chat-bubble-user`** — human message bubble. Dark surface, white text.
820
608
 
@@ -822,7 +610,7 @@ Status-tag variants share the same compact sans rectangle at `{typography.captio
822
610
 
823
611
  **`tool-call-trace`** — compact code/trace row. Use only when tool use is relevant to the explanation.
824
612
 
825
- State-tag variants share the same compact rectangular shape at `{typography.caption-mono}` and differentiate by a 3 px colored `border-left` consuming the matching `{colors.state-*}` token. Shape carries meaning; color carries variant. State is never conveyed through swatches, dots, pulses, breathing animations, or loading spinners.
613
+ State-tag variants share the same compact rectangular shape at `{typography.caption-mono}` and differentiate by a 3 px colored `border-left` consuming the matching `{colors.state-*}` token. Shape carries meaning; color carries variant.
826
614
 
827
615
  **`state-tag-ready`** — workflow state tag for work that is ready or waiting to start. Uses `{colors.state-ready}` for the left edge.
828
616
 
@@ -834,6 +622,10 @@ State-tag variants share the same compact rectangular shape at `{typography.capt
834
622
 
835
623
  **`state-tag-complete`** — workflow state tag for completed work. Uses `{colors.state-complete}` for the left edge.
836
624
 
625
+ **`state-row`** — full-width workflow-state divider inside an agentic work surface. Its bounded hairlines belong to the row and its dot consumes the same state token as the matching `state-tag` variant.
626
+
627
+ **`typing-dots`** — compact agent typing indicator. It uses the agent accent rail and the shared motion hooks; reduced-motion behavior comes from the package motion layer.
628
+
837
629
  **`approval-gate`** — human-in-the-loop pause surface. Use when an agent action requires explicit review, correction, approval, or rejection.
838
630
 
839
631
  **`agent-avatar`** — identity slot for an agent personality or role. The chrome is reusable; the visual asset is project-specific.
@@ -879,10 +671,8 @@ State-tag variants share the same compact rectangular shape at `{typography.capt
879
671
  - Don't name NadicodeAI components after external reference brands.
880
672
  - Don't promote homepage-specific copy, one-off page order, or prototype-only modules into this contract.
881
673
  - Don't use one full-lane stage to present multiple unrelated use cases.
882
- - Don't add component prop APIs, state matrices, screenshots, implementation notes, page placement examples, or framework-specific instructions to this file.
674
+ - Don't add component prop APIs, state matrices, screenshots, component implementation notes, page placement examples, or framework-specific instructions to this file. (The token-pipeline architecture section is contract, not component documentation.)
883
675
  - Don't use pricing, logo, or banner compositions as placeholder credibility or decoration when the underlying content does not exist.
884
- - Don't use status swatches, status dots, pulses, breathing animations, or loading spinners to communicate operational state; the `state-tag` family carries state through a 3 px colored `border-left`.
885
- - Don't animate outside the motion layer's four moves (Settle, Type, Confirm, Invite); `src/css/motion.css` owns the motion contract — register, vocabulary, craft rules, and what is banned.
886
676
 
887
677
  ## Iconography
888
678
 
@@ -892,3 +682,48 @@ text color. The render is consistent everywhere an icon appears — standalone a
892
682
  inside components — at sizes sm / md / lg = 12 / 16 / 24 px (md default), each
893
683
  tinted with a `{colors.*}` token. Rounded outer corners are retained — the
894
684
  engineered register comes from stroke weight and terminals, not squared geometry.
685
+
686
+ ## CSS Architecture & Token Pipeline
687
+
688
+ How this contract becomes shipped CSS. The private CSS authoring graph lives in `src/css/`; the build flattens that graph and inlines its component icon dependencies into the single public `dist/css/index.css` artifact exported as `@nadicodeai/design-system/css`. Generated files and partials never ship as package subpaths. The cascade is `@layer tokens, theme, reset, foundation, motion, layout, primitives, components;` with no `sections` layer. Since the Tailwind+shadcn migration (ADR 0007), the bundle ships only framework-agnostic brand and display CSS components. Generic marketing/SaaS components and the former `sections/*` layer ship as React components from `@nadicodeai/ui`.
689
+
690
+ ### Public style interfaces
691
+
692
+ There is one public stylesheet interface per runtime, selected by the caller's runtime rather than composed by the caller:
693
+
694
+ - Static HTML and non-React consumers use `@nadicodeai/design-system/css`.
695
+ - React consumers use `@nadicodeai/ui/globals.css`. That React adapter composes the complete design-system CSS interface with Tailwind v4 and shadcn. Narrow protocol adapters may translate a third-party class vocabulary, but they do not declare another token hierarchy.
696
+
697
+ Callers never import generated files, CSS partials, or framework adapters directly. React callers never add `@nadicodeai/design-system/css` beside the UI stylesheet. The package export map and interface guards enforce this boundary. React installation and source-scanning setup live in [`@nadicodeai/ui/docs/consuming-cross-repo.md`](../@nadicodeai/ui/docs/consuming-cross-repo.md).
698
+
699
+ ### Authoring homes
700
+
701
+ Each delivery tier (see Layout, "Delivery Tiers") has exactly one authoring file:
702
+
703
+ - Tokens: `src/css/tokens.generated.css`, built from this contract and never hand-edited. Runtime composition belongs to the owning layer, such as responsive switching in `layout.css`; there is no hand-authored token partial.
704
+ - Type utilities: the `.nc-type-*` classes live in `foundation.css`.
705
+ - Page grammar: `layout.css`, which also owns all responsive `@media` switching.
706
+ - CSS primitives and components: `primitives.css` plus `components/*`. Every shipped component is named once in `## Components`; the two-way guard derives the CSS relationship from that catalog.
707
+ - Specimens: `examples/`, which only assemble already-defined tiers.
708
+
709
+ ### Generated outputs
710
+
711
+ Style Dictionary (`scripts/sd/`, driven from `scripts/build.ts`) emits three CSS files from the `@google/design.md` export of this contract:
712
+
713
+ 1. The token layer `tokens.generated.css`: a complete projection, every token as `--nc-<exact-name>: <exact-value>`, each name once. Never an allowlist, subset, or rename, and never containing `@media` or `calc()`; responsive and composed runtime variables live only in their owning layer and reference emitted `--nc-*` tokens. Emitted-but-unreferenced contract tokens remain part of the package vocabulary; private compatibility variables with no caller do not.
714
+ 2. The mode layer `modes.generated.css`: derives every color pair named `X` and `dark-X` from the complete token graph, then remaps `--nc-X` inside `.dark`. There is no component list or token allowlist to maintain. A dark-only token without an `X` counterpart remains available by its explicit name and is not remapped.
715
+ 3. The theme layer `theme.generated.css`: emits the standard shadcn `:root` and `.dark` role maps, the Tailwind v4 `@theme inline` semantic bridge, and the raw contract projection. Standard `--color-*` utilities are reserved for semantic shadcn roles. Raw contract colors use the explicit `--color-nc-*` namespace; the remaining Tailwind token families keep their generated font, type, radius, and spacing namespaces. Every emitted value is derived from this contract, with no hand-authored bridge, compatibility alias, or raw `--nc-*` mode-remap table in the formatter.
716
+
717
+ The private source entry imports all three generated files, and the package build compiles the complete graph into an import-free public artifact. Raw mode behavior and the Tailwind semantic bridge therefore belong to the framework-neutral design-system module, not to the React adapter or individual CSS components. `@nadicodeai/ui/globals.css` composes that complete module with Tailwind and owns only narrow technology integration, such as ANSI class translation; React components consume the generated shadcn roles or namespaced raw utilities directly.
718
+
719
+ `npm run build` also exports `dist/tokens/nadicode.dtcg.json` and `dist/tailwind/nadicode.tailwind.json` as generated, tracked data artifacts, and bakes `dist/icons/` from the pinned `lucide-static` dependency.
720
+
721
+ #### Brand media authority
722
+
723
+ The logo has one authored geometry source: the framework-neutral module exported as `@nadicodeai/design-system/assets/logo-geometry`. No SVG, React component, favicon, document, or app re-authors its paths or shapes. The wordmark provides textual brand presence; the mark provides icon and favicon presence; a full React lockup composes one mark followed by one wordmark.
724
+
725
+ The package build renders public mark and wordmark SVGs from that geometry and the current `colors.*` contract. The operator-only favicon generator wraps the same mark geometry in the platform tile and may adapt tile radius, output size, and fixed-tile paint roles; it does not substitute another mark. Private geometry templates do not ship. A contract or geometry change is completed by regeneration, never by repainting an output or updating a fallback by hand.
726
+
727
+ ### Enforcement
728
+
729
+ Correctness is structural, not a byte snapshot: `tests/guards/token-structural-parity.test.ts` verifies the complete `--nc-*` projection; `tests/guards/tailwind-v4-theme.test.ts` verifies mode-pair derivation, `@theme` values, and light/dark role integrity; `tests/guards/component-contract-matches-css.test.ts` verifies the retained CSS component surface against this contract; `tests/guards/css-bundle.test.ts` verifies the public artifact is flat, complete, and contains no shipped partials; and `tests/guards/consumer-css-discipline.test.ts` verifies reference integrity, the absence of raw color literals and second value sources, and DTCG drift. Cross-package guards verify that React callers use only the React stylesheet interface. ADR 0006 supersedes ADR 0005 D1–D3/D5; ADR 0008 supersedes ADR 0005 D4; ADR 0019 defines the public stylesheet interfaces and supersedes their earlier delivery-path clauses; ADR 0020 removes the unused component-recipe layer and defines executable authority.