@nadicodeai/design-system 1.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -2
- package/CONTEXT.md +8 -0
- package/DESIGN.md +482 -92
- package/LICENSES/shadow-plugin-MIT.txt +21 -0
- package/README.md +30 -1
- package/dist/css/index.css +128 -69
- package/dist/tailwind/nadicode.tailwind.json +3 -49
- package/dist/tokens/nadicode.dtcg-resolved.json +5092 -0
- package/dist/tokens/nadicode.dtcg.json +4602 -2169
- package/package.json +5 -1
package/DESIGN.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
version: alpha
|
|
3
3
|
name: NadicodeAI Design System
|
|
4
4
|
description: >-
|
|
5
|
-
Reusable design-system contract for NadicodeAI:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
Reusable design-system contract for NadicodeAI: one foundation of colour,
|
|
6
|
+
type, spacing, radius, material, elevation, and motion, applied by three
|
|
7
|
+
registers, the website, the Portal, and the Nadia desktop app, plus the
|
|
8
|
+
package token, CSS, and asset exports they consume.
|
|
9
9
|
|
|
10
10
|
colors:
|
|
11
11
|
primary: "#007a3c"
|
|
@@ -45,6 +45,7 @@ colors:
|
|
|
45
45
|
warning-soft: "#fff3d1"
|
|
46
46
|
warning-deep: "#7a5800"
|
|
47
47
|
flag-red: "#d3302f"
|
|
48
|
+
verde-vivo: "#008c45"
|
|
48
49
|
selection-bg: "#111111"
|
|
49
50
|
selection-fg: "#fafafa"
|
|
50
51
|
navigation-selection-bg: "#ededed"
|
|
@@ -126,6 +127,7 @@ colors:
|
|
|
126
127
|
dark-navigation-selection-fg: "#ededed"
|
|
127
128
|
dark-navigation-selection-hover: "#262626"
|
|
128
129
|
dark-cross: "#555555"
|
|
130
|
+
dark-verde-vivo: "#62d494"
|
|
129
131
|
dark-chart-1: "#4d6bff"
|
|
130
132
|
dark-chart-2: "#00a85a"
|
|
131
133
|
dark-chart-3: "#ffd866"
|
|
@@ -266,7 +268,6 @@ rounded:
|
|
|
266
268
|
|
|
267
269
|
spacing:
|
|
268
270
|
xxs: 4px
|
|
269
|
-
filter-chip-gap: 6px
|
|
270
271
|
xs: 8px
|
|
271
272
|
sm: 12px
|
|
272
273
|
md: 16px
|
|
@@ -277,7 +278,6 @@ spacing:
|
|
|
277
278
|
4xl: 64px
|
|
278
279
|
5xl: 96px
|
|
279
280
|
6xl: 128px
|
|
280
|
-
section: 192px
|
|
281
281
|
guide: 1px
|
|
282
282
|
icon-stroke: 1.6px
|
|
283
283
|
focus-outline-width: 2px
|
|
@@ -285,60 +285,16 @@ spacing:
|
|
|
285
285
|
control-height: 32px
|
|
286
286
|
control-padding-inline: 10px
|
|
287
287
|
touch-target: 44px
|
|
288
|
-
page-pad: 24px
|
|
289
|
-
page-max-mobile: 448px
|
|
290
|
-
page-max-tablet: 624px
|
|
291
|
-
page-max-desktop: 1440px
|
|
292
|
-
frame-max: 1392px
|
|
293
|
-
frame-gap: 24px
|
|
294
|
-
cell-padding: 24px
|
|
295
|
-
section-gap: 48px
|
|
296
|
-
cross-size-mobile: 11px
|
|
297
|
-
cross-size-tablet: 15px
|
|
298
|
-
cross-size-desktop: 21px
|
|
299
|
-
h-strip-mobile: 72px
|
|
300
|
-
h-strip-tablet: 80px
|
|
301
|
-
h-strip-desktop: 88px
|
|
302
|
-
h-cell-sm: 120px
|
|
303
|
-
h-cell-md-mobile: 144px
|
|
304
|
-
h-cell-md-tablet: 160px
|
|
305
|
-
h-cell-md-desktop: 168px
|
|
306
|
-
h-cell-lg-mobile: 220px
|
|
307
|
-
h-cell-lg-desktop: 240px
|
|
308
|
-
h-visual-mobile: 276px
|
|
309
|
-
h-visual-tablet: 318px
|
|
310
|
-
h-visual-desktop: 360px
|
|
311
|
-
h-precision-mobile: 276px
|
|
312
|
-
h-precision-tablet: 480px
|
|
313
|
-
h-precision-desktop: 720px
|
|
314
|
-
h-hero-mobile: 560px
|
|
315
|
-
h-hero-desktop: 720px
|
|
316
|
-
h-action-strip-mobile: 20px
|
|
317
|
-
h-action-strip-desktop: 32px
|
|
318
|
-
h-action-body-mobile: 320px
|
|
319
|
-
h-action-body-tablet: 338px
|
|
320
|
-
h-action-band: 260px
|
|
321
|
-
h-feature-mobile: 360px
|
|
322
|
-
h-feature-tablet: 400px
|
|
323
|
-
h-feature-desktop: 456px
|
|
324
|
-
h-editorial-feature-mobile: 360px
|
|
325
|
-
h-editorial-feature-tablet: 440px
|
|
326
|
-
h-editorial-feature-desktop: 560px
|
|
327
|
-
h-bento-primary: 384px
|
|
328
|
-
h-bento-secondary: 240px
|
|
329
|
-
h-bento-mobile-copy: 248px
|
|
330
|
-
h-bento-mobile-main: 537px
|
|
331
|
-
h-bento-strip: 20px
|
|
332
|
-
filter-chip-height: 28px
|
|
333
|
-
filter-chip-icon: 14px
|
|
334
288
|
|
|
335
289
|
---
|
|
336
290
|
|
|
337
291
|
## Overview
|
|
338
292
|
|
|
339
|
-
NadicodeAI is an AI agency for SMBs. The design system exists to make the public website and
|
|
293
|
+
NadicodeAI is an AI agency for SMBs. The design system exists to make the public website and the shipped product feel engineered, clear, and serious without becoming enterprise software theatre. The interface should help a pragmatic buyer understand the work: repeated workflows, agents trained with people, inspectable outputs, human approval, and one useful first use case.
|
|
340
294
|
|
|
341
|
-
|
|
295
|
+
One foundation, three registers. The foundation is every `core` value in this contract: the colour roles and their dark pairs, the two type families and the type scale, the spacing ladder and the control geometry, the radius scale, the material values, the four-rung elevation ladder, the motion durations and easings, the icon render, and the brand marks. It is owned by no single product and available to every product; a value stays foundation whether one product renders it or three. A register is one product's way of applying it: its direction, its density, the rungs and steps it reaches for, its dark-mode stance, its structural grammar, its motion budget. The three registers are the website, the Portal, and the Nadia desktop app; `## Registers` names each one's rulebook, its own token families, and its dark-mode stance.
|
|
296
|
+
|
|
297
|
+
A register decides where a foundation value appears and adds rules of its own. It never redefines a foundation value and never mints one: a value its physics need and the foundation lacks is authored in this contract under `register.<name>`.
|
|
342
298
|
|
|
343
299
|
The kernel is the reusable implementation layer. `DESIGN.md` defines the reusable contract and exported scalar tokens; the `@nadicodeai/design-system/css` bundle (`src/css/**`) demonstrates and exercises that contract. Homepage copy, page-specific ordering, and temporary prototypes do not belong in this file.
|
|
344
300
|
|
|
@@ -363,6 +319,7 @@ Every value a role needs is carried by the role token itself; the ten-step numer
|
|
|
363
319
|
- **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.
|
|
364
320
|
- **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.
|
|
365
321
|
- **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.
|
|
322
|
+
- **Verde vivo** (`{colors.verde-vivo}` = `#008c45`, dark `{colors.dark-verde-vivo}` = `#62d494`): Nadia's presence accent. It paints the marks that say *Nadia herself is here*: the first-run medallion, a live-presence indicator beside her portrait. It is a mark colour, never a control fill, a text colour, a link, or a status; `action`, `link`, and `success` keep their jobs. It clears the 3:1 non-text floor on `{colors.canvas}` (4.3:1) and `{colors.dark-canvas}` (11.4:1) and carries no text of its own. White on it is 4.34:1, below AA for normal text, so a label never sits on a `verde-vivo` fill; the ring, halo, or portrait sits on it and the words sit on the canvas.
|
|
366
323
|
- **Workflow States** (`{colors.state-ready}` neutral, `{colors.state-running}` cobalto, `{colors.state-review}` giallo, `{colors.state-blocked}` rosso, `{colors.state-complete}` verde): the left-border/state vocabulary for agentic work surfaces — cobalto means in motion, verde means done. The dark counterparts (`{colors.dark-state-ready}`, `{colors.dark-state-running}`, `{colors.dark-state-review}`, `{colors.dark-state-blocked}`, `{colors.dark-state-complete}`) keep the same functional identity. These colours are carried by non-text state accents only — meter and bullet segments, delta marks, and the brand book's own rails; label text stays on the neutral foreground roles for contrast in both themes. Status is not one of their jobs: every status the product renders is the Badge status vocabulary (see `## Status Vocabulary`), which reads from the semantic feedback and link pairs, and the two token sets never cross.
|
|
367
324
|
|
|
368
325
|
### Chart categoricals (functional tier)
|
|
@@ -383,7 +340,7 @@ Four campo rules govern their use:
|
|
|
383
340
|
1. **One campo per room.** A section owns exactly one field; adjacent sections must jump in luminance, so two mid-tone rooms never touch.
|
|
384
341
|
2. **Type on a campo is bianco or inchiostro only.** Arancio and Giallo carry ink; Verde, Rosso, Cobalto, and Inchiostro carry white. No tinted text on fields.
|
|
385
342
|
3. **Campi are planes, not chips.** The minimum duty of a campo is a section ground, poster field, or full media mount. UI states come from the functional roles, never campi.
|
|
386
|
-
4. **One paint box.** Generated editorial imagery draws its flat fields from these values; `
|
|
343
|
+
4. **One paint box.** Generated editorial imagery draws its flat fields from these values; `skills/marketing/blog-imagegen/references/editorial-register.md` references these tokens and keeps no private palette.
|
|
387
344
|
|
|
388
345
|
### Dark primitives
|
|
389
346
|
|
|
@@ -453,15 +410,60 @@ All body, title, caption, and code typography uses `letterSpacing: 0px`. Do not
|
|
|
453
410
|
|
|
454
411
|
## Layout
|
|
455
412
|
|
|
456
|
-
|
|
413
|
+
Layout is mathematical and single-owner in every register: one owner per visible line, every gap and height from the tokens below, never eyeballed.
|
|
414
|
+
|
|
415
|
+
The page grammar this section documents, the 12-column frame with its rows, its centered 10-column active lane, its stage and its markers, is the website register's structure. The Portal and the Nadia desktop app build their own structure by their rulebooks (`## Registers`) and reach for the spacing ladder and the control geometry, not for the frame.
|
|
416
|
+
|
|
417
|
+
### Spacing
|
|
418
|
+
|
|
419
|
+
One ladder carries every gap, pad, and stack step. A register picks the rungs it needs; it never interpolates between them.
|
|
420
|
+
|
|
421
|
+
| Token | Value |
|
|
422
|
+
| --- | --- |
|
|
423
|
+
| `{spacing.xxs}` | 4 px |
|
|
424
|
+
| `{spacing.xs}` | 8 px |
|
|
425
|
+
| `{spacing.sm}` | 12 px |
|
|
426
|
+
| `{spacing.md}` | 16 px |
|
|
427
|
+
| `{spacing.lg}` | 24 px |
|
|
428
|
+
| `{spacing.xl}` | 32 px |
|
|
429
|
+
| `{spacing.2xl}` | 40 px |
|
|
430
|
+
| `{spacing.3xl}` | 48 px |
|
|
431
|
+
| `{spacing.4xl}` | 64 px |
|
|
432
|
+
| `{spacing.5xl}` | 96 px |
|
|
433
|
+
| `{spacing.6xl}` | 128 px |
|
|
434
|
+
|
|
435
|
+
Control geometry is foundation, so a control has the same physical size and the same focus treatment in every register.
|
|
436
|
+
|
|
437
|
+
| Token | Value | Owns |
|
|
438
|
+
| --- | --- | --- |
|
|
439
|
+
| `{spacing.guide}` | 1 px | Every ordinary seam, and the crosshair weight |
|
|
440
|
+
| `{spacing.icon-stroke}` | 1.6 px | The house icon stroke |
|
|
441
|
+
| `{spacing.focus-outline-width}` | 2 px | The one keyboard focus outline |
|
|
442
|
+
| `{spacing.focus-outline-offset}` | 2 px | That outline's offset |
|
|
443
|
+
| `{spacing.control-height}` | 32 px | Minimum height of every default control |
|
|
444
|
+
| `{spacing.control-padding-inline}` | 10 px | Inline padding of a control |
|
|
445
|
+
| `{spacing.touch-target}` | 44 px | Minimum target on coarse or non-hover input |
|
|
446
|
+
|
|
447
|
+
Page-grammar geometry and the fixed component heights belong to the website register and are authored in `register.website.layout`; the filter-chip sizes belong to the Portal register and are authored in `register.portal.density`. Both emit today's `--nc-*` names, and the values live in the one `json design-tokens` fence ("CSS Architecture & Token Pipeline").
|
|
448
|
+
|
|
449
|
+
| Family | Tokens | Register |
|
|
450
|
+
| --- | --- | --- |
|
|
451
|
+
| Band rhythm | `section` | Website |
|
|
452
|
+
| Page shell | `page-pad`, `page-max-mobile`, `page-max-tablet`, `page-max-desktop` | Website |
|
|
453
|
+
| Frame | `frame-max`, `frame-gap`, `cell-padding`, `section-gap` | Website |
|
|
454
|
+
| Crosshair | `cross-size-mobile`, `cross-size-tablet`, `cross-size-desktop` | Website |
|
|
455
|
+
| Cell and strip heights | `h-cell-sm`, `h-cell-md-*`, `h-cell-lg-*`, `h-strip-*` | Website |
|
|
456
|
+
| Media and stage heights | `h-visual-*`, `h-precision-*`, `h-hero-*` | Website |
|
|
457
|
+
| Band and feature heights | `h-action-strip-*`, `h-action-body-*`, `h-action-band`, `h-feature-*`, `h-editorial-feature-*` | Website |
|
|
458
|
+
| Bento heights | `h-bento-primary`, `h-bento-secondary`, `h-bento-mobile-copy`, `h-bento-mobile-main`, `h-bento-strip` | Website |
|
|
459
|
+
| Filter chip | `filter-chip-gap`, `filter-chip-height`, `filter-chip-icon` | Portal |
|
|
457
460
|
|
|
458
461
|
### Frame System
|
|
459
462
|
|
|
460
|
-
-
|
|
461
|
-
- `page-
|
|
462
|
-
- `page-frame` is centered and capped at `{spacing.frame-max}`. It owns the outer left/right/top borders.
|
|
463
|
+
- `page-system` adds `--nc-page-pad` horizontal page padding and `{spacing.4xl}` vertical padding, so the frame floats on clear canvas between the sticky nav chrome and the footer instead of stacking against their hairlines.
|
|
464
|
+
- `page-frame` is centered and capped at `--nc-frame-max`. It owns the outer left/right/top borders.
|
|
463
465
|
- `page-row` is the only direct section unit inside `page-frame`. It owns the bottom border for each row.
|
|
464
|
-
- Desktop rows use 12 equal columns with
|
|
466
|
+
- Desktop rows use 12 equal columns with `--nc-frame-gap` gutters.
|
|
465
467
|
- `active-lane` spans columns 2 through 11 on desktop and all columns on smaller viewports.
|
|
466
468
|
- Full-lane rows span all 12 columns only when the content owns columns 1 and 12 explicitly through the `stage` geometry (`nc-stage-frame`/`nc-stage-fill`/`nc-stage-grid`/`nc-stage-active`).
|
|
467
469
|
- Columns 1 and 12 are the page's quiet margin: empty canvas by default. Their presence is the whitespace itself — the grid sizes them whether or not anything paints there, matching the reference container model where structure lives inside bounded modules and never as page-length gutter texture. The diagonal `side-fill` is a scarce structural accent a row opts into with `data-rails="hatch"`; reserve it for the page's anchor rows (the opening hero, the closing conversion row), never as a default on every row. When present, the fill is bounded on both sides — the frame perimeter outside, the fill's own inner rail inside — so the texture reads as a deliberate panel, not an unbounded wash.
|
|
@@ -488,7 +490,7 @@ Kernel compositions arrange approved primitives for a content role. They must no
|
|
|
488
490
|
|
|
489
491
|
Each reusable concern has one home and one authoring surface, so a member is documented and shipped in exactly one place:
|
|
490
492
|
|
|
491
|
-
- **Tokens** — exact reusable values live in this contract's `colors`, `spacing`, `rounded`, and `typography
|
|
493
|
+
- **Tokens** — exact reusable values live in this contract's `colors`, `spacing`, `rounded`, and `typography` front matter, and in the one `json design-tokens` fence for material, elevation, motion, and the register groups; they export to the generated token layer. No component or section may re-encode a token value.
|
|
492
494
|
- **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.
|
|
493
495
|
- **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.
|
|
494
496
|
- **Layout grammar** — the page-frame, row, lane, seam, stage, and marker system documented across this `## Layout` section, carried by the layout CSS layer.
|
|
@@ -500,7 +502,7 @@ The page grammar below is the `## Layout` home for the structural names; the sec
|
|
|
500
502
|
|
|
501
503
|
Page grammar is the NadicodeAI structural system. It defines how pages are built before any content surface appears. These names live in this layout section, not in the component catalog. Exact reusable values are exported through `colors`, `spacing`, `rounded`, and `typography`; the structural semantics live here as layout doctrine, not as interface components.
|
|
502
504
|
|
|
503
|
-
**`page-frame`** (`nc-page-frame`) — centered bordered frame capped by
|
|
505
|
+
**`page-frame`** (`nc-page-frame`) — centered bordered frame capped by `--nc-frame-max`. Owns the outer left/right/top seams.
|
|
504
506
|
|
|
505
507
|
**`page-row`** (`nc-page-row`) — one continuous section row inside `page-frame`. Owns the bottom seam and default row background.
|
|
506
508
|
|
|
@@ -510,7 +512,7 @@ Page grammar is the NadicodeAI structural system. It defines how pages are built
|
|
|
510
512
|
|
|
511
513
|
**`cell-grid`** (`nc-row-grid`) — repeated cell math. Uses `{colors.line}` parent background and `{spacing.guide}` gaps so the seam has one owner. Supports 2, 3, 4, 5, and 6 column desktop variants with responsive collapse.
|
|
512
514
|
|
|
513
|
-
**`panel-cell`** — a square structural content cell inside `cell-grid`. Uses
|
|
515
|
+
**`panel-cell`** — a square structural content cell inside `cell-grid`. Uses `--nc-cell-padding` and no local border.
|
|
514
516
|
|
|
515
517
|
**`marker`** — sparse crosshair marker for major section/frame corners. It marks intersections; it is not decorative chrome for every card. It is placed on a grid-field track intersection and derives its position from the grid, not from a frame-relative offset.
|
|
516
518
|
|
|
@@ -536,29 +538,20 @@ These live helpers are part of the kept page-grammar layout layer. They support
|
|
|
536
538
|
|
|
537
539
|
## Elevation & Depth
|
|
538
540
|
|
|
539
|
-
|
|
540
|
-
|
|
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.
|
|
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 falloff of the rung, and the four rungs are the four owned utilities: `nc-elevation-resting` for resting content, then `nc-elevation-raised`, `nc-elevation-floating`, and `nc-elevation-modal` when an object is physically raised, floating, or modal. Each rung is authored per mode, light and dark, and carries its own ring as the recipe's final layer, so an elevated root never adds a border, a second ring, a local ring tint, or an opacity override. Product code chooses only the semantic role.
|
|
542
542
|
|
|
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.
|
|
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. Inside the window, glass composites only over our own content; a product whose window the operating system composites states its window material in its register. 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.
|
|
544
544
|
|
|
545
|
-
The Google design schema
|
|
546
|
-
|
|
547
|
-
```css material-tokens
|
|
548
|
-
--nc-material-scrim-opacity: 10%;
|
|
549
|
-
--nc-material-glass-opacity: 76%;
|
|
550
|
-
--nc-material-glass-blur: 28px;
|
|
551
|
-
--nc-material-glass-saturation: 116%;
|
|
552
|
-
```
|
|
545
|
+
The Google design schema defines no opacity, elevation, or motion group. Those values are authored in the one `json design-tokens` fence under "CSS Architecture & Token Pipeline", "Authored token extension". `core.material` holds the four values this section applies and emits them as `--nc-material-*`: `scrim-opacity` becomes the theme layer's `--opacity-scrim`, and the three glass values are consumed by `@nadicodeai/ui/globals.css`. `core.elevation` holds the four rungs and emits `--nc-elevation-resting`, `-raised`, `-floating`, and `-modal`.
|
|
553
546
|
|
|
554
547
|
| Material role | Construction | Use |
|
|
555
548
|
| ------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
556
549
|
| Workspace | `dotted-field` on `{colors.material-workspace}` / `{colors.dark-material-workspace}`; no edge or shadow | The continuous work area behind product objects |
|
|
557
|
-
| Resting | Solid fill;
|
|
558
|
-
| Raised | Same solid fill
|
|
559
|
-
| Floating | Same solid fill
|
|
560
|
-
| Modal | Same solid fill
|
|
561
|
-
| Glass control | Translucent solid fill at 76%, 28 px backdrop blur,
|
|
550
|
+
| Resting | Solid fill; `nc-elevation-resting` with its own ring; `{rounded.3xl}` (16 px) | KPI, card, table, setting, and persistent content surfaces |
|
|
551
|
+
| Raised | Same solid fill; `nc-elevation-raised`; `{rounded.3xl}` (16 px) | Active work, a selected object, or an attached inspector above resting siblings |
|
|
552
|
+
| Floating | Same solid fill; `nc-elevation-floating`; 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) |
|
|
553
|
+
| Modal | Same solid fill; `nc-elevation-modal`; `{rounded.3xl}` (16 px) | Dialog, sheet, drawer, and takeover |
|
|
554
|
+
| Glass control | Translucent solid fill at 76%, 28 px backdrop blur, and the rung for its physical level with that rung's ring | Floating chrome above our own content: menus, popovers, selects, comboboxes, the command palette, and bars; never a content container |
|
|
562
555
|
|
|
563
556
|
`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.
|
|
564
557
|
|
|
@@ -586,6 +579,38 @@ Public page-grammar cells are not cards and remain square because their parent f
|
|
|
586
579
|
|
|
587
580
|
Motion clarifies state, feedback, hierarchy, or continuity; it does not decorate routine work. Repeated interactions stay fast and quiet, while rare explanatory moments may be more expressive. Motion preserves meaning when movement is reduced.
|
|
588
581
|
|
|
582
|
+
The durations and easings live in `core.motion` of the authored token extension ("CSS Architecture & Token Pipeline"); the Google design schema defines no motion group. The build emits every duration as `--nc-duration-*` and every easing as `--nc-ease-*`. `src/css/motion.css` owns the keyframes, the `nc-anim-*` and `nc-transition-*` classes, and the reduced-motion law, and references those names; it declares no duration, easing, or alias of its own. A register decides where motion appears; it never picks a duration outside this list.
|
|
583
|
+
|
|
584
|
+
| Token | Use |
|
|
585
|
+
| --- | --- |
|
|
586
|
+
| `control` | Hover and press on a control in a dense register |
|
|
587
|
+
| `confirm` | Confirmation feedback and instant state flips |
|
|
588
|
+
| `close` / `open` | Floating chrome and overlays leaving and arriving |
|
|
589
|
+
| `transition` | Property transitions on a working surface |
|
|
590
|
+
| `msg-in` | A transcript message arriving |
|
|
591
|
+
| `drawer` / `drawer-swipe` | Sheets and drawers, programmatic and pointer-driven |
|
|
592
|
+
| `stagger` | The step between siblings in one arrival |
|
|
593
|
+
| `spin` | One revolution of a busy spinner |
|
|
594
|
+
| `typing` / `pulse` / `shimmer` | Ambient loops; each has a reduced-motion fallback in `motion.css` |
|
|
595
|
+
|
|
596
|
+
The easings are `emphasized`, `out-strong`, `in-out-strong`, and `drawer`.
|
|
597
|
+
|
|
598
|
+
## Registers
|
|
599
|
+
|
|
600
|
+
One foundation, three products. The foundation is every `core` value in this contract: owned by no single product, available to every product, and foundation whether one product renders it or three. A register is one product's way of applying it: direction, density, the rungs of the ladder it uses and where, the tiers of the type scale it speaks, its dark-mode stance, its structural grammar, its motion budget.
|
|
601
|
+
|
|
602
|
+
A register adds rules. It never redefines a foundation value. A value one register's physics need and the foundation lacks is authored here under `register.<name>`; a register never consumes another register's token; a value two registers share moves to `core`; no product mints a value of its own.
|
|
603
|
+
|
|
604
|
+
| Register | Rulebook | Its own token families | Dark mode |
|
|
605
|
+
| --- | --- | --- | --- |
|
|
606
|
+
| Website | `skills/design/product-design/references/surfaces-website.md` over `## Layout` here | `register.website.layout`: `section`, `page-*`, `frame-*`, `cell-padding`, `section-gap`, `cross-size-*`, every `h-*` height. It speaks `display-xl`, `display-lg`, and `title-lg` | Light only |
|
|
607
|
+
| Portal | `apps/portal/docs/design-doctrine.md` | `register.portal.density`: `filter-chip-gap`, `filter-chip-height`, `filter-chip-icon` | System, light, dark, on the `.dark` class |
|
|
608
|
+
| Nadia desktop app | `skills/design/product-design/references/surfaces-nadia.md` | `register.nadia.*`: the colour-role aliases, the radius aliases, six elevation recipes, and the overlay border; data only, never projected to CSS | Follows the operating system, on the `.dark` class |
|
|
609
|
+
|
|
610
|
+
The website's depth is flat and architectural: hairlines, contrast, dotted fields, diagonal fills, and dark action bands make hierarchy, and the page frame and row grid stay dominant. It uses no rung of the material ladder and no floating card stack as page structure. Marketing bands may use `register.website.layout.section`, emitted as `--nc-section`, when they need the broader inherited hero rhythm. The website kernel uses no negative letter spacing outside the two display tiers.
|
|
611
|
+
|
|
612
|
+
The Portal and the desktop are product shells on the material ladder above, each by its rulebook. The desktop's window material is the operating system's where the OS composites the window; inside the window the foundation's glass law holds.
|
|
613
|
+
|
|
589
614
|
## Components
|
|
590
615
|
|
|
591
616
|
This section is the semantic catalog for framework-agnostic components. Exact reusable values stay in the token maps above; CSS owns component composition. Page grammar and composition semantics live in `## Layout`, while React components and reusable sections live in `@nadicodeai/ui`.
|
|
@@ -608,13 +633,13 @@ Keyboard focus has one owner: the kit's foundation layer draws the full-opacity
|
|
|
608
633
|
|
|
609
634
|
Content surfaces display specific content types inside the grammar. They are valid when the content exists; they do not replace the page frame, row model, or seam rules.
|
|
610
635
|
|
|
611
|
-
**`image`** — editorial media mount, the single home for art-directed imagery inside the grammar. A bounded media fill (img, picture, video, or inline SVG) with an optional mono tag chip overlaid on the media and an optional body-tone caption bar below it, both typed by the generated caption utilities applied in markup. Square-cornered (`{rounded.none}`): a mounted print, not a floating card — the parent frame supplies the visual system. With `data-frame="true"` it draws exactly one hairline (its own `{colors.line}` border), so it sits inside a borderless `panel-cell` or a visual slot without repairing or stacking onto any grid seam. The aspect ratio is the per-instance `--nc-image-ratio` knob (default 4 / 3) — set the prop on the element, never re-derive geometry inline. Variant: `data-strip="true"` is the full-width divider form for thin editorial bands between page rows (thread, texture, panorama) — the ratio unlocks and the height resolves from the responsive
|
|
636
|
+
**`image`** — editorial media mount, the single home for art-directed imagery inside the grammar. A bounded media fill (img, picture, video, or inline SVG) with an optional mono tag chip overlaid on the media and an optional body-tone caption bar below it, both typed by the generated caption utilities applied in markup. Square-cornered (`{rounded.none}`): a mounted print, not a floating card — the parent frame supplies the visual system. With `data-frame="true"` it draws exactly one hairline (its own `{colors.line}` border), so it sits inside a borderless `panel-cell` or a visual slot without repairing or stacking onto any grid seam. The aspect ratio is the per-instance `--nc-image-ratio` knob (default 4 / 3) — set the prop on the element, never re-derive geometry inline. Variant: `data-strip="true"` is the full-width divider form for thin editorial bands between page rows (thread, texture, panorama) — the ratio unlocks and the height resolves from the responsive `--nc-h-strip-*` tokens through the layout-layer collapsed alias. Use `image` for every illustrated image, photographic surface, or image divider. Conversation artifacts render through assistant-ui rather than a design-system CSS family.
|
|
612
637
|
|
|
613
638
|
### Agentic Work Surfaces
|
|
614
639
|
|
|
615
640
|
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.
|
|
616
641
|
|
|
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 [`
|
|
642
|
+
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 [`packages/ui/docs/agent-visual.md`](../ui/docs/agent-visual.md). `@nadicodeai/ui` owns the typed React implementation. Consuming apps assign a recipe explicitly and own placement, data, actions, and accessible meaning.
|
|
618
643
|
|
|
619
644
|
**`artifact-surface`** — inspectable output area outside a conversation. Use for proposal previews, reports, plans, spreadsheets, schedules, run logs, and workflow maps.
|
|
620
645
|
|
|
@@ -682,8 +707,10 @@ whole map in one module and no surface picks a status colour anywhere else.
|
|
|
682
707
|
- Don't stack borders or rings around an elevated surface, promote a resting card because its content is important, or blur modal scrims.
|
|
683
708
|
- Don't tune seam contrast with local opacity, raw colors, or component-specific border colors.
|
|
684
709
|
- Don't use viewport-scaled typography.
|
|
685
|
-
- Don't use negative letter spacing in the website kernel.
|
|
686
710
|
- Don't use gradients, decorative blobs, or atmospheric chrome as the page structure.
|
|
711
|
+
- Don't apply the page grammar or the Portal's glass to the desktop; each register's structure and chrome are its own.
|
|
712
|
+
- Don't put text on a `{colors.verde-vivo}` fill.
|
|
713
|
+
- Don't reach for a vendor shadow utility; the four `nc-elevation-*` rungs are the ladder this contract owns.
|
|
687
714
|
- Don't name NadicodeAI components after external reference brands.
|
|
688
715
|
- Don't promote homepage-specific copy, one-off page order, or prototype-only modules into this contract.
|
|
689
716
|
- Don't use one full-lane stage to present multiple unrelated use cases.
|
|
@@ -692,9 +719,13 @@ whole map in one module and no surface picks a status colour anywhere else.
|
|
|
692
719
|
|
|
693
720
|
## Iconography
|
|
694
721
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
722
|
+
Which icon set a product draws from is a register decision; the render
|
|
723
|
+
discipline below, the sizes, the stroke, and the decorative-versus-named rule,
|
|
724
|
+
is foundation and holds in every register.
|
|
725
|
+
|
|
726
|
+
The website, the Portal, and `@nadicodeai/ui` draw from Lucide (ISC) with the
|
|
727
|
+
NadicodeAI house render: a `{spacing.icon-stroke}` round-cap, round-join
|
|
728
|
+
stroke, no fill, and `currentColor` inheritance.
|
|
698
729
|
The lighter stroke preserves the clarity of the accepted Portal concept while
|
|
699
730
|
round terminals keep Lucide's calm character. The package bakes the complete
|
|
700
731
|
pinned `lucide-static` set through that house render; a surface draws a small,
|
|
@@ -727,17 +758,376 @@ Each delivery tier (see Layout, "Delivery Tiers") has exactly one authoring file
|
|
|
727
758
|
- CSS primitives and components: `primitives.css` plus `components/*`. Every shipped component is named once in `## Components`; the two-way guard derives the CSS relationship from that catalog.
|
|
728
759
|
- Specimens: `examples/`, which only assemble already-defined tiers.
|
|
729
760
|
|
|
761
|
+
### Authored token extension
|
|
762
|
+
|
|
763
|
+
The YAML front matter carries the four groups the Google design schema defines: colors, typography, rounded, spacing. Everything else this contract owns is authored in the one `json design-tokens` fence below, as DTCG 2025.10. It holds `core.material`, `core.elevation` (four rungs per mode, each recipe ending in its own ring), `core.motion.duration` and `core.motion.ease`, and the register groups: `register.website.layout` (the page-grammar geometry), `register.portal.density` (the filter-chip sizes), and `register.nadia` (the desktop's colour and radius aliases onto `core`, plus its own six elevation recipes and overlay border).
|
|
764
|
+
|
|
765
|
+
An alias is written in the short `{core.color.canvas}` form here; the build rewrites it to the public rooted form `{nadicode.core.color.canvas}` in `dist/tokens/nadicode.dtcg.json`. `$extensions."ai.nadicode.targets"` on a register group lists where its values go: `css` puts them in the generated stylesheets, `data` keeps them in the token files only. A register group without that key fails the build. `core` carries no key and always reaches both.
|
|
766
|
+
|
|
767
|
+
```json design-tokens
|
|
768
|
+
{
|
|
769
|
+
"core": {
|
|
770
|
+
"material": {
|
|
771
|
+
"$type": "number",
|
|
772
|
+
"scrim-opacity": {"$value":0.1},
|
|
773
|
+
"glass-opacity": {"$value":0.76},
|
|
774
|
+
"glass-saturation": {"$value":1.16},
|
|
775
|
+
"glass-blur": {"$type":"dimension","$value":{"value":28,"unit":"px"}}
|
|
776
|
+
},
|
|
777
|
+
"elevation": {
|
|
778
|
+
"$type": "shadow",
|
|
779
|
+
"light": {
|
|
780
|
+
"resting": {
|
|
781
|
+
"$value": [
|
|
782
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":17.54,"unit":"px"},"blur":{"value":23.39,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.04}},
|
|
783
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":9.4,"unit":"px"},"blur":{"value":12.5,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.03}},
|
|
784
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":5.25,"unit":"px"},"blur":{"value":7,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.02}},
|
|
785
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":2.79,"unit":"px"},"blur":{"value":3.72,"unit":"px"},"spread":{"value":-2,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.01}},
|
|
786
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":1.16,"unit":"px"},"blur":{"value":1.5,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.01}},
|
|
787
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}}
|
|
788
|
+
]
|
|
789
|
+
},
|
|
790
|
+
"raised": {
|
|
791
|
+
"$value": [
|
|
792
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":25,"unit":"px"},"blur":{"value":50,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
793
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":12,"unit":"px"},"blur":{"value":24,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.04}},
|
|
794
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":6,"unit":"px"},"blur":{"value":12,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.03}},
|
|
795
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":3,"unit":"px"},"blur":{"value":6,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.02}},
|
|
796
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":1.5,"unit":"px"},"blur":{"value":3,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.02}},
|
|
797
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}}
|
|
798
|
+
]
|
|
799
|
+
},
|
|
800
|
+
"floating": {
|
|
801
|
+
"$value": [
|
|
802
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":40,"unit":"px"},"blur":{"value":80,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.06}},
|
|
803
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":20,"unit":"px"},"blur":{"value":40,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
804
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":10,"unit":"px"},"blur":{"value":20,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.04}},
|
|
805
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":5,"unit":"px"},"blur":{"value":10,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.03}},
|
|
806
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":2,"unit":"px"},"blur":{"value":4,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.02}},
|
|
807
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}}
|
|
808
|
+
]
|
|
809
|
+
},
|
|
810
|
+
"modal": {
|
|
811
|
+
"$value": [
|
|
812
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":60,"unit":"px"},"blur":{"value":120,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.07}},
|
|
813
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":30,"unit":"px"},"blur":{"value":60,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.06}},
|
|
814
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":15,"unit":"px"},"blur":{"value":30,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
815
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":7.5,"unit":"px"},"blur":{"value":15,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.04}},
|
|
816
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":3,"unit":"px"},"blur":{"value":6,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.03}},
|
|
817
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}}
|
|
818
|
+
]
|
|
819
|
+
}
|
|
820
|
+
},
|
|
821
|
+
"dark": {
|
|
822
|
+
"resting": {
|
|
823
|
+
"$value": [
|
|
824
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":17.54,"unit":"px"},"blur":{"value":23.39,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.04}},
|
|
825
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":9.4,"unit":"px"},"blur":{"value":12.5,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.03}},
|
|
826
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":5.25,"unit":"px"},"blur":{"value":7,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.02}},
|
|
827
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":2.79,"unit":"px"},"blur":{"value":3.72,"unit":"px"},"spread":{"value":-2,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.01}},
|
|
828
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":1.16,"unit":"px"},"blur":{"value":1.5,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.01}},
|
|
829
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[1,1,1],"alpha":0.18}}
|
|
830
|
+
]
|
|
831
|
+
},
|
|
832
|
+
"raised": {
|
|
833
|
+
"$value": [
|
|
834
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":25,"unit":"px"},"blur":{"value":50,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
835
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":12,"unit":"px"},"blur":{"value":24,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.04}},
|
|
836
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":6,"unit":"px"},"blur":{"value":12,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.03}},
|
|
837
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":3,"unit":"px"},"blur":{"value":6,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.02}},
|
|
838
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":1.5,"unit":"px"},"blur":{"value":3,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.02}},
|
|
839
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[1,1,1],"alpha":0.18}}
|
|
840
|
+
]
|
|
841
|
+
},
|
|
842
|
+
"floating": {
|
|
843
|
+
"$value": [
|
|
844
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":40,"unit":"px"},"blur":{"value":80,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.06}},
|
|
845
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":20,"unit":"px"},"blur":{"value":40,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
846
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":10,"unit":"px"},"blur":{"value":20,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.04}},
|
|
847
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":5,"unit":"px"},"blur":{"value":10,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.03}},
|
|
848
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":2,"unit":"px"},"blur":{"value":4,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.02}},
|
|
849
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[1,1,1],"alpha":0.18}}
|
|
850
|
+
]
|
|
851
|
+
},
|
|
852
|
+
"modal": {
|
|
853
|
+
"$value": [
|
|
854
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":60,"unit":"px"},"blur":{"value":120,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.07}},
|
|
855
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":30,"unit":"px"},"blur":{"value":60,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.06}},
|
|
856
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":15,"unit":"px"},"blur":{"value":30,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
857
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":7.5,"unit":"px"},"blur":{"value":15,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.04}},
|
|
858
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":3,"unit":"px"},"blur":{"value":6,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.03}},
|
|
859
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[1,1,1],"alpha":0.18}}
|
|
860
|
+
]
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
},
|
|
864
|
+
"motion": {
|
|
865
|
+
"duration": {
|
|
866
|
+
"$type": "duration",
|
|
867
|
+
"stagger": {"$value":{"value":60,"unit":"ms"}},
|
|
868
|
+
"control": {"$value":{"value":100,"unit":"ms"}},
|
|
869
|
+
"close": {"$value":{"value":140,"unit":"ms"}},
|
|
870
|
+
"confirm": {"$value":{"value":180,"unit":"ms"}},
|
|
871
|
+
"open": {"$value":{"value":220,"unit":"ms"}},
|
|
872
|
+
"msg-in": {"$value":{"value":240,"unit":"ms"}},
|
|
873
|
+
"transition": {"$value":{"value":240,"unit":"ms"}},
|
|
874
|
+
"drawer-swipe": {"$value":{"value":400,"unit":"ms"}},
|
|
875
|
+
"drawer": {"$value":{"value":450,"unit":"ms"}},
|
|
876
|
+
"spin": {"$value":{"value":600,"unit":"ms"}},
|
|
877
|
+
"typing": {"$value":{"value":1,"unit":"s"}},
|
|
878
|
+
"pulse": {"$value":{"value":1.6,"unit":"s"}},
|
|
879
|
+
"shimmer": {"$value":{"value":2,"unit":"s"}}
|
|
880
|
+
},
|
|
881
|
+
"ease": {
|
|
882
|
+
"$type": "cubicBezier",
|
|
883
|
+
"emphasized": {"$value":[0.3,0.7,0.2,1]},
|
|
884
|
+
"out-strong": {"$value":[0.23,1,0.32,1]},
|
|
885
|
+
"in-out-strong": {"$value":[0.77,0,0.175,1]},
|
|
886
|
+
"drawer": {"$value":[0.32,0.72,0,1]}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
},
|
|
890
|
+
"register": {
|
|
891
|
+
"website": {
|
|
892
|
+
"$extensions": {"ai.nadicode.targets":["css","data"]},
|
|
893
|
+
"layout": {
|
|
894
|
+
"$type": "dimension",
|
|
895
|
+
"section": {"$value":{"value":192,"unit":"px"}},
|
|
896
|
+
"page-pad": {"$value":{"value":24,"unit":"px"}},
|
|
897
|
+
"page-max-mobile": {"$value":{"value":448,"unit":"px"}},
|
|
898
|
+
"page-max-tablet": {"$value":{"value":624,"unit":"px"}},
|
|
899
|
+
"page-max-desktop": {"$value":{"value":1440,"unit":"px"}},
|
|
900
|
+
"frame-max": {"$value":{"value":1392,"unit":"px"}},
|
|
901
|
+
"frame-gap": {"$value":{"value":24,"unit":"px"}},
|
|
902
|
+
"cell-padding": {"$value":{"value":24,"unit":"px"}},
|
|
903
|
+
"section-gap": {"$value":{"value":48,"unit":"px"}},
|
|
904
|
+
"cross-size-mobile": {"$value":{"value":11,"unit":"px"}},
|
|
905
|
+
"cross-size-tablet": {"$value":{"value":15,"unit":"px"}},
|
|
906
|
+
"cross-size-desktop": {"$value":{"value":21,"unit":"px"}},
|
|
907
|
+
"h-strip-mobile": {"$value":{"value":72,"unit":"px"}},
|
|
908
|
+
"h-strip-tablet": {"$value":{"value":80,"unit":"px"}},
|
|
909
|
+
"h-strip-desktop": {"$value":{"value":88,"unit":"px"}},
|
|
910
|
+
"h-cell-sm": {"$value":{"value":120,"unit":"px"}},
|
|
911
|
+
"h-cell-md-mobile": {"$value":{"value":144,"unit":"px"}},
|
|
912
|
+
"h-cell-md-tablet": {"$value":{"value":160,"unit":"px"}},
|
|
913
|
+
"h-cell-md-desktop": {"$value":{"value":168,"unit":"px"}},
|
|
914
|
+
"h-cell-lg-mobile": {"$value":{"value":220,"unit":"px"}},
|
|
915
|
+
"h-cell-lg-desktop": {"$value":{"value":240,"unit":"px"}},
|
|
916
|
+
"h-visual-mobile": {"$value":{"value":276,"unit":"px"}},
|
|
917
|
+
"h-visual-tablet": {"$value":{"value":318,"unit":"px"}},
|
|
918
|
+
"h-visual-desktop": {"$value":{"value":360,"unit":"px"}},
|
|
919
|
+
"h-precision-mobile": {"$value":{"value":276,"unit":"px"}},
|
|
920
|
+
"h-precision-tablet": {"$value":{"value":480,"unit":"px"}},
|
|
921
|
+
"h-precision-desktop": {"$value":{"value":720,"unit":"px"}},
|
|
922
|
+
"h-hero-mobile": {"$value":{"value":560,"unit":"px"}},
|
|
923
|
+
"h-hero-desktop": {"$value":{"value":720,"unit":"px"}},
|
|
924
|
+
"h-action-strip-mobile": {"$value":{"value":20,"unit":"px"}},
|
|
925
|
+
"h-action-strip-desktop": {"$value":{"value":32,"unit":"px"}},
|
|
926
|
+
"h-action-body-mobile": {"$value":{"value":320,"unit":"px"}},
|
|
927
|
+
"h-action-body-tablet": {"$value":{"value":338,"unit":"px"}},
|
|
928
|
+
"h-action-band": {"$value":{"value":260,"unit":"px"}},
|
|
929
|
+
"h-feature-mobile": {"$value":{"value":360,"unit":"px"}},
|
|
930
|
+
"h-feature-tablet": {"$value":{"value":400,"unit":"px"}},
|
|
931
|
+
"h-feature-desktop": {"$value":{"value":456,"unit":"px"}},
|
|
932
|
+
"h-editorial-feature-mobile": {"$value":{"value":360,"unit":"px"}},
|
|
933
|
+
"h-editorial-feature-tablet": {"$value":{"value":440,"unit":"px"}},
|
|
934
|
+
"h-editorial-feature-desktop": {"$value":{"value":560,"unit":"px"}},
|
|
935
|
+
"h-bento-primary": {"$value":{"value":384,"unit":"px"}},
|
|
936
|
+
"h-bento-secondary": {"$value":{"value":240,"unit":"px"}},
|
|
937
|
+
"h-bento-mobile-copy": {"$value":{"value":248,"unit":"px"}},
|
|
938
|
+
"h-bento-mobile-main": {"$value":{"value":537,"unit":"px"}},
|
|
939
|
+
"h-bento-strip": {"$value":{"value":20,"unit":"px"}}
|
|
940
|
+
}
|
|
941
|
+
},
|
|
942
|
+
"portal": {
|
|
943
|
+
"$extensions": {"ai.nadicode.targets":["css","data"]},
|
|
944
|
+
"density": {
|
|
945
|
+
"$type": "dimension",
|
|
946
|
+
"filter-chip-gap": {"$value":{"value":6,"unit":"px"}},
|
|
947
|
+
"filter-chip-height": {"$value":{"value":28,"unit":"px"}},
|
|
948
|
+
"filter-chip-icon": {"$value":{"value":14,"unit":"px"}}
|
|
949
|
+
}
|
|
950
|
+
},
|
|
951
|
+
"nadia": {
|
|
952
|
+
"$extensions": {"ai.nadicode.targets":["data"]},
|
|
953
|
+
"color": {
|
|
954
|
+
"light": {
|
|
955
|
+
"$type": "color",
|
|
956
|
+
"background": {"$value":"{core.color.canvas}"},
|
|
957
|
+
"foreground": {"$value":"{core.color.ink}"},
|
|
958
|
+
"card": {"$value":"{core.color.canvas}"},
|
|
959
|
+
"card-foreground": {"$value":"{core.color.ink}"},
|
|
960
|
+
"muted": {"$value":"{core.color.canvas-soft-2}"},
|
|
961
|
+
"muted-foreground": {"$value":"{core.color.body}"},
|
|
962
|
+
"popover": {"$value":"{core.color.canvas}"},
|
|
963
|
+
"popover-foreground": {"$value":"{core.color.ink}"},
|
|
964
|
+
"primary": {"$value":"{core.color.primary}"},
|
|
965
|
+
"primary-foreground": {"$value":"{core.color.on-primary}"},
|
|
966
|
+
"secondary": {"$value":"{core.color.canvas-soft}"},
|
|
967
|
+
"secondary-foreground": {"$value":"{core.color.ink}"},
|
|
968
|
+
"accent": {"$value":"{core.color.canvas-soft-2}"},
|
|
969
|
+
"accent-foreground": {"$value":"{core.color.ink}"},
|
|
970
|
+
"border": {"$value":"{core.color.line}"},
|
|
971
|
+
"input": {"$value":"{core.color.seam}"},
|
|
972
|
+
"ring": {"$value":"{core.color.primary}"},
|
|
973
|
+
"midground": {"$value":"{core.color.body}"},
|
|
974
|
+
"composer-ring": {"$value":"{core.color.primary}"},
|
|
975
|
+
"destructive": {"$value":"{core.color.error}"},
|
|
976
|
+
"destructive-foreground": {"$value":"{core.color.on-primary}"},
|
|
977
|
+
"sidebar-background": {"$value":"{core.color.canvas-soft}"},
|
|
978
|
+
"sidebar-border": {"$value":"{core.color.line}"},
|
|
979
|
+
"user-bubble": {"$value":"{core.color.link-bg-soft}"},
|
|
980
|
+
"user-bubble-border": {"$value":"{core.color.link}"},
|
|
981
|
+
"medallion": {"$value":"{core.color.verde-vivo}"}
|
|
982
|
+
},
|
|
983
|
+
"dark": {
|
|
984
|
+
"$type": "color",
|
|
985
|
+
"background": {"$value":"{core.color.dark-canvas}"},
|
|
986
|
+
"foreground": {"$value":"{core.color.dark-ink}"},
|
|
987
|
+
"card": {"$value":"{core.color.dark-canvas}"},
|
|
988
|
+
"card-foreground": {"$value":"{core.color.dark-ink}"},
|
|
989
|
+
"muted": {"$value":"{core.color.dark-canvas-soft-2}"},
|
|
990
|
+
"muted-foreground": {"$value":"{core.color.dark-muted}"},
|
|
991
|
+
"popover": {"$value":"{core.color.dark-canvas}"},
|
|
992
|
+
"popover-foreground": {"$value":"{core.color.dark-ink}"},
|
|
993
|
+
"primary": {"$value":"{core.color.dark-primary}"},
|
|
994
|
+
"primary-foreground": {"$value":"{core.color.dark-on-primary}"},
|
|
995
|
+
"secondary": {"$value":"{core.color.dark-canvas-soft-2}"},
|
|
996
|
+
"secondary-foreground": {"$value":"{core.color.dark-body}"},
|
|
997
|
+
"accent": {"$value":"{core.color.dark-canvas-soft-2}"},
|
|
998
|
+
"accent-foreground": {"$value":"{core.color.dark-ink}"},
|
|
999
|
+
"border": {"$value":"{core.color.dark-line}"},
|
|
1000
|
+
"input": {"$value":"{core.color.dark-input}"},
|
|
1001
|
+
"ring": {"$value":"{core.color.dark-primary}"},
|
|
1002
|
+
"midground": {"$value":"{core.color.dark-muted}"},
|
|
1003
|
+
"composer-ring": {"$value":"{core.color.dark-success}"},
|
|
1004
|
+
"destructive": {"$value":"{core.color.flag-red}"},
|
|
1005
|
+
"destructive-foreground": {"$value":"{core.color.on-primary}"},
|
|
1006
|
+
"sidebar-background": {"$value":"{core.color.dark-canvas}"},
|
|
1007
|
+
"sidebar-border": {"$value":"{core.color.dark-seam}"},
|
|
1008
|
+
"user-bubble": {"$value":"{core.color.dark-link-bg-soft}"},
|
|
1009
|
+
"user-bubble-border": {"$value":"{core.color.dark-link}"},
|
|
1010
|
+
"medallion": {"$value":"{core.color.dark-verde-vivo}"}
|
|
1011
|
+
}
|
|
1012
|
+
},
|
|
1013
|
+
"radius": {
|
|
1014
|
+
"$type": "dimension",
|
|
1015
|
+
"xs": {"$value":"{core.rounded.xs}"},
|
|
1016
|
+
"sm": {"$value":"{core.rounded.sm}"},
|
|
1017
|
+
"md": {"$value":"{core.rounded.md}"},
|
|
1018
|
+
"lg": {"$value":"{core.rounded.lg}"},
|
|
1019
|
+
"xl": {"$value":"{core.rounded.xl}"},
|
|
1020
|
+
"2xl": {"$value":"{core.rounded.2xl}"},
|
|
1021
|
+
"3xl": {"$value":"{core.rounded.3xl}"},
|
|
1022
|
+
"4xl": {"$value":"{core.rounded.3xl}"}
|
|
1023
|
+
},
|
|
1024
|
+
"elevation": {
|
|
1025
|
+
"light": {
|
|
1026
|
+
"$type": "shadow",
|
|
1027
|
+
"control": {
|
|
1028
|
+
"$value": [
|
|
1029
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
1030
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":1,"unit":"px"},"blur":{"value":2,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.04}}
|
|
1031
|
+
]
|
|
1032
|
+
},
|
|
1033
|
+
"panel": {
|
|
1034
|
+
"$value": [
|
|
1035
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
1036
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":1,"unit":"px"},"blur":{"value":3,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}}
|
|
1037
|
+
]
|
|
1038
|
+
},
|
|
1039
|
+
"raised": {
|
|
1040
|
+
"$value": [
|
|
1041
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
1042
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":4,"unit":"px"},"blur":{"value":10,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.07}},
|
|
1043
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":10,"unit":"px"},"blur":{"value":22,"unit":"px"},"spread":{"value":-14,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.16}}
|
|
1044
|
+
]
|
|
1045
|
+
},
|
|
1046
|
+
"overlay": {
|
|
1047
|
+
"$value": [
|
|
1048
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":8,"unit":"px"},"blur":{"value":18,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.09}},
|
|
1049
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":20,"unit":"px"},"blur":{"value":36,"unit":"px"},"spread":{"value":-20,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.22}}
|
|
1050
|
+
]
|
|
1051
|
+
},
|
|
1052
|
+
"modal": {
|
|
1053
|
+
"$value": [
|
|
1054
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}},
|
|
1055
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":14,"unit":"px"},"blur":{"value":30,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.13}},
|
|
1056
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":32,"unit":"px"},"blur":{"value":60,"unit":"px"},"spread":{"value":-24,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.3}}
|
|
1057
|
+
]
|
|
1058
|
+
},
|
|
1059
|
+
"composer": {
|
|
1060
|
+
"$value": [
|
|
1061
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":1,"unit":"px"},"blur":{"value":2,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}}
|
|
1062
|
+
]
|
|
1063
|
+
},
|
|
1064
|
+
"overlay-border": {
|
|
1065
|
+
"$type": "border",
|
|
1066
|
+
"$value": {"width":{"value":1,"unit":"px"},"style":"solid","color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.05}}
|
|
1067
|
+
}
|
|
1068
|
+
},
|
|
1069
|
+
"dark": {
|
|
1070
|
+
"$type": "shadow",
|
|
1071
|
+
"control": {
|
|
1072
|
+
"$value": [
|
|
1073
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[1,1,1],"alpha":0.18}},
|
|
1074
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":1,"unit":"px"},"blur":{"value":2,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.5}}
|
|
1075
|
+
]
|
|
1076
|
+
},
|
|
1077
|
+
"panel": {
|
|
1078
|
+
"$value": [
|
|
1079
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[1,1,1],"alpha":0.18}},
|
|
1080
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":2,"unit":"px"},"blur":{"value":6,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.6}}
|
|
1081
|
+
]
|
|
1082
|
+
},
|
|
1083
|
+
"raised": {
|
|
1084
|
+
"$value": [
|
|
1085
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[1,1,1],"alpha":0.18}},
|
|
1086
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":6,"unit":"px"},"blur":{"value":16,"unit":"px"},"spread":{"value":-10,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.85}}
|
|
1087
|
+
]
|
|
1088
|
+
},
|
|
1089
|
+
"overlay": {
|
|
1090
|
+
"$value": [
|
|
1091
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":12,"unit":"px"},"blur":{"value":26,"unit":"px"},"spread":{"value":-12,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.9}}
|
|
1092
|
+
]
|
|
1093
|
+
},
|
|
1094
|
+
"modal": {
|
|
1095
|
+
"$value": [
|
|
1096
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":0,"unit":"px"},"blur":{"value":0,"unit":"px"},"spread":{"value":1,"unit":"px"},"color":{"colorSpace":"srgb","components":[1,1,1],"alpha":0.18}},
|
|
1097
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":16,"unit":"px"},"blur":{"value":32,"unit":"px"},"spread":{"value":-14,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.95}}
|
|
1098
|
+
]
|
|
1099
|
+
},
|
|
1100
|
+
"composer": {
|
|
1101
|
+
"$value": [
|
|
1102
|
+
{"offsetX":{"value":0,"unit":"px"},"offsetY":{"value":1,"unit":"px"},"blur":{"value":2,"unit":"px"},"spread":{"value":0,"unit":"px"},"color":{"colorSpace":"srgb","components":[0,0,0],"alpha":0.5}}
|
|
1103
|
+
]
|
|
1104
|
+
},
|
|
1105
|
+
"overlay-border": {
|
|
1106
|
+
"$type": "border",
|
|
1107
|
+
"$value": {"width":{"value":1,"unit":"px"},"style":"solid","color":{"colorSpace":"srgb","components":[1,1,1],"alpha":0.18}}
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
```
|
|
1115
|
+
|
|
730
1116
|
### Generated outputs
|
|
731
1117
|
|
|
732
|
-
|
|
1118
|
+
`scripts/build.ts` runs the pipeline once. The `@google/design.md` CLI exports the YAML front matter, `scripts/sd/design-tokens-fence.ts` reads the one `json design-tokens` fence, and `scripts/sd/compose-token-graph.ts` composes the two into the single `nadicode` graph. That composer is the only code that creates the root: it merges without collision, rewrites every short alias to its rooted public form, and checks ownership and reference direction (`core` reaches outside nothing, a register reaches `core` and itself, never another register).
|
|
1119
|
+
|
|
1120
|
+
The composer returns three views of one validated object. The canonical graph keeps every alias and every `$extensions` entry and ships as `dist/tokens/nadicode.dtcg.json` (`@nadicodeai/design-system/tokens/dtcg`), the public contract a conformance tool or a theme generator reads. The resolved graph replaces each alias with its value and ships as `dist/tokens/nadicode.dtcg-resolved.json` (`./tokens/dtcg-resolved`), for data-only consumers that want literals. Both are validated against the vendored DTCG 2025.10 schema (`scripts/sd/schemas/`) before they are written. The third view is the CSS projection: the leaves of every group whose `ai.nadicode.targets` includes `css`, which is `core` plus `register.website` and `register.portal`; `register.nadia` is data only and reaches no stylesheet.
|
|
1121
|
+
|
|
1122
|
+
Style Dictionary (`scripts/sd/`) is the exporter over that projection, not the validator. It emits three CSS files:
|
|
733
1123
|
|
|
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: `
|
|
1124
|
+
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: `core.color` and `core.spacing` emit `--nc-<name>`, as do `register.website.layout` and `register.portal.density`, so a moved token keeps the name it had; `core.rounded` emits `--nc-rounded-<name>`; `core.material` emits `--nc-material-<name>`; `core.elevation.light.<role>` emits `--nc-elevation-<role>` in `:root` and `core.elevation.dark.<role>` the same name inside `.dark`; `core.motion.duration` emits `--nc-duration-<name>` and `core.motion.ease` emits `--nc-ease-<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, durations emit as authored, easings as `cubic-bezier()`, elevation recipes as the complete multi-layer `box-shadow` for their mode, and the material ratios as the percentages their callers read. Emitted-but-unreferenced contract tokens remain part of the package vocabulary; private compatibility variables with no caller do not.
|
|
735
1125
|
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.
|
|
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.
|
|
1126
|
+
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 projection fills `--ease-nc-<name>` for every easing; it fills no `--shadow-*` entry, because the four elevation rungs reach React only through the owned `nc-elevation-*` utilities, one spelling per rung; Tailwind v4 owns no duration namespace, so a call site writes `duration-(--nc-duration-open)`. 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.
|
|
737
1127
|
|
|
738
1128
|
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.
|
|
739
1129
|
|
|
740
|
-
`npm run build` also
|
|
1130
|
+
`npm run build` also writes the two DTCG artifacts above and `dist/tailwind/nadicode.tailwind.json` as generated, tracked data artifacts, and bakes `dist/icons/` from the pinned `lucide-static` dependency. The Tailwind export stays for what it uniquely supplies: the typography line-height with its declared unit, which the DTCG composite normaliser strips, and the logo paint lookup.
|
|
741
1131
|
|
|
742
1132
|
#### Brand media authority
|
|
743
1133
|
|
|
@@ -749,7 +1139,7 @@ The NadicodeAI logo has three approved forms:
|
|
|
749
1139
|
|
|
750
1140
|
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.
|
|
751
1141
|
|
|
752
|
-
Nadia's portrait, Agent identity visuals, and generated imagery are not NadicodeAI company logos. Nadia's identity and selection rules live in [`brand/
|
|
1142
|
+
Nadia's portrait, Agent identity visuals, and generated imagery are not NadicodeAI company logos. Nadia's identity and selection rules live in [`brand/AGENTS.md`](../../brand/AGENTS.md); the Agent identity system lives in [`packages/ui/docs/agent-visual.md`](../ui/docs/agent-visual.md); editorial imagery routes through [`skills/marketing/blog-imagegen/references/editorial-register.md`](../../skills/marketing/blog-imagegen/references/editorial-register.md). This contract owns only the package delivery interface.
|
|
753
1143
|
|
|
754
1144
|
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.
|
|
755
1145
|
|
|
@@ -767,4 +1157,4 @@ The package build renders and publicly exports full-colour, mono-ink, inverse, a
|
|
|
767
1157
|
|
|
768
1158
|
### Enforcement
|
|
769
1159
|
|
|
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.
|
|
1160
|
+
Correctness is structural, not a byte snapshot: `scripts/sd/design-tokens-fence.test.ts` verifies the fence reader, one fence, strict JSON, typed leaves, legal names; `scripts/sd/compose-token-graph.test.ts` verifies the composition, one construction of the root, alias rewriting, ownership and reference direction, extension preservation, and the CSS projection; `tests/guards/dtcg-shape.test.ts` verifies both published artifacts against the vendored DTCG schema and the Nadicode profile; `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.
|