@nadicodeai/design-system 0.10.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/AGENTS.md +30 -101
  2. package/CONTEXT.md +75 -0
  3. package/DESIGN.md +180 -345
  4. package/README.md +27 -54
  5. package/dist/assets/logo-mark.svg +6 -0
  6. package/dist/assets/logo-wordmark.svg +4 -0
  7. package/dist/assets/nadia-canonical-face.png +0 -0
  8. package/dist/css/chat-autoplay.js +18 -27
  9. package/dist/css/index.css +2540 -56
  10. package/dist/favicon/apple-touch-icon.png +0 -0
  11. package/dist/favicon/favicon.ico +0 -0
  12. package/dist/favicon/favicon.svg +6 -16
  13. package/dist/favicon/icon-192.png +0 -0
  14. package/dist/favicon/icon-512.png +0 -0
  15. package/dist/favicon/site.webmanifest +2 -2
  16. package/dist/tailwind/nadicode.tailwind.json +98 -143
  17. package/dist/tokens/nadicode.dtcg.json +413 -908
  18. package/package.json +19 -11
  19. package/src/assets/logo-geometry.d.ts +27 -0
  20. package/src/assets/logo-geometry.js +204 -0
  21. package/src/assets/nadia-canonical-face.d.ts +2 -0
  22. package/dist/css/components/.gitkeep +0 -0
  23. package/dist/css/components/agent-avatar.css +0 -52
  24. package/dist/css/components/approval-gate.css +0 -145
  25. package/dist/css/components/artifact-preview.css +0 -81
  26. package/dist/css/components/chat-bubble-agent.css +0 -63
  27. package/dist/css/components/chat-bubble-user.css +0 -28
  28. package/dist/css/components/chat-thread.css +0 -159
  29. package/dist/css/components/handoff-banner.css +0 -37
  30. package/dist/css/components/image.css +0 -87
  31. package/dist/css/components/memory-item.css +0 -36
  32. package/dist/css/components/run-timeline.css +0 -160
  33. package/dist/css/components/state-row.css +0 -64
  34. package/dist/css/components/state-tag.css +0 -67
  35. package/dist/css/components/status-tag.css +0 -101
  36. package/dist/css/components/tool-call-trace.css +0 -36
  37. package/dist/css/components/typing-dots.css +0 -54
  38. package/dist/css/components/usage-meter.css +0 -63
  39. package/dist/css/foundation.css +0 -177
  40. package/dist/css/layout.css +0 -657
  41. package/dist/css/motion.css +0 -225
  42. package/dist/css/primitives.css +0 -333
  43. package/dist/css/reset.css +0 -22
  44. package/dist/css/tokens.generated.css +0 -349
  45. package/dist/css/tokens.local.css +0 -11
  46. package/dist/tailwind/nadicode.theme.css +0 -596
  47. package/src/assets/favicon.svg +0 -17
  48. package/src/assets/logo-mark.svg +0 -15
  49. package/src/assets/logo-wordmark.svg +0 -26
  50. package/src/assets/nadia.d.ts +0 -9
  51. package/src/assets/nadia.png +0 -0
@@ -1,225 +0,0 @@
1
- /*
2
- * motion layer — the brand's motion contract, defined once and reused.
3
- *
4
- * REGISTER: the page breathes; it never performs. Every moment of movement
5
- * has one owner and one meaning; motion that cannot say what it means is
6
- * decoration and is cut.
7
- *
8
- * THE FOUR MOVES (the complete vocabulary — nothing else animates):
9
- * Settle — entrance. A row's content rises in once on scroll-into-view,
10
- * as ONE unit, never element-by-element. (.nc-settle, opt-in)
11
- * Type — the demonstration. chat-autoplay's staggered message/trace
12
- * rhythm. The only sustained animation; it is content, not effect.
13
- * Confirm — state change. Approval and state surfaces transition at
14
- * --nc-duration-confirm; color arrives WITH the meaning, never
15
- * before it.
16
- * Invite — hover/press. Surface and underline shifts on hover, gated
17
- * behind @media (hover: hover) and (pointer: fine); :active press
18
- * feedback at scale(0.97). Nothing changes position on hover.
19
- *
20
- * CRAFT RULES:
21
- * - Entrances and exits ease OUT (--nc-ease-emphasized for Settle,
22
- * --nc-ease-out-strong for feedback); never ease-in, never a weak
23
- * built-in where a brand curve exists.
24
- * - State feedback completes in 150–200 ms; press <= 160 ms; only the
25
- * demonstration (Type) may run longer.
26
- * - DURATION TIERS: UI feedback stays under 300 ms.
27
- * --nc-duration-msg-in (360 ms) is reserved for the one-time Settle
28
- * entrance, never for motion the operator meets on every refetch. No
29
- * reflow/count-up timing is adopted; the deprecated compatibility token
30
- * below is not an approved semantic use.
31
- * - ASYMMETRIC TIMING: a deliberate action opens slower than it dismisses.
32
- * Popovers/menus/dialogs open at --nc-duration-open (220 ms) and close at
33
- * --nc-duration-close (140 ms); the open invites, the close gets out of the
34
- * way.
35
- * - ORIGIN-AWARE: a surface that springs from a trigger scales FROM that
36
- * trigger (transform-origin at the anchor), not from its own centre — a
37
- * popover grows out of the button that opened it.
38
- * - INTERRUPTIBLE: gesture- or toast-driven motion retargets from its
39
- * current position; it is never restarted from a fixed keyframe mid-flight.
40
- * - Nothing enters from scale(0) or from nothing.
41
- * - PROPERTY DISCIPLINE: shared product primitive feedback and overlays use
42
- * compositor-only opacity and individual translate/scale properties; they
43
- * never take over a consumer's full transform. The opt-in Settle/Type
44
- * presentation hooks below retain their legacy keyframes.
45
- * The Confirm move may additionally transition background-color,
46
- * border-color, and color at --nc-duration-confirm — colour is the state
47
- * change itself, and a paint-only transition triggers no reflow. Never
48
- * animate a property that shifts surrounding layout; no will-change;
49
- * zero CLS.
50
- * - FREQUENCY RULE: motion a user meets repeatedly (product UI, keyboard-
51
- * triggered actions) does not animate. Delight is reserved for rarely-
52
- * seen surfaces (marketing pages, first runs). Product surfaces that
53
- * grow from this kit inherit THIS rule, not the marketing motion.
54
- *
55
- * BANNED: parallax, scroll-jacking, floating/bobbing idle loops, gradient
56
- * shimmer, staggered letter reveals, anything that moves a seam or hairline
57
- * after it settles, more than one theatrical moment per page, and
58
- * `transition: all` / `transition-property: all` (name the properties you
59
- * animate — a blanket transition drags unintended props off the compositor).
60
- *
61
- * REDUCED MOTION: prefers-reduced-motion removes movement entirely — Settle
62
- * and Type loops gone, Confirm instant, press transforms removed. Immediate
63
- * state and focus semantics remain. The page must read identically motionless.
64
- *
65
- * BOUNDARY: nc-pulse is the live running-state indicator on agentic surfaces
66
- * ONLY (state-row / run-timeline, running kind). DESIGN.md bans pulses for
67
- * state communication on state-tag; the two never blur.
68
- *
69
- * Provenance: duration/ease token values extracted from the archived prototype
70
- * `docs/experiments/design-canvas/chat-anim.jsx`. The prototype defined three
71
- * keyframes (nc-msg-in, nc-typing, nc-pulse) but only wired nc-typing;
72
- * nc-msg-in was defined-but-dead and nc-pulse's state dot was never rendered,
73
- * and there was NO reduced-motion handling. This layer finishes the motion.
74
- */
75
-
76
- :root {
77
- /* Durations — extracted from chat-anim.jsx applied timings.
78
- --nc-duration-stagger : 160ms ← `nc-typing 1s ${i*160}ms` per-dot stagger step
79
- (also the per-message rise-in delay step);
80
- the smallest brand cadence unit.
81
- --nc-duration-msg-in : 360ms ← the brand transition rhythm; the prototype's
82
- rise-in had no explicit duration, so it is
83
- mapped to the footer's 360ms transition.
84
- --nc-duration-transition: 360ms ← footer `width 360ms cubic-bezier(.3,.7,.2,1)`.
85
- --nc-duration-typing : 1s ← `nc-typing 1s ... infinite` dot bounce loop.
86
- --nc-duration-pulse : 1.6s ← `nc-pulse 1.6s ease-out infinite` ring loop.
87
- --nc-duration-confirm : 180ms ← state feedback; 150–200 ms band (Confirm move). */
88
- --nc-duration-stagger: 160ms;
89
- --nc-duration-msg-in: 360ms;
90
- --nc-duration-transition: 360ms;
91
- --nc-duration-typing: 1s;
92
- --nc-duration-pulse: 1.6s;
93
- --nc-duration-confirm: 180ms;
94
-
95
- /* Deprecated 0.10.x compatibility token; remove in a breaking release.
96
- It remains defined only so patch upgrades do not invalidate existing
97
- consumer CSS. Do not use it for reflow, count-up, or new runtime motion. */
98
- --nc-duration-reflow: 250ms;
99
-
100
- /* Asymmetric open/close cadence (craft-rule tokens for the ASYMMETRIC TIMING
101
- rule above — a deliberate action opens slower than it dismisses).
102
- --nc-duration-open : 220ms drives a popover/menu/dialog opening; the open
103
- invites.
104
- --nc-duration-close: 140ms drives its dismissal; the close gets out of the
105
- way. Both stay under the 300ms UI-feedback ceiling. */
106
- --nc-duration-open: 220ms;
107
- --nc-duration-close: 140ms;
108
-
109
- /* Easings — extracted from chat-anim.jsx.
110
- --nc-ease-emphasized : cubic-bezier(.3,.7,.2,1) ← footer width transition;
111
- the brand's settle curve.
112
- --nc-ease-bounce : ease-in-out ← `nc-typing ... ease-in-out` dot bounce.
113
- --nc-ease-out : ease-out ← `nc-pulse 1.6s ease-out` ring decay;
114
- the weak built-in stays only where
115
- nc-pulse already uses it.
116
- --nc-ease-out-strong : cubic-bezier(0.23, 1, 0.32, 1) ← the strong exit/
117
- feedback curve (Confirm, Invite, press). */
118
- --nc-ease-emphasized: cubic-bezier(0.3, 0.7, 0.2, 1);
119
- --nc-ease-bounce: ease-in-out;
120
- --nc-ease-out: ease-out;
121
- --nc-ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1);
122
- }
123
-
124
- /* ── Keyframes ────────────────────────────────────────────────────────────
125
- Three REAL keyframes, all wired below via the `.nc-anim-*` hooks. */
126
-
127
- /* Message bubble rise-in — opacity 0→1 + translateY(4px)→0.
128
- Was defined-but-dead in the prototype; now real. */
129
- @keyframes nc-msg-in {
130
- from {
131
- opacity: 0;
132
- transform: translateY(4px);
133
- }
134
- to {
135
- opacity: 1;
136
- transform: translateY(0);
137
- }
138
- }
139
-
140
- /* Typing-indicator dot bounce — the only keyframe the prototype actually applied. */
141
- @keyframes nc-typing {
142
- 0%,
143
- 80%,
144
- 100% {
145
- opacity: 0.25;
146
- transform: translateY(0);
147
- }
148
- 40% {
149
- opacity: 1;
150
- transform: translateY(-2px);
151
- }
152
- }
153
-
154
- /* Running-state pulse — a deliberate, subtle expanding ring. Drawn with
155
- `currentColor` so the consuming atom owns the hue (no hard-coded color here);
156
- for the running state only, not every dot. */
157
- @keyframes nc-pulse {
158
- 0% {
159
- box-shadow: 0 0 0 0 currentColor;
160
- }
161
- 70% {
162
- box-shadow: 0 0 0 6px transparent;
163
- }
164
- 100% {
165
- box-shadow: 0 0 0 0 transparent;
166
- }
167
- }
168
-
169
- /* ── Animation utility hooks (the reuse mechanism, D5) ─────────────────────
170
- Each keyframe name appears here in an `animation` declaration so it is wired,
171
- not just defined (AC-013). M6 chat atoms opt into these classes. Every hook
172
- exposes `--nc-anim-delay` (default 0ms) so atoms can stagger by setting it,
173
- e.g. `style="--nc-anim-delay: calc(var(--i) * var(--nc-duration-stagger))"`. */
174
-
175
- .nc-anim-msg-in {
176
- animation: nc-msg-in var(--nc-duration-msg-in) var(--nc-ease-emphasized) both;
177
- animation-delay: var(--nc-anim-delay, 0ms);
178
- }
179
-
180
- .nc-anim-typing {
181
- animation: nc-typing var(--nc-duration-typing) var(--nc-ease-bounce) infinite;
182
- animation-delay: var(--nc-anim-delay, 0ms);
183
- }
184
-
185
- .nc-anim-pulse {
186
- animation: nc-pulse var(--nc-duration-pulse) var(--nc-ease-out) infinite;
187
- animation-delay: var(--nc-anim-delay, 0ms);
188
- }
189
-
190
- /* ── Settle — enhancer-armed entrance (opt-in) ────────────────────────────
191
- .nc-settle is the layout-container opt-in for scroll-driven entrance.
192
- Base state is FULLY VISIBLE — no opacity rule on .nc-settle itself — so
193
- no-JS and reduced-motion users get the complete static page.
194
-
195
- Mechanism: enhancer-armed, run-once (no view() scrubbing).
196
- chat-autoplay.js sets data-nc-settle="armed" on elements that are fully
197
- below the viewport at init, then switches to data-nc-settle="in" on first
198
- intersection (IntersectionObserver, threshold ~0.1). The observer unobserves
199
- immediately after firing — the rise-in plays once and is never re-triggered
200
- on re-entry or reversed on scroll-back. Elements already in or above the
201
- viewport at load are never armed (no flash, hero region untouched).
202
- No JS → no attribute → page fully visible. */
203
- @media (prefers-reduced-motion: no-preference) {
204
- [data-nc-settle="armed"] {
205
- opacity: 0;
206
- }
207
-
208
- [data-nc-settle="in"] {
209
- animation: nc-msg-in var(--nc-duration-msg-in) var(--nc-ease-emphasized) both;
210
- }
211
- }
212
-
213
- /* ── Reduced motion (mandatory, D5) ───────────────────────────────────────
214
- Neutralize every hook: no animation, and a static, fully-visible end-state
215
- so rise-in content is not stuck hidden at opacity 0. */
216
- @media (prefers-reduced-motion: reduce) {
217
- .nc-anim-msg-in,
218
- .nc-anim-typing,
219
- .nc-anim-pulse {
220
- animation: none;
221
- opacity: 1;
222
- transform: none;
223
- box-shadow: none;
224
- }
225
- }
@@ -1,333 +0,0 @@
1
- /* primitives layer — atoms and molecules that sit on the layout-layer grid.
2
- *
3
- * Structural-geometry foundation (kept through the Tailwind+shadcn migration; see
4
- * index.css). The `.nc-marker` crosshair is the brand's corner mark: it stays
5
- * corners-only (placed via the `data-position` → grid-line-index map below,
6
- * never auto-placed), monochrome (a single `--nc-cross` color on both arms), and
7
- * token-weighted (`--nc-guide` line weight). Its position is derived from grid
8
- * placement (`grid-column-start`/`grid-row-start` against the field's track
9
- * lines), never a frame-relative pixel offset measured by eye. Every value in
10
- * this layer references an emitted `--nc-*` token; no raw color/radius/dimension
11
- * literal lives here. */
12
- .nc-cell {
13
- position: relative;
14
- z-index: 2;
15
- display: grid;
16
- min-width: 0;
17
- min-height: var(--nc-h-cell-sm);
18
- margin-right: var(--nc-guide);
19
- margin-bottom: var(--nc-guide);
20
- padding: var(--nc-cell-padding);
21
- overflow: hidden;
22
- overflow-wrap: anywhere;
23
- place-content: center;
24
- background: var(--nc-canvas);
25
- }
26
-
27
- .nc-cell-flush {
28
- padding: 0;
29
- }
30
-
31
- .nc-diagonal-fill,
32
- .nc-cell-filler {
33
- background:
34
- repeating-linear-gradient(
35
- -45deg,
36
- var(--nc-canvas-soft) 0,
37
- var(--nc-canvas-soft) 7px,
38
- var(--nc-line) 7px,
39
- var(--nc-line) 8px
40
- ),
41
- var(--nc-canvas);
42
- }
43
-
44
- .nc-dotted-field {
45
- background:
46
- radial-gradient(var(--nc-line) 0.8px, transparent 0.8px) 0 0 / 12px 12px,
47
- var(--nc-canvas);
48
- }
49
-
50
- .nc-marker {
51
- /* Centering offset built ONLY from the marker's own size + the universal line
52
- token — never a sibling box. The marker is placed as a grid child so its box
53
- corner lands on a track-line intersection (grid-column-start/grid-row-start);
54
- pulling it back by half-its-size + half-a-line centers the crosshair arms
55
- exactly on that intersection. This replaces the deleted seam-offset model,
56
- which floated the crosshair off the frame border-half. */
57
- --nc-cross-half: calc((var(--nc-cross-size) / 2) + (var(--nc-guide) / 2));
58
- position: absolute;
59
- z-index: 4;
60
- grid-column-start: var(--nc-cross-column);
61
- grid-row-start: var(--nc-cross-row);
62
- width: var(--nc-cross-size);
63
- height: var(--nc-cross-size);
64
- inset: calc(var(--nc-cross-half) * -1);
65
- pointer-events: none;
66
- }
67
-
68
- /* data-position is the declarative placement API: it maps the four frame
69
- corners to the grid-line indices .nc-marker already consumes, so authored
70
- markup that names a corner actually lands there. Inline --nc-cross-column /
71
- --nc-cross-row still win (inline styles beat stylesheet rules), keeping an
72
- explicit escape hatch for internal-track markers. -1 is the last grid line,
73
- so corners track the grid across breakpoints — never a hardcoded 13/9. */
74
- .nc-marker[data-position="top-left"] {
75
- --nc-cross-column: 1;
76
- --nc-cross-row: 1;
77
- }
78
-
79
- .nc-marker[data-position="top-right"] {
80
- --nc-cross-column: -1;
81
- --nc-cross-row: 1;
82
- }
83
-
84
- .nc-marker[data-position="bottom-left"] {
85
- --nc-cross-column: 1;
86
- --nc-cross-row: -1;
87
- }
88
-
89
- .nc-marker[data-position="bottom-right"] {
90
- --nc-cross-column: -1;
91
- --nc-cross-row: -1;
92
- }
93
-
94
- .nc-marker::before,
95
- .nc-marker::after {
96
- content: "";
97
- position: absolute;
98
- display: block;
99
- background: var(--nc-cross);
100
- }
101
-
102
- .nc-marker::before {
103
- top: 0;
104
- bottom: 0;
105
- left: 50%;
106
- width: var(--nc-guide);
107
- transform: translateX(-50%);
108
- }
109
-
110
- .nc-marker::after {
111
- left: 0;
112
- right: 0;
113
- top: 50%;
114
- height: var(--nc-guide);
115
- transform: translateY(-50%);
116
- }
117
-
118
- .nc-blueprint-field {
119
- /* The structural grid drawn as a background texture instead of bordered DOM
120
- guide elements. Lines are painted at STRUCTURAL pitch — one tile per column
121
- and row — so the 12-column reading is preserved (a fixed px pitch would read
122
- as graph paper). Pitch reuses the surrounding grid field's column/row count.
123
- This is the same technique nc-action-visual already uses; nc-blueprint-field
124
- generalizes it so any surface can carry the blueprint without DOM guides. */
125
- --nc-blueprint-columns: var(--nc-grid-columns, 12);
126
- --nc-blueprint-rows: var(--nc-grid-rows, 8);
127
- --nc-blueprint-line: var(--nc-line);
128
- background-image:
129
- linear-gradient(to right, var(--nc-blueprint-line) var(--nc-guide), transparent var(--nc-guide)),
130
- linear-gradient(
131
- to bottom,
132
- var(--nc-blueprint-line) var(--nc-guide),
133
- transparent var(--nc-guide)
134
- );
135
- background-size:
136
- calc(100% / var(--nc-blueprint-columns)) calc(100% / var(--nc-blueprint-rows)),
137
- calc(100% / var(--nc-blueprint-columns)) calc(100% / var(--nc-blueprint-rows));
138
- }
139
-
140
- /* Opt-in feather: soften the blueprint so it reads as atmosphere, not
141
- scaffolding (used by atmospheric surfaces like the brand hero). */
142
- .nc-blueprint-field[data-feather="top"] {
143
- -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 22%, black 100%);
144
- mask-image: linear-gradient(to bottom, transparent 0%, black 22%, black 100%);
145
- }
146
-
147
- .nc-rule-svg {
148
- color: var(--nc-seam);
149
- overflow: visible;
150
- }
151
-
152
- .nc-rule-svg line {
153
- stroke: currentColor;
154
- stroke-dasharray: 4 6;
155
- stroke-linecap: round;
156
- }
157
-
158
- .nc-panel-cell {
159
- display: grid;
160
- min-width: 0;
161
- min-height: var(--nc-h-cell-md);
162
- padding: var(--nc-cell-padding);
163
- align-content: center;
164
- gap: 12px;
165
- overflow: hidden;
166
- overflow-wrap: anywhere;
167
- background: var(--nc-canvas);
168
- color: var(--nc-body);
169
- }
170
-
171
- .nc-artifact-surface {
172
- display: grid;
173
- gap: 12px;
174
- min-width: 0;
175
- border: var(--nc-guide) solid var(--nc-line);
176
- padding: 18px;
177
- /* The retired gradient tokens (Italia color contract §6) are gone; the artifact
178
- surface keeps a calm, scale-driven dot-grid atmosphere on canvas. */
179
- background:
180
- radial-gradient(var(--nc-line) 0.8px, transparent 0.8px) 0 0 / 12px 12px,
181
- var(--nc-canvas);
182
- color: var(--nc-body);
183
- }
184
-
185
- .nc-artifact-bar {
186
- height: 10px;
187
- background: var(--nc-line);
188
- }
189
-
190
- .nc-artifact-bar:nth-of-type(1) {
191
- width: 76%;
192
- }
193
-
194
- .nc-artifact-bar:nth-of-type(2) {
195
- width: 56%;
196
- }
197
-
198
- .nc-artifact-bar:nth-of-type(3) {
199
- width: 38%;
200
- }
201
-
202
- /* nc-icon — the icon slot. Icons are derived from Lucide (ISC) by a build
203
- transform that bakes the house render into the SVG (see scripts/generate-icons.ts).
204
- This primitive renders an INLINE <svg> child and re-asserts that key — 1.5px
205
- stroke, butt caps, miter joins, currentColor — so a raw upstream icon dropped in
206
- here also conforms. Size is set by [data-size] (sm 12 / md 16 / lg 24); md is the
207
- default. Inline SVG is required for currentColor inheritance — an <img> renders in
208
- isolation and cannot read it. */
209
- .nc-icon {
210
- display: inline-flex;
211
- flex: none;
212
- width: 16px;
213
- height: 16px;
214
- color: inherit;
215
- vertical-align: middle;
216
- }
217
-
218
- .nc-icon[data-size="sm"] {
219
- width: 12px;
220
- height: 12px;
221
- }
222
-
223
- .nc-icon[data-size="lg"] {
224
- width: 24px;
225
- height: 24px;
226
- }
227
-
228
- .nc-icon svg {
229
- display: block;
230
- width: 100%;
231
- height: 100%;
232
- fill: none;
233
- stroke: currentColor;
234
- stroke-width: 1.5;
235
- stroke-linecap: butt;
236
- stroke-linejoin: miter;
237
- }
238
-
239
- /* nc-badge-secondary — a small fully-rounded metadata badge for "New", "Beta",
240
- "Live", or similar labels (DESIGN.md badge-secondary). It carries the
241
- {colors.canvas-soft} surface, {colors.body} text, and the {rounded.full}
242
- radius; the caption type is applied in markup via .nc-type-caption so the
243
- contract is the single source of the type. It is an inline chip with no seam
244
- of its own beyond its hairline border. */
245
- .nc-badge-secondary {
246
- display: inline-flex;
247
- width: fit-content;
248
- align-items: center;
249
- justify-content: center;
250
- gap: 6px;
251
- border: var(--nc-guide) solid var(--nc-line);
252
- border-radius: var(--nc-rounded-full);
253
- padding: 1px 8px;
254
- background: var(--nc-canvas-soft);
255
- color: var(--nc-body);
256
- }
257
-
258
- /* nc-filter-chip — removable selected-filter label (DESIGN.md filter-chip).
259
- It uses neutral chrome only: applied filter state is not workflow, lifecycle,
260
- or taxonomy state, so color is reserved for the remove affordance focus ring. */
261
- .nc-filter-chip {
262
- display: inline-flex;
263
- width: fit-content;
264
- min-height: var(--nc-filter-chip-height);
265
- align-items: center;
266
- justify-content: center;
267
- gap: var(--nc-filter-chip-gap);
268
- border: var(--nc-guide) solid var(--nc-line);
269
- border-radius: var(--nc-rounded-sm);
270
- padding: 0 var(--nc-xs);
271
- background: var(--nc-canvas-soft);
272
- color: var(--nc-body);
273
- }
274
-
275
- .nc-filter-chip svg {
276
- width: var(--nc-filter-chip-icon);
277
- height: var(--nc-filter-chip-icon);
278
- flex: none;
279
- stroke: currentColor;
280
- stroke-width: 1.5;
281
- }
282
-
283
- .dark .nc-filter-chip {
284
- border-color: var(--nc-dark-line);
285
- background: var(--nc-dark-canvas-soft);
286
- color: var(--nc-dark-body);
287
- }
288
-
289
- .nc-filter-chip:focus-visible {
290
- outline: var(--nc-focus-ring-width) solid var(--nc-focus-ring);
291
- outline-offset: 0;
292
- }
293
-
294
- /* nc-link-inline — the inline body link style (DESIGN.md link-inline). It reads
295
- in the {colors.link} accent against the body rhythm (the body type is applied
296
- in markup via .nc-type-body-md), keeps the natural underline so it stays
297
- recognisable in running prose, and exposes a contrast-safe focus ring. It is
298
- an inline atom, never a block. */
299
- .nc-link-inline {
300
- color: var(--nc-link);
301
- text-decoration: underline;
302
- text-underline-offset: 2px;
303
- text-decoration-thickness: var(--nc-guide);
304
- transition:
305
- background-color var(--nc-duration-stagger) var(--nc-ease-out-strong),
306
- border-color var(--nc-duration-stagger) var(--nc-ease-out-strong),
307
- color var(--nc-duration-stagger) var(--nc-ease-out-strong),
308
- opacity var(--nc-duration-stagger) var(--nc-ease-out-strong);
309
- }
310
-
311
- @media (hover: hover) and (pointer: fine) {
312
- .nc-link-inline:hover {
313
- color: var(--nc-link-deep);
314
- }
315
- }
316
-
317
- .nc-link-inline:focus-visible {
318
- outline: var(--nc-focus-ring-width) solid var(--nc-focus-ring);
319
- outline-offset: 0;
320
- border-radius: var(--nc-rounded-md);
321
- }
322
-
323
- /* nc-label-mono — the mono eyebrow/kicker for section labels and low-priority
324
- metadata (DESIGN.md label-mono). It reads in the {colors.muted} tone and the
325
- caption-mono scale (applied in markup via .nc-type-caption-mono); this rule
326
- adds only the uppercase eyebrow treatment, which is presentation the type
327
- scale does not carry. It owns no box and no seam. */
328
- .nc-label-mono {
329
- display: block;
330
- margin: 0;
331
- color: var(--nc-muted);
332
- text-transform: uppercase;
333
- }
@@ -1,22 +0,0 @@
1
- /* reset layer — box-sizing, html/body, heading margins (split from old foundation per D10). */
2
- * {
3
- box-sizing: border-box;
4
- }
5
-
6
- html {
7
- min-width: 320px;
8
- overflow-x: clip;
9
- text-rendering: optimizeLegibility;
10
- }
11
-
12
- body {
13
- margin: 0;
14
- overflow-x: clip;
15
- }
16
-
17
- h1,
18
- h2,
19
- h3,
20
- p {
21
- margin: 0;
22
- }