@nadicodeai/design-system 1.0.1 → 1.1.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 CHANGED
@@ -1,16 +1,16 @@
1
1
  # @nadicodeai/design-system
2
2
 
3
- The `@nadicodeai/design-system` npm workspace. `DESIGN.md` is the normative contract for reusable design tokens and package output; the package ships tokens, the CSS kit (structural geometry plus framework-agnostic brand display components), and assets. Repo-only `examples/` specimens prove that public surface. Standard, interactive, and section UI ships as React components from `@nadicodeai/ui`, not from here. Paths here are relative to `design-system/`; run commands from this directory, or with `-w @nadicodeai/design-system` from the repo root.
3
+ The `@nadicodeai/design-system` npm workspace. `DESIGN.md` is the normative contract for reusable design tokens and package output. The package ships tokens, the CSS kit (structural geometry plus framework-agnostic brand display components), and assets. Repo-only `examples/` specimens prove that public surface. Standard, interactive, and section UI ships as React components from `@nadicodeai/ui`, not from here. Paths here are relative to `packages/design-system/`. Run commands from this directory, or with `-w @nadicodeai/design-system` from the repo root.
4
4
 
5
5
  ## Commands
6
6
 
7
- Proof escalates by the ladder in the root `AGENTS.md` "Commands": `npm run check -w @nadicodeai/design-system` and `npm run test -w @nadicodeai/design-system` before pushing. `check` carries the `DESIGN.md` contract lint, so a contract edit needs no separate command. This workspace has no app to boot: it ships a package, and `examples/` renders through the website's verification routes.
7
+ Proof escalates by the ladder in the root `AGENTS.md` "Commands": `npm run check -w @nadicodeai/design-system` and `npm run test -w @nadicodeai/design-system` before pushing. `check` carries the `DESIGN.md` contract lint, so a contract edit needs no separate command. This workspace has no app to boot: it ships a package, and `examples/` specimens are static HTML pages served from the repo root by `../../scripts/lib/static-design-server.ts`, which `npm run test:visual` starts.
8
8
 
9
9
  | Command | When |
10
10
  | --- | --- |
11
- | `npm run build -w @nadicodeai/design-system` | After any `DESIGN.md` edit; regenerates every `dist/` artifact (tokens, Tailwind data, icons, complete CSS bundle) |
12
- | `npm run generate:icons -w @nadicodeai/design-system` | After bumping `lucide-static`; rebakes `dist/icons/` (also runs inside `build`) |
13
- | `npm run generate:favicons -w @nadicodeai/design-system` | After a favicon source change; the output is git-tracked and the build does not regenerate it |
11
+ | `npm run build -w @nadicodeai/design-system` | After any `DESIGN.md` edit. Regenerates every `dist/` artifact except `dist/favicon/` (tokens, Tailwind data, icons, complete CSS bundle) |
12
+ | `npm run generate:icons -w @nadicodeai/design-system` | After bumping `lucide-static`. Rebakes `dist/icons/` (also runs inside `build`) |
13
+ | `npm run generate:favicons -w @nadicodeai/design-system` | After a favicon source change. The output is git-tracked and the build does not regenerate it |
14
14
  | `npm run test:visual -w @nadicodeai/design-system` | Rendered CSS checks (`playwright.visual.config.ts`, `tests/visual/`), outside the browser-free default suite |
15
15
 
16
16
  ## Routing
@@ -19,25 +19,25 @@ Proof escalates by the ladder in the root `AGENTS.md` "Commands": `npm run check
19
19
  | --- | --- |
20
20
  | Shared design-language terms | `CONTEXT.md` |
21
21
  | Colors, tokens, typography, layout doctrine, seam ownership, component semantics | `DESIGN.md` (read it before stating any of these) |
22
- | CSS layers, token pipeline, dark remaps, generated outputs, their guards | `DESIGN.md` "CSS Architecture & Token Pipeline"; decision history in `../docs/adr/` |
23
- | Motion direction and runtime | `DESIGN.md` "Motion", `src/css/motion.css`, then `../skills/nadicodeai-product-design/references/motion-craft.md` for agent procedure |
24
- | Package exports | `package.json` (guard: `tests/guards/build-produces-exports.test.ts`) |
22
+ | CSS layers, token pipeline, dark remaps, generated outputs, their guards | `DESIGN.md` "CSS Architecture & Token Pipeline". Decision history in `../../docs/adr/` |
23
+ | Motion direction and runtime | `DESIGN.md` "Motion", `src/css/motion.css`, then the `product-design` skill for agent procedure |
24
+ | Package exports | `package.json` (guard: `../../scripts/check-export-targets.mjs`, run by the root `build` script, so root `npm run check` and the post-merge suite, never the workspace `check` or the required gate) |
25
25
  | Static or non-React consumption | `README.md` |
26
- | React consumption | `../@nadicodeai/ui/docs/consuming-cross-repo.md` |
27
- | Logo hierarchy, usage, geometry, and asset delivery | `DESIGN.md` "Brand media authority"; static package routes in `README.md`; implementation routes through `src/assets/`; `dist/` is generated, never hand-edited |
28
- | `examples/` specimen work | `examples/` plus `../skills/nadicodeai-brand-copy/SKILL.md` for specimen copy (guard: `tests/guards/examples-package-coherence.test.ts`) |
29
- | Releasing a change to package-consumed output | `../docs/internal/npm-publishing.md` |
26
+ | React consumption | `../ui/docs/consuming-cross-repo.md` |
27
+ | Logo hierarchy, usage, geometry, and asset delivery | `DESIGN.md` "Brand media authority". Static package routes in `README.md`. Implementation routes through `src/assets/`. `dist/` is generated, never hand-edited |
28
+ | `examples/` specimen work | `examples/` plus the `write-clearly` skill for specimen copy (guard: `tests/guards/examples-package-coherence.test.ts`) |
29
+ | Releasing a change to package-consumed output | `../../docs/agents/npm-publishing.md` |
30
30
  | Visual test implementation | `playwright.visual.config.ts` and `tests/visual/` |
31
31
 
32
32
  ## Boundaries
33
33
 
34
- - Never edit `dist/**` or `src/css/tokens.generated.css` by hand; both regenerate from `DESIGN.md` via `npm run build` (enforced by `tests/guards/token-structural-parity.test.ts` and the DTCG drift check in `tests/guards/consumer-css-discipline.test.ts`).
35
- - Token-only CSS: no raw color/radius/dimension literal in `src/css/`, `examples/`, or the Tailwind adapter, fallback-encoded or not; a new value enters `DESIGN.md` first (enforced by `tests/guards/consumer-css-discipline.test.ts`).
34
+ - Never edit `dist/**` or `src/css/*.generated.css` by hand. The build-covered files regenerate from `DESIGN.md` via `npm run build`. No test guard catches a hand-edit. The fence is the cleanliness step in `.github/workflows/ci.yml`'s `design-system` job (why the guards cannot hold it, and the `dist/favicon/**` carve-out: `DESIGN.md` "Enforcement").
35
+ - Token-only CSS: no raw color or radius literal in hand-authored `src/css/` or `examples/`, fallback-encoded or not. A new value enters `DESIGN.md` first (colors and the examples scan: `tests/guards/consumer-css-discipline.test.ts`; kit radius: `tests/guards/kernel-css-architecture.test.ts`).
36
36
  - Emitted-but-unreferenced contract tokens are intentional. Runtime aliases and compatibility variables are different: each must have a live caller or be removed (`DESIGN.md` "CSS Architecture & Token Pipeline").
37
- - `DESIGN.md` `## Components` is the semantic component catalog; CSS is its implementation, and `tests/guards/component-contract-matches-css.test.ts` derives the two-way fence without a copied inventory.
38
- - `DESIGN.md` stays contract-only and spec-shaped: check `npm exec --package=@google/design.md -- design.md spec` before changing YAML fields; exact reusable values go in YAML, application guidance in prose; add a non-spec YAML field only when repo code or a test reads it (spec-shape don'ts: `DESIGN.md` "Do's and Don'ts").
37
+ - `DESIGN.md` `## Components` is the semantic component catalog. CSS is its implementation, and `tests/guards/component-contract-matches-css.test.ts` derives the two-way fence without a copied inventory.
38
+ - `DESIGN.md` stays contract-only and spec-shaped: check `npm exec --package=@google/design.md -- design.md spec` before changing YAML fields. Exact reusable values go in YAML, application guidance in prose. Add a non-spec YAML field only when repo code or a test reads it (spec-shape don'ts: `DESIGN.md` "Do's and Don'ts").
39
39
  - Seams and grids are computed, single-owner, never eyeballed (doctrine home: `DESIGN.md` "## Layout" and "Seam Ownership").
40
- - Authoring is contract-first: a visual behavior comes from `DESIGN.md`, from our own shipped surfaces, or from an explicit user approval never from another product's rendered output (ADR 0047). Screenshots verify, they never author. Ask when the contract leaves a decision open, and stop and re-read `DESIGN.md` before a second visual patch to the same component.
41
- - Name everything as NadicodeAI-owned primitives. A source brand appears only in a `../docs/adr/` decision record, as the history of what once inspired a choice; never in a name, a comment, a contract, or any living design document (ADR 0047).
42
- - Any change to package-consumed output ends with an explicit release decision, a version bump or a `[no-publish]` commit marker (enforced by the pre-push release gate; procedure: `../docs/internal/npm-publishing.md`).
43
- - The deleted `design-canvas/` prototypes and static chat/autoplay surface live only in git history. `src/css/motion.css` owns shared runtime motion primitives; never reconstruct the prototypes or add a runtime JS surface.
40
+ - Authoring is contract-first: a visual behavior comes from `DESIGN.md`, from our own shipped surfaces, or from an explicit user approval, never from another product's rendered output. Screenshots verify, they never author. Ask when the contract leaves a decision open, and stop and re-read `DESIGN.md` before a second visual patch to the same component.
41
+ - Name everything as NadicodeAI-owned primitives. A source brand never appears in a name, a comment, a contract, or any living design document.
42
+ - Any change to package-consumed output ends with an explicit release decision, a version bump or a `[no-publish]` commit marker (enforced by the pre-push release gate, procedure: `../../docs/agents/npm-publishing.md`).
43
+ - The deleted `design-canvas/` prototypes and static chat/autoplay surface live only in git history. `src/css/motion.css` owns shared runtime motion primitives. Never reconstruct the prototypes or add a runtime JS surface.
package/CONTEXT.md CHANGED
@@ -38,7 +38,7 @@ The perceptual brightness difference that makes the edge between adjacent campi,
38
38
  The shared structural system of frames, rows, lanes, fills, seams, markers, grids, and stages used to compose NadicodeAI pages.
39
39
 
40
40
  **Seam**:
41
- A visible structural line in the page grammar: the shared edge where a frame, row, lane, or grid cell meets its neighbour. Exactly one element owns and draws each seam, so no coordinate is ever drawn twice, and seam placement is computed from grid math rather than eyeballed; the rule and the tokens that colour it live in `design-system/DESIGN.md` "Seam Ownership" and "Layout". This is the visual sense of the word only. Its architectural sense, a boundary in code a test can substitute, is general software vocabulary and not part of the design language.
41
+ A visible structural line in the page grammar: the shared edge where a frame, row, lane, or grid cell meets its neighbour. Exactly one element owns and draws each seam, so no coordinate is ever drawn twice, and seam placement is computed from grid math rather than eyeballed; the rule and the tokens that colour it live in `packages/design-system/DESIGN.md` "Seam Ownership" and "Layout". This is the visual sense of the word only. Its architectural sense, a boundary in code a test can substitute, is general software vocabulary and not part of the design language.
42
42
 
43
43
  **CSS primitive**:
44
44
  A low-level, framework-agnostic CSS helper for geometry, type, seams, fills, or structural behavior. It carries no product-specific meaning.
@@ -46,13 +46,8 @@ A low-level, framework-agnostic CSS helper for geometry, type, seams, fills, or
46
46
  **CSS component**:
47
47
  A framework-agnostic visual component that remains useful on both static and interactive surfaces without owning an app feature.
48
48
 
49
- **Run-state tag**:
50
- The visual label for the state of agentic work, such as ready, running, review, blocked, or complete.
51
- _Avoid_: Status badge
52
-
53
- **Entity status tag**:
54
- The visual label for an entity's lifecycle, health, or exception state. It does not represent the state of agentic work.
55
- _Avoid_: Run-state tag
49
+ **Status vocabulary**:
50
+ The one way the product shows a status. What it is, which carrier renders it, and which tone each value takes live in `packages/design-system/DESIGN.md` "Status Vocabulary".
56
51
 
57
52
  **Content surface**:
58
53
  A visual family for presenting a concrete content type, such as an image or artifact, inside the page grammar.
package/DESIGN.md CHANGED
@@ -26,7 +26,7 @@ colors:
26
26
  input: "#757575"
27
27
  seam: "#d4d4d4"
28
28
  cross: "#999999"
29
- focus-ring: "#00713d"
29
+ focus-ring: "#111111"
30
30
  scrim: "#111111"
31
31
  link: "#00713d"
32
32
  link-deep: "#00522c"
@@ -47,9 +47,9 @@ colors:
47
47
  flag-red: "#d3302f"
48
48
  selection-bg: "#111111"
49
49
  selection-fg: "#fafafa"
50
- navigation-selection-bg: "#1e3cff"
51
- navigation-selection-fg: "#ffffff"
52
- navigation-selection-hover: "#1735df"
50
+ navigation-selection-bg: "#ededed"
51
+ navigation-selection-fg: "#111111"
52
+ navigation-selection-hover: "#e5e5e5"
53
53
  state-ready: "#6b6b6b"
54
54
  state-running: "#1e3cff"
55
55
  state-review: "#ffc220"
@@ -98,7 +98,7 @@ colors:
98
98
  dark-link: "#4ecf8c"
99
99
  dark-link-deep: "#93e3b8"
100
100
  dark-link-bg-soft: "#00351c"
101
- dark-focus-ring: "#4ecf8c"
101
+ dark-focus-ring: "#ededed"
102
102
  dark-scrim: "#ededed"
103
103
  dark-error: "#f5a3a1"
104
104
  dark-error-soft: "#380a09"
@@ -122,9 +122,9 @@ colors:
122
122
  dark-state-complete: "#00a85a"
123
123
  dark-selection-bg: "#ededed"
124
124
  dark-selection-fg: "#0a0a0a"
125
- dark-navigation-selection-bg: "#2743d8"
125
+ dark-navigation-selection-bg: "#1a1a1a"
126
126
  dark-navigation-selection-fg: "#ededed"
127
- dark-navigation-selection-hover: "#3552e6"
127
+ dark-navigation-selection-hover: "#262626"
128
128
  dark-cross: "#555555"
129
129
  dark-chart-1: "#4d6bff"
130
130
  dark-chart-2: "#00a85a"
@@ -280,7 +280,8 @@ spacing:
280
280
  section: 192px
281
281
  guide: 1px
282
282
  icon-stroke: 1.6px
283
- focus-ring-width: 3px
283
+ focus-outline-width: 2px
284
+ focus-outline-offset: 2px
284
285
  control-height: 32px
285
286
  control-padding-inline: 10px
286
287
  touch-target: 44px
@@ -345,7 +346,9 @@ The kernel is the reusable implementation layer. `DESIGN.md` defines the reusabl
345
346
 
346
347
  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.
347
348
 
348
- 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 strictly achromatic: every neutral is an equal-channel gray (OKLCH chroma 0) in both themes. The five campi are cross-spectrum equals, so any neutral bias would flatter one field and dirty another; hue arrives full-strength through the chromatic roles or not at all, and no tint ever paints an app surface. Colours are authored as sRGB hex here and emitted as `oklch()` in the generated CSS.
349
+ Interaction states are material, not meaning: focus, hover, and selection read as contrast steps on the neutral spine, never as identity colour. Verde stays on action, links, presence, and success; cobalto stays on info and running. A hover ground is a neutral step; the only hue a hover carries is a semantic fill stepping inside its own family, as `{colors.action-hover}` does on the action control.
350
+
351
+ Every value a role needs is carried by the role token itself; the ten-step numeric scale families were removed deliberately and must not be reintroduced. 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 strictly achromatic: every neutral is an equal-channel gray (OKLCH chroma 0) in both themes. The five campi are cross-spectrum equals, so any neutral bias would flatter one field and dirty another; hue arrives full-strength through the chromatic roles or not at all, and no tint ever paints an app surface. Colours are authored as sRGB hex here and emitted as `oklch()` in the generated CSS.
349
352
 
350
353
  ### Semantic roles (functional tier)
351
354
 
@@ -353,10 +356,10 @@ Every value a role needs is carried by the role token itself; there are no ten-s
353
356
  - **Action** (`{colors.action}` = deep verde, `{colors.action-foreground}` = white, `{colors.action-hover}`, `{colors.action-active}`): the primary-control family — a white label on the deep verde field, hover and active stepping darker. The shadcn `primary` roles map here. Dark mode uses the `dark-action-*` roles, a brightened verde that clears the dark canvas and carries a near-black label.
354
357
  - **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.
355
358
  - **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.
356
- - **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.
359
+ - **Focus ring** (`{colors.focus-ring}` / `{colors.dark-focus-ring}`): the ink keyboard-focus indicator, a full-opacity `outline` of `{spacing.focus-outline-width}` at `{spacing.focus-outline-offset}` offset, never a box-shadow. Focus is a state of material, so the indicator is the maximum-contrast neutral on each ground rather than a hue; the offset keeps it independent of the resting border, and it clears the 3:1 non-text floor against the adjacent canvas.
357
360
  - **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.
358
- - **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.
359
- - **Navigation selection** (`{colors.navigation-selection-bg}`, `{colors.navigation-selection-fg}`, `{colors.navigation-selection-hover}`): the selected destination in persistent product navigation. This is the Portal's cobalt wayfinding role, not feedback, workflow state, chart data, or a brand campo borrowed into UI. The dark counterparts are tuned independently for the black console. Resting and hover pairs clear AA for text; keyboard focus adds the selection foreground as an inner boundary before the ordinary focus ring, so the indicator remains visible against both the cobalt fill and adjacent canvas.
361
+ - **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 ground for link and tag chrome only: a message or conversation plane is a neutral surface, never a link-tinted one.
362
+ - **Navigation selection** (`{colors.navigation-selection-bg}`, `{colors.navigation-selection-fg}`, `{colors.navigation-selection-hover}`): the selected destination in persistent product navigation, a neutral ink pill. Selection is a place, not a meaning, so it holds by contrast on the neutral spine; cobalto belongs to the semantic info and running roles only. The dark counterparts are tuned independently for the black console. Resting and hover pairs clear AA for text, and the offset focus outline stays visible against both the pill fill and the adjacent canvas.
360
363
  - **Semantic feedback** (`{colors.success}` = verde with `{colors.success-soft}`/`{colors.success-deep}`; `{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. The success pair intentionally reuses the link pair's AA-safe verde values; its feedback meaning remains distinct from inline navigation and entity-status semantics.
361
364
  - **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.
362
365
  - **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.
@@ -384,9 +387,9 @@ Four campo rules govern their use:
384
387
 
385
388
  ### Dark primitives
386
389
 
387
- **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. `dark-canvas` is true black: the only base plane for dark product shells. The remaining dark neutrals (`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 exact equal-channel grays (OKLCH chroma 0), so no hue paints a surface. The soft canvas steps belong only to bounded interaction states such as hover, selection, keycaps, and inline controls; they never replace true black as a page, section, card, popover, sidebar, or large-panel ground. `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, `dark-navigation-selection-*` the selected product-navigation field, and `dark-error`/`dark-error-deep`, `dark-warning`/`dark-warning-deep`, `dark-info`/`dark-info-deep`, `dark-success`/`dark-success-deep` 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.
390
+ **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. `dark-canvas` is true black: the only base plane for dark product shells. The remaining dark neutrals (`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 exact equal-channel grays (OKLCH chroma 0), so no hue paints a surface. The soft canvas steps belong only to bounded interaction states such as hover, selection, keycaps, and inline controls; they never replace true black as a page, section, card, popover, sidebar, or large-panel ground. `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`/`dark-success-deep` the brightened feedback hues, each `*-soft` a deep tinted ground. `dark-navigation-selection-*` and `dark-focus-ring` sit on the neutral spine: selection and focus are material states, not meanings. 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.
388
391
 
389
- This achromatic-neutral discipline is not dark-specific: it governs the generated shadcn surface-role bridge in both the light `:root` and dark `.dark` maps. The neutral surface family — `background`, `card`, `popover`, `muted`, `secondary`, `sidebar`, `sidebar-accent`, their neutral foreground/border variants, plus `border` and `input` — resolves only to exact equal-channel grays (OKLCH chroma 0) in both themes. Hue in the role bridge is reserved for explicit semantic roles: `primary`, `destructive`, `success`, `warning`, the focus rings (`ring`/`sidebar-ring`), and the `sidebar-primary*` navigation-selection family defined above. 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.
392
+ This achromatic-neutral discipline is not dark-specific: it governs the generated shadcn surface-role bridge in both the light `:root` and dark `.dark` maps. The neutral surface family — `background`, `card`, `popover`, `muted`, `secondary`, `sidebar`, `sidebar-accent`, their neutral foreground/border variants, plus `border` and `input` — resolves only to exact equal-channel grays (OKLCH chroma 0) in both themes. Hue in the role bridge is reserved for explicit semantic roles: `primary`, `destructive`, `success`, and `warning`. The focus rings (`ring`/`sidebar-ring`) and the `sidebar-primary*` navigation-selection family resolve to equal-channel grays like the surface family: focus and selection are material states, and no interaction state carries a hue. 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.
390
393
 
391
394
  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.
392
395
 
@@ -485,7 +488,7 @@ Kernel compositions arrange approved primitives for a content role. They must no
485
488
 
486
489
  Each reusable concern has one home and one authoring surface, so a member is documented and shipped in exactly one place:
487
490
 
488
- - **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.
491
+ - **Tokens** — exact reusable values live in this contract's `colors`, `spacing`, `rounded`, and `typography`; they export to the generated token layer. No component or section may re-encode a token value.
489
492
  - **Framework-agnostic CSS components** — the brand/display CSS components that remain in this package (agent-work artifacts, `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.
490
493
  - **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.
491
494
  - **Layout grammar** — the page-frame, row, lane, seam, stage, and marker system documented across this `## Layout` section, carried by the layout CSS layer.
@@ -537,9 +540,9 @@ NadicodeAI website depth is flat and architectural. Hairlines, contrast, dotted
537
540
 
538
541
  Product UI uses one shared material ladder. The workspace is one continuous ground (`{colors.material-workspace}` / `{colors.dark-material-workspace}`); every solid object uses the same fill (`{colors.material-solid}` / `{colors.dark-material-solid}`). In dark mode, both are true black. The workspace remains legible because it carries the existing `dotted-field` texture and solid objects occlude it. Elevation never means progressively greyer cards. Physical distance changes only the `shadow-plugin` falloff: `smooth-shadow-ring-md` for resting content, then `lg`, `xl`, and `2xl` when an object is physically raised, floating, or modal. Each utility already integrates the plugin's adaptive optical ring, including the plugin's 18% white dark-mode ring, so an elevated root never adds a border, second ring, local ring tint, or opacity override. Product code chooses only the semantic role.
539
542
 
540
- Glass is a material variant, not an elevation step. It is reserved for compact control chrome floating over legible content. Cards, KPIs, tables, inspectors, and ordinary modal bodies remain solid. Reduced-transparency mode replaces glass with the same solid material at the same elevation.
543
+ Glass is a material variant, not an elevation step. Floating chrome may be glass: menus, popovers, selects, comboboxes, the command palette, and bars, the surfaces that stand over the room and show it through themselves. Content surfaces stay solid: cards, KPIs, tables, inspectors, and dialog, sheet, and drawer bodies, because glass floats but never carries content. The ground and the window stay opaque, so glass composites only over our own content, never over anything behind the app. Glass keeps exactly one separator, the integrated edge ring of its elevation falloff, never ring plus shadow plus border stacked. Reduced-transparency mode replaces glass with the same solid material at the same elevation.
541
544
 
542
- The Google design schema does not define opacity groups. These declarations are therefore the authored material-token source inside this contract. The build reads this block strictly and emits generated `--nc-*` hooks. The UI package owns the exact `shadow-plugin` dependency and maps semantic component roles to its utilities without copying the vendor shadow values into this contract.
545
+ The Google design schema does not define opacity groups. These declarations are therefore the authored material-token source inside this contract. The build reads this block strictly and emits every declaration in it as a generated `--nc-material-*` hook. Each name below is required, because shipped output references it: `scrim-opacity` becomes the theme layer's `--opacity-scrim`, and the three glass values are consumed by `@nadicodeai/ui/globals.css`. A name added here that no output references is emitted the same way and is not required. The UI package owns the exact `shadow-plugin` dependency and maps semantic component roles to its utilities without copying the vendor shadow values into this contract.
543
546
 
544
547
  ```css material-tokens
545
548
  --nc-material-scrim-opacity: 10%;
@@ -555,7 +558,7 @@ The Google design schema does not define opacity groups. These declarations are
555
558
  | Raised | Same solid fill and ring; `smooth-shadow-ring-lg`; `{rounded.3xl}` (16 px) | Active work, a selected object, or an attached inspector above resting siblings |
556
559
  | Floating | Same solid fill and ring; `smooth-shadow-ring-xl`; role-specific corner radius | Compact menus, popovers, dropdowns, and anchored surfaces use `{rounded.2xl}` (12 px); small artifacts such as tooltips and toasts keep `{rounded.md}` (6 px); detached product surfaces may use `{rounded.3xl}` (16 px) |
557
560
  | Modal | Same solid fill and ring; `smooth-shadow-ring-2xl`; `{rounded.3xl}` (16 px) | Dialog, sheet, drawer, and takeover |
558
- | Glass control | Translucent solid fill at 76%, 28 px backdrop blur, integrated plugin ring, and the falloff for its physical level | Compact control chrome floating above content; never a content container |
561
+ | Glass control | Translucent solid fill at 76%, 28 px backdrop blur, integrated plugin ring, and the falloff for its physical level | Floating chrome above our own content: menus, popovers, selects, comboboxes, the command palette, and bars; never a content container |
559
562
 
560
563
  `Card` is the fundamental product container. Its content does not create a second material family: KPIs, Agent cards, settings, and ordinary grouped content use the resting role unless the object is physically raised. Interaction variants may change state or emphasis without changing the material role.
561
564
 
@@ -563,7 +566,7 @@ Absence follows the container that owns it. A page-level or region-level empty s
563
566
 
564
567
  Resting form controls are not elevated material planes. They keep the 1 px `{colors.input}` / `{colors.dark-input}` boundary, `{rounded.md}` (6 px), and no shadow. Their inline padding is `{spacing.control-padding-inline}`, textareas use `{spacing.xs}` block padding, and every default control is at least `{spacing.control-height}` high.
565
568
 
566
- 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.
569
+ 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-outline-width}` `{colors.focus-ring}` / `{colors.dark-focus-ring}` outline at `{spacing.focus-outline-offset}` offset, never a box-shadow ring. Avoid nested decorative borders: one container owns containment, while child groups use spacing, headings, or dividers only when those dividers clarify structure.
567
570
 
568
571
  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.
569
572
 
@@ -591,7 +594,7 @@ This section is the semantic catalog for framework-agnostic components. Exact re
591
594
 
592
595
  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.
593
596
 
594
- 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.
597
+ Keyboard focus has one owner: the kit's foundation layer draws the full-opacity `{spacing.focus-outline-width}` `{colors.focus-ring}` / `{colors.dark-focus-ring}` outline at `{spacing.focus-outline-offset}` offset on every `:focus-visible` element. A component never repaints focus with its own ring, hue, or width, and never removes the outline without a contrast-safe equivalent.
595
598
 
596
599
  **`label-mono`** — mono eyebrow text, identifiers and code, and low-priority metadata. The mono register marks what the machine owns, not what a heading says, so a card, panel, or section title never takes it: titles are sentence-case sans.
597
600
 
@@ -611,7 +614,7 @@ Content surfaces display specific content types inside the grammar. They are val
611
614
 
612
615
  Agentic work surfaces are the NadicodeAI-specific display layer outside the conversation renderer. They show concrete work output or workflow state such as memory, state, run progress, identity, and handoffs. Conversation messages, tools, artifacts, approvals, and pending indicators belong to assistant-ui.
613
616
 
614
- Agent identity is decorative product identity, not a work artifact or a status signal. Its approved metaball form, closed Agent-type recipes, four surface treatments, palette, still frames, and motion rules live in [`brand/visual-design/AGENT-VISUAL-SYSTEM.md`](../brand/visual-design/AGENT-VISUAL-SYSTEM.md). `@nadicodeai/ui` owns the typed React implementation. Consuming apps assign a recipe explicitly and own placement, data, actions, and accessible meaning.
617
+ Agent identity is decorative product identity, not a work artifact or a status signal. Its approved metaball form, closed Agent-type recipes, four surface treatments, palette, still frames, and motion rules live in [`brand/visual-design/AGENT-VISUAL-SYSTEM.md`](../../brand/visual-design/AGENT-VISUAL-SYSTEM.md). `@nadicodeai/ui` owns the typed React implementation. Consuming apps assign a recipe explicitly and own placement, data, actions, and accessible meaning.
615
618
 
616
619
  **`artifact-surface`** — inspectable output area outside a conversation. Use for proposal previews, reports, plans, spreadsheets, schedules, run logs, and workflow maps.
617
620
 
@@ -634,7 +637,7 @@ its icon slot. It is not a CSS component in this package: there is no
634
637
  framework-neutral status class, and a static surface that needs to show a status
635
638
  shows it as ordinary text. Its React API — the tone variants, the icon slot, and
636
639
  what a consuming app must supply — is contracted in
637
- [`@nadicodeai/ui/docs/contract.md`](../@nadicodeai/ui/docs/contract.md).
640
+ [`packages/ui/docs/contract.md`](../ui/docs/contract.md).
638
641
 
639
642
  **Why.** A status read by colour alone is not read by everyone, and a product
640
643
  that speaks status in three grammars teaches its next surface to invent a
@@ -693,15 +696,17 @@ Icons are derived from Lucide (ISC) and carry the NadicodeAI house render: a
693
696
  `{spacing.icon-stroke}` round-cap, round-join stroke, no fill, and
694
697
  `currentColor` inheritance.
695
698
  The lighter stroke preserves the clarity of the accepted Portal concept while
696
- round terminals keep Lucide's calm character. A small curated glyph vocabulary,
697
- disciplined placement, and sizes sm / md / lg = 12 / 16 / 24 px (md default)
699
+ round terminals keep Lucide's calm character. The package bakes the complete
700
+ pinned `lucide-static` set through that house render; a surface draws a small,
701
+ disciplined vocabulary from it rather than reaching across the whole set.
702
+ Placement discipline and sizes sm / md / lg = 12 / 16 / 24 px (md default)
698
703
  complete the treatment. Static and React icon sources stay version-aligned so a
699
704
  glyph has one silhouette everywhere. Text-paired icons are decorative; icon-only
700
705
  controls carry an accessible name.
701
706
 
702
707
  ## CSS Architecture & Token Pipeline
703
708
 
704
- 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`.
709
+ 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, 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`.
705
710
 
706
711
  ### Public style interfaces
707
712
 
@@ -710,7 +715,7 @@ There is one public stylesheet interface per runtime, selected by the caller's r
710
715
  - Static HTML and non-React consumers use `@nadicodeai/design-system/css`.
711
716
  - 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.
712
717
 
713
- 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).
718
+ 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 [`packages/ui/docs/consuming-cross-repo.md`](../ui/docs/consuming-cross-repo.md).
714
719
 
715
720
  ### Authoring homes
716
721
 
@@ -726,9 +731,9 @@ Each delivery tier (see Layout, "Delivery Tiers") has exactly one authoring file
726
731
 
727
732
  Style Dictionary (`scripts/sd/`, driven from `scripts/build.ts`) emits three CSS files from the `@google/design.md` export of this contract:
728
733
 
729
- 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.
734
+ 1. The token layer `tokens.generated.css`: a complete projection of every export token, with each emitted `--nc-*` name appearing once. Never an allowlist or subset, and never containing `@media` or `calc()`; responsive and composed runtime variables live only in their owning layer and reference emitted `--nc-*` tokens. Names map per group: `colors` and `spacing` emit `--nc-<name>`, `rounded` emits `--nc-rounded-<name>`, and each composite `typography` scale expands per property into `--nc-type-<scale>-font-family`, `-font-size`, `-font-weight`, `-line-height`, and `-letter-spacing`, never the CSS `font:` shorthand, which drops the line-height unit. Values serialize deterministically: authored hex colors emit as `oklch()`, dimensions keep their authored value and unit, typography line-height comes from this contract's own unit-preserving Tailwind export because the DTCG composite export carries it as a bare number, and material-fence values emit unchanged. Emitted-but-unreferenced contract tokens remain part of the package vocabulary; private compatibility variables with no caller do not.
730
735
  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.
731
- 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.
736
+ 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 derives from this contract, and the formatter holds no raw `--nc-*` mode-remap table. The raw `@theme` block also carries a small hand-maintained alias set — `--outline-width-focus`, `--outline-offset-focus`, `--opacity-scrim`, `--spacing-control-height`, `--spacing-control-padding-inline`, `--spacing-touch-target` — each a `var()` reference onto a generated token, and each must have a live caller or be removed.
732
737
 
733
738
  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.
734
739
 
@@ -742,11 +747,11 @@ The NadicodeAI logo has three approved forms:
742
747
  2. **Mark.** The two interlocked rounded-square links may stand alone where space is tight: favicons, app icons, avatars, watermarks, stamps, and compact navigation. A containing link or control names NadicodeAI when the mark is used without visible text.
743
748
  3. **Wordmark.** The NadicodeAI letterforms may stand alone where the name must read by itself, including document headers and editorial layouts.
744
749
 
745
- Other companies' marks are not NadicodeAI company logos and are not governed by anything in this section. They are generated identity images owned by `@nadicodeai/ui/components/brand-icons`, decided in [`docs/adr/0042-third-party-brand-marks-are-generated-identity-images.md`](../docs/adr/0042-third-party-brand-marks-are-generated-identity-images.md). A third-party mark never enters a NadicodeAI logo form, composition, or clear-space measurement.
750
+ Other companies' marks are not NadicodeAI company logos and are not governed by anything in this section. They are generated identity images owned by `@nadicodeai/ui/components/brand-icons`; [`packages/ui/docs/contract.md`](../ui/docs/contract.md) carries their rules. A third-party mark never enters a NadicodeAI logo form, composition, or clear-space measurement.
746
751
 
747
- Nadia's portrait, Agent identity visuals, and generated imagery are not NadicodeAI company logos. Nadia's identity and selection rules live in [`brand/visual-design/NADIA-VISUAL-IDENTITY.md`](../brand/visual-design/NADIA-VISUAL-IDENTITY.md); the Agent identity system lives in [`brand/visual-design/AGENT-VISUAL-SYSTEM.md`](../brand/visual-design/AGENT-VISUAL-SYSTEM.md); editorial imagery routes through [`brand/visual-design/EDITORIAL-ILLUSTRATION.md`](../brand/visual-design/EDITORIAL-ILLUSTRATION.md). This contract owns only the package delivery interface.
752
+ Nadia's portrait, Agent identity visuals, and generated imagery are not NadicodeAI company logos. Nadia's identity and selection rules live in [`brand/visual-design/NADIA-VISUAL-IDENTITY.md`](../../brand/visual-design/NADIA-VISUAL-IDENTITY.md); the Agent identity system lives in [`brand/visual-design/AGENT-VISUAL-SYSTEM.md`](../../brand/visual-design/AGENT-VISUAL-SYSTEM.md); editorial imagery routes through [`brand/visual-design/EDITORIAL-ILLUSTRATION.md`](../../brand/visual-design/EDITORIAL-ILLUSTRATION.md). This contract owns only the package delivery interface.
748
753
 
749
- The approved transparent Nadia master ships at `assets/nadia-solid-surface`.
754
+ The approved transparent Nadia master ships at `assets/nadia-solid-surface`. The package also delivers the three remaining material states as compatibility routes: `assets/nadia-ordered-points`, `assets/nadia-triangulated-wire`, and `assets/nadia-irregular-particles`. Package delivery does not grant brand approval; which Nadia image a surface may use stays with the identity document named above.
750
755
 
751
756
  All three forms derive from one authored, framework-neutral geometry source exported as `@nadicodeai/design-system/assets/logo-geometry`. The lockup combines the shared mark and wordmark geometry at the established proportion and spacing. No SVG, React component, favicon, document, or app re-authors, traces, typesets, or rearranges those shapes.
752
757
 
@@ -762,4 +767,4 @@ The package build renders and publicly exports full-colour, mono-ink, inverse, a
762
767
 
763
768
  ### Enforcement
764
769
 
765
- 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.
770
+ 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 in the hand-authored kit CSS and of raw color and radius literals in `examples/`, second value sources, and DTCG drift. These guards read freshly built output (the test global-setup rebuilds before any of them run), so they prove the generator; a hand-edited or stale committed generated file is caught by the CI cleanliness step in the `design-system` job, which requires a fresh build to reproduce the committed bytes exactly, with `dist/favicon/**` outside it, regenerated only by `generate:favicons` and fenced by review rather than machinery. Cross-package guards verify that React callers use only the React stylesheet interface.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  The `@nadicodeai/design-system` package. [`DESIGN.md`](./DESIGN.md) is the normative contract for reusable design tokens, mode behavior, CSS architecture, and generated output. The canonical human brand book lives in the monorepo at `brand/brand-book/index.html`.
4
4
 
5
- This README is a package map and the setup guide for static or non-React consumers. React consumers use the UI package's single stylesheet interface and follow [`@nadicodeai/ui/docs/consuming-cross-repo.md`](../@nadicodeai/ui/docs/consuming-cross-repo.md). They do not compose design-system stylesheets themselves.
5
+ This README is a package map and the setup guide for static or non-React consumers. React consumers use the UI package's single stylesheet interface and follow [`packages/ui/docs/consuming-cross-repo.md`](../ui/docs/consuming-cross-repo.md). They do not compose design-system stylesheets themselves.
6
6
 
7
7
  ## Static and non-React consumption
8
8
 
@@ -59,7 +59,7 @@ The approved background-neutral transparent Nadia master is available through:
59
59
  | --- | --- |
60
60
  | Canonical Nadia | `@nadicodeai/design-system/assets/nadia-solid-surface` |
61
61
 
62
- The import resolves to the approved transparent PNG. Identity and composition are owned by [`brand/visual-design/NADIA-VISUAL-IDENTITY.md`](../brand/visual-design/NADIA-VISUAL-IDENTITY.md); this package README documents only the import surface.
62
+ The import resolves to the approved transparent PNG. Identity and composition are owned by [`brand/visual-design/NADIA-VISUAL-IDENTITY.md`](../../brand/visual-design/NADIA-VISUAL-IDENTITY.md); this package README documents only the import surface.
63
63
 
64
64
  ## Package surface
65
65
 
@@ -59,7 +59,7 @@
59
59
  --nc-input: oklch(0.5624 0.0000 0.00);
60
60
  --nc-seam: oklch(0.8699 0.0000 0.00);
61
61
  --nc-cross: oklch(0.6830 0.0000 0.00);
62
- --nc-focus-ring: oklch(0.4815 0.1209 154.24);
62
+ --nc-focus-ring: oklch(0.1776 0.0000 0.00);
63
63
  --nc-scrim: oklch(0.1776 0.0000 0.00);
64
64
  --nc-link: oklch(0.4815 0.1209 154.24);
65
65
  --nc-link-deep: oklch(0.3852 0.0953 154.99);
@@ -80,9 +80,9 @@
80
80
  --nc-flag-red: oklch(0.5688 0.1995 26.59);
81
81
  --nc-selection-bg: oklch(0.1776 0.0000 0.00);
82
82
  --nc-selection-fg: oklch(0.9851 0.0000 0.00);
83
- --nc-navigation-selection-bg: oklch(0.5005 0.2804 266.17);
84
- --nc-navigation-selection-fg: oklch(1.0000 0.0000 0.00);
85
- --nc-navigation-selection-hover: oklch(0.4542 0.2521 265.86);
83
+ --nc-navigation-selection-bg: oklch(0.9461 0.0000 0.00);
84
+ --nc-navigation-selection-fg: oklch(0.1776 0.0000 0.00);
85
+ --nc-navigation-selection-hover: oklch(0.9219 0.0000 0.00);
86
86
  --nc-state-ready: oklch(0.5278 0.0000 0.00);
87
87
  --nc-state-running: oklch(0.5005 0.2804 266.17);
88
88
  --nc-state-review: oklch(0.8466 0.1678 84.63);
@@ -131,7 +131,7 @@
131
131
  --nc-dark-link: oklch(0.7661 0.1498 157.10);
132
132
  --nc-dark-link-deep: oklch(0.8524 0.0996 159.83);
133
133
  --nc-dark-link-bg-soft: oklch(0.2893 0.0697 156.32);
134
- --nc-dark-focus-ring: oklch(0.7661 0.1498 157.10);
134
+ --nc-dark-focus-ring: oklch(0.9461 0.0000 0.00);
135
135
  --nc-dark-scrim: oklch(0.9461 0.0000 0.00);
136
136
  --nc-dark-error: oklch(0.7955 0.0980 21.02);
137
137
  --nc-dark-error-soft: oklch(0.2296 0.0728 26.06);
@@ -155,9 +155,9 @@
155
155
  --nc-dark-state-complete: oklch(0.6415 0.1644 153.23);
156
156
  --nc-dark-selection-bg: oklch(0.9461 0.0000 0.00);
157
157
  --nc-dark-selection-fg: oklch(0.1448 0.0000 0.00);
158
- --nc-dark-navigation-selection-bg: oklch(0.4725 0.2271 267.41);
158
+ --nc-dark-navigation-selection-bg: oklch(0.2178 0.0000 0.00);
159
159
  --nc-dark-navigation-selection-fg: oklch(0.9461 0.0000 0.00);
160
- --nc-dark-navigation-selection-hover: oklch(0.5162 0.2247 268.31);
160
+ --nc-dark-navigation-selection-hover: oklch(0.2686 0.0000 0.00);
161
161
  --nc-dark-cross: oklch(0.4495 0.0000 0.00);
162
162
  --nc-dark-chart-1: oklch(0.5923 0.2215 269.61);
163
163
  --nc-dark-chart-2: oklch(0.6415 0.1644 153.23);
@@ -188,7 +188,8 @@
188
188
  --nc-section: 192px;
189
189
  --nc-guide: 1px;
190
190
  --nc-icon-stroke: 1.6px;
191
- --nc-focus-ring-width: 3px;
191
+ --nc-focus-outline-width: 2px;
192
+ --nc-focus-outline-offset: 2px;
192
193
  --nc-control-height: 32px;
193
194
  --nc-control-padding-inline: 10px;
194
195
  --nc-touch-target: 44px;
@@ -593,8 +594,8 @@
593
594
  --sidebar-border: var(--nc-dark-line);
594
595
  --sidebar-ring: var(--nc-dark-focus-ring);
595
596
  }
597
+ @theme { --color-*: initial; --color-nc-primary: oklch(0.5075 0.1338 151.91); --color-nc-on-primary: oklch(1.0000 0.0000 0.00); --color-nc-action: oklch(0.5075 0.1338 151.91); --color-nc-action-foreground: oklch(1.0000 0.0000 0.00); --color-nc-action-hover: oklch(0.4285 0.1117 152.40); --color-nc-action-active: oklch(0.2722 0.0643 157.47); --color-nc-ink: oklch(0.1776 0.0000 0.00); --color-nc-body: oklch(0.3867 0.0000 0.00); --color-nc-muted: oklch(0.5278 0.0000 0.00); --color-nc-canvas: oklch(1.0000 0.0000 0.00); --color-nc-canvas-soft: oklch(0.9851 0.0000 0.00); --color-nc-canvas-soft-2: oklch(0.9702 0.0000 0.00); --color-nc-material-workspace: oklch(0.9761 0.0000 0.00); --color-nc-material-solid: oklch(1.0000 0.0000 0.00); --color-nc-line: oklch(0.9219 0.0000 0.00); --color-nc-input: oklch(0.5624 0.0000 0.00); --color-nc-seam: oklch(0.8699 0.0000 0.00); --color-nc-cross: oklch(0.6830 0.0000 0.00); --color-nc-focus-ring: oklch(0.1776 0.0000 0.00); --color-nc-scrim: oklch(0.1776 0.0000 0.00); --color-nc-link: oklch(0.4815 0.1209 154.24); --color-nc-link-deep: oklch(0.3852 0.0953 154.99); --color-nc-link-bg-soft: oklch(0.9170 0.0519 161.77); --color-nc-accent: oklch(0.6824 0.2108 37.70); --color-nc-info: oklch(0.5005 0.2804 266.17); --color-nc-info-soft: oklch(0.9457 0.0259 276.40); --color-nc-info-deep: oklch(0.3197 0.1758 266.79); --color-nc-success: oklch(0.6415 0.1644 153.23); --color-nc-success-soft: oklch(0.9170 0.0519 161.77); --color-nc-success-deep: oklch(0.3852 0.0953 154.99); --color-nc-error: oklch(0.5688 0.1995 26.59); --color-nc-error-soft: oklch(0.9522 0.0207 17.52); --color-nc-error-deep: oklch(0.4235 0.1525 27.08); --color-nc-warning: oklch(0.8466 0.1678 84.63); --color-nc-warning-soft: oklch(0.9649 0.0461 90.87); --color-nc-warning-deep: oklch(0.4834 0.0995 82.44); --color-nc-flag-red: oklch(0.5688 0.1995 26.59); --color-nc-selection-bg: oklch(0.1776 0.0000 0.00); --color-nc-selection-fg: oklch(0.9851 0.0000 0.00); --color-nc-navigation-selection-bg: oklch(0.9461 0.0000 0.00); --color-nc-navigation-selection-fg: oklch(0.1776 0.0000 0.00); --color-nc-navigation-selection-hover: oklch(0.9219 0.0000 0.00); --color-nc-state-ready: oklch(0.5278 0.0000 0.00); --color-nc-state-running: oklch(0.5005 0.2804 266.17); --color-nc-state-review: oklch(0.8466 0.1678 84.63); --color-nc-state-blocked: oklch(0.5688 0.1995 26.59); --color-nc-state-complete: oklch(0.6415 0.1644 153.23); --color-nc-background-100: oklch(1.0000 0.0000 0.00); --color-nc-background-200: oklch(0.9851 0.0000 0.00); --color-nc-campo-verde: oklch(0.6415 0.1644 153.23); --color-nc-campo-rosso: oklch(0.5688 0.1995 26.59); --color-nc-campo-arancio: oklch(0.6824 0.2108 37.70); --color-nc-campo-giallo: oklch(0.8466 0.1678 84.63); --color-nc-campo-cobalto: oklch(0.5005 0.2804 266.17); --color-nc-campo-inchiostro: oklch(0.0000 0.0000 0.00); --color-nc-campo-bianco: oklch(1.0000 0.0000 0.00); --color-nc-chart-1: oklch(0.5005 0.2804 266.17); --color-nc-chart-2: oklch(0.6415 0.1644 153.23); --color-nc-chart-3: oklch(0.7638 0.1562 86.86); --color-nc-chart-4: oklch(0.5688 0.1995 26.59); --color-nc-chart-5: oklch(0.6161 0.1062 208.85); --color-nc-chart-6: oklch(0.5015 0.1883 294.99); --color-nc-chart-seq-1: oklch(0.6998 0.1347 269.48); --color-nc-chart-seq-2: oklch(0.5724 0.1897 270.11); --color-nc-chart-seq-3: oklch(0.4725 0.2271 267.41); --color-nc-chart-seq-4: oklch(0.3989 0.1934 267.50); --color-nc-chart-seq-5: oklch(0.3270 0.1487 267.91); --color-nc-chart-div-warm: oklch(0.7592 0.1560 83.30); --color-nc-chart-div-mid: oklch(0.5278 0.0000 0.00); --color-nc-chart-div-cool: oklch(0.5923 0.2215 269.61); --color-nc-dark-canvas: oklch(0.0000 0.0000 0.00); --color-nc-dark-canvas-soft: oklch(0.1776 0.0000 0.00); --color-nc-dark-canvas-soft-2: oklch(0.2178 0.0000 0.00); --color-nc-dark-material-workspace: oklch(0.0000 0.0000 0.00); --color-nc-dark-material-solid: oklch(0.0000 0.0000 0.00); --color-nc-dark-ink: oklch(0.9461 0.0000 0.00); --color-nc-dark-body: oklch(0.8297 0.0000 0.00); --color-nc-dark-muted: oklch(0.6500 0.0000 0.00); --color-nc-dark-line: oklch(0.2686 0.0000 0.00); --color-nc-dark-input: oklch(0.5208 0.0000 0.00); --color-nc-dark-seam: oklch(0.2178 0.0000 0.00); --color-nc-dark-primary: oklch(0.7727 0.1753 155.96); --color-nc-dark-on-primary: oklch(0.1448 0.0000 0.00); --color-nc-dark-action: oklch(0.7727 0.1753 155.96); --color-nc-dark-action-foreground: oklch(0.1448 0.0000 0.00); --color-nc-dark-action-hover: oklch(0.7661 0.1498 157.10); --color-nc-dark-action-active: oklch(0.7019 0.1753 153.20); --color-nc-dark-link: oklch(0.7661 0.1498 157.10); --color-nc-dark-link-deep: oklch(0.8524 0.0996 159.83); --color-nc-dark-link-bg-soft: oklch(0.2893 0.0697 156.32); --color-nc-dark-focus-ring: oklch(0.9461 0.0000 0.00); --color-nc-dark-scrim: oklch(0.9461 0.0000 0.00); --color-nc-dark-error: oklch(0.7955 0.0980 21.02); --color-nc-dark-error-soft: oklch(0.2296 0.0728 26.06); --color-nc-dark-error-deep: oklch(0.8856 0.0534 19.64); --color-nc-dark-warning: oklch(0.8939 0.1387 90.47); --color-nc-dark-warning-soft: oklch(0.3135 0.0643 85.04); --color-nc-dark-warning-deep: oklch(0.9320 0.0896 90.86); --color-nc-dark-info: oklch(0.7067 0.1528 272.08); --color-nc-dark-info-soft: oklch(0.2118 0.1033 268.28); --color-nc-dark-info-deep: oklch(0.8222 0.0888 274.44); --color-nc-dark-cyan: oklch(0.7820 0.1247 190.99); --color-nc-dark-cyan-soft: oklch(0.8646 0.1000 187.55); --color-nc-dark-cyan-deep: oklch(0.6347 0.1029 191.54); --color-nc-dark-success: oklch(0.7019 0.1753 153.20); --color-nc-dark-success-soft: oklch(0.2893 0.0697 156.32); --color-nc-dark-success-deep: oklch(0.8524 0.0996 159.83); --color-nc-dark-state-ready: oklch(0.5624 0.0000 0.00); --color-nc-dark-state-running: oklch(0.5923 0.2215 269.61); --color-nc-dark-state-review: oklch(0.8466 0.1678 84.63); --color-nc-dark-state-blocked: oklch(0.5688 0.1995 26.59); --color-nc-dark-state-complete: oklch(0.6415 0.1644 153.23); --color-nc-dark-selection-bg: oklch(0.9461 0.0000 0.00); --color-nc-dark-selection-fg: oklch(0.1448 0.0000 0.00); --color-nc-dark-navigation-selection-bg: oklch(0.2178 0.0000 0.00); --color-nc-dark-navigation-selection-fg: oklch(0.9461 0.0000 0.00); --color-nc-dark-navigation-selection-hover: oklch(0.2686 0.0000 0.00); --color-nc-dark-cross: oklch(0.4495 0.0000 0.00); --color-nc-dark-chart-1: oklch(0.5923 0.2215 269.61); --color-nc-dark-chart-2: oklch(0.6415 0.1644 153.23); --color-nc-dark-chart-3: oklch(0.8939 0.1387 90.47); --color-nc-dark-chart-4: oklch(0.6627 0.1685 23.66); --color-nc-dark-chart-5: oklch(0.7820 0.1247 190.99); --color-nc-dark-chart-6: oklch(0.6297 0.1321 299.36); --color-nc-dark-chart-seq-1: oklch(0.5724 0.1897 270.11); --color-nc-dark-chart-seq-2: oklch(0.6998 0.1347 269.48); --color-nc-dark-chart-seq-3: oklch(0.8072 0.0884 269.44); --color-nc-dark-chart-seq-4: oklch(0.8877 0.0514 270.78); --color-nc-dark-chart-seq-5: oklch(0.9619 0.0179 272.31); --color-nc-dark-chart-div-warm: oklch(0.8939 0.1387 90.47); --color-nc-dark-chart-div-mid: oklch(0.9219 0.0000 0.00); --color-nc-dark-chart-div-cool: oklch(0.8222 0.0888 274.44); --font-display-xl: Geist, Inter, system-ui, -apple-system, sans-serif; --font-display-lg: Geist, Inter, system-ui, -apple-system, sans-serif; --font-display-md: Geist, Inter, system-ui, -apple-system, sans-serif; --font-display-sm: Geist, Inter, system-ui, -apple-system, sans-serif; --font-title-lg: Geist, Inter, system-ui, -apple-system, sans-serif; --font-title-md: Geist, Inter, system-ui, -apple-system, sans-serif; --font-title-sm: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-lg: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-md: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-md-strong: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-sm: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-sm-strong: Geist, Inter, system-ui, -apple-system, sans-serif; --font-caption: Geist, Inter, system-ui, -apple-system, sans-serif; --font-caption-strong: Geist, Inter, system-ui, -apple-system, sans-serif; --font-caption-mono: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace; --font-code: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace; --font-button-md: Geist, Inter, system-ui, -apple-system, sans-serif; --font-button-lg: Geist, Inter, system-ui, -apple-system, sans-serif; --text-display-xl: 72px; --text-display-xl--line-height: 74px; --leading-display-xl: 74px; --text-display-xl--letter-spacing: -1.5px; --tracking-display-xl: -1.5px; --text-display-xl--font-weight: 600; --font-weight-display-xl: 600; --text-display-lg: 52px; --text-display-lg--line-height: 54px; --leading-display-lg: 54px; --text-display-lg--letter-spacing: -1px; --tracking-display-lg: -1px; --text-display-lg--font-weight: 600; --font-weight-display-lg: 600; --text-display-md: 24px; --text-display-md--line-height: 32px; --leading-display-md: 32px; --text-display-md--letter-spacing: 0px; --tracking-display-md: 0px; --text-display-md--font-weight: 600; --font-weight-display-md: 600; --text-display-sm: 20px; --text-display-sm--line-height: 28px; --leading-display-sm: 28px; --text-display-sm--letter-spacing: 0px; --tracking-display-sm: 0px; --text-display-sm--font-weight: 600; --font-weight-display-sm: 600; --text-title-lg: 40px; --text-title-lg--line-height: 41px; --leading-title-lg: 41px; --text-title-lg--letter-spacing: 0px; --tracking-title-lg: 0px; --text-title-lg--font-weight: 600; --font-weight-title-lg: 600; --text-title-md: 30px; --text-title-md--line-height: 32px; --leading-title-md: 32px; --text-title-md--letter-spacing: 0px; --tracking-title-md: 0px; --text-title-md--font-weight: 600; --font-weight-title-md: 600; --text-title-sm: 22px; --text-title-sm--line-height: 25px; --leading-title-sm: 25px; --text-title-sm--letter-spacing: 0px; --tracking-title-sm: 0px; --text-title-sm--font-weight: 600; --font-weight-title-sm: 600; --text-body-lg: 18px; --text-body-lg--line-height: 27px; --leading-body-lg: 27px; --text-body-lg--letter-spacing: 0px; --tracking-body-lg: 0px; --text-body-lg--font-weight: 400; --font-weight-body-lg: 400; --text-body-md: 16px; --text-body-md--line-height: 25px; --leading-body-md: 25px; --text-body-md--letter-spacing: 0px; --tracking-body-md: 0px; --text-body-md--font-weight: 400; --font-weight-body-md: 400; --text-body-md-strong: 16px; --text-body-md-strong--line-height: 24px; --leading-body-md-strong: 24px; --text-body-md-strong--letter-spacing: 0px; --tracking-body-md-strong: 0px; --text-body-md-strong--font-weight: 500; --font-weight-body-md-strong: 500; --text-body-sm: 14px; --text-body-sm--line-height: 20px; --leading-body-sm: 20px; --text-body-sm--letter-spacing: 0px; --tracking-body-sm: 0px; --text-body-sm--font-weight: 400; --font-weight-body-sm: 400; --text-body-sm-strong: 14px; --text-body-sm-strong--line-height: 20px; --leading-body-sm-strong: 20px; --text-body-sm-strong--letter-spacing: 0px; --tracking-body-sm-strong: 0px; --text-body-sm-strong--font-weight: 500; --font-weight-body-sm-strong: 500; --text-caption: 12px; --text-caption--line-height: 16px; --leading-caption: 16px; --text-caption--letter-spacing: 0px; --tracking-caption: 0px; --text-caption--font-weight: 400; --font-weight-caption: 400; --text-caption-strong: 12px; --text-caption-strong--line-height: 16px; --leading-caption-strong: 16px; --text-caption-strong--letter-spacing: 0px; --tracking-caption-strong: 0px; --text-caption-strong--font-weight: 500; --font-weight-caption-strong: 500; --text-caption-mono: 12px; --text-caption-mono--line-height: 16px; --leading-caption-mono: 16px; --text-caption-mono--letter-spacing: 0px; --tracking-caption-mono: 0px; --text-caption-mono--font-weight: 500; --font-weight-caption-mono: 500; --text-code: 13px; --text-code--line-height: 20px; --leading-code: 20px; --text-code--letter-spacing: 0px; --tracking-code: 0px; --text-code--font-weight: 400; --font-weight-code: 400; --text-button-md: 14px; --text-button-md--line-height: 18px; --leading-button-md: 18px; --text-button-md--letter-spacing: 0px; --tracking-button-md: 0px; --text-button-md--font-weight: 500; --font-weight-button-md: 500; --text-button-lg: 16px; --text-button-lg--line-height: 24px; --leading-button-lg: 24px; --text-button-lg--letter-spacing: 0px; --tracking-button-lg: 0px; --text-button-lg--font-weight: 500; --font-weight-button-lg: 500; --radius-none: 0px; --radius-xs: 2px; --radius-sm: 4px; --radius-md: 6px; --radius-lg: 8px; --radius-xl: 10px; --radius-2xl: 12px; --radius-3xl: 16px; --radius-pill-sm: 64px; --radius-pill: 100px; --radius-full: 9999px; --outline-width-focus: var(--spacing-nadicode-focus-outline-width); --outline-offset-focus: var(--spacing-nadicode-focus-outline-offset); --opacity-scrim: var(--nc-material-scrim-opacity); --spacing-nadicode-xxs: 4px; --spacing-nadicode-filter-chip-gap: 6px; --spacing-nadicode-xs: 8px; --spacing-nadicode-sm: 12px; --spacing-nadicode-md: 16px; --spacing-nadicode-lg: 24px; --spacing-nadicode-xl: 32px; --spacing-nadicode-2xl: 40px; --spacing-nadicode-3xl: 48px; --spacing-nadicode-4xl: 64px; --spacing-nadicode-5xl: 96px; --spacing-nadicode-6xl: 128px; --spacing-nadicode-section: 192px; --spacing-nadicode-guide: 1px; --spacing-nadicode-icon-stroke: 1.6px; --spacing-nadicode-focus-outline-width: 2px; --spacing-nadicode-focus-outline-offset: 2px; --spacing-nadicode-control-height: 32px; --spacing-nadicode-control-padding-inline: 10px; --spacing-nadicode-touch-target: 44px; --spacing-nadicode-page-pad: 24px; --spacing-nadicode-page-max-mobile: 448px; --spacing-nadicode-page-max-tablet: 624px; --spacing-nadicode-page-max-desktop: 1440px; --spacing-nadicode-frame-max: 1392px; --spacing-nadicode-frame-gap: 24px; --spacing-nadicode-cell-padding: 24px; --spacing-nadicode-section-gap: 48px; --spacing-nadicode-cross-size-mobile: 11px; --spacing-nadicode-cross-size-tablet: 15px; --spacing-nadicode-cross-size-desktop: 21px; --spacing-nadicode-h-strip-mobile: 72px; --spacing-nadicode-h-strip-tablet: 80px; --spacing-nadicode-h-strip-desktop: 88px; --spacing-nadicode-h-cell-sm: 120px; --spacing-nadicode-h-cell-md-mobile: 144px; --spacing-nadicode-h-cell-md-tablet: 160px; --spacing-nadicode-h-cell-md-desktop: 168px; --spacing-nadicode-h-cell-lg-mobile: 220px; --spacing-nadicode-h-cell-lg-desktop: 240px; --spacing-nadicode-h-visual-mobile: 276px; --spacing-nadicode-h-visual-tablet: 318px; --spacing-nadicode-h-visual-desktop: 360px; --spacing-nadicode-h-precision-mobile: 276px; --spacing-nadicode-h-precision-tablet: 480px; --spacing-nadicode-h-precision-desktop: 720px; --spacing-nadicode-h-hero-mobile: 560px; --spacing-nadicode-h-hero-desktop: 720px; --spacing-nadicode-h-action-strip-mobile: 20px; --spacing-nadicode-h-action-strip-desktop: 32px; --spacing-nadicode-h-action-body-mobile: 320px; --spacing-nadicode-h-action-body-tablet: 338px; --spacing-nadicode-h-action-band: 260px; --spacing-nadicode-h-feature-mobile: 360px; --spacing-nadicode-h-feature-tablet: 400px; --spacing-nadicode-h-feature-desktop: 456px; --spacing-nadicode-h-editorial-feature-mobile: 360px; --spacing-nadicode-h-editorial-feature-tablet: 440px; --spacing-nadicode-h-editorial-feature-desktop: 560px; --spacing-nadicode-h-bento-primary: 384px; --spacing-nadicode-h-bento-secondary: 240px; --spacing-nadicode-h-bento-mobile-copy: 248px; --spacing-nadicode-h-bento-mobile-main: 537px; --spacing-nadicode-h-bento-strip: 20px; --spacing-nadicode-filter-chip-height: 28px; --spacing-nadicode-filter-chip-icon: 14px; --spacing-control-height: var(--spacing-nadicode-control-height); --spacing-control-padding-inline: var(--spacing-nadicode-control-padding-inline); --spacing-touch-target: var(--spacing-nadicode-touch-target); }
596
598
  @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground); --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-primary-hover: var(--primary-hover); --color-primary-active: var(--primary-active); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-placeholder: var(--placeholder); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); --color-destructive-foreground: var(--destructive-foreground); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); --color-scrim: var(--scrim); --color-chart-1: var(--chart-1); --color-chart-2: var(--chart-2); --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); --color-sidebar: var(--sidebar); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar-primary: var(--sidebar-primary); --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); --color-sidebar-primary-hover: var(--sidebar-primary-hover); --color-sidebar-accent: var(--sidebar-accent); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); }
597
- @theme { --color-nc-primary: oklch(0.5075 0.1338 151.91); --color-nc-on-primary: oklch(1.0000 0.0000 0.00); --color-nc-action: oklch(0.5075 0.1338 151.91); --color-nc-action-foreground: oklch(1.0000 0.0000 0.00); --color-nc-action-hover: oklch(0.4285 0.1117 152.40); --color-nc-action-active: oklch(0.2722 0.0643 157.47); --color-nc-ink: oklch(0.1776 0.0000 0.00); --color-nc-body: oklch(0.3867 0.0000 0.00); --color-nc-muted: oklch(0.5278 0.0000 0.00); --color-nc-canvas: oklch(1.0000 0.0000 0.00); --color-nc-canvas-soft: oklch(0.9851 0.0000 0.00); --color-nc-canvas-soft-2: oklch(0.9702 0.0000 0.00); --color-nc-material-workspace: oklch(0.9761 0.0000 0.00); --color-nc-material-solid: oklch(1.0000 0.0000 0.00); --color-nc-line: oklch(0.9219 0.0000 0.00); --color-nc-input: oklch(0.5624 0.0000 0.00); --color-nc-seam: oklch(0.8699 0.0000 0.00); --color-nc-cross: oklch(0.6830 0.0000 0.00); --color-nc-focus-ring: oklch(0.4815 0.1209 154.24); --color-nc-scrim: oklch(0.1776 0.0000 0.00); --color-nc-link: oklch(0.4815 0.1209 154.24); --color-nc-link-deep: oklch(0.3852 0.0953 154.99); --color-nc-link-bg-soft: oklch(0.9170 0.0519 161.77); --color-nc-accent: oklch(0.6824 0.2108 37.70); --color-nc-info: oklch(0.5005 0.2804 266.17); --color-nc-info-soft: oklch(0.9457 0.0259 276.40); --color-nc-info-deep: oklch(0.3197 0.1758 266.79); --color-nc-success: oklch(0.6415 0.1644 153.23); --color-nc-success-soft: oklch(0.9170 0.0519 161.77); --color-nc-success-deep: oklch(0.3852 0.0953 154.99); --color-nc-error: oklch(0.5688 0.1995 26.59); --color-nc-error-soft: oklch(0.9522 0.0207 17.52); --color-nc-error-deep: oklch(0.4235 0.1525 27.08); --color-nc-warning: oklch(0.8466 0.1678 84.63); --color-nc-warning-soft: oklch(0.9649 0.0461 90.87); --color-nc-warning-deep: oklch(0.4834 0.0995 82.44); --color-nc-flag-red: oklch(0.5688 0.1995 26.59); --color-nc-selection-bg: oklch(0.1776 0.0000 0.00); --color-nc-selection-fg: oklch(0.9851 0.0000 0.00); --color-nc-navigation-selection-bg: oklch(0.5005 0.2804 266.17); --color-nc-navigation-selection-fg: oklch(1.0000 0.0000 0.00); --color-nc-navigation-selection-hover: oklch(0.4542 0.2521 265.86); --color-nc-state-ready: oklch(0.5278 0.0000 0.00); --color-nc-state-running: oklch(0.5005 0.2804 266.17); --color-nc-state-review: oklch(0.8466 0.1678 84.63); --color-nc-state-blocked: oklch(0.5688 0.1995 26.59); --color-nc-state-complete: oklch(0.6415 0.1644 153.23); --color-nc-background-100: oklch(1.0000 0.0000 0.00); --color-nc-background-200: oklch(0.9851 0.0000 0.00); --color-nc-campo-verde: oklch(0.6415 0.1644 153.23); --color-nc-campo-rosso: oklch(0.5688 0.1995 26.59); --color-nc-campo-arancio: oklch(0.6824 0.2108 37.70); --color-nc-campo-giallo: oklch(0.8466 0.1678 84.63); --color-nc-campo-cobalto: oklch(0.5005 0.2804 266.17); --color-nc-campo-inchiostro: oklch(0.0000 0.0000 0.00); --color-nc-campo-bianco: oklch(1.0000 0.0000 0.00); --color-nc-chart-1: oklch(0.5005 0.2804 266.17); --color-nc-chart-2: oklch(0.6415 0.1644 153.23); --color-nc-chart-3: oklch(0.7638 0.1562 86.86); --color-nc-chart-4: oklch(0.5688 0.1995 26.59); --color-nc-chart-5: oklch(0.6161 0.1062 208.85); --color-nc-chart-6: oklch(0.5015 0.1883 294.99); --color-nc-chart-seq-1: oklch(0.6998 0.1347 269.48); --color-nc-chart-seq-2: oklch(0.5724 0.1897 270.11); --color-nc-chart-seq-3: oklch(0.4725 0.2271 267.41); --color-nc-chart-seq-4: oklch(0.3989 0.1934 267.50); --color-nc-chart-seq-5: oklch(0.3270 0.1487 267.91); --color-nc-chart-div-warm: oklch(0.7592 0.1560 83.30); --color-nc-chart-div-mid: oklch(0.5278 0.0000 0.00); --color-nc-chart-div-cool: oklch(0.5923 0.2215 269.61); --color-nc-dark-canvas: oklch(0.0000 0.0000 0.00); --color-nc-dark-canvas-soft: oklch(0.1776 0.0000 0.00); --color-nc-dark-canvas-soft-2: oklch(0.2178 0.0000 0.00); --color-nc-dark-material-workspace: oklch(0.0000 0.0000 0.00); --color-nc-dark-material-solid: oklch(0.0000 0.0000 0.00); --color-nc-dark-ink: oklch(0.9461 0.0000 0.00); --color-nc-dark-body: oklch(0.8297 0.0000 0.00); --color-nc-dark-muted: oklch(0.6500 0.0000 0.00); --color-nc-dark-line: oklch(0.2686 0.0000 0.00); --color-nc-dark-input: oklch(0.5208 0.0000 0.00); --color-nc-dark-seam: oklch(0.2178 0.0000 0.00); --color-nc-dark-primary: oklch(0.7727 0.1753 155.96); --color-nc-dark-on-primary: oklch(0.1448 0.0000 0.00); --color-nc-dark-action: oklch(0.7727 0.1753 155.96); --color-nc-dark-action-foreground: oklch(0.1448 0.0000 0.00); --color-nc-dark-action-hover: oklch(0.7661 0.1498 157.10); --color-nc-dark-action-active: oklch(0.7019 0.1753 153.20); --color-nc-dark-link: oklch(0.7661 0.1498 157.10); --color-nc-dark-link-deep: oklch(0.8524 0.0996 159.83); --color-nc-dark-link-bg-soft: oklch(0.2893 0.0697 156.32); --color-nc-dark-focus-ring: oklch(0.7661 0.1498 157.10); --color-nc-dark-scrim: oklch(0.9461 0.0000 0.00); --color-nc-dark-error: oklch(0.7955 0.0980 21.02); --color-nc-dark-error-soft: oklch(0.2296 0.0728 26.06); --color-nc-dark-error-deep: oklch(0.8856 0.0534 19.64); --color-nc-dark-warning: oklch(0.8939 0.1387 90.47); --color-nc-dark-warning-soft: oklch(0.3135 0.0643 85.04); --color-nc-dark-warning-deep: oklch(0.9320 0.0896 90.86); --color-nc-dark-info: oklch(0.7067 0.1528 272.08); --color-nc-dark-info-soft: oklch(0.2118 0.1033 268.28); --color-nc-dark-info-deep: oklch(0.8222 0.0888 274.44); --color-nc-dark-cyan: oklch(0.7820 0.1247 190.99); --color-nc-dark-cyan-soft: oklch(0.8646 0.1000 187.55); --color-nc-dark-cyan-deep: oklch(0.6347 0.1029 191.54); --color-nc-dark-success: oklch(0.7019 0.1753 153.20); --color-nc-dark-success-soft: oklch(0.2893 0.0697 156.32); --color-nc-dark-success-deep: oklch(0.8524 0.0996 159.83); --color-nc-dark-state-ready: oklch(0.5624 0.0000 0.00); --color-nc-dark-state-running: oklch(0.5923 0.2215 269.61); --color-nc-dark-state-review: oklch(0.8466 0.1678 84.63); --color-nc-dark-state-blocked: oklch(0.5688 0.1995 26.59); --color-nc-dark-state-complete: oklch(0.6415 0.1644 153.23); --color-nc-dark-selection-bg: oklch(0.9461 0.0000 0.00); --color-nc-dark-selection-fg: oklch(0.1448 0.0000 0.00); --color-nc-dark-navigation-selection-bg: oklch(0.4725 0.2271 267.41); --color-nc-dark-navigation-selection-fg: oklch(0.9461 0.0000 0.00); --color-nc-dark-navigation-selection-hover: oklch(0.5162 0.2247 268.31); --color-nc-dark-cross: oklch(0.4495 0.0000 0.00); --color-nc-dark-chart-1: oklch(0.5923 0.2215 269.61); --color-nc-dark-chart-2: oklch(0.6415 0.1644 153.23); --color-nc-dark-chart-3: oklch(0.8939 0.1387 90.47); --color-nc-dark-chart-4: oklch(0.6627 0.1685 23.66); --color-nc-dark-chart-5: oklch(0.7820 0.1247 190.99); --color-nc-dark-chart-6: oklch(0.6297 0.1321 299.36); --color-nc-dark-chart-seq-1: oklch(0.5724 0.1897 270.11); --color-nc-dark-chart-seq-2: oklch(0.6998 0.1347 269.48); --color-nc-dark-chart-seq-3: oklch(0.8072 0.0884 269.44); --color-nc-dark-chart-seq-4: oklch(0.8877 0.0514 270.78); --color-nc-dark-chart-seq-5: oklch(0.9619 0.0179 272.31); --color-nc-dark-chart-div-warm: oklch(0.8939 0.1387 90.47); --color-nc-dark-chart-div-mid: oklch(0.9219 0.0000 0.00); --color-nc-dark-chart-div-cool: oklch(0.8222 0.0888 274.44); --font-display-xl: Geist, Inter, system-ui, -apple-system, sans-serif; --font-display-lg: Geist, Inter, system-ui, -apple-system, sans-serif; --font-display-md: Geist, Inter, system-ui, -apple-system, sans-serif; --font-display-sm: Geist, Inter, system-ui, -apple-system, sans-serif; --font-title-lg: Geist, Inter, system-ui, -apple-system, sans-serif; --font-title-md: Geist, Inter, system-ui, -apple-system, sans-serif; --font-title-sm: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-lg: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-md: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-md-strong: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-sm: Geist, Inter, system-ui, -apple-system, sans-serif; --font-body-sm-strong: Geist, Inter, system-ui, -apple-system, sans-serif; --font-caption: Geist, Inter, system-ui, -apple-system, sans-serif; --font-caption-strong: Geist, Inter, system-ui, -apple-system, sans-serif; --font-caption-mono: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace; --font-code: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace; --font-button-md: Geist, Inter, system-ui, -apple-system, sans-serif; --font-button-lg: Geist, Inter, system-ui, -apple-system, sans-serif; --text-display-xl: 72px; --text-display-xl--line-height: 74px; --leading-display-xl: 74px; --text-display-xl--letter-spacing: -1.5px; --tracking-display-xl: -1.5px; --text-display-xl--font-weight: 600; --font-weight-display-xl: 600; --text-display-lg: 52px; --text-display-lg--line-height: 54px; --leading-display-lg: 54px; --text-display-lg--letter-spacing: -1px; --tracking-display-lg: -1px; --text-display-lg--font-weight: 600; --font-weight-display-lg: 600; --text-display-md: 24px; --text-display-md--line-height: 32px; --leading-display-md: 32px; --text-display-md--letter-spacing: 0px; --tracking-display-md: 0px; --text-display-md--font-weight: 600; --font-weight-display-md: 600; --text-display-sm: 20px; --text-display-sm--line-height: 28px; --leading-display-sm: 28px; --text-display-sm--letter-spacing: 0px; --tracking-display-sm: 0px; --text-display-sm--font-weight: 600; --font-weight-display-sm: 600; --text-title-lg: 40px; --text-title-lg--line-height: 41px; --leading-title-lg: 41px; --text-title-lg--letter-spacing: 0px; --tracking-title-lg: 0px; --text-title-lg--font-weight: 600; --font-weight-title-lg: 600; --text-title-md: 30px; --text-title-md--line-height: 32px; --leading-title-md: 32px; --text-title-md--letter-spacing: 0px; --tracking-title-md: 0px; --text-title-md--font-weight: 600; --font-weight-title-md: 600; --text-title-sm: 22px; --text-title-sm--line-height: 25px; --leading-title-sm: 25px; --text-title-sm--letter-spacing: 0px; --tracking-title-sm: 0px; --text-title-sm--font-weight: 600; --font-weight-title-sm: 600; --text-body-lg: 18px; --text-body-lg--line-height: 27px; --leading-body-lg: 27px; --text-body-lg--letter-spacing: 0px; --tracking-body-lg: 0px; --text-body-lg--font-weight: 400; --font-weight-body-lg: 400; --text-body-md: 16px; --text-body-md--line-height: 25px; --leading-body-md: 25px; --text-body-md--letter-spacing: 0px; --tracking-body-md: 0px; --text-body-md--font-weight: 400; --font-weight-body-md: 400; --text-body-md-strong: 16px; --text-body-md-strong--line-height: 24px; --leading-body-md-strong: 24px; --text-body-md-strong--letter-spacing: 0px; --tracking-body-md-strong: 0px; --text-body-md-strong--font-weight: 500; --font-weight-body-md-strong: 500; --text-body-sm: 14px; --text-body-sm--line-height: 20px; --leading-body-sm: 20px; --text-body-sm--letter-spacing: 0px; --tracking-body-sm: 0px; --text-body-sm--font-weight: 400; --font-weight-body-sm: 400; --text-body-sm-strong: 14px; --text-body-sm-strong--line-height: 20px; --leading-body-sm-strong: 20px; --text-body-sm-strong--letter-spacing: 0px; --tracking-body-sm-strong: 0px; --text-body-sm-strong--font-weight: 500; --font-weight-body-sm-strong: 500; --text-caption: 12px; --text-caption--line-height: 16px; --leading-caption: 16px; --text-caption--letter-spacing: 0px; --tracking-caption: 0px; --text-caption--font-weight: 400; --font-weight-caption: 400; --text-caption-strong: 12px; --text-caption-strong--line-height: 16px; --leading-caption-strong: 16px; --text-caption-strong--letter-spacing: 0px; --tracking-caption-strong: 0px; --text-caption-strong--font-weight: 500; --font-weight-caption-strong: 500; --text-caption-mono: 12px; --text-caption-mono--line-height: 16px; --leading-caption-mono: 16px; --text-caption-mono--letter-spacing: 0px; --tracking-caption-mono: 0px; --text-caption-mono--font-weight: 500; --font-weight-caption-mono: 500; --text-code: 13px; --text-code--line-height: 20px; --leading-code: 20px; --text-code--letter-spacing: 0px; --tracking-code: 0px; --text-code--font-weight: 400; --font-weight-code: 400; --text-button-md: 14px; --text-button-md--line-height: 18px; --leading-button-md: 18px; --text-button-md--letter-spacing: 0px; --tracking-button-md: 0px; --text-button-md--font-weight: 500; --font-weight-button-md: 500; --text-button-lg: 16px; --text-button-lg--line-height: 24px; --leading-button-lg: 24px; --text-button-lg--letter-spacing: 0px; --tracking-button-lg: 0px; --text-button-lg--font-weight: 500; --font-weight-button-lg: 500; --radius-none: 0px; --radius-xs: 2px; --radius-sm: 4px; --radius-md: 6px; --radius-lg: 8px; --radius-xl: 10px; --radius-2xl: 12px; --radius-3xl: 16px; --radius-pill-sm: 64px; --radius-pill: 100px; --radius-full: 9999px; --ring-width-focus: var(--spacing-nadicode-focus-ring-width); --opacity-scrim: var(--nc-material-scrim-opacity); --spacing-nadicode-xxs: 4px; --spacing-nadicode-filter-chip-gap: 6px; --spacing-nadicode-xs: 8px; --spacing-nadicode-sm: 12px; --spacing-nadicode-md: 16px; --spacing-nadicode-lg: 24px; --spacing-nadicode-xl: 32px; --spacing-nadicode-2xl: 40px; --spacing-nadicode-3xl: 48px; --spacing-nadicode-4xl: 64px; --spacing-nadicode-5xl: 96px; --spacing-nadicode-6xl: 128px; --spacing-nadicode-section: 192px; --spacing-nadicode-guide: 1px; --spacing-nadicode-icon-stroke: 1.6px; --spacing-nadicode-focus-ring-width: 3px; --spacing-nadicode-control-height: 32px; --spacing-nadicode-control-padding-inline: 10px; --spacing-nadicode-touch-target: 44px; --spacing-nadicode-page-pad: 24px; --spacing-nadicode-page-max-mobile: 448px; --spacing-nadicode-page-max-tablet: 624px; --spacing-nadicode-page-max-desktop: 1440px; --spacing-nadicode-frame-max: 1392px; --spacing-nadicode-frame-gap: 24px; --spacing-nadicode-cell-padding: 24px; --spacing-nadicode-section-gap: 48px; --spacing-nadicode-cross-size-mobile: 11px; --spacing-nadicode-cross-size-tablet: 15px; --spacing-nadicode-cross-size-desktop: 21px; --spacing-nadicode-h-strip-mobile: 72px; --spacing-nadicode-h-strip-tablet: 80px; --spacing-nadicode-h-strip-desktop: 88px; --spacing-nadicode-h-cell-sm: 120px; --spacing-nadicode-h-cell-md-mobile: 144px; --spacing-nadicode-h-cell-md-tablet: 160px; --spacing-nadicode-h-cell-md-desktop: 168px; --spacing-nadicode-h-cell-lg-mobile: 220px; --spacing-nadicode-h-cell-lg-desktop: 240px; --spacing-nadicode-h-visual-mobile: 276px; --spacing-nadicode-h-visual-tablet: 318px; --spacing-nadicode-h-visual-desktop: 360px; --spacing-nadicode-h-precision-mobile: 276px; --spacing-nadicode-h-precision-tablet: 480px; --spacing-nadicode-h-precision-desktop: 720px; --spacing-nadicode-h-hero-mobile: 560px; --spacing-nadicode-h-hero-desktop: 720px; --spacing-nadicode-h-action-strip-mobile: 20px; --spacing-nadicode-h-action-strip-desktop: 32px; --spacing-nadicode-h-action-body-mobile: 320px; --spacing-nadicode-h-action-body-tablet: 338px; --spacing-nadicode-h-action-band: 260px; --spacing-nadicode-h-feature-mobile: 360px; --spacing-nadicode-h-feature-tablet: 400px; --spacing-nadicode-h-feature-desktop: 456px; --spacing-nadicode-h-editorial-feature-mobile: 360px; --spacing-nadicode-h-editorial-feature-tablet: 440px; --spacing-nadicode-h-editorial-feature-desktop: 560px; --spacing-nadicode-h-bento-primary: 384px; --spacing-nadicode-h-bento-secondary: 240px; --spacing-nadicode-h-bento-mobile-copy: 248px; --spacing-nadicode-h-bento-mobile-main: 537px; --spacing-nadicode-h-bento-strip: 20px; --spacing-nadicode-filter-chip-height: 28px; --spacing-nadicode-filter-chip-icon: 14px; --spacing-control-height: var(--spacing-nadicode-control-height); --spacing-control-padding-inline: var(--spacing-nadicode-control-padding-inline); --spacing-touch-target: var(--spacing-nadicode-touch-target); }
598
599
  }
599
600
 
600
601
  /* src/css/reset.css */
@@ -629,6 +630,10 @@
629
630
  -apple-system,
630
631
  sans-serif;
631
632
  }
633
+ :focus-visible {
634
+ outline: var(--nc-focus-outline-width) solid var(--nc-focus-ring);
635
+ outline-offset: var(--nc-focus-outline-offset);
636
+ }
632
637
  .nc-page {
633
638
  width: 100%;
634
639
  max-width: var(--nc-page-max);
@@ -1592,9 +1597,9 @@
1592
1597
  height: 100%;
1593
1598
  fill: none;
1594
1599
  stroke: currentColor;
1595
- stroke-width: 1.5;
1596
- stroke-linecap: butt;
1597
- stroke-linejoin: miter;
1600
+ stroke-width: var(--nc-icon-stroke);
1601
+ stroke-linecap: round;
1602
+ stroke-linejoin: round;
1598
1603
  }
1599
1604
  .nc-badge-secondary {
1600
1605
  display: inline-flex;
@@ -1626,11 +1631,7 @@
1626
1631
  height: var(--nc-filter-chip-icon);
1627
1632
  flex: none;
1628
1633
  stroke: currentColor;
1629
- stroke-width: 1.5;
1630
- }
1631
- .nc-filter-chip:focus-visible {
1632
- outline: var(--nc-focus-ring-width) solid var(--nc-focus-ring);
1633
- outline-offset: 0;
1634
+ stroke-width: var(--nc-icon-stroke);
1634
1635
  }
1635
1636
  .nc-link-inline {
1636
1637
  color: var(--nc-link);
@@ -1649,8 +1650,6 @@
1649
1650
  }
1650
1651
  }
1651
1652
  .nc-link-inline:focus-visible {
1652
- outline: var(--nc-focus-ring-width) solid var(--nc-focus-ring);
1653
- outline-offset: 0;
1654
1653
  border-radius: var(--nc-rounded-md);
1655
1654
  }
1656
1655
  .nc-label-mono {
@@ -20,7 +20,7 @@
20
20
  "input": "#757575",
21
21
  "seam": "#d4d4d4",
22
22
  "cross": "#999999",
23
- "focus-ring": "#00713d",
23
+ "focus-ring": "#111111",
24
24
  "scrim": "#111111",
25
25
  "link": "#00713d",
26
26
  "link-deep": "#00522c",
@@ -41,9 +41,9 @@
41
41
  "flag-red": "#d3302f",
42
42
  "selection-bg": "#111111",
43
43
  "selection-fg": "#fafafa",
44
- "navigation-selection-bg": "#1e3cff",
45
- "navigation-selection-fg": "#ffffff",
46
- "navigation-selection-hover": "#1735df",
44
+ "navigation-selection-bg": "#ededed",
45
+ "navigation-selection-fg": "#111111",
46
+ "navigation-selection-hover": "#e5e5e5",
47
47
  "state-ready": "#6b6b6b",
48
48
  "state-running": "#1e3cff",
49
49
  "state-review": "#ffc220",
@@ -92,7 +92,7 @@
92
92
  "dark-link": "#4ecf8c",
93
93
  "dark-link-deep": "#93e3b8",
94
94
  "dark-link-bg-soft": "#00351c",
95
- "dark-focus-ring": "#4ecf8c",
95
+ "dark-focus-ring": "#ededed",
96
96
  "dark-scrim": "#ededed",
97
97
  "dark-error": "#f5a3a1",
98
98
  "dark-error-soft": "#380a09",
@@ -116,9 +116,9 @@
116
116
  "dark-state-complete": "#00a85a",
117
117
  "dark-selection-bg": "#ededed",
118
118
  "dark-selection-fg": "#0a0a0a",
119
- "dark-navigation-selection-bg": "#2743d8",
119
+ "dark-navigation-selection-bg": "#1a1a1a",
120
120
  "dark-navigation-selection-fg": "#ededed",
121
- "dark-navigation-selection-hover": "#3552e6",
121
+ "dark-navigation-selection-hover": "#262626",
122
122
  "dark-cross": "#555555",
123
123
  "dark-chart-1": "#4d6bff",
124
124
  "dark-chart-2": "#00a85a",
@@ -366,7 +366,8 @@
366
366
  "section": "192px",
367
367
  "guide": "1px",
368
368
  "icon-stroke": "1.6px",
369
- "focus-ring-width": "3px",
369
+ "focus-outline-width": "2px",
370
+ "focus-outline-offset": "2px",
370
371
  "control-height": "32px",
371
372
  "control-padding-inline": "10px",
372
373
  "touch-target": "44px",
@@ -206,11 +206,11 @@
206
206
  "$value": {
207
207
  "colorSpace": "srgb",
208
208
  "components": [
209
- 0,
210
- 0.443,
211
- 0.239
209
+ 0.067,
210
+ 0.067,
211
+ 0.067
212
212
  ],
213
- "hex": "#00713d"
213
+ "hex": "#111111"
214
214
  }
215
215
  },
216
216
  "scrim": {
@@ -437,33 +437,33 @@
437
437
  "$value": {
438
438
  "colorSpace": "srgb",
439
439
  "components": [
440
- 0.118,
441
- 0.235,
442
- 1
440
+ 0.929,
441
+ 0.929,
442
+ 0.929
443
443
  ],
444
- "hex": "#1e3cff"
444
+ "hex": "#ededed"
445
445
  }
446
446
  },
447
447
  "navigation-selection-fg": {
448
448
  "$value": {
449
449
  "colorSpace": "srgb",
450
450
  "components": [
451
- 1,
452
- 1,
453
- 1
451
+ 0.067,
452
+ 0.067,
453
+ 0.067
454
454
  ],
455
- "hex": "#ffffff"
455
+ "hex": "#111111"
456
456
  }
457
457
  },
458
458
  "navigation-selection-hover": {
459
459
  "$value": {
460
460
  "colorSpace": "srgb",
461
461
  "components": [
462
- 0.09,
463
- 0.208,
464
- 0.875
462
+ 0.898,
463
+ 0.898,
464
+ 0.898
465
465
  ],
466
- "hex": "#1735df"
466
+ "hex": "#e5e5e5"
467
467
  }
468
468
  },
469
469
  "state-ready": {
@@ -998,11 +998,11 @@
998
998
  "$value": {
999
999
  "colorSpace": "srgb",
1000
1000
  "components": [
1001
- 0.306,
1002
- 0.812,
1003
- 0.549
1001
+ 0.929,
1002
+ 0.929,
1003
+ 0.929
1004
1004
  ],
1005
- "hex": "#4ecf8c"
1005
+ "hex": "#ededed"
1006
1006
  }
1007
1007
  },
1008
1008
  "dark-scrim": {
@@ -1262,11 +1262,11 @@
1262
1262
  "$value": {
1263
1263
  "colorSpace": "srgb",
1264
1264
  "components": [
1265
- 0.153,
1266
- 0.263,
1267
- 0.847
1265
+ 0.102,
1266
+ 0.102,
1267
+ 0.102
1268
1268
  ],
1269
- "hex": "#2743d8"
1269
+ "hex": "#1a1a1a"
1270
1270
  }
1271
1271
  },
1272
1272
  "dark-navigation-selection-fg": {
@@ -1284,11 +1284,11 @@
1284
1284
  "$value": {
1285
1285
  "colorSpace": "srgb",
1286
1286
  "components": [
1287
- 0.208,
1288
- 0.322,
1289
- 0.902
1287
+ 0.149,
1288
+ 0.149,
1289
+ 0.149
1290
1290
  ],
1291
- "hex": "#3552e6"
1291
+ "hex": "#262626"
1292
1292
  }
1293
1293
  },
1294
1294
  "dark-cross": {
@@ -1549,9 +1549,15 @@
1549
1549
  "unit": "px"
1550
1550
  }
1551
1551
  },
1552
- "focus-ring-width": {
1552
+ "focus-outline-width": {
1553
1553
  "$value": {
1554
- "value": 3,
1554
+ "value": 2,
1555
+ "unit": "px"
1556
+ }
1557
+ },
1558
+ "focus-outline-offset": {
1559
+ "$value": {
1560
+ "value": 2,
1555
1561
  "unit": "px"
1556
1562
  }
1557
1563
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nadicodeai/design-system",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -162,11 +162,15 @@
162
162
  },
163
163
  "devDependencies": {
164
164
  "@google/design.md": "0.1.1",
165
+ "@nadicodeai/eslint-plugin": "*",
165
166
  "@playwright/test": "^1.57.0",
166
167
  "@types/node": "^22",
167
168
  "esbuild": "^0.28.0",
168
169
  "eslint": "^9.39.4",
169
170
  "lucide-static": "1.21.0",
171
+ "parse5": "^7.3.0",
172
+ "postcss": "^8.5.15",
173
+ "postcss-value-parser": "^4.2.0",
170
174
  "sharp": "^0.34.5",
171
175
  "style-dictionary": "^5.4.3",
172
176
  "tsx": "^4.21.0",