@nadicodeai/design-system 0.5.3 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -10
- package/DESIGN.md +125 -36
- package/README.md +1 -1
- package/dist/css/components/agent-avatar.css +15 -5
- package/dist/css/components/approval-gate.css +10 -8
- package/dist/css/components/artifact-preview.css +17 -5
- package/dist/css/components/chat-bubble-agent.css +15 -5
- package/dist/css/components/chat-thread.css +5 -4
- package/dist/css/components/handoff-banner.css +1 -1
- package/dist/css/components/run-timeline.css +36 -11
- package/dist/css/components/state-row.css +15 -5
- package/dist/css/components/state-tag.css +4 -3
- package/dist/css/components/status-tag.css +101 -0
- package/dist/css/components/tool-call-trace.css +1 -1
- package/dist/css/components/typing-dots.css +15 -5
- package/dist/css/foundation.css +8 -0
- package/dist/css/index.css +6 -2
- package/dist/css/layout.css +7 -8
- package/dist/css/primitives.css +16 -33
- package/dist/css/tokens.generated.css +31 -0
- package/dist/tailwind/nadicode.tailwind.json +30 -0
- package/dist/tailwind/nadicode.theme.css +66 -11
- package/dist/tokens/nadicode.dtcg.json +196 -1
- package/package.json +2 -2
package/AGENTS.md
CHANGED
|
@@ -14,7 +14,7 @@ Plain imperatives are the default. The few hard prohibitions below use `never`/`
|
|
|
14
14
|
- Preserve approved `DESIGN.md` token and component families unless the user explicitly approves a palette/component migration. Website/kernel CSS is implementation evidence, not the complete palette authority; never delete tokens because current prototypes do not use them or because `@google/design.md lint` reports them as unused.
|
|
15
15
|
- Name implemented grids, components, modules, and page elements as NadicodeAI-owned primitives; source brands such as Vercel or Attio may appear only in reference notes, never in component names, CSS comments, `data-module` values, or public-facing contracts.
|
|
16
16
|
- Calculate page grids, module spans, seams, borders, and element placement from explicit grid math; never hand-place visual structure by eye.
|
|
17
|
-
- Author CSS-bundle work as a reusable design-system component architecture first, not as showcase/page-specific code. The design-system CSS lives in `src/css/` (`tokens.generated` [built from `DESIGN.md`] + `tokens.local` [hand-authored] / `reset`/`foundation`/`motion`/`layout`/`primitives` + `components/*`, mirrored to `dist/css/` and exported as `@nadicodeai/design-system/css`). Since the Tailwind+shadcn migration (ADR 0007) the bundle ships only framework-agnostic brand/display CSS components: the cascade is `@layer tokens, reset, foundation, motion, layout, primitives, components;` (no `sections` layer), and `components/*` holds the agent-chat CSS component family, the run-state `state-tag` family, and `image` — the generic marketing/SaaS component CSS and the whole `sections/*` layer retired to React shadcn components in `@nadicodeai/ui`. The delivery tiers map to real authoring homes: tokens → `tokens.generated`/`tokens.local`; page grammar → `layout.css`; CSS primitives/components → `primitives.css` + `components/*`; specimens → `examples/`. Contracted CSS components are paired with `DESIGN.md components:` entries; the three named CSS-internal components are deliberate no-token exceptions. Pages, site-specific page assemblies, and the standard/interactive/section UI belong to consuming surfaces (`../website/`, `../portal/`, sibling Nadia apps) and to the React package (`@nadicodeai/ui`), not this package. Study current source HTML/CSS for approved external references before implementing similar NadicodeAI primitives, then adapt the structure into NadicodeAI-owned tokens, primitives, and components. Specimen HTML demonstrates only already-defined primitives/components; it never invents component geometry, seams, borders, fillers, heights, or responsive behavior inline. The generated token layer (`tokens.generated.css`) and the Tailwind adapter (`nadicode.theme.css`) are emitted by Style Dictionary (`scripts/sd/`, driven from `scripts/build.ts`) as a complete projection of the `@google/design.md` export — never an allowlist or subset; responsive `@media` switching and composed/`calc` vars live in `layout.css`/`tokens.local.css` and reference emitted `--nc-*` tokens only, while the `.nc-type-*` utility classes live in `foundation.css`. Emitted-but-unreferenced tokens are intentional (the contract drives emission, not consumption), and the generated Tailwind adapter owns standard shadcn role maps for both `:root` and `.dark` using generated `--color-*`/`--radius-*` references, plus a small set of `--nc-*` remaps in the `.dark` block (the `state-*`, `selection-*`, and `cross` families → their `--nc-dark-*` counterparts) so design-system CSS components that read those raw brand tokens directly flip on the dark console; `@nadicodeai/ui/globals.css` keeps the Tailwind role bridge plus UI-local product aliases. Correctness is enforced by export-derived structural parity (`tests/token-structural-parity.test.ts` for the `--nc-*` layer; the per-token `@theme` value loops and light/dark role-integrity checks in `tests/tailwind-v4-theme.test.ts` for the adapter), the narrowed two-way parity between `DESIGN.md` component YAML/prose and the retained CSS component surface (`tests/components-yaml-matches-css.test.ts`, ADR 0007 D4), plus consumer discipline (`tests/consumer-css-discipline.test.ts`), not a byte snapshot (ADR 0006 supersedes ADR 0005 D1–D3/D5; ADR 0008 supersedes ADR 0005 D4).
|
|
17
|
+
- Author CSS-bundle work as a reusable design-system component architecture first, not as showcase/page-specific code. The design-system CSS lives in `src/css/` (`tokens.generated` [built from `DESIGN.md`] + `tokens.local` [hand-authored] / `reset`/`foundation`/`motion`/`layout`/`primitives` + `components/*`, mirrored to `dist/css/` and exported as `@nadicodeai/design-system/css`). Since the Tailwind+shadcn migration (ADR 0007) the bundle ships only framework-agnostic brand/display CSS components: the cascade is `@layer tokens, reset, foundation, motion, layout, primitives, components;` (no `sections` layer), and `components/*` holds the agent-chat CSS component family, the run-state `state-tag` family, the entity-status `status-tag` family, and `image` — the generic marketing/SaaS component CSS and the whole `sections/*` layer retired to React shadcn components in `@nadicodeai/ui`. The delivery tiers map to real authoring homes: tokens → `tokens.generated`/`tokens.local`; page grammar → `layout.css`; CSS primitives/components → `primitives.css` + `components/*`; specimens → `examples/`. Contracted CSS components are paired with `DESIGN.md components:` entries; the three named CSS-internal components are deliberate no-token exceptions. Pages, site-specific page assemblies, and the standard/interactive/section UI belong to consuming surfaces (`../website/`, `../portal/`, sibling Nadia apps) and to the React package (`@nadicodeai/ui`), not this package. Study current source HTML/CSS for approved external references before implementing similar NadicodeAI primitives, then adapt the structure into NadicodeAI-owned tokens, primitives, and components. Specimen HTML demonstrates only already-defined primitives/components; it never invents component geometry, seams, borders, fillers, heights, or responsive behavior inline. The generated token layer (`tokens.generated.css`) and the Tailwind adapter (`nadicode.theme.css`) are emitted by Style Dictionary (`scripts/sd/`, driven from `scripts/build.ts`) as a complete projection of the `@google/design.md` export — never an allowlist or subset; responsive `@media` switching and composed/`calc` vars live in `layout.css`/`tokens.local.css` and reference emitted `--nc-*` tokens only, while the `.nc-type-*` utility classes live in `foundation.css`. Emitted-but-unreferenced tokens are intentional (the contract drives emission, not consumption), and the generated Tailwind adapter owns standard shadcn role maps for both `:root` and `.dark` using generated `--color-*`/`--radius-*` references, plus a small set of `--nc-*` remaps in the `.dark` block (the `state-*`, `selection-*`, and `cross` families → their `--nc-dark-*` counterparts) so design-system CSS components that read those raw brand tokens directly flip on the dark console; `@nadicodeai/ui/globals.css` keeps the Tailwind role bridge plus UI-local product aliases. Correctness is enforced by export-derived structural parity (`tests/guards/token-structural-parity.test.ts` for the `--nc-*` layer; the per-token `@theme` value loops and light/dark role-integrity checks in `tests/guards/tailwind-v4-theme.test.ts` for the adapter), the narrowed two-way parity between `DESIGN.md` component YAML/prose and the retained CSS component surface (`tests/guards/components-yaml-matches-css.test.ts`, ADR 0007 D4), plus consumer discipline (`tests/guards/consumer-css-discipline.test.ts`), not a byte snapshot (ADR 0006 supersedes ADR 0005 D1–D3/D5; ADR 0008 supersedes ADR 0005 D4).
|
|
18
18
|
- Follow a source-first reference workflow for external visual references: inspect live/source DOM, stylesheet/CSSOM rules, inline styles, custom properties, computed styles, grid tracks, spans, seam ownership, colors, heights, and breakpoints before writing NadicodeAI code. Screenshots are verification evidence only after implementation; never use them as the source for authoring structure, geometry, or CSS.
|
|
19
19
|
- Never derive reusable kernel geometry from screenshots, eyeballing, one-off browser coordinates, or local patch experiments. Browser measurements may verify an implementation after the source CSS/DOM model is understood, but they do not replace reading the source rules that create the behavior.
|
|
20
20
|
- Map every imported visual behavior to either `DESIGN.md`, an existing kernel token/primitive, or an explicit user-approved change before implementation. If the reference leaves a required decision open, or if `DESIGN.md` does not decide it, ask before coding the missing decision, including height/row span, surface color, visual payload, content slots, crosshair placement, and responsive behavior.
|
|
@@ -32,21 +32,21 @@ Generated-artifact and runtime-JS prohibitions live in the Forbidden Patterns ta
|
|
|
32
32
|
- Treat `dist/tokens/nadicode.dtcg.json` and `dist/tailwind/nadicode.tailwind.json` as generated, tracked consumer artifacts.
|
|
33
33
|
- Treat `src/assets/` as the source for exported brand SVG assets.
|
|
34
34
|
- Treat `dist/icons/` as a generated icon set baked from the pinned `lucide-static` dependency by `npm run generate:icons` (also run inside `npm run build`) and exported via `./icons/*`; regenerate by bumping `lucide-static`, never hand-edit.
|
|
35
|
-
-
|
|
35
|
+
- The `design-canvas/` prototypes that `src/css/motion.css`, `src/js/chat-autoplay.js`, and `tests/guards/chat-showcase.test.ts` re-express are deleted from the tree; git history retains them under docs/experiments/design-canvas/. The kernel CSS and its tests are the living expression — never reconstruct the prototypes as a build, runtime component surface, or normative brand contract.
|
|
36
36
|
- Any change to package-consumed output (`DESIGN.md`, generated tokens, CSS bundle, Tailwind theme output, package exports, assets, package docs, or agent instructions) must end with an explicit npm release decision before handoff — enforced by the pre-push release gate: bump the version (merge then auto-publishes; see `../docs/agents/npm-publishing.md`) or mark a commit `[no-publish]`. If the change should reach external consumers, bump `@nadicodeai/design-system` and run `npm pack --dry-run -w @nadicodeai/design-system`. When `@nadicodeai/ui` consumes the changed output, publish `@nadicodeai/design-system` first, then bump/update/publish `@nadicodeai/ui`. Never claim the package is shipped to npm until `npm view @nadicodeai/design-system version` reports the intended version.
|
|
37
37
|
|
|
38
38
|
## Task Routing
|
|
39
39
|
|
|
40
40
|
| Task | Read first | Then read | Verify |
|
|
41
41
|
| --- | --- | --- | --- |
|
|
42
|
-
| Design token, contract, or token-pipeline change | `DESIGN.md`, `scripts/sd/config.ts`, `scripts/sd/transforms.ts`, `scripts/sd/format-token-layer.ts`, `scripts/sd/format-tailwind-v4-theme.ts` | `npm exec -- design.md spec`, `scripts/build.ts`, `tests/token-structural-parity.test.ts`, `tests/consumer-css-discipline.test.ts`, `tests/tailwind-v4-theme.test.ts` | `npm run lint:design && npm run build && npm run test` |
|
|
43
|
-
| Kernel geometry or component work | `DESIGN.md` Layout and Components | `src/css/index.css`, `src/css/layout.css`, `src/css/primitives.css`, `src/css/components/*.css`, `src/css/motion.css`, `tests/kernel-css-architecture.test.ts`, `tests/kernel-rendered-geometry.test.ts` | from design-system/: `npx vitest run tests/kernel-css-architecture.test.ts tests/kernel-rendered-geometry.test.ts` |
|
|
44
|
-
| CSS component or `examples/` specimen work | `DESIGN.md` Layout and Components | `src/css/components/`, `examples/`, `../skills/nadicodeai-brand-copy/SKILL.md`, `../skills/nadicodeai-brand-copy/references/writing-craft.md`, `../skills/nadicodeai-brand-copy/references/brand-voice-profile.md`, `../skills/nadicodeai-brand-copy/references/voice-examples.md` | `npm run test -- tests/examples-package-coherence.test.ts` |
|
|
45
|
-
| Package consumption or export surface | `README.md` | `package.json`, `scripts/build.ts`, `dist/tailwind/`, `dist/tokens/` | `npm run build && npm run test -- tests/build-produces-exports.test.ts tests/tailwind-v4-theme.test.ts` |
|
|
42
|
+
| Design token, contract, or token-pipeline change | `DESIGN.md`, `scripts/sd/config.ts`, `scripts/sd/transforms.ts`, `scripts/sd/format-token-layer.ts`, `scripts/sd/format-tailwind-v4-theme.ts` | `npm exec --package=@google/design.md -- design.md spec`, `scripts/build.ts`, `tests/guards/token-structural-parity.test.ts`, `tests/guards/consumer-css-discipline.test.ts`, `tests/guards/tailwind-v4-theme.test.ts` | `npm run lint:design && npm run build && npm run test` |
|
|
43
|
+
| Kernel geometry or component work | `DESIGN.md` Layout and Components | `src/css/index.css`, `src/css/layout.css`, `src/css/primitives.css`, `src/css/components/*.css`, `src/css/motion.css`, `tests/guards/kernel-css-architecture.test.ts`, `tests/guards/kernel-rendered-geometry.test.ts` | from design-system/: `npx vitest run tests/guards/kernel-css-architecture.test.ts tests/guards/kernel-rendered-geometry.test.ts` |
|
|
44
|
+
| CSS component or `examples/` specimen work | `DESIGN.md` Layout and Components | `src/css/components/`, `examples/`, `../skills/nadicodeai-brand-copy/SKILL.md`, `../skills/nadicodeai-brand-copy/references/writing-craft.md`, `../skills/nadicodeai-brand-copy/references/brand-voice-profile.md`, `../skills/nadicodeai-brand-copy/references/voice-examples.md` | `npm run test -- tests/guards/examples-package-coherence.test.ts` |
|
|
45
|
+
| Package consumption or export surface | `README.md` | `package.json`, `scripts/build.ts`, `dist/tailwind/`, `dist/tokens/` | `npm run build && npm run test -- tests/guards/build-produces-exports.test.ts tests/guards/tailwind-v4-theme.test.ts` |
|
|
46
46
|
|
|
47
47
|
## DESIGN.md Authoring
|
|
48
48
|
|
|
49
|
-
- Check `npm exec -- design.md spec` before adding or changing YAML front matter fields.
|
|
49
|
+
- Check `npm exec --package=@google/design.md -- design.md spec` before adding or changing YAML front matter fields.
|
|
50
50
|
- Put exact reusable values in YAML when they should export through `npm run build`: colors, typography, rounded, spacing, and component fields listed by the current spec.
|
|
51
51
|
- Put application guidance in prose when it describes how to use values: borders, gradients, grid placement, motion, state behavior, responsive composition, markup shape, and accessibility.
|
|
52
52
|
- Keep component identity paired inside `## Components`: every named YAML `components:` entry needs a matching Markdown `**\`component-name\`**` entry in the Components section, and every Markdown component entry in that section needs a matching YAML `components:` entry. YAML carries machine-readable component style hooks; Markdown carries usage, variants, constraints, and judgment.
|
|
@@ -89,7 +89,7 @@ Before claiming work complete (from this directory, or with `-w design-system` f
|
|
|
89
89
|
npm run lint:design && npm run build && npm run test
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
`npm run test` MUST stay browser-free: browser-driven tests live in `tests
|
|
92
|
+
`npm run test` MUST stay browser-free: browser-driven tests live in `tests/visual/*.visual.ts` (outside the default `*.test.ts` glob) and run only via `npm run test:visual`. Never add a browser test to the default suite — parallel headless sessions inside the gate are what orphaned Chrome and hung it; that is the real constraint, not `agent-browser` itself.
|
|
93
93
|
|
|
94
94
|
For a visual check, agents use the workspace-local `agent-browser` package (`npm exec -w design-system -- agent-browser ...` from the repo root, or `npm exec -- agent-browser ...` from this directory): open the rendered page, save a screenshot into the ignored evidence folder (`../tmp/visual-evidence/`), inspect it, confirm it looks right, and **close the session** so no Chrome daemon is left running. Run these checks **sequentially, one page at a time** — never as a parallel suite. The repo-level `agent-browser.json` and this directory's `agent-browser.json` set the idle timeout for ad hoc commands, but explicit close is still required. The screenshots persist in `../tmp/visual-evidence/` as evidence for the operator to review.
|
|
95
95
|
|
|
@@ -104,11 +104,10 @@ For a visual check, agents use the workspace-local `agent-browser` package (`npm
|
|
|
104
104
|
| `scripts/build.ts` | Exports DTCG + Tailwind tokens from `DESIGN.md`, runs the Style Dictionary build for the CSS token layer + Tailwind v4 theme, generates the icon set, then mirrors `dist/css` |
|
|
105
105
|
| `scripts/sd/` | Style Dictionary build: `config.ts` (entrypoints), `transforms.ts` (`name/nc`/`color/nc-hex`/`dimension/nc-px` + FORK-A line-height), `format-token-layer.ts` (OUTPUT 1), `format-tailwind-v4-theme.ts` (OUTPUT 2). See ADR 0006 |
|
|
106
106
|
| `scripts/generate-icons.ts` | Bakes the NadicodeAI icon set into `dist/icons/` from the pinned `lucide-static` dependency |
|
|
107
|
-
| `tests/` | Vitest gate
|
|
107
|
+
| `tests/` | Vitest suites, foldered per ADR 0011: `guards/` (the package-spanning gate — design lint, build exports, accepted repo-local validators), `visual/` (opt-in browser suite), `global-setup.ts`. Unit tests for build modules sit beside them in `scripts/` |
|
|
108
108
|
| `agent-browser.json` | Project-level timeout defaults for workspace-local `agent-browser` visual checks |
|
|
109
109
|
| `src/assets/` | Package logo SVG exports |
|
|
110
110
|
| `dist/` | Generated token exports tracked for package consumers |
|
|
111
111
|
| `dist/icons/` | Generated Lucide-derived icon set, exported via `./icons/*` |
|
|
112
112
|
| `../docs/adr/` | Decision records (ADR 0005/0006 govern the token pipeline) |
|
|
113
|
-
| `../docs/experiments/` | Archived `design-canvas/` prototype source-of-record for the kernel chat motion and CSS components |
|
|
114
113
|
| `src/css/motion.css` | The brand motion contract: register, the four moves, craft rules, banned moves — read before any animation work |
|
package/DESIGN.md
CHANGED
|
@@ -3,13 +3,17 @@ version: alpha
|
|
|
3
3
|
name: NadicodeAI Design System
|
|
4
4
|
description: >-
|
|
5
5
|
Reusable design-system contract for NadicodeAI: engineered page geometry,
|
|
6
|
-
neutral high-contrast surfaces, AI-agent work artifacts,
|
|
7
|
-
12-column/10-column composition
|
|
8
|
-
|
|
6
|
+
neutral high-contrast product surfaces, AI-agent work artifacts, strict
|
|
7
|
+
12-column/10-column public-page composition, and the package token exports
|
|
8
|
+
shared by every NadicodeAI interface.
|
|
9
9
|
|
|
10
10
|
colors:
|
|
11
11
|
primary: "#008c45"
|
|
12
12
|
on-primary: "#ffffff"
|
|
13
|
+
action: "#007a3c"
|
|
14
|
+
action-foreground: "#ffffff"
|
|
15
|
+
action-hover: "#00602f"
|
|
16
|
+
action-active: "#00301a"
|
|
13
17
|
ink: "#171717"
|
|
14
18
|
body: "#4d4d4d"
|
|
15
19
|
muted: "#888888"
|
|
@@ -17,8 +21,11 @@ colors:
|
|
|
17
21
|
canvas-soft: "#fafafa"
|
|
18
22
|
canvas-soft-2: "#f5f5f5"
|
|
19
23
|
line: "#e5e5e5"
|
|
24
|
+
input: "#8f8f8f"
|
|
20
25
|
seam: "#e4e7ec"
|
|
21
26
|
cross: "#a1a1a1"
|
|
27
|
+
focus-ring: "#007a3c"
|
|
28
|
+
scrim: "#171717"
|
|
22
29
|
link: "#007a3c"
|
|
23
30
|
link-deep: "#00602f"
|
|
24
31
|
link-bg-soft: "#d9f6e4"
|
|
@@ -123,9 +130,15 @@ colors:
|
|
|
123
130
|
dark-seam: "#1f1f1f"
|
|
124
131
|
dark-primary: "#ededed"
|
|
125
132
|
dark-on-primary: "#0a0a0a"
|
|
133
|
+
dark-action: "#ededed"
|
|
134
|
+
dark-action-foreground: "#0a0a0a"
|
|
135
|
+
dark-action-hover: "#d4d4d4"
|
|
136
|
+
dark-action-active: "#a3a3a3"
|
|
126
137
|
dark-link: "#9fe6bc"
|
|
127
138
|
dark-link-deep: "#c3f0d4"
|
|
128
139
|
dark-link-bg-soft: "#00301a"
|
|
140
|
+
dark-focus-ring: "#9fe6bc"
|
|
141
|
+
dark-scrim: "#f5f5f5"
|
|
129
142
|
dark-error: "#f7b3b5"
|
|
130
143
|
dark-error-soft: "#4a000e"
|
|
131
144
|
dark-error-deep: "#fad3d4"
|
|
@@ -238,6 +251,12 @@ typography:
|
|
|
238
251
|
fontWeight: 400
|
|
239
252
|
lineHeight: 16px
|
|
240
253
|
letterSpacing: 0px
|
|
254
|
+
caption-strong:
|
|
255
|
+
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
256
|
+
fontSize: 12px
|
|
257
|
+
fontWeight: 500
|
|
258
|
+
lineHeight: 16px
|
|
259
|
+
letterSpacing: 0px
|
|
241
260
|
caption-mono:
|
|
242
261
|
fontFamily: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace
|
|
243
262
|
fontSize: 12px
|
|
@@ -270,6 +289,8 @@ rounded:
|
|
|
270
289
|
md: 6px
|
|
271
290
|
lg: 8px
|
|
272
291
|
xl: 10px
|
|
292
|
+
2xl: 12px
|
|
293
|
+
3xl: 16px
|
|
273
294
|
pill-sm: 64px
|
|
274
295
|
pill: 100px
|
|
275
296
|
full: 9999px
|
|
@@ -289,6 +310,10 @@ spacing:
|
|
|
289
310
|
6xl: 128px
|
|
290
311
|
section: 192px
|
|
291
312
|
guide: 1px
|
|
313
|
+
focus-ring-width: 3px
|
|
314
|
+
control-height: 32px
|
|
315
|
+
control-padding-inline: 10px
|
|
316
|
+
touch-target: 44px
|
|
292
317
|
page-pad: 24px
|
|
293
318
|
page-max-mobile: 448px
|
|
294
319
|
page-max-tablet: 624px
|
|
@@ -345,20 +370,41 @@ components:
|
|
|
345
370
|
backgroundColor: "{colors.canvas}"
|
|
346
371
|
textColor: "{colors.ink}"
|
|
347
372
|
padding: "{spacing.lg}"
|
|
348
|
-
status-tag:
|
|
349
|
-
backgroundColor: "{colors.
|
|
350
|
-
textColor: "{colors.
|
|
351
|
-
typography: "{typography.caption-
|
|
352
|
-
rounded: "{rounded.
|
|
353
|
-
padding: "
|
|
354
|
-
height:
|
|
355
|
-
status-tag-
|
|
356
|
-
backgroundColor: "{colors.
|
|
357
|
-
textColor: "{colors.
|
|
358
|
-
typography: "{typography.caption-
|
|
359
|
-
rounded: "{rounded.
|
|
360
|
-
padding: "
|
|
361
|
-
height:
|
|
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
|
|
362
408
|
image:
|
|
363
409
|
backgroundColor: "{colors.canvas-soft}"
|
|
364
410
|
textColor: "{colors.body}"
|
|
@@ -369,7 +415,7 @@ components:
|
|
|
369
415
|
backgroundColor: "{colors.canvas-soft}"
|
|
370
416
|
textColor: "{colors.body}"
|
|
371
417
|
typography: "{typography.caption}"
|
|
372
|
-
rounded: "{rounded.
|
|
418
|
+
rounded: "{rounded.md}"
|
|
373
419
|
padding: "0px {spacing.xs}"
|
|
374
420
|
filter-chip:
|
|
375
421
|
backgroundColor: "{colors.canvas-soft}"
|
|
@@ -502,14 +548,17 @@ Backgrounds are `{colors.background-100}` (page default, white) and `{colors.bac
|
|
|
502
548
|
|
|
503
549
|
### Semantic roles (functional tier)
|
|
504
550
|
|
|
505
|
-
- **Primary** (`{colors.primary}` = `green-italia-700`):
|
|
506
|
-
- **
|
|
507
|
-
- **
|
|
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.
|
|
556
|
+
- **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.
|
|
508
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.
|
|
509
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.
|
|
510
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.
|
|
511
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.
|
|
512
|
-
- **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.
|
|
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.
|
|
513
562
|
|
|
514
563
|
### Chart categoricals (functional tier)
|
|
515
564
|
|
|
@@ -533,7 +582,7 @@ Four campo rules govern their use:
|
|
|
533
582
|
|
|
534
583
|
### Dark primitives
|
|
535
584
|
|
|
536
|
-
**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`) 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
|
|
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.
|
|
537
586
|
|
|
538
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.
|
|
539
588
|
|
|
@@ -572,7 +621,7 @@ Do not delete a color because the current website kernel does not consume it. Pr
|
|
|
572
621
|
|
|
573
622
|
## Typography
|
|
574
623
|
|
|
575
|
-
Geist Sans carries all narrative and interface copy. Geist Mono is reserved for eyebrows, labels,
|
|
624
|
+
Geist Sans carries all narrative and interface copy, including the entity-status `status-tag` family. Geist Mono is reserved for eyebrows, labels, run-state `state-tag` labels, code, traces, and small technical metadata.
|
|
576
625
|
|
|
577
626
|
All body, title, caption, and code typography uses `letterSpacing: 0px`. Do not use viewport-scaled type (no `vw`/`vh` font sizing): use fixed token sizes stepped by breakpoint-specific rules when a headline must grow. The two large display tiers carry a small negative tracking — `display-xl` at `-1.5px` and `display-lg` at `-1px` — so large type reads optically tight; this is a display-heading-only exception and every non-display tier stays at `0px`.
|
|
578
627
|
|
|
@@ -591,7 +640,8 @@ All body, title, caption, and code typography uses `letterSpacing: 0px`. Do not
|
|
|
591
640
|
| `{typography.body-sm}` | 14px | 400 | 20px | Secondary copy, nav, compact cell copy. |
|
|
592
641
|
| `{typography.body-sm-strong}` | 14px | 500 | 20px | Emphasised secondary copy and compact labels. |
|
|
593
642
|
| `{typography.caption}` | 12px | 400 | 16px | Footer secondary lines and badge labels. |
|
|
594
|
-
| `{typography.caption-
|
|
643
|
+
| `{typography.caption-strong}` | 12px | 500 | 16px | Entity-status `status-tag` labels. |
|
|
644
|
+
| `{typography.caption-mono}` | 12px | 500 | 16px | Eyebrows, labels, run-state `state-tag` labels. |
|
|
595
645
|
| `{typography.code}` | 13px | 400 | 20px | Tool calls, snippets, traces. |
|
|
596
646
|
| `{typography.button-lg}` | 16px | 500 | 24px | Marketing-scale button labels. |
|
|
597
647
|
| `{typography.button-md}` | 14px | 500 | 18px | Standard button and control labels. |
|
|
@@ -634,7 +684,7 @@ Kernel compositions arrange approved primitives for a content role. They must no
|
|
|
634
684
|
Each reusable concern has one home and one authoring surface, so a member is documented and shipped in exactly one place:
|
|
635
685
|
|
|
636
686
|
- **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.
|
|
637
|
-
- **Framework-agnostic CSS components** — the brand/display CSS components that remain in this package (the agent-chat family, the run-state `state-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.
|
|
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.
|
|
638
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.
|
|
639
689
|
- **Layout grammar** — the page-frame, row, lane, seam, stage, and marker system documented across this `## Layout` section, carried by the layout CSS layer.
|
|
640
690
|
- **Specimens** — static demonstrations of already-defined primitives. They invent no geometry, seams, heights, or responsive behavior; they only assemble shipped tiers for inspection.
|
|
@@ -681,19 +731,46 @@ These live helpers are part of the kept page-grammar layout layer. They are not
|
|
|
681
731
|
|
|
682
732
|
## Elevation & Depth
|
|
683
733
|
|
|
684
|
-
NadicodeAI website depth is flat and architectural. Hairlines, contrast, dotted fields, diagonal fills, and dark action bands create hierarchy.
|
|
734
|
+
NadicodeAI website depth is flat and architectural. Hairlines, contrast, dotted fields, diagonal fills, and dark action bands create hierarchy. The public website does not use floating card stacks as its main structure; the page frame and row grid remain dominant.
|
|
735
|
+
|
|
736
|
+
Product UI uses explicit material roles. Resting content surfaces use no shadow; hierarchy comes from one owned border, spacing, and surface contrast. Shadows identify genuinely floating UI only. The same low-opacity black shadow stacks are used in light and dark themes so elevation does not change character between modes.
|
|
737
|
+
|
|
738
|
+
The Google design schema does not define elevation or opacity groups. These declarations are therefore the authored material-token source inside this contract. The build reads this block strictly, emits generated `--nc-*` hooks, and maps Tailwind's named opacity and shadow utilities to them; consumers never repeat these values.
|
|
685
739
|
|
|
686
|
-
|
|
740
|
+
```css material-tokens
|
|
741
|
+
--nc-material-scrim-opacity: 10%;
|
|
742
|
+
--nc-material-shadow-tooltip: 0 1px 1px rgb(0 0 0 / 2%), 0 4px 8px rgb(0 0 0 / 4%);
|
|
743
|
+
--nc-material-shadow-menu: 0 1px 1px rgb(0 0 0 / 2%), 0 4px 8px -4px rgb(0 0 0 / 4%), 0 16px 24px -8px rgb(0 0 0 / 6%);
|
|
744
|
+
--nc-material-shadow-dialog: 0 1px 1px rgb(0 0 0 / 2%), 0 8px 16px -4px rgb(0 0 0 / 4%), 0 24px 32px -8px rgb(0 0 0 / 6%);
|
|
745
|
+
--nc-material-shadow-sheet: 0 2px 2px rgb(0 0 0 / 4%), 0 8px 16px -4px rgb(0 0 0 / 4%);
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
| Material role | Border / radius | Elevation | Internal spacing |
|
|
749
|
+
| --- | --- | --- | --- |
|
|
750
|
+
| Resting content surface | 1 px `{colors.line}` / `{colors.dark-line}`; `{rounded.md}` (6 px) | none | 24 px, or 16 px only for an explicitly compact surface |
|
|
751
|
+
| Resting control | 1 px `{colors.input}` / `{colors.dark-input}`; `{rounded.md}` (6 px) | none | `{spacing.control-padding-inline}` inline; `{spacing.xs}` block for textareas; minimum height `{spacing.control-height}` |
|
|
752
|
+
| Tooltip | 1 px `{colors.line}` / `{colors.dark-line}`; `{rounded.md}` (6 px) | tooltip shadow | 6 px block / 12 px inline |
|
|
753
|
+
| Menu | 1 px `{colors.line}` / `{colors.dark-line}`; `{rounded.2xl}` (12 px) | menu shadow | 4 px |
|
|
754
|
+
| Popover | 1 px `{colors.line}` / `{colors.dark-line}`; `{rounded.2xl}` (12 px) | menu shadow | 10 px |
|
|
755
|
+
| Dialog | 1 px `{colors.line}` / `{colors.dark-line}`; `{rounded.2xl}` (12 px) | dialog shadow | 24 px body / 16 px footer |
|
|
756
|
+
| Inset sheet | 1 px `{colors.line}` / `{colors.dark-line}`; `{rounded.3xl}` (16 px) | sheet shadow | 12 px outer inset / 24 px sections |
|
|
757
|
+
| Takeover | 1 px `{colors.line}` / `{colors.dark-line}`; `{rounded.3xl}` (16 px) | dialog shadow | 24 px |
|
|
758
|
+
|
|
759
|
+
Modal overlays use `{colors.scrim}` / `{colors.dark-scrim}` at the generated `scrim` opacity with no blur. Focus is not elevation: controls use a full-opacity `{spacing.focus-ring-width}` `{colors.focus-ring}` / `{colors.dark-focus-ring}` ring with no offset. Avoid nested decorative borders: one container owns containment, while child groups use spacing, headings, or dividers only when those dividers clarify structure.
|
|
760
|
+
|
|
761
|
+
On coarse or non-hover input capability, every interactive target is at least 44 × 44 px at every viewport width. A compact visual mark such as a checkbox or radio stays compact while its label or hit area supplies the target size. Fine, hover-capable pointers may use the compact control scale.
|
|
687
762
|
|
|
688
763
|
## Shapes
|
|
689
764
|
|
|
690
|
-
Corners are restrained.
|
|
765
|
+
Corners are restrained and assigned by material role.
|
|
691
766
|
|
|
692
767
|
- Use `{rounded.none}` for page rows, frame edges, grid cells, and structural modules.
|
|
693
|
-
- Use `{rounded.
|
|
694
|
-
- Use `{rounded.
|
|
768
|
+
- Use `{rounded.md}` (6 px) for resting content surfaces, controls, buttons, chips, status tags, tooltips, chat bubbles, and small artifacts.
|
|
769
|
+
- Use `{rounded.2xl}` (12 px) for menus, popovers, and dialogs.
|
|
770
|
+
- Use `{rounded.3xl}` (16 px) for inset sheets and takeovers.
|
|
771
|
+
- Use `{rounded.full}` only for intrinsically circular identity/avatar chrome and compact control marks whose geometry is inherently round or pill-shaped. It never turns a content surface, button, badge, or navigation item into a pill by default.
|
|
695
772
|
|
|
696
|
-
|
|
773
|
+
Public page-grammar cells are not cards and remain square because their parent frame supplies the visual system. Product cards are resting content surfaces and use the 6 px role above; they do not gain thicker borders, nested frames, or a shadow merely because they contain grouped settings.
|
|
697
774
|
|
|
698
775
|
## Components
|
|
699
776
|
|
|
@@ -703,7 +780,7 @@ Component entries are grouped by design-system family so the decision model stay
|
|
|
703
780
|
|
|
704
781
|
Interface CSS components provide small metadata, label, and link chrome. They inherit NadicodeAI tokens and stay subordinate to the page grammar; they must not create independent layout systems or repair structural seams. The generic interactive controls (navigation, buttons, inputs, footer chrome, the marketing card/code/pricing/proof surfaces, the standard sections) ship as React shadcn components from `@nadicodeai/ui`; this contract keeps only the brand/display CSS components and primitives that belong in the framework-agnostic package.
|
|
705
782
|
|
|
706
|
-
Interactive CSS components must expose a visible `:focus-visible` state using the
|
|
783
|
+
Interactive CSS components must expose a visible `:focus-visible` state using the `{spacing.focus-ring-width}` full-opacity `{colors.focus-ring}` / `{colors.dark-focus-ring}` role with no offset. Do not remove outlines without that contrast-safe equivalent.
|
|
707
784
|
|
|
708
785
|
**`label-mono`** — mono eyebrow/label text for section labels and low-priority metadata.
|
|
709
786
|
|
|
@@ -725,9 +802,17 @@ Agentic work surfaces are the NadicodeAI-specific layer. They show people and ag
|
|
|
725
802
|
|
|
726
803
|
**`artifact-surface`** — inspectable output area. Use for proposal previews, reports, plans, spreadsheets, schedules, approval states, source traces, run logs, workflow maps, and conversation artifacts.
|
|
727
804
|
|
|
728
|
-
|
|
805
|
+
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
|
+
|
|
807
|
+
**`status-tag-gray`** — default and terminal entity status: no action pending, nothing to watch (inactive, archived, rejected, canceled, expired, revoked, denied).
|
|
808
|
+
|
|
809
|
+
**`status-tag-green`** — a healthy, active, or successfully completed entity status.
|
|
810
|
+
|
|
811
|
+
**`status-tag-red`** — a failed, blocked, or otherwise exceptional entity status that needs attention.
|
|
812
|
+
|
|
813
|
+
**`status-tag-amber`** — a degrading, retiring, or past-due entity status between healthy and failed.
|
|
729
814
|
|
|
730
|
-
**`status-tag-
|
|
815
|
+
**`status-tag-blue`** — an in-progress, pending, or trial entity status still moving toward a resolution.
|
|
731
816
|
|
|
732
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.
|
|
733
818
|
|
|
@@ -737,7 +822,7 @@ Agentic work surfaces are the NadicodeAI-specific layer. They show people and ag
|
|
|
737
822
|
|
|
738
823
|
**`tool-call-trace`** — compact code/trace row. Use only when tool use is relevant to the explanation.
|
|
739
824
|
|
|
740
|
-
State-tag variants share the same
|
|
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.
|
|
741
826
|
|
|
742
827
|
**`state-tag-ready`** — workflow state tag for work that is ready or waiting to start. Uses `{colors.state-ready}` for the left edge.
|
|
743
828
|
|
|
@@ -769,6 +854,8 @@ State-tag variants share the same shape — a compact rectangular pill at `{typo
|
|
|
769
854
|
- Do keep centered content in the 10-column `active-lane` while preserving visible ownership of columns 1 and 12.
|
|
770
855
|
- Do use `side-fill`, guide strips, or component-owned fillers whenever content does not occupy the outer columns.
|
|
771
856
|
- Do use `{spacing.guide}` and `{colors.line}` for ordinary seams.
|
|
857
|
+
- Do use `{colors.input}` / `{colors.dark-input}` for resting control boundaries and the dedicated focus-ring roles for keyboard focus.
|
|
858
|
+
- Do use exactly one material role per container: resting surfaces are border-only; menus, popovers, dialogs, sheets, and takeovers use their specified floating treatment.
|
|
772
859
|
- Do tune line visibility by changing `{colors.line}` at the token contract, then rebuilding generated exports.
|
|
773
860
|
- Do use `{colors.cross}` for crosshair color while keeping crosshair weight equal to `{spacing.guide}`.
|
|
774
861
|
- Do use fixed height tokens for default component/specimen height and let content grow only when required.
|
|
@@ -783,6 +870,8 @@ State-tag variants share the same shape — a compact rectangular pill at `{typo
|
|
|
783
870
|
- Don't create naked centered 10-column sections without visible ownership of columns 1 and 12.
|
|
784
871
|
- Don't draw the same seam from two adjacent elements.
|
|
785
872
|
- Don't add borders inside cells to fix visual seams; fix the owner layer.
|
|
873
|
+
- Don't use a 1 px decorative line as an input boundary, or locally increase card border weight to manufacture hierarchy.
|
|
874
|
+
- Don't stack borders around nested groups, add shadows to resting cards, or blur modal scrims.
|
|
786
875
|
- Don't tune seam contrast with local opacity, raw colors, or component-specific border colors.
|
|
787
876
|
- Don't use viewport-scaled typography.
|
|
788
877
|
- Don't use negative letter spacing in the website kernel.
|
package/README.md
CHANGED
|
@@ -120,4 +120,4 @@ For motion, the package ships exactly one optional, vanilla, dependency-free enh
|
|
|
120
120
|
|
|
121
121
|
Use the monorepo's `brand/brand-book/` for NadicodeAI story, positioning, buyer, promise, method, use cases, technology story, trust doctrine, identity, voice, visual direction, sales behavior, language, and boundaries.
|
|
122
122
|
|
|
123
|
-
The
|
|
123
|
+
The `design-canvas/` prototypes the kernel re-expresses (chat motion and component prototypes) are deleted from the tree; git history retains them under `docs/experiments/design-canvas/`. They are not package runtime or current brand canon.
|
|
@@ -35,8 +35,18 @@
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/* Optional identity accent — same AC-016 map as chat-bubble-agent. */
|
|
38
|
-
.nc-agent-avatar[data-accent="green"]
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
.nc-agent-avatar[data-accent="
|
|
42
|
-
|
|
38
|
+
.nc-agent-avatar[data-accent="green"] {
|
|
39
|
+
--nc-accent: var(--nc-link);
|
|
40
|
+
}
|
|
41
|
+
.nc-agent-avatar[data-accent="cyan"] {
|
|
42
|
+
--nc-accent: var(--nc-info);
|
|
43
|
+
}
|
|
44
|
+
.nc-agent-avatar[data-accent="amber"] {
|
|
45
|
+
--nc-accent: var(--nc-warning-deep);
|
|
46
|
+
}
|
|
47
|
+
.nc-agent-avatar[data-accent="ink"] {
|
|
48
|
+
--nc-accent: var(--nc-ink);
|
|
49
|
+
}
|
|
50
|
+
.nc-agent-avatar[data-accent="red"] {
|
|
51
|
+
--nc-accent: var(--nc-error);
|
|
52
|
+
}
|
|
@@ -12,16 +12,18 @@
|
|
|
12
12
|
display: grid;
|
|
13
13
|
gap: 6px;
|
|
14
14
|
padding: 12px;
|
|
15
|
-
border: var(--nc-guide) solid
|
|
15
|
+
border: var(--nc-guide) solid
|
|
16
|
+
color-mix(in srgb, var(--nc-warning-deep) 40%, var(--nc-warning-soft));
|
|
16
17
|
border-radius: var(--nc-rounded-md);
|
|
17
18
|
background: var(--nc-warning-soft);
|
|
18
19
|
color: var(--nc-ink);
|
|
19
20
|
font-family: "Geist", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
20
21
|
animation-name: nc-msg-in;
|
|
21
22
|
/* Confirm move: state transitions at the 150–200 ms feedback band. */
|
|
22
|
-
transition:
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
transition:
|
|
24
|
+
background-color var(--nc-duration-confirm) var(--nc-ease-out-strong),
|
|
25
|
+
border-color var(--nc-duration-confirm) var(--nc-ease-out-strong),
|
|
26
|
+
color var(--nc-duration-confirm) var(--nc-ease-out-strong);
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
.nc-approval-gate-label {
|
|
@@ -87,15 +89,15 @@
|
|
|
87
89
|
vertical-align: -2px;
|
|
88
90
|
background-color: currentColor;
|
|
89
91
|
-webkit-mask: url("../../icons/check.svg") center / contain no-repeat;
|
|
90
|
-
|
|
92
|
+
mask: url("../../icons/check.svg") center / contain no-repeat;
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
.nc-approval-gate-actions button[data-variant="secondary"]::before {
|
|
94
96
|
-webkit-mask-image: url("../../icons/square-pen.svg");
|
|
95
|
-
|
|
97
|
+
mask-image: url("../../icons/square-pen.svg");
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
.nc-approval-gate-actions button:focus-visible {
|
|
99
|
-
outline: var(--nc-
|
|
100
|
-
outline-offset:
|
|
101
|
+
outline: var(--nc-focus-ring-width) solid var(--nc-focus-ring);
|
|
102
|
+
outline-offset: 0;
|
|
101
103
|
}
|
|
@@ -35,12 +35,24 @@
|
|
|
35
35
|
height: 14px;
|
|
36
36
|
background-color: var(--nc-muted);
|
|
37
37
|
-webkit-mask: url("../../icons/file-text.svg") center / contain no-repeat;
|
|
38
|
-
|
|
38
|
+
mask: url("../../icons/file-text.svg") center / contain no-repeat;
|
|
39
|
+
}
|
|
40
|
+
.nc-artifact-preview[data-kind="sheet"] .nc-artifact-preview-header::before {
|
|
41
|
+
-webkit-mask-image: url("../../icons/table.svg");
|
|
42
|
+
mask-image: url("../../icons/table.svg");
|
|
43
|
+
}
|
|
44
|
+
.nc-artifact-preview[data-kind="code"] .nc-artifact-preview-header::before {
|
|
45
|
+
-webkit-mask-image: url("../../icons/code.svg");
|
|
46
|
+
mask-image: url("../../icons/code.svg");
|
|
47
|
+
}
|
|
48
|
+
.nc-artifact-preview[data-kind="pdf"] .nc-artifact-preview-header::before {
|
|
49
|
+
-webkit-mask-image: url("../../icons/file.svg");
|
|
50
|
+
mask-image: url("../../icons/file.svg");
|
|
51
|
+
}
|
|
52
|
+
.nc-artifact-preview[data-kind="report"] .nc-artifact-preview-header::before {
|
|
53
|
+
-webkit-mask-image: url("../../icons/chart-column.svg");
|
|
54
|
+
mask-image: url("../../icons/chart-column.svg");
|
|
39
55
|
}
|
|
40
|
-
.nc-artifact-preview[data-kind="sheet"] .nc-artifact-preview-header::before { -webkit-mask-image: url("../../icons/table.svg"); mask-image: url("../../icons/table.svg"); }
|
|
41
|
-
.nc-artifact-preview[data-kind="code"] .nc-artifact-preview-header::before { -webkit-mask-image: url("../../icons/code.svg"); mask-image: url("../../icons/code.svg"); }
|
|
42
|
-
.nc-artifact-preview[data-kind="pdf"] .nc-artifact-preview-header::before { -webkit-mask-image: url("../../icons/file.svg"); mask-image: url("../../icons/file.svg"); }
|
|
43
|
-
.nc-artifact-preview[data-kind="report"] .nc-artifact-preview-header::before { -webkit-mask-image: url("../../icons/chart-column.svg"); mask-image: url("../../icons/chart-column.svg"); }
|
|
44
56
|
|
|
45
57
|
.nc-artifact-preview-title {
|
|
46
58
|
font-size: 13px;
|
|
@@ -36,11 +36,21 @@
|
|
|
36
36
|
/* AC-016 accent map → existing --nc-* tokens. Each rule references a token, no
|
|
37
37
|
hard-coded hex. green→link, cyan→info (blue-cobalto; the killed cyan token
|
|
38
38
|
retired per Italia contract §6), amber→warning-deep, ink→ink, red→error. */
|
|
39
|
-
.nc-chat-bubble-agent[data-accent="green"]
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.nc-chat-bubble-agent[data-accent="
|
|
43
|
-
|
|
39
|
+
.nc-chat-bubble-agent[data-accent="green"] {
|
|
40
|
+
--nc-accent: var(--nc-link);
|
|
41
|
+
}
|
|
42
|
+
.nc-chat-bubble-agent[data-accent="cyan"] {
|
|
43
|
+
--nc-accent: var(--nc-info);
|
|
44
|
+
}
|
|
45
|
+
.nc-chat-bubble-agent[data-accent="amber"] {
|
|
46
|
+
--nc-accent: var(--nc-warning-deep);
|
|
47
|
+
}
|
|
48
|
+
.nc-chat-bubble-agent[data-accent="ink"] {
|
|
49
|
+
--nc-accent: var(--nc-ink);
|
|
50
|
+
}
|
|
51
|
+
.nc-chat-bubble-agent[data-accent="red"] {
|
|
52
|
+
--nc-accent: var(--nc-error);
|
|
53
|
+
}
|
|
44
54
|
|
|
45
55
|
/* Inline mono token chip inside an agent bubble (prototype renderInline). */
|
|
46
56
|
.nc-chat-bubble-agent code {
|
|
@@ -117,10 +117,11 @@
|
|
|
117
117
|
line-height: var(--nc-type-caption-mono-line-height);
|
|
118
118
|
letter-spacing: var(--nc-type-caption-mono-letter-spacing);
|
|
119
119
|
cursor: pointer;
|
|
120
|
-
transition:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
transition:
|
|
121
|
+
background-color var(--nc-duration-stagger) var(--nc-ease-out-strong),
|
|
122
|
+
border-color var(--nc-duration-stagger) var(--nc-ease-out-strong),
|
|
123
|
+
color var(--nc-duration-stagger) var(--nc-ease-out-strong),
|
|
124
|
+
opacity var(--nc-duration-stagger) var(--nc-ease-out-strong);
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
@media (hover: hover) and (pointer: fine) {
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
height: 16px;
|
|
34
34
|
background-color: var(--nc-link);
|
|
35
35
|
-webkit-mask: url("../../icons/arrow-right.svg") center / contain no-repeat;
|
|
36
|
-
|
|
36
|
+
mask: url("../../icons/arrow-right.svg") center / contain no-repeat;
|
|
37
37
|
}
|