@nadicodeai/design-system 9.2.1 → 10.0.1
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 +1 -1
- package/DESIGN.md +153 -298
- package/GLOSSARY.md +4 -4
- package/README.md +32 -27
- package/dist/assets/app-icon.png +0 -0
- package/dist/assets/app-icon.svg +1 -0
- package/dist/assets/logo-one-ink-white.png +0 -0
- package/dist/assets/logo-one-ink-white.svg +1 -0
- package/dist/assets/logo-one-ink.png +0 -0
- package/dist/assets/logo-one-ink.svg +1 -0
- package/dist/assets/logo-white.png +0 -0
- package/dist/assets/logo-white.svg +1 -0
- package/dist/assets/logo.png +0 -0
- package/dist/assets/logo.svg +1 -0
- package/dist/assets/mark-white.png +0 -0
- package/dist/assets/mark-white.svg +1 -0
- package/dist/assets/mark.png +0 -0
- package/dist/assets/mark.svg +1 -0
- package/dist/css/host.css +45 -150
- package/dist/css/index.css +112 -922
- package/dist/css/tokens.css +44 -149
- package/dist/favicon/apple-touch-icon.png +0 -0
- package/dist/favicon/favicon.ico +0 -0
- package/dist/favicon/favicon.svg +1 -7
- package/dist/favicon/icon-192.png +0 -0
- package/dist/favicon/icon-512.png +0 -0
- package/dist/favicon/site.webmanifest +4 -4
- package/dist/icons/agent.svg +1 -1
- package/dist/icons/approvals.svg +1 -1
- package/dist/icons/arch.svg +1 -1
- package/dist/tailwind/nadicode.tailwind.json +23 -91
- package/dist/tokens/nadicode.dtcg-resolved.json +56 -426
- package/dist/tokens/nadicode.dtcg.json +56 -426
- package/package.json +43 -83
- package/src/assets/logo-geometry.d.ts +10 -7
- package/src/assets/logo-geometry.js +119 -172
- package/dist/assets/logo-lockup-inverse.png +0 -0
- package/dist/assets/logo-lockup-inverse.svg +0 -4
- package/dist/assets/logo-lockup-mono.png +0 -0
- package/dist/assets/logo-lockup-mono.svg +0 -4
- package/dist/assets/logo-lockup-on-verde.png +0 -0
- package/dist/assets/logo-lockup-on-verde.svg +0 -4
- package/dist/assets/logo-lockup.png +0 -0
- package/dist/assets/logo-lockup.svg +0 -4
- package/dist/assets/logo-mark-inverse.png +0 -0
- package/dist/assets/logo-mark-inverse.svg +0 -6
- package/dist/assets/logo-mark-mono.png +0 -0
- package/dist/assets/logo-mark-mono.svg +0 -6
- package/dist/assets/logo-mark-on-verde.png +0 -0
- package/dist/assets/logo-mark-on-verde.svg +0 -6
- package/dist/assets/logo-mark.png +0 -0
- package/dist/assets/logo-mark.svg +0 -6
- package/dist/assets/logo-wordmark-inverse.png +0 -0
- package/dist/assets/logo-wordmark-inverse.svg +0 -4
- package/dist/assets/logo-wordmark-mono.png +0 -0
- package/dist/assets/logo-wordmark-mono.svg +0 -4
- package/dist/assets/logo-wordmark-on-verde.png +0 -0
- package/dist/assets/logo-wordmark-on-verde.svg +0 -4
- package/dist/assets/logo-wordmark.png +0 -0
- package/dist/assets/logo-wordmark.svg +0 -4
- package/src/assets/logo-mark.d.ts +0 -2
- package/src/assets/logo-wordmark.d.ts +0 -2
- /package/src/assets/{logo-lockup.d.ts → logo-asset.d.ts} +0 -0
package/DESIGN.md
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
version: alpha
|
|
3
|
-
name:
|
|
3
|
+
name: nadicode Design System
|
|
4
4
|
description: >-
|
|
5
|
-
Reusable design-system contract for
|
|
5
|
+
Reusable design-system contract for nadicode: one foundation of colour,
|
|
6
6
|
type, spacing, radius, material, elevation, and motion, applied by three
|
|
7
7
|
registers, the website, the Portal, and the Nadia desktop app, plus the
|
|
8
8
|
package token, CSS, and asset exports they consume.
|
|
9
9
|
|
|
10
10
|
colors:
|
|
11
|
-
primary: "#007a3c"
|
|
12
11
|
on-primary: "#ffffff"
|
|
13
12
|
action: "#111111"
|
|
14
13
|
action-foreground: "#ffffff"
|
|
@@ -44,7 +43,6 @@ colors:
|
|
|
44
43
|
warning: "#ffc220"
|
|
45
44
|
warning-soft: "#fff3d1"
|
|
46
45
|
warning-deep: "#7a5800"
|
|
47
|
-
verde-vivo: "#008c45"
|
|
48
46
|
selection-bg: "#111111"
|
|
49
47
|
selection-fg: "#fafafa"
|
|
50
48
|
navigation-selection-bg: "#ededed"
|
|
@@ -63,6 +61,7 @@ colors:
|
|
|
63
61
|
identity-azzurro: "#0f6ee8"
|
|
64
62
|
identity-ink: "#000000"
|
|
65
63
|
identity-white: "#ffffff"
|
|
64
|
+
logo-dot: "#1e3cff"
|
|
66
65
|
chart-1: "#1e3cff"
|
|
67
66
|
chart-2: "#00a85a"
|
|
68
67
|
chart-3: "#ddaa00"
|
|
@@ -88,7 +87,6 @@ colors:
|
|
|
88
87
|
dark-line: "#262626"
|
|
89
88
|
dark-input: "#696969"
|
|
90
89
|
dark-seam: "#1a1a1a"
|
|
91
|
-
dark-primary: "#2fd584"
|
|
92
90
|
dark-on-primary: "#0a0a0a"
|
|
93
91
|
dark-action: "#ffffff"
|
|
94
92
|
dark-action-foreground: "#0a0a0a"
|
|
@@ -116,13 +114,13 @@ colors:
|
|
|
116
114
|
dark-state-review: "#ffc220"
|
|
117
115
|
dark-state-blocked: "#d3302f"
|
|
118
116
|
dark-state-complete: "#00a85a"
|
|
117
|
+
dark-logo-dot: "#4d6bff"
|
|
119
118
|
dark-selection-bg: "#ededed"
|
|
120
119
|
dark-selection-fg: "#0a0a0a"
|
|
121
120
|
dark-navigation-selection-bg: "#1a1a1a"
|
|
122
121
|
dark-navigation-selection-fg: "#ededed"
|
|
123
122
|
dark-navigation-selection-hover: "#262626"
|
|
124
123
|
dark-cross: "#555555"
|
|
125
|
-
dark-verde-vivo: "#62d494"
|
|
126
124
|
dark-chart-1: "#4d6bff"
|
|
127
125
|
dark-chart-2: "#00a85a"
|
|
128
126
|
dark-chart-3: "#ffd866"
|
|
@@ -144,42 +142,36 @@ typography:
|
|
|
144
142
|
fontSize: 72px
|
|
145
143
|
fontWeight: 600
|
|
146
144
|
lineHeight: 74px
|
|
147
|
-
letterSpacing: -
|
|
145
|
+
letterSpacing: -2.52px
|
|
148
146
|
display-lg:
|
|
149
147
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
150
148
|
fontSize: 52px
|
|
151
149
|
fontWeight: 600
|
|
152
150
|
lineHeight: 54px
|
|
153
|
-
letterSpacing: -
|
|
151
|
+
letterSpacing: -1.5px
|
|
154
152
|
display-md:
|
|
155
153
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
156
|
-
fontSize:
|
|
157
|
-
fontWeight: 600
|
|
158
|
-
lineHeight: 32px
|
|
159
|
-
letterSpacing: 0px
|
|
160
|
-
display-sm:
|
|
161
|
-
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
162
|
-
fontSize: 20px
|
|
154
|
+
fontSize: 40px
|
|
163
155
|
fontWeight: 600
|
|
164
|
-
lineHeight:
|
|
165
|
-
letterSpacing:
|
|
166
|
-
|
|
156
|
+
lineHeight: 42px
|
|
157
|
+
letterSpacing: -1px
|
|
158
|
+
heading-lg:
|
|
167
159
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
168
|
-
fontSize:
|
|
160
|
+
fontSize: 30px
|
|
169
161
|
fontWeight: 600
|
|
170
|
-
lineHeight:
|
|
162
|
+
lineHeight: 32px
|
|
171
163
|
letterSpacing: 0px
|
|
172
|
-
|
|
164
|
+
heading-md:
|
|
173
165
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
174
|
-
fontSize:
|
|
166
|
+
fontSize: 24px
|
|
175
167
|
fontWeight: 600
|
|
176
168
|
lineHeight: 32px
|
|
177
169
|
letterSpacing: 0px
|
|
178
|
-
|
|
170
|
+
heading-sm:
|
|
179
171
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
180
|
-
fontSize:
|
|
172
|
+
fontSize: 20px
|
|
181
173
|
fontWeight: 600
|
|
182
|
-
lineHeight:
|
|
174
|
+
lineHeight: 28px
|
|
183
175
|
letterSpacing: 0px
|
|
184
176
|
body-lg:
|
|
185
177
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
@@ -193,59 +185,29 @@ typography:
|
|
|
193
185
|
fontWeight: 400
|
|
194
186
|
lineHeight: 25px
|
|
195
187
|
letterSpacing: 0px
|
|
196
|
-
body-md-strong:
|
|
197
|
-
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
198
|
-
fontSize: 16px
|
|
199
|
-
fontWeight: 500
|
|
200
|
-
lineHeight: 24px
|
|
201
|
-
letterSpacing: 0px
|
|
202
188
|
body-sm:
|
|
203
189
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
204
190
|
fontSize: 14px
|
|
205
191
|
fontWeight: 400
|
|
206
192
|
lineHeight: 20px
|
|
207
193
|
letterSpacing: 0px
|
|
208
|
-
body-sm-strong:
|
|
209
|
-
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
210
|
-
fontSize: 14px
|
|
211
|
-
fontWeight: 500
|
|
212
|
-
lineHeight: 20px
|
|
213
|
-
letterSpacing: 0px
|
|
214
194
|
caption:
|
|
215
195
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
216
196
|
fontSize: 12px
|
|
217
197
|
fontWeight: 400
|
|
218
198
|
lineHeight: 16px
|
|
219
199
|
letterSpacing: 0px
|
|
220
|
-
caption-strong:
|
|
221
|
-
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
222
|
-
fontSize: 12px
|
|
223
|
-
fontWeight: 500
|
|
224
|
-
lineHeight: 16px
|
|
225
|
-
letterSpacing: 0px
|
|
226
|
-
caption-mono:
|
|
227
|
-
fontFamily: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace
|
|
228
|
-
fontSize: 12px
|
|
229
|
-
fontWeight: 500
|
|
230
|
-
lineHeight: 16px
|
|
231
|
-
letterSpacing: 0px
|
|
232
200
|
code:
|
|
233
201
|
fontFamily: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace
|
|
234
202
|
fontSize: 13px
|
|
235
203
|
fontWeight: 400
|
|
236
204
|
lineHeight: 20px
|
|
237
205
|
letterSpacing: 0px
|
|
238
|
-
|
|
239
|
-
fontFamily: Geist
|
|
240
|
-
fontSize:
|
|
241
|
-
fontWeight: 500
|
|
242
|
-
lineHeight: 18px
|
|
243
|
-
letterSpacing: 0px
|
|
244
|
-
button-lg:
|
|
245
|
-
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
246
|
-
fontSize: 16px
|
|
206
|
+
label-mono:
|
|
207
|
+
fontFamily: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace
|
|
208
|
+
fontSize: 12px
|
|
247
209
|
fontWeight: 500
|
|
248
|
-
lineHeight:
|
|
210
|
+
lineHeight: 16px
|
|
249
211
|
letterSpacing: 0px
|
|
250
212
|
|
|
251
213
|
rounded:
|
|
@@ -286,7 +248,7 @@ spacing:
|
|
|
286
248
|
|
|
287
249
|
## Overview
|
|
288
250
|
|
|
289
|
-
nadicode is an AI agency for SMBs. The design system makes the website and the shipped product read as one family: a calm, high-contrast monochrome architecture in which the identity layer — the Agent orbs
|
|
251
|
+
nadicode is an AI agency for SMBs. The design system makes the website and the shipped product read as one family: a calm, high-contrast monochrome architecture in which the identity layer — the Agent orbs and Nadia's striped ribbon among them — is the expressive element. Structure, chrome, and controls are neutral; a desaturated screen loses nothing structural. The interface helps a pragmatic buyer understand the work: repeated workflows, agents working beside people, inspectable outputs, human approval.
|
|
290
252
|
|
|
291
253
|
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.
|
|
292
254
|
|
|
@@ -298,9 +260,9 @@ The settled target state of this contract is [the nadicode design system ADR](..
|
|
|
298
260
|
|
|
299
261
|
## Colors
|
|
300
262
|
|
|
301
|
-
**
|
|
263
|
+
**Two greens, and only two.** `{colors.link}` #00713d, dark `{colors.dark-link}` #4ecf8c, is the green that carries text: links, navigational accents, approval states, and the deep and soft steps the `success` pair reuses. Identity verde `{colors.identity-verde}` #00a85a is the green that carries marks. Nothing else in this contract is green. A third green always turned out to be one of those two at a slightly different lightness, which is why `primary` #007a3c and `verde-vivo` #008c45, with their dark pairs `dark-primary` and `dark-verde-vivo`, no longer exist: the logo is ink with a cobalt dot and needs no brand verde, and the presence mark `verde-vivo` painted is retired with the portrait it sat on. The shadcn `primary` role is unaffected and still maps to the neutral action family.
|
|
302
264
|
|
|
303
|
-
Neutrals carry the interface: grounds, chrome, hierarchy, and every control come from the achromatic spine, and the strongest contrast on any surface lands on the primary action. Chromatic colour appears where it says something a reader already knows how to read: the semantic feedback hues, the
|
|
265
|
+
Neutrals carry the interface: grounds, chrome, hierarchy, and every control come from the achromatic spine, and the strongest contrast on any surface lands on the primary action. Chromatic colour appears where it says something a reader already knows how to read: the semantic feedback hues, the two greens in their scoped duties, the chart palettes on data, and the Agent identity palette inside the Agent visuals. Chrome, sections, and controls stay unpainted.
|
|
304
266
|
|
|
305
267
|
Interaction states are material, not meaning: focus, hover, and selection read as contrast steps on the neutral spine. A hover ground is a neutral step; the only change a control hover carries is a step inside its own family, as `{colors.action-hover}` does on the action control. Cobalto stays on info and running.
|
|
306
268
|
|
|
@@ -323,8 +285,7 @@ Every value a role needs is carried by the role token itself; there is no numeri
|
|
|
323
285
|
|
|
324
286
|
### Semantic roles (functional tier)
|
|
325
287
|
|
|
326
|
-
- **Action** (`{colors.action}` = ink `#111111`, `{colors.action-foreground}` = white, `{colors.action-hover}`, `{colors.action-active}`): the primary-control family is neutral — a white label on the ink field in light shells, and in dark shells the `dark-action-*` roles, a white control carrying a near-black label. Maximum contrast belongs to the thing that acts. The shadcn `primary` roles map here.
|
|
327
|
-
- **Brand accent — verde** (`{colors.primary}` = deep verde `#007a3c`, white `{colors.on-primary}` text on its field): identity marks, logo contexts, and brand accents. Verde's working duties are exactly the scoped roles below — links, success, and Nadia's presence — and the brighter verde `#00a85a` stays the imagery-tier anchor, never carrying normal-size white text.
|
|
288
|
+
- **Action** (`{colors.action}` = ink `#111111`, `{colors.action-foreground}` = white, `{colors.action-hover}`, `{colors.action-active}`): the primary-control family is neutral — a white label on the ink field in light shells, and in dark shells the `dark-action-*` roles, a white control carrying a near-black label. Maximum contrast belongs to the thing that acts. The shadcn `primary` roles map here, and `{colors.on-primary}` / `{colors.dark-on-primary}` are the foregrounds that role carries.
|
|
328
289
|
- **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. A labeled filter or search control already identified by readable text and its icon may use the quiet line role for an optional perimeter, configured by its composition owner. Form fields whose boundary identifies the input keep the input role. Focus remains a separate full-contrast state. Never darken a decorative border locally to make it behave like a control.
|
|
329
290
|
- **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.
|
|
330
291
|
- **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.
|
|
@@ -333,7 +294,6 @@ Every value a role needs is carried by the role token itself; there is no numeri
|
|
|
333
294
|
- **Navigation selection** (`{colors.navigation-selection-bg}`, `{colors.navigation-selection-fg}`, `{colors.navigation-selection-hover}`): the selected destination in persistent product navigation, a neutral selection field. 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 selection fill and the adjacent canvas.
|
|
334
295
|
- **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.
|
|
335
296
|
- **Accent** (`{colors.accent}` = arancio `#ff5a1f`): a small emphasis mark for exception flags and highlights; it appears as a mark, carries no text, and paints no fill or background. The identically-named shadcn surface role is a different thing — a neutral (`{colors.canvas-soft-2}` light, `{colors.dark-canvas-soft-2}` dark) with no hue.
|
|
336
|
-
- **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*, such as the success beat over her silhouette on Nadia's entry screen. 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.
|
|
337
297
|
- **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 fills, 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.
|
|
338
298
|
|
|
339
299
|
### Chart categoricals (functional tier)
|
|
@@ -347,7 +307,7 @@ Five full-strength hues are the system's expressive chromatic range: verde `{col
|
|
|
347
307
|
|
|
348
308
|
### Dark primitives
|
|
349
309
|
|
|
350
|
-
**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. The `dark-action` family is a white control stepping through light grays, ink-labelled — the primary control stays neutral on black. Chroma lives only in the intentional accents: `dark-
|
|
310
|
+
**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. The `dark-action` family is a white control stepping through light grays, ink-labelled — the primary control stays neutral on black. Chroma lives only in the intentional accents: `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.
|
|
351
311
|
|
|
352
312
|
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 the explicit semantic roles `destructive`, `success`, and `warning`; `primary` resolves to the neutral action family. 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.
|
|
353
313
|
|
|
@@ -411,40 +371,34 @@ is never the only explanation.
|
|
|
411
371
|
|
|
412
372
|
## Typography
|
|
413
373
|
|
|
414
|
-
**
|
|
415
|
-
|
|
416
|
-
Geist Sans and Geist Mono are the two families. Each token below carries its own — `
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
| Token
|
|
421
|
-
|
|
|
422
|
-
| `{typography.display-xl}`
|
|
423
|
-
| `{typography.display-lg}`
|
|
424
|
-
| `{typography.display-md}`
|
|
425
|
-
| `{typography.
|
|
426
|
-
| `{typography.
|
|
427
|
-
| `{typography.
|
|
428
|
-
| `{typography.
|
|
429
|
-
| `{typography.body-
|
|
430
|
-
| `{typography.body-
|
|
431
|
-
| `{typography.
|
|
432
|
-
| `{typography.
|
|
433
|
-
| `{typography.
|
|
434
|
-
| `{typography.caption}` | 12px | 400 | 16px | Footer secondary lines and badge labels. |
|
|
435
|
-
| `{typography.caption-strong}` | 12px | 500 | 16px | Compact emphasised labels on chrome and chips. |
|
|
436
|
-
| `{typography.caption-mono}` | 12px | 500 | 16px | Eyebrows, identifiers and code. |
|
|
437
|
-
| `{typography.code}` | 13px | 400 | 20px | Tool calls, snippets, traces. |
|
|
438
|
-
| `{typography.button-lg}` | 16px | 500 | 24px | Large button labels. |
|
|
439
|
-
| `{typography.button-md}` | 14px | 500 | 18px | Standard button and control labels. |
|
|
374
|
+
**Twelve sizes, named by the role they play.** A token says what a string is — a display line, a heading, body copy, a caption, code, a mono label — never how big it is, so a page that changes its mind about size changes one token and not every call site. Strong is a weight, not a token: a 500 run of body copy is `body-md` with `font-weight: 500`, which is why `body-md-strong`, `body-sm-strong`, `caption-strong` and the two `button-*` tokens are gone.
|
|
375
|
+
|
|
376
|
+
Geist Sans and Geist Mono are the two families, and there is no third. Each token below carries its own — `code` and `label-mono` are Geist Mono, every other token is Geist Sans — and its Use column says what that token is for. The register law that decides which family a given string takes, and what a card, panel, or section title therefore takes, is stated once in `## Components` → **`label-mono`**.
|
|
377
|
+
|
|
378
|
+
Do not use viewport-scaled type (no `vw`/`vh` font sizing): use fixed token sizes stepped by breakpoint-specific rules when a headline must grow. Tracking is a display-tier exception and nothing else: the three display sizes tighten from -0.035em at 72px to -0.025em at 40px so large type reads optically tight, and every heading, body, caption, code and label tier stays at `0px`. The contract authors the result in px, because DTCG dimensions are px or rem.
|
|
379
|
+
|
|
380
|
+
| Token | Size | Weight | Line Height | Tracking | Use |
|
|
381
|
+
| --------------------------- | ---- | ------ | ----------- | ---------- | ---------------------------------------------------------------------- |
|
|
382
|
+
| `{typography.display-xl}` | 72px | 600 | 74px | `-2.52px` | Hero headline at the widest breakpoint. |
|
|
383
|
+
| `{typography.display-lg}` | 52px | 600 | 54px | `-1.5px` | Compact hero and major landing headlines. |
|
|
384
|
+
| `{typography.display-md}` | 40px | 600 | 42px | `-1px` | Major section headings and the smallest display line. |
|
|
385
|
+
| `{typography.heading-lg}` | 30px | 600 | 32px | `0px` | Standard section title. |
|
|
386
|
+
| `{typography.heading-md}` | 24px | 600 | 32px | `0px` | Cell, artifact and panel titles; action bands and plan names. |
|
|
387
|
+
| `{typography.heading-sm}` | 20px | 600 | 28px | `0px` | The smallest heading, inline above a group. |
|
|
388
|
+
| `{typography.body-lg}` | 18px | 400 | 27px | `0px` | Hero and lead paragraphs. |
|
|
389
|
+
| `{typography.body-md}` | 16px | 400 | 25px | `0px` | Default body copy, and large control labels at weight 500. |
|
|
390
|
+
| `{typography.body-sm}` | 14px | 400 | 20px | `0px` | Secondary copy, nav, compact cell copy, control labels at weight 500. |
|
|
391
|
+
| `{typography.caption}` | 12px | 400 | 16px | `0px` | Footer secondary lines, badge labels, compact chrome labels. |
|
|
392
|
+
| `{typography.code}` | 13px | 400 | 20px | `0px` | Tool calls, snippets, traces. Geist Mono. |
|
|
393
|
+
| `{typography.label-mono}` | 12px | 500 | 16px | `0px` | Mono eyebrows, identifiers and low-priority metadata. Geist Mono. |
|
|
440
394
|
|
|
441
395
|
## Layout
|
|
442
396
|
|
|
443
|
-
|
|
397
|
+
Layout is mathematical and single-owner in every register: one owner per visible line, every gap from the tokens below, never eyeballed.
|
|
444
398
|
|
|
445
|
-
|
|
399
|
+
The website's structure is three kinds of full-bleed section and nothing else: white for reading, black for a scene, and at most one flat, full-strength colour section per page for its single statement. Every section runs edge to edge and centres its content in the one column, `.nc-page`: a single content max-width with side gutters that grow from phone to desktop. Inside a section the content is a single column or a picture-and-text split, and between two sections there is one spacing step. Nothing else on the website sets a page width, and a section adds no frame, no row grid and no gutter texture.
|
|
446
400
|
|
|
447
|
-
The
|
|
401
|
+
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 website's column.
|
|
448
402
|
|
|
449
403
|
### Spacing
|
|
450
404
|
|
|
@@ -468,7 +422,7 @@ Control geometry is foundation, so a control has the same physical size and the
|
|
|
468
422
|
|
|
469
423
|
| Token | Value | Owns |
|
|
470
424
|
| --- | --- | --- |
|
|
471
|
-
| `{spacing.guide}` | 1 px | Every ordinary seam
|
|
425
|
+
| `{spacing.guide}` | 1 px | Every ordinary seam |
|
|
472
426
|
| `{spacing.icon-stroke}` | 1.5 px | The house icon line, on screen, at 16, 20 and 24 px |
|
|
473
427
|
| `{spacing.icon-stroke-sm}` | 1.25 px | The same line at 12 px |
|
|
474
428
|
| `{spacing.focus-outline-width}` | 2 px | The one keyboard focus outline |
|
|
@@ -477,109 +431,29 @@ Control geometry is foundation, so a control has the same physical size and the
|
|
|
477
431
|
| `{spacing.control-padding-inline}` | 10 px | Inline padding of a control |
|
|
478
432
|
| `{spacing.touch-target}` | 44 px | Minimum target on coarse or non-hover input |
|
|
479
433
|
|
|
480
|
-
|
|
434
|
+
The website's column and its section rhythm 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"). Six tokens are the whole of the website's geometry; a page that needs a seventh is asking for a section kind the register does not have.
|
|
481
435
|
|
|
482
|
-
|
|
|
436
|
+
| Token | Owns | Register |
|
|
483
437
|
| --- | --- | --- |
|
|
484
|
-
|
|
|
485
|
-
|
|
|
486
|
-
|
|
|
487
|
-
|
|
|
488
|
-
|
|
|
489
|
-
|
|
|
490
|
-
|
|
|
491
|
-
| Bento heights | `h-bento-primary`, `h-bento-secondary`, `h-bento-mobile-copy`, `h-bento-mobile-main`, `h-bento-strip` | Website |
|
|
492
|
-
| Filter chip | `filter-chip-gap`, `filter-chip-height`, `filter-chip-icon` | Portal |
|
|
493
|
-
|
|
494
|
-
### Frame System
|
|
495
|
-
|
|
496
|
-
**Target state** (#2270): retires from the website with the rebuild; see `## Layout`.
|
|
497
|
-
|
|
498
|
-
- `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.
|
|
499
|
-
- `page-frame` is centered and capped at `--nc-frame-max`. It owns the outer left/right/top borders.
|
|
500
|
-
- `page-row` is the only direct section unit inside `page-frame`. It owns the bottom border for each row.
|
|
501
|
-
- Desktop rows use 12 equal columns with `--nc-frame-gap` gutters.
|
|
502
|
-
- `active-lane` spans columns 2 through 11 on desktop and all columns on smaller viewports.
|
|
503
|
-
- 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`).
|
|
504
|
-
- 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.
|
|
505
|
-
|
|
506
|
-
### Seam Ownership
|
|
507
|
-
|
|
508
|
-
**Target state** (#2270): retires from the website with the rebuild; see `## Layout`.
|
|
509
|
-
|
|
510
|
-
Every visible line has one owner. Do not draw borders on both adjacent children at the same coordinate. Use a line-colored parent background plus `{spacing.guide}` gaps, or use a single explicit border owned by the parent row/component.
|
|
511
|
-
|
|
512
|
-
On a `blueprint-field` surface the model is draw-all-then-occlude: the texture layer owns every line uniformly and opaque content (`cell-solid` or a content slot) occludes the lines it covers. This is distinct from the parent-plus-gap model used by `cell-grid`; both keep exactly one owner per visible line.
|
|
513
|
-
|
|
514
|
-
The universal guide weight is `{spacing.guide}`. Crosshairs use the same physical weight as the line they mark; they are darker through `{colors.cross}`, not thicker.
|
|
438
|
+
| `content-max` | 1200 px: the widest the reading column ever grows | Website |
|
|
439
|
+
| `gutter-mobile` | 20 px: the side gutter beside that column below 600 px | Website |
|
|
440
|
+
| `gutter-tablet` | 40 px: the same gutter from 600 px | Website |
|
|
441
|
+
| `gutter-desktop` | 64 px: the same gutter from 960 px | Website |
|
|
442
|
+
| `section-step-mobile` | 64 px: the one gap between two sections below 960 px | Website |
|
|
443
|
+
| `section-step-desktop` | 96 px: the same gap from 960 px | Website |
|
|
444
|
+
| `filter-chip-gap`, `filter-chip-height`, `filter-chip-icon` | The Portal's filter chip | Portal |
|
|
515
445
|
|
|
516
446
|
### Responsive Rules
|
|
517
447
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
Height tokens are fixed by component family and breakpoint. Components may grow when real content requires it, but the default specimen height comes from the exported height tokens so repeated rows align predictably.
|
|
521
|
-
|
|
522
|
-
Page shells must prevent horizontal scrollbars when a mathematically aligned full-bleed surface uses viewport width. Clip horizontal overflow at the shell/root level; do not hide overflow on structural cells to mask bad seam math.
|
|
523
|
-
|
|
524
|
-
Compositions arrange approved primitives for a content role. They must not redefine page-frame math, row seams, marker placement, side-fill ownership, active-lane spans, or global guide primitives. If a composition needs new structural geometry, promote that geometry into the page grammar or a real component first.
|
|
525
|
-
|
|
526
|
-
### Delivery Tiers
|
|
527
|
-
|
|
528
|
-
**Target state** (#2270): retires from the website with the rebuild; see `## Layout`.
|
|
529
|
-
|
|
530
|
-
Each reusable concern has one home and one authoring surface, so a member is documented and shipped in exactly one place:
|
|
531
|
-
|
|
532
|
-
- **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.
|
|
533
|
-
- **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.
|
|
534
|
-
- **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.
|
|
535
|
-
- **Layout grammar** — the page-frame, row, lane, seam, stage, and marker system documented across this `## Layout` section, carried by the layout CSS layer.
|
|
536
|
-
- **Specimens** — static demonstrations of already-defined primitives. They invent no geometry, seams, heights, or responsive behavior; they only assemble shipped tiers for inspection.
|
|
537
|
-
|
|
538
|
-
The page grammar below is the `## Layout` home for the structural names; the section-level compositions that arrange them ship from `@nadicodeai/ui`.
|
|
539
|
-
|
|
540
|
-
### Page Grammar
|
|
541
|
-
|
|
542
|
-
**Target state** (#2270): retires from the website with the rebuild; see `## Layout`.
|
|
543
|
-
|
|
544
|
-
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.
|
|
545
|
-
|
|
546
|
-
**`page-frame`** (`nc-page-frame`) — centered bordered frame capped by `--nc-frame-max`. Owns the outer left/right/top seams.
|
|
448
|
+
The website has two breakpoints, 600 px and 960 px. They live in the application CSS layer, never in the generated token layer: `foundation.css` collapses `gutter-*` into `--nc-gutter` and `section-step-*` into `--nc-section-step` at those widths, so a section reads one name and resolves the value for the viewport it is on. No register adds a third breakpoint to this column.
|
|
547
449
|
|
|
548
|
-
|
|
450
|
+
Page shells must prevent horizontal scrollbars when a full-bleed section uses viewport width. Clip horizontal overflow at the shell or root level; do not hide overflow on an inner surface to mask bad math.
|
|
549
451
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
**`side-fill`** (`nc-side-fill`) — the opt-in owner for columns 1 and 12 when a row uses the active lane. Hidden by default (the quiet-gutter doctrine: the empty margin column is the default treatment); a row enables it with `data-rails="hatch"` on the `page-row`, reserved for the page's anchor rows. When shown, it paints the diagonal filler, expands into the frame gutter so the texture touches the active content edge, and owns its single inner boundary rail (`{colors.line}` on its lane-facing edge) so the hatch is bounded on both sides — frame perimeter outside, fill rail inside.
|
|
553
|
-
|
|
554
|
-
**`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.
|
|
555
|
-
|
|
556
|
-
**`panel-cell`** — a square structural content cell inside `cell-grid`. Uses `--nc-cell-padding` and no local border.
|
|
557
|
-
|
|
558
|
-
**`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.
|
|
559
|
-
|
|
560
|
-
**`diagonal-fill`** — structural filler for outer columns and empty side lanes.
|
|
561
|
-
|
|
562
|
-
**`dotted-field`** — artifact/canvas background for conversations, outputs, and diagrams. It indicates a work surface, not generic decoration.
|
|
563
|
-
|
|
564
|
-
**`blueprint-field`** — a feathered structural-pitch background texture that visualizes a grid as graph-paper rather than as load-bearing DOM. Column and row pitch track the meaningful column count so it stays legible; the field is always feathered so it reads as texture, not as paper. On the blueprint surface the lines are drawn once underneath and occluded by opaque content (`cell-solid` or the content slot) — the draw-all-then-occlude model. It is incidental brand texture: if the blueprint field is the first thing you notice, it is too strong.
|
|
565
|
-
|
|
566
|
-
**`rule-svg`** — bounded dashed connector rule. Uses `{colors.seam}` and never overlaps a cell seam.
|
|
567
|
-
|
|
568
|
-
Reusable section compositions ship as React components from `@nadicodeai/ui`, composed over the page grammar above; the page grammar is the framework-agnostic foundation they assemble.
|
|
569
|
-
|
|
570
|
-
### Related Layout Helpers
|
|
571
|
-
|
|
572
|
-
This live helper is part of the kept page-grammar layout layer. It supports index-style page assemblies rather than naming an interface component.
|
|
573
|
-
|
|
574
|
-
**`index-grid`** — layout helper for index-style page assemblies (blog, learn, and case-study rows whose guide layer owns the dividers).
|
|
575
|
-
|
|
576
|
-
`index-card` is the repeated item class inside `index-grid`, not a standalone contract key.
|
|
452
|
+
Compositions arrange approved primitives for a content role. They do not redefine the content max-width, the gutters, or the step between sections. If a composition needs structural geometry this section does not name, promote that geometry here first.
|
|
577
453
|
|
|
578
454
|
## Elevation & Depth
|
|
579
455
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
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.
|
|
456
|
+
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. In light mode every rung's ring is black at 5%, because the shadow carries the height. On true black the shadows vanish, so the dark ring carries it instead and steps with the rung: resting 12%, raised 16%, floating 22%, modal 28% white. The falloff layers are identical in both modes; only the ring differs. Product code chooses only the semantic role.
|
|
583
457
|
|
|
584
458
|
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.
|
|
585
459
|
|
|
@@ -609,34 +483,44 @@ On coarse or non-hover input capability, every interactive target is at least 44
|
|
|
609
483
|
One radius rounds every surface. The reference is the search field: `{rounded.md}` (6 px). A surface never earns a larger corner by sitting higher on the elevation ladder, and no register may reintroduce a second surface radius.
|
|
610
484
|
|
|
611
485
|
- Use `{rounded.md}` (6 px) for every surface and every control: resting, raised, outlined, floating, and modal surfaces; cards, KPI cards, chart cards, tables, menus, selects, popovers, dropdowns, dialogs, sheets, drawers, takeovers, tooltips, toasts, inspectors; and buttons, inputs, chips, status tags, and small artifacts.
|
|
612
|
-
- Use `{rounded.none}` for
|
|
486
|
+
- Use `{rounded.none}` for full-bleed sections, structural cells, and structural modules.
|
|
613
487
|
- Use `{rounded.full}` only for intrinsically circular identity/avatar chrome and compact control marks whose geometry is inherently round or pill-shaped. It never turns a content surface, button, badge, or navigation item into a pill by default.
|
|
614
488
|
|
|
615
489
|
The radius scale itself is unchanged: `{rounded.xs}` through `{rounded.3xl}` stay exported for inner marks and for geometry a component owns, such as a progress track or a bar end. Only the rung that surfaces take is fixed.
|
|
616
490
|
|
|
617
|
-
|
|
491
|
+
Structural cells on the website are not cards and remain square, because the section around them supplies the visual system. Product cards use the resting material role. A details composition may divide its header and bound individual facts with the outlined role; each edge has one owner and fact cells add no elevation. Grouping does not justify another ring around the same container or a stronger shadow.
|
|
618
492
|
|
|
619
493
|
## Motion
|
|
620
494
|
|
|
621
|
-
**
|
|
495
|
+
**One motion law.** Only Agents move on their own. The interface answers a person's action, briefly, and stops: motion follows the action, stays under 300 ms, grows from the element that was pressed, and settles. While a person waits for something they asked for, one waiting line moves and nothing else.
|
|
496
|
+
|
|
497
|
+
Only Agents move on their own. An idle orb holds still, and under reduced
|
|
498
|
+
motion a thinking or working orb breathes in opacity, 1.6 s ease-in-out from
|
|
499
|
+
full ink to 0.45, so busy still reads as busy while every other orb is still
|
|
500
|
+
([agent orbs](../ui/docs/agent-orb.md)). Opening an Agent in the Portal is the
|
|
501
|
+
one view transition: the orb travels from the list row into the Agent's page
|
|
502
|
+
on `transition` with `in-out-strong`, over a root crossfade on `close`, and
|
|
503
|
+
reduced motion navigates instantly; the Portal's `portal.css` owns those rules
|
|
504
|
+
because that one navigation is the only place the product moves a page.
|
|
622
505
|
|
|
623
|
-
|
|
506
|
+
**One default transition in every product**: `confirm`, 180 ms, `out-strong`. It is set once, on `--default-transition-duration` and `--default-transition-timing-function` in `src/css/motion.css`, so a bounded Tailwind transition utility inherits the cadence and no product declares a default of its own.
|
|
624
507
|
|
|
625
|
-
|
|
508
|
+
**One reduced-motion policy**, stated once in `motion.css` and repeated nowhere: under `prefers-reduced-motion: reduce`, movement stops and paint continues. Transforms and keyframed movement go to their end state; opacity and colour transitions are kept, because a fade or a colour change is the state change itself rather than decoration around it, and an Agent that is thinking or working still has to read as busy. A component never answers reduced motion by turning every transition off.
|
|
509
|
+
|
|
510
|
+
The durations and easings live in `core.motion` of the authored token extension ("CSS Architecture & Token Pipeline"). 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, and `tests/guards/motion-durations.test.ts` fails on a time literal anywhere in the motion layer.
|
|
626
511
|
|
|
627
512
|
| Token | Use |
|
|
628
513
|
| --- | --- |
|
|
629
|
-
| `
|
|
630
|
-
| `
|
|
631
|
-
| `close` / `open` | Floating chrome and overlays leaving and arriving |
|
|
632
|
-
| `
|
|
633
|
-
| `msg-in` | A transcript message arriving |
|
|
634
|
-
| `
|
|
635
|
-
| `
|
|
636
|
-
| `
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
The easings are `emphasized`, `out-strong`, `in-out-strong`, and `drawer`.
|
|
514
|
+
| `stagger` 60 ms | The step between siblings in one arrival |
|
|
515
|
+
| `control` 100 ms | Hover and press on a control in a dense register |
|
|
516
|
+
| `close` 140 ms / `open` 220 ms | Floating chrome and overlays leaving and arriving |
|
|
517
|
+
| `confirm` 180 ms | Confirmation feedback, instant state flips, and the default transition |
|
|
518
|
+
| `msg-in` 240 ms | A transcript message arriving |
|
|
519
|
+
| `transition` 240 ms | Property transitions on a working surface, and the Agent view transition |
|
|
520
|
+
| `drawer-swipe` 400 ms / `drawer` 450 ms | Sheets and drawers, pointer-driven and programmatic |
|
|
521
|
+
| `wait` 1.6 s | The one waiting line, and nothing else |
|
|
522
|
+
|
|
523
|
+
The easings are `emphasized`, `out-strong`, `in-out-strong`, and `drawer`. Every remaining duration has a job these rules allow, which is why `spin`, `typing` and `shimmer` retired with the spinner, the typewriter line and the three shimmer systems: a busy spinner is not an Agent, and ambient decoration is not an answer to anything a person did.
|
|
640
524
|
|
|
641
525
|
## Registers
|
|
642
526
|
|
|
@@ -646,23 +530,29 @@ A register adds rules. It never redefines a foundation value. A value one regist
|
|
|
646
530
|
|
|
647
531
|
| Register | Rulebook | Its own token families | Dark mode |
|
|
648
532
|
| --- | --- | --- | --- |
|
|
649
|
-
| Website | `apps/website/docs/design-doctrine.md` over `## Layout` here | `register.website.layout`: `
|
|
533
|
+
| Website | `apps/website/docs/design-doctrine.md` over `## Layout` here | `register.website.layout`: `content-max`, `gutter-*`, `section-step-*`. It speaks `display-xl`, `display-lg`, and `title-lg` | Light only |
|
|
650
534
|
| Portal | `apps/portal/docs/information-architecture.md` for direction; `apps/portal/docs/design-doctrine.md` for implementation | `register.portal.density`: `filter-chip-gap`, `filter-chip-height`, `filter-chip-icon` | System, light, dark, on the `.dark` class |
|
|
651
535
|
| Nadia desktop app | `apps/nadia/docs/design-doctrine.md` | `register.nadia.*`: colour-role and radius aliases; six deprecated elevation recipes and the legacy overlay border remain as compatibility data. New surfaces consume the foundation's material roles | Follows the operating system, on the `.dark` class |
|
|
652
536
|
|
|
653
|
-
|
|
537
|
+
The website is built from three kinds of full-bleed section and nothing else: white for reading, black for a scene with a marble figure and the live orb, and at most one flat, full-strength colour section per page for its single statement, in the hue of that page's picture. One content max-width with growing side gutters centres the reading content, a section holds a single column or a picture-and-text split, and one spacing step separates two sections (`## Layout`).
|
|
654
538
|
|
|
655
|
-
The website's depth is flat and architectural:
|
|
539
|
+
The website's depth is flat and architectural: the three section grounds, contrast, large Geist headlines and the approved pictures make hierarchy. It has no page frame, no row grid, no diagonal fill and no dotted field; the dotted field is the Portal's work surface. It uses no rung of the material ladder and no floating card stack as page structure, and no negative letter spacing outside the two display tiers.
|
|
656
540
|
|
|
657
541
|
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.
|
|
658
542
|
|
|
659
543
|
## Components
|
|
660
544
|
|
|
661
|
-
This section is the semantic catalog for framework-agnostic components. Exact reusable values stay in the token maps above; CSS owns component composition.
|
|
545
|
+
This section is the semantic catalog for framework-agnostic components. Exact reusable values stay in the token maps above; CSS owns component composition. The section grammar and the content column live in `## Layout`, while React components and reusable sections live in `@nadicodeai/ui`.
|
|
546
|
+
|
|
547
|
+
### Structural Surfaces
|
|
548
|
+
|
|
549
|
+
One surface carries structure rather than content. It is square (`{rounded.none}`), takes no rung of the elevation ladder, and draws no border of its own.
|
|
550
|
+
|
|
551
|
+
**`dotted-field`** — the Portal's work surface: the dotted ground behind conversations, outputs, and diagrams, on the material ladder's workspace role ("Elevation & Depth"). It indicates a work surface, never decoration, and the website does not use it.
|
|
662
552
|
|
|
663
553
|
### Interface Atoms
|
|
664
554
|
|
|
665
|
-
Interface CSS components provide small metadata, label, and link chrome. They inherit
|
|
555
|
+
Interface CSS components provide small metadata, label, and link chrome. They inherit nadicode tokens and stay subordinate to the layout; 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.
|
|
666
556
|
|
|
667
557
|
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.
|
|
668
558
|
|
|
@@ -676,13 +566,13 @@ Keyboard focus has one owner: the kit's foundation layer draws the full-opacity
|
|
|
676
566
|
|
|
677
567
|
### Content Surfaces
|
|
678
568
|
|
|
679
|
-
Content surfaces display specific content types inside
|
|
569
|
+
Content surfaces display specific content types inside a section. They are valid when the content exists; they do not replace the section, the content column, or the seam rules.
|
|
680
570
|
|
|
681
|
-
**`image`** — editorial media mount, the single home for art-directed imagery inside
|
|
571
|
+
**`image`** — editorial media mount, the single home for art-directed imagery inside a section. 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 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. It has one form: there is no divider-strip variant. Use `image` for every illustrated image and every photographic surface. Conversation artifacts render through assistant-ui rather than a design-system CSS family.
|
|
682
572
|
|
|
683
573
|
### Agentic Work Surfaces
|
|
684
574
|
|
|
685
|
-
Agentic work surfaces are the
|
|
575
|
+
Agentic work surfaces are the nadicode-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.
|
|
686
576
|
|
|
687
577
|
Agent identity is decorative product identity, not a work artifact or a status signal: the Agent orbs, owned by [`packages/ui/docs/agent-orb.md`](../ui/docs/agent-orb.md).
|
|
688
578
|
|
|
@@ -719,32 +609,41 @@ whole map in one module.
|
|
|
719
609
|
|
|
720
610
|
## System activity
|
|
721
611
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
and
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
612
|
+
Who does the work decides how it looks. An Agent's work shows that Agent's orb
|
|
613
|
+
in its state and a sentence saying what it is doing; Nadia connecting is
|
|
614
|
+
Nadia's ribbon, working. Everything below is the system's own work, and an orb
|
|
615
|
+
means an Agent, so no system wait takes one.
|
|
616
|
+
|
|
617
|
+
System work under about a second is a still pending label on the control: its
|
|
618
|
+
own word changes, it holds its place and its icon, and it carries `disabled`
|
|
619
|
+
and `aria-busy`. Past a second, one 2 px waiting line of ink moves beside the
|
|
620
|
+
work, a 32% segment crossing its track linearly on `wait`; nothing else on the
|
|
621
|
+
screen moves while it does. Measurable work is a progress line with a written
|
|
622
|
+
count. A page load shows still placeholders in the shape of the content.
|
|
623
|
+
Reduced motion drops the travel and breathes the whole line in opacity.
|
|
624
|
+
|
|
625
|
+
The colour of a wait is ink: the cobalto info role belonged to the retired
|
|
626
|
+
activity particles and marks no system wait now. Success, warning and error
|
|
627
|
+
keep their meanings; waiting for a person or a failed operation uses the
|
|
628
|
+
feedback treatment, not an activity one.
|
|
629
|
+
|
|
630
|
+
The renderers are `PendingLabel`, `WaitingLine`, `Progress` and `Skeleton` in
|
|
631
|
+
`@nadicodeai/ui`. The one-second delay, the geometry, the ink and the motion
|
|
632
|
+
are owned by [`packages/ui/docs/activity.md`](../ui/docs/activity.md); the
|
|
633
|
+
motion vocabulary owns `.nc-anim-wait` and its reduced-motion law; a consuming
|
|
634
|
+
app chooses the wait and supplies its readable words.
|
|
736
635
|
|
|
737
636
|
## Do's and Don'ts
|
|
738
637
|
|
|
739
638
|
This section states the correct form; a complete positive definition is the whole rule.
|
|
740
639
|
|
|
741
|
-
-
|
|
742
|
-
- Every visible line has one owner: ordinary seams are `{spacing.guide}` at `{colors.line}`, tuned only at the token contract; required control boundaries are `{colors.input}` / `{colors.dark-input}`; named collection controls may use the optional-perimeter rule above; keyboard focus is the dedicated focus-ring roles
|
|
743
|
-
- Page structure is architectural: hairlines, luminance, spacing, and the grammar above. One material role per product container; structural
|
|
744
|
-
- Typography uses fixed token sizes stepped by breakpoint;
|
|
745
|
-
- Agent orbs identify an Agent; conversations, artifacts, review states, and work output belong to assistant-ui and the agentic work surfaces. Text
|
|
746
|
-
- Components are named as
|
|
747
|
-
- Each register keeps its own structure and chrome: the
|
|
640
|
+
- A website page is a sequence of full-bleed sections in three kinds only: white for reading, black for a scene, and at most one flat colour section for one statement. Each one centres its content in the same column, capped at `content-max` with the gutter its viewport gives it, and the sections sit one spacing step apart.
|
|
641
|
+
- Every visible line has one owner: ordinary seams are `{spacing.guide}` at `{colors.line}`, tuned only at the token contract; required control boundaries are `{colors.input}` / `{colors.dark-input}`; named collection controls may use the optional-perimeter rule above; keyboard focus is the dedicated focus-ring roles.
|
|
642
|
+
- Page structure is architectural: hairlines, luminance, spacing, and the section grammar above. One material role per product container; structural cells carry no elevation; the four `nc-elevation-*` rungs are the complete shadow vocabulary; modal scrims stay unblurred.
|
|
643
|
+
- Typography uses fixed token sizes stepped by breakpoint; a component's height comes from its content and the spacing ladder, never from a fixed height of its own.
|
|
644
|
+
- Agent orbs identify an Agent; conversations, artifacts, review states, and work output belong to assistant-ui and the agentic work surfaces. Text sits on the canvas beside an identity mark, never on it.
|
|
645
|
+
- Components are named as nadicode-owned primitives, and this file carries contract only: tokens, semantics, and application rules — component prop APIs, state matrices, screenshots, and page-specific material live with their owners.
|
|
646
|
+
- Each register keeps its own structure and chrome: the three section kinds on the website, the material ladder in the Portal and the desktop, the desktop window following the operating system.
|
|
748
647
|
|
|
749
648
|
## Iconography
|
|
750
649
|
|
|
@@ -753,7 +652,7 @@ discipline below, the sizes, the stroke, and the decorative-versus-named rule,
|
|
|
753
652
|
is foundation and holds in every register.
|
|
754
653
|
|
|
755
654
|
The website, the Portal, and `@nadicodeai/ui` draw from Lucide (ISC). Lucide's
|
|
756
|
-
shapes are never edited; the
|
|
655
|
+
shapes are never edited; the nadicode house render changes only how they are
|
|
757
656
|
drawn: a line of `{spacing.icon-stroke}` on screen at every size, held there by
|
|
758
657
|
`vector-effect: non-scaling-stroke` on each shape, round caps, round joins, no
|
|
759
658
|
fill, and `currentColor` inheritance. A 12 px icon takes
|
|
@@ -792,9 +691,9 @@ Other companies' marks are not nadicode company logos and are not governed by an
|
|
|
792
691
|
|
|
793
692
|
Agent orbs, Nadia's included, and generated imagery are not nadicode company logos. The orbs live in [`packages/ui/docs/agent-orb.md`](../ui/docs/agent-orb.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.
|
|
794
693
|
|
|
795
|
-
All forms derive from one authored, framework-neutral geometry source exported as `@nadicodeai/design-system/assets/logo-geometry`: on a 100-unit x-height, an 18-unit stroke with flat ends, bowls and the n's arch of radius 41, and the dot of radius
|
|
694
|
+
All forms derive from one authored, framework-neutral geometry source exported as `@nadicodeai/design-system/assets/logo-geometry`: on a 100-unit x-height, an 18-unit stroke with flat ends, bowls and the n's arch of radius 41, and the dot of radius 14 centred 79 units above the baseline over the i's stem. No SVG, React component, favicon, document, or app re-authors, traces, typesets, or rearranges those shapes. The eight reference files beside the ADR are the target each generated output matches, byte for byte, and the package guard fails on any output that drifts from them.
|
|
796
695
|
|
|
797
|
-
On `{colors.canvas}` and the soft neutral canvases, the letters are ink and the dot is `{colors.
|
|
696
|
+
On `{colors.canvas}` and the soft neutral canvases, the letters are ink and the dot is `{colors.logo-dot}`. On `{colors.identity-ink}` and other dark grounds, the letters are `{colors.identity-white}` and the dot is `{colors.dark-logo-dot}`, a brighter cobalt, so it does not sink into black. `{colors.logo-dot}` is the logo's own colour role and the only token a consumer paints the dot with; the generated mode layer flips it under any dark ancestor, so React draws one form on both grounds. A one-ink form, letters and dot in one colour, exists only where a single ink prints: embossing, stamps, one-colour print. On photography, place the logo in a quiet area or over a scrim that keeps every part legible; when neither is available, mount it on an approved solid field. One surface uses one treatment.
|
|
798
697
|
|
|
799
698
|
The clear-space unit is one stroke width of the rendered wordmark or mark. Keep at least one unit free on every side, with no text, rule, image, or container edge inside it. Minimum rendered sizes are 72 CSS pixels wide for the wordmark, 12 CSS pixels for the mark, and 16 CSS pixels for the favicon. Browser and operating-system icon slots use the supplied favicon or app-icon files at the platform's required size. Never compress, crop, or distort a logo to fit.
|
|
800
699
|
|
|
@@ -802,13 +701,11 @@ For a meaningful standalone image, use the accessible name `nadicode`; the acces
|
|
|
802
701
|
|
|
803
702
|
Do not redraw, retype, reorder, stretch, crop, rotate, recolor, outline, shadow, animate, or add effects or gradients to a logo form. Do not add a dot or any shape to the mark, move the dot off the i, or substitute Nadia imagery for the logo.
|
|
804
703
|
|
|
805
|
-
The package build renders and publicly exports
|
|
806
|
-
|
|
807
|
-
**Target state** (#2272): the geometry source and every generated output, favicon and React component still draw the previous interlocked-link NadicodeAI lockup with its verde AI suffix; #2272 replaces them with the forms above and regenerates everything.
|
|
704
|
+
The package build renders and publicly exports seven files as SVG and transparent PNG from the geometry and the current `colors.*` contract: `assets/logo` and `assets/logo-white`, `assets/logo-one-ink` and `assets/logo-one-ink-white`, `assets/mark` and `assets/mark-white`, and `assets/app-icon`. React consumers use `BrandMark` or `BrandWordmark` according to the roles above; there is no lockup adapter, because the wordmark is the logo and the mark is already inside it, so no surface places the two together. The operator-only favicon generator draws the same icon tile at the sizes a browser and a platform ask for; it does not substitute another mark. Private geometry templates do not ship. A contract or geometry change is completed by regeneration, never by repainting an output or updating a fallback by hand.
|
|
808
705
|
|
|
809
706
|
## CSS Architecture & Token Pipeline
|
|
810
707
|
|
|
811
|
-
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,
|
|
708
|
+
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, primitives, components;` with no `layout` and no `sections` layer. The bundle ships only framework-agnostic brand and display CSS components; generic marketing and SaaS components ship as React components from `@nadicodeai/ui`.
|
|
812
709
|
|
|
813
710
|
### Public style interfaces
|
|
814
711
|
|
|
@@ -821,17 +718,17 @@ Callers never import generated files, CSS partials, or framework adapters direct
|
|
|
821
718
|
|
|
822
719
|
### Authoring homes
|
|
823
720
|
|
|
824
|
-
Each
|
|
721
|
+
Each part of the shipped CSS has exactly one authoring file:
|
|
825
722
|
|
|
826
|
-
- Tokens: `src/css/tokens.generated.css`, built from this contract and never hand-edited. Runtime composition belongs to the owning layer, such as responsive switching in `
|
|
723
|
+
- Tokens: `src/css/tokens.generated.css`, built from this contract and never hand-edited. Runtime composition belongs to the owning layer, such as the website's responsive switching in `foundation.css`; there is no hand-authored token partial.
|
|
827
724
|
- Type utilities: the `.nc-type-*` classes live in `foundation.css`.
|
|
828
|
-
-
|
|
725
|
+
- The website's content column, `.nc-page`, and the responsive `@media` switching behind it: `foundation.css`.
|
|
829
726
|
- 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.
|
|
830
727
|
- Specimens: `examples/`, which only assemble already-defined tiers.
|
|
831
728
|
|
|
832
729
|
### Authored token extension
|
|
833
730
|
|
|
834
|
-
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
|
|
731
|
+
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 website's column and section rhythm), `register.portal.density` (the filter-chip sizes), and `register.nadia` (the desktop's colour and radius aliases onto `core`, plus deprecated elevation data retained for older consumers).
|
|
835
732
|
|
|
836
733
|
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.
|
|
837
734
|
|
|
@@ -897,7 +794,7 @@ An alias is written in the short `{core.color.canvas}` form here; the build rewr
|
|
|
897
794
|
{"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}},
|
|
898
795
|
{"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}},
|
|
899
796
|
{"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}},
|
|
900
|
-
{"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.
|
|
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":[1,1,1],"alpha":0.12}}
|
|
901
798
|
]
|
|
902
799
|
},
|
|
903
800
|
"raised": {
|
|
@@ -907,7 +804,7 @@ An alias is written in the short `{core.color.canvas}` form here; the build rewr
|
|
|
907
804
|
{"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}},
|
|
908
805
|
{"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}},
|
|
909
806
|
{"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}},
|
|
910
|
-
{"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.
|
|
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":[1,1,1],"alpha":0.16}}
|
|
911
808
|
]
|
|
912
809
|
},
|
|
913
810
|
"floating": {
|
|
@@ -917,7 +814,7 @@ An alias is written in the short `{core.color.canvas}` form here; the build rewr
|
|
|
917
814
|
{"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}},
|
|
918
815
|
{"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}},
|
|
919
816
|
{"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}},
|
|
920
|
-
{"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.
|
|
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":[1,1,1],"alpha":0.22}}
|
|
921
818
|
]
|
|
922
819
|
},
|
|
923
820
|
"modal": {
|
|
@@ -927,7 +824,7 @@ An alias is written in the short `{core.color.canvas}` form here; the build rewr
|
|
|
927
824
|
{"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}},
|
|
928
825
|
{"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}},
|
|
929
826
|
{"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}},
|
|
930
|
-
{"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.
|
|
827
|
+
{"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.28}}
|
|
931
828
|
]
|
|
932
829
|
}
|
|
933
830
|
}
|
|
@@ -944,10 +841,7 @@ An alias is written in the short `{core.color.canvas}` form here; the build rewr
|
|
|
944
841
|
"transition": {"$value":{"value":240,"unit":"ms"}},
|
|
945
842
|
"drawer-swipe": {"$value":{"value":400,"unit":"ms"}},
|
|
946
843
|
"drawer": {"$value":{"value":450,"unit":"ms"}},
|
|
947
|
-
"
|
|
948
|
-
"typing": {"$value":{"value":1,"unit":"s"}},
|
|
949
|
-
"pulse": {"$value":{"value":1.6,"unit":"s"}},
|
|
950
|
-
"shimmer": {"$value":{"value":2,"unit":"s"}}
|
|
844
|
+
"wait": {"$value":{"value":1.6,"unit":"s"}}
|
|
951
845
|
},
|
|
952
846
|
"ease": {
|
|
953
847
|
"$type": "cubicBezier",
|
|
@@ -963,51 +857,12 @@ An alias is written in the short `{core.color.canvas}` form here; the build rewr
|
|
|
963
857
|
"$extensions": {"ai.nadicode.targets":["css","data"]},
|
|
964
858
|
"layout": {
|
|
965
859
|
"$type": "dimension",
|
|
966
|
-
"
|
|
967
|
-
"
|
|
968
|
-
"
|
|
969
|
-
"
|
|
970
|
-
"
|
|
971
|
-
"
|
|
972
|
-
"frame-gap": {"$value":{"value":24,"unit":"px"}},
|
|
973
|
-
"cell-padding": {"$value":{"value":24,"unit":"px"}},
|
|
974
|
-
"section-gap": {"$value":{"value":48,"unit":"px"}},
|
|
975
|
-
"cross-size-mobile": {"$value":{"value":11,"unit":"px"}},
|
|
976
|
-
"cross-size-tablet": {"$value":{"value":15,"unit":"px"}},
|
|
977
|
-
"cross-size-desktop": {"$value":{"value":21,"unit":"px"}},
|
|
978
|
-
"h-strip-mobile": {"$value":{"value":72,"unit":"px"}},
|
|
979
|
-
"h-strip-tablet": {"$value":{"value":80,"unit":"px"}},
|
|
980
|
-
"h-strip-desktop": {"$value":{"value":88,"unit":"px"}},
|
|
981
|
-
"h-cell-sm": {"$value":{"value":120,"unit":"px"}},
|
|
982
|
-
"h-cell-md-mobile": {"$value":{"value":144,"unit":"px"}},
|
|
983
|
-
"h-cell-md-tablet": {"$value":{"value":160,"unit":"px"}},
|
|
984
|
-
"h-cell-md-desktop": {"$value":{"value":168,"unit":"px"}},
|
|
985
|
-
"h-cell-lg-mobile": {"$value":{"value":220,"unit":"px"}},
|
|
986
|
-
"h-cell-lg-desktop": {"$value":{"value":240,"unit":"px"}},
|
|
987
|
-
"h-visual-mobile": {"$value":{"value":276,"unit":"px"}},
|
|
988
|
-
"h-visual-tablet": {"$value":{"value":318,"unit":"px"}},
|
|
989
|
-
"h-visual-desktop": {"$value":{"value":360,"unit":"px"}},
|
|
990
|
-
"h-precision-mobile": {"$value":{"value":276,"unit":"px"}},
|
|
991
|
-
"h-precision-tablet": {"$value":{"value":480,"unit":"px"}},
|
|
992
|
-
"h-precision-desktop": {"$value":{"value":720,"unit":"px"}},
|
|
993
|
-
"h-hero-mobile": {"$value":{"value":560,"unit":"px"}},
|
|
994
|
-
"h-hero-desktop": {"$value":{"value":720,"unit":"px"}},
|
|
995
|
-
"h-action-strip-mobile": {"$value":{"value":20,"unit":"px"}},
|
|
996
|
-
"h-action-strip-desktop": {"$value":{"value":32,"unit":"px"}},
|
|
997
|
-
"h-action-body-mobile": {"$value":{"value":320,"unit":"px"}},
|
|
998
|
-
"h-action-body-tablet": {"$value":{"value":338,"unit":"px"}},
|
|
999
|
-
"h-action-band": {"$value":{"value":260,"unit":"px"}},
|
|
1000
|
-
"h-feature-mobile": {"$value":{"value":360,"unit":"px"}},
|
|
1001
|
-
"h-feature-tablet": {"$value":{"value":400,"unit":"px"}},
|
|
1002
|
-
"h-feature-desktop": {"$value":{"value":456,"unit":"px"}},
|
|
1003
|
-
"h-editorial-feature-mobile": {"$value":{"value":360,"unit":"px"}},
|
|
1004
|
-
"h-editorial-feature-tablet": {"$value":{"value":440,"unit":"px"}},
|
|
1005
|
-
"h-editorial-feature-desktop": {"$value":{"value":560,"unit":"px"}},
|
|
1006
|
-
"h-bento-primary": {"$value":{"value":384,"unit":"px"}},
|
|
1007
|
-
"h-bento-secondary": {"$value":{"value":240,"unit":"px"}},
|
|
1008
|
-
"h-bento-mobile-copy": {"$value":{"value":248,"unit":"px"}},
|
|
1009
|
-
"h-bento-mobile-main": {"$value":{"value":537,"unit":"px"}},
|
|
1010
|
-
"h-bento-strip": {"$value":{"value":20,"unit":"px"}}
|
|
860
|
+
"content-max": {"$value":{"value":1200,"unit":"px"}},
|
|
861
|
+
"gutter-mobile": {"$value":{"value":20,"unit":"px"}},
|
|
862
|
+
"gutter-tablet": {"$value":{"value":40,"unit":"px"}},
|
|
863
|
+
"gutter-desktop": {"$value":{"value":64,"unit":"px"}},
|
|
864
|
+
"section-step-mobile": {"$value":{"value":64,"unit":"px"}},
|
|
865
|
+
"section-step-desktop": {"$value":{"value":96,"unit":"px"}}
|
|
1011
866
|
}
|
|
1012
867
|
},
|
|
1013
868
|
"portal": {
|