@nebutra/ui 0.2.1 → 0.2.3

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 (56) hide show
  1. package/LICENSE +21 -676
  2. package/README.md +81 -86
  3. package/dist/agent/index.d.ts +119 -0
  4. package/dist/agent/index.js +135 -0
  5. package/dist/agent/index.js.map +1 -0
  6. package/dist/canonical-Drca5UMj.d.ts +4309 -0
  7. package/dist/components/index.d.ts +51 -56
  8. package/dist/components/index.js +1696 -1203
  9. package/dist/components/index.js.map +1 -1
  10. package/dist/hooks/index.d.ts +62 -15
  11. package/dist/hooks/index.js +56 -34
  12. package/dist/hooks/index.js.map +1 -1
  13. package/dist/index-CKLIGfiU.d.ts +19 -0
  14. package/dist/index-Dg4jRJV2.d.ts +57 -0
  15. package/dist/layout/index.d.ts +7 -3
  16. package/dist/layout/index.js +525 -542
  17. package/dist/layout/index.js.map +1 -1
  18. package/dist/layouts/index.d.ts +80 -2
  19. package/dist/layouts/index.js +32 -19
  20. package/dist/layouts/index.js.map +1 -1
  21. package/dist/patterns/index.d.ts +131 -5
  22. package/dist/patterns/index.js +1594 -806
  23. package/dist/patterns/index.js.map +1 -1
  24. package/dist/primitives/canonical.d.ts +25 -0
  25. package/dist/primitives/canonical.js +12269 -0
  26. package/dist/primitives/canonical.js.map +1 -0
  27. package/dist/primitives/index.d.ts +694 -3544
  28. package/dist/primitives/index.js +8994 -6583
  29. package/dist/primitives/index.js.map +1 -1
  30. package/dist/shared/animation/css/index.d.ts +1 -0
  31. package/dist/shared/animation/css/index.js +14 -0
  32. package/dist/shared/animation/css/index.js.map +1 -0
  33. package/dist/shared/animation/index.d.ts +6 -0
  34. package/dist/shared/animation/index.js +272 -0
  35. package/dist/shared/animation/index.js.map +1 -0
  36. package/dist/shared/animation/motion/index.d.ts +4 -0
  37. package/dist/shared/animation/motion/index.js +205 -0
  38. package/dist/shared/animation/motion/index.js.map +1 -0
  39. package/dist/styles/brand-override.css +11 -11
  40. package/dist/tailwind.preset.d.ts +10 -10
  41. package/dist/tailwind.preset.js +7 -4
  42. package/dist/tailwind.preset.js.map +1 -1
  43. package/dist/theme/index.d.ts +2 -2
  44. package/dist/tokens-EAC6uPem.d.ts +302 -0
  45. package/dist/typography/fonts.css +51 -37
  46. package/dist/typography/index.d.ts +27 -27
  47. package/dist/typography/index.js +24 -4
  48. package/dist/typography/index.js.map +1 -1
  49. package/dist/utils/index.d.ts +66 -14
  50. package/dist/utils/index.js +53 -10
  51. package/dist/utils/index.js.map +1 -1
  52. package/package.json +56 -14
  53. package/src/styles/brand-override.css +61 -0
  54. package/src/styles/preset.css +29 -0
  55. package/src/styles/sources.css +37 -0
  56. package/src/typography/fonts.css +124 -0
@@ -1,26 +1,135 @@
1
1
  "use client";
2
- import * as React14 from 'react';
3
- import { useState, useRef, useCallback, useMemo, Fragment as Fragment$1 } from 'react';
4
2
  import { clsx } from 'clsx';
5
3
  import { twMerge } from 'tailwind-merge';
6
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
- import { ChevronRight, Check, Status, ChevronUpDown, Pencil, FileText, TextBold, TextItalic, Code, Hash, ListUnordered, Link, Image, ChevronUp, ChevronDown, Calendar, Eye, Bookmark, StarFill, Share, Flag, Pin, MoreHorizontal } from '@nebutra/icons';
4
+ import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
5
+ import * as React from 'react';
6
+ import { useState, useRef, useCallback, useMemo, Fragment, isValidElement } from 'react';
7
+ import { Check, Copy, Pencil, FileText, TextBold, TextItalic, Code, Hash, ListUnordered, Link, Image, ChevronUp, ChevronDown, Calendar, Eye, Bookmark, StarFill, Share, Flag, ChevronUpDown, Pin, ChevronRight, MoreHorizontal } from '@nebutra/icons';
8
8
  import { cva } from 'class-variance-authority';
9
9
  import { Menu } from '@base-ui/react/menu';
10
- import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
11
10
  import { colors } from '@nebutra/brand';
11
+ import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
12
12
  import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
13
13
  import ReactMarkdown from 'react-markdown';
14
14
  import remarkGfm from 'remark-gfm';
15
15
  import { Separator as Separator$1 } from '@base-ui/react/separator';
16
16
  import { Avatar as Avatar$1 } from '@base-ui/react/avatar';
17
- import { AnimatePresence, motion } from 'framer-motion';
17
+ import { useReducedMotion, AnimatePresence, motion } from 'framer-motion';
18
18
 
19
- // src/patterns/Card/Card.tsx
19
+ // src/utils/cn.ts
20
20
  function cn(...inputs) {
21
21
  return twMerge(clsx(inputs));
22
22
  }
23
- var CardContext = React14.createContext(null);
23
+ function ArtifactShiftCard({
24
+ className,
25
+ contentClassName,
26
+ children,
27
+ ...props
28
+ }) {
29
+ return /* @__PURE__ */ jsxs(
30
+ "div",
31
+ {
32
+ className: cn(
33
+ "group/card relative flex h-full min-h-[560px] flex-col overflow-hidden rounded-[var(--radius-panel)] border bg-background/90 transition-[transform,border-color,box-shadow] duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] hover:-translate-y-1 hover:border-foreground/25 hover:shadow-ambient-lg focus-within:-translate-y-1 focus-within:border-foreground/25",
34
+ className
35
+ ),
36
+ "data-taste": "nebutra-shift-card",
37
+ ...props,
38
+ children: [
39
+ /* @__PURE__ */ jsx(
40
+ "div",
41
+ {
42
+ "aria-hidden": "true",
43
+ className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_1px_1px,var(--neutral-8)_1px,transparent_0)] bg-[length:22px_22px] opacity-[0.09]"
44
+ }
45
+ ),
46
+ /* @__PURE__ */ jsx(
47
+ "div",
48
+ {
49
+ "aria-hidden": "true",
50
+ className: "pointer-events-none absolute inset-x-0 top-0 h-32 bg-gradient-to-b from-primary/10 via-primary/5 to-transparent opacity-80"
51
+ }
52
+ ),
53
+ /* @__PURE__ */ jsx("div", { className: cn("relative flex h-full flex-col p-4 sm:p-5", contentClassName), children })
54
+ ]
55
+ }
56
+ );
57
+ }
58
+ function ArtifactShiftCardPreview({
59
+ filename,
60
+ language,
61
+ code,
62
+ label,
63
+ maxLines = 8,
64
+ signals = ["typed", "scoped", "ready"],
65
+ className,
66
+ ...props
67
+ }) {
68
+ const lines = code.split("\n").slice(0, maxLines);
69
+ return /* @__PURE__ */ jsxs(
70
+ "section",
71
+ {
72
+ "aria-label": label,
73
+ className: cn(
74
+ "relative min-h-[260px] overflow-hidden rounded-[var(--radius-xl)] border border-border/60 bg-background/80 p-3 shadow-ambient-sm transition-[transform,border-color,box-shadow] duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] group-hover/card:-translate-y-1 group-hover/card:border-foreground/20 group-hover/card:shadow-ambient-md group-focus-within/card:-translate-y-1 group-focus-within/card:border-foreground/20 sm:p-4",
75
+ className
76
+ ),
77
+ ...props,
78
+ children: [
79
+ /* @__PURE__ */ jsx(
80
+ "div",
81
+ {
82
+ "aria-hidden": "true",
83
+ className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_1px_1px,var(--neutral-7)_1px,transparent_0)] bg-[length:18px_18px] opacity-[0.16]"
84
+ }
85
+ ),
86
+ /* @__PURE__ */ jsx(
87
+ "div",
88
+ {
89
+ "aria-hidden": "true",
90
+ className: "pointer-events-none absolute inset-x-0 top-0 h-24 bg-gradient-to-b from-primary/10 to-transparent opacity-80"
91
+ }
92
+ ),
93
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-between gap-3 rounded-[var(--radius-md)] border border-border/60 bg-background/85 px-3 py-2", children: [
94
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate font-mono text-[11px] text-foreground/80", translate: "no", children: filename }),
95
+ /* @__PURE__ */ jsx(
96
+ "span",
97
+ {
98
+ className: "rounded-full border border-border/70 bg-muted/40 px-2 py-0.5 font-mono text-[10px] text-muted-foreground uppercase",
99
+ translate: "no",
100
+ children: language
101
+ }
102
+ )
103
+ ] }),
104
+ /* @__PURE__ */ jsx("div", { className: "relative mt-3 space-y-1.5 rounded-[var(--radius-lg)] border border-border/50 bg-muted/25 p-3 font-mono text-[11px] leading-5", children: lines.map((line, index) => /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 gap-3", children: [
105
+ /* @__PURE__ */ jsx("span", { className: "w-5 shrink-0 text-right text-muted-foreground/55 tabular-nums", children: index + 1 }),
106
+ /* @__PURE__ */ jsx("code", { className: "min-w-0 truncate text-foreground/75", translate: "no", children: line || " " })
107
+ ] }, `${line}-${index}`)) }),
108
+ /* @__PURE__ */ jsx("div", { className: "relative mt-3 grid grid-cols-3 gap-2", children: signals.map((signal) => /* @__PURE__ */ jsx(
109
+ "span",
110
+ {
111
+ className: "rounded-[var(--radius-md)] border border-border/55 bg-background/75 px-2 py-1.5 text-center font-mono text-[10px] text-muted-foreground uppercase tracking-[0.14em]",
112
+ children: signal
113
+ },
114
+ signal
115
+ )) })
116
+ ]
117
+ }
118
+ );
119
+ }
120
+ function ArtifactShiftCardFooter({ className, ...props }) {
121
+ return /* @__PURE__ */ jsx(
122
+ "footer",
123
+ {
124
+ className: cn(
125
+ "relative mt-4 flex flex-wrap items-center justify-between gap-3 rounded-[var(--radius-xl)] border border-border/60 bg-background/85 px-4 py-3 shadow-ambient-sm backdrop-blur-xl transition-[transform,border-color,box-shadow] duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] group-hover/card:-translate-y-2 group-hover/card:border-foreground/20 group-hover/card:shadow-ambient-md group-focus-within/card:-translate-y-2 group-focus-within/card:border-foreground/20",
126
+ className
127
+ ),
128
+ ...props
129
+ }
130
+ );
131
+ }
132
+ var CardContext = React.createContext(null);
24
133
  var paddingMap = {
25
134
  none: "",
26
135
  sm: "p-4",
@@ -34,14 +143,14 @@ var variantStyles = {
34
143
  ghost: "bg-transparent",
35
144
  gradient: "bg-gradient-to-br from-card to-muted border border-border"
36
145
  };
37
- var CardRoot = React14.forwardRef(
146
+ var CardRoot = React.forwardRef(
38
147
  ({ className, variant = "default", padding = "md", children, ...props }, ref) => {
39
148
  return /* @__PURE__ */ jsx(CardContext.Provider, { value: { variant }, children: /* @__PURE__ */ jsx(
40
149
  "div",
41
150
  {
42
151
  ref,
43
152
  className: cn(
44
- "rounded-[var(--radius-xl)] transition-all duration-200",
153
+ "rounded-[var(--radius-xl)] transition-[background-color,border-color,box-shadow,color] duration-micro",
45
154
  variantStyles[variant],
46
155
  paddingMap[padding],
47
156
  className
@@ -53,26 +162,26 @@ var CardRoot = React14.forwardRef(
53
162
  }
54
163
  );
55
164
  CardRoot.displayName = "Card";
56
- var CardHeader = React14.forwardRef(
165
+ var CardHeader = React.forwardRef(
57
166
  ({ className, spacing: gap = "md", children, ...props }, ref) => {
58
167
  const gapMap = { sm: "gap-2", md: "gap-3", lg: "gap-4" };
59
168
  return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-start", gapMap[gap], className), ...props, children });
60
169
  }
61
170
  );
62
171
  CardHeader.displayName = "Card.Header";
63
- var CardBody = React14.forwardRef(
172
+ var CardBody = React.forwardRef(
64
173
  ({ className, children, ...props }, ref) => {
65
174
  return /* @__PURE__ */ jsx("div", { ref, className: cn("mt-4", className), ...props, children });
66
175
  }
67
176
  );
68
177
  CardBody.displayName = "Card.Body";
69
- var CardFooter = React14.forwardRef(
178
+ var CardFooter = React.forwardRef(
70
179
  ({ className, children, ...props }, ref) => {
71
180
  return /* @__PURE__ */ jsx("div", { ref, className: cn("mt-6 pt-4 border-t border-border/50", className), ...props, children });
72
181
  }
73
182
  );
74
183
  CardFooter.displayName = "Card.Footer";
75
- var CardIcon = React14.forwardRef(
184
+ var CardIcon = React.forwardRef(
76
185
  ({ className, size = "md", children, ...props }, ref) => {
77
186
  const sizeMap = {
78
187
  sm: "w-8 h-8",
@@ -95,14 +204,14 @@ var CardIcon = React14.forwardRef(
95
204
  }
96
205
  );
97
206
  CardIcon.displayName = "Card.Icon";
98
- var CardTitle = React14.forwardRef(
207
+ var CardTitle = React.forwardRef(
99
208
  ({ className, as: Tag = "h3", children, ...props }, ref) => {
100
209
  return /* @__PURE__ */ jsx(Tag, { ref, className: cn("text-lg font-semibold text-foreground", className), ...props, children });
101
210
  }
102
211
  );
103
212
  CardTitle.displayName = "Card.Title";
104
- var CardDescription = React14.forwardRef(({ className, as: Tag = "p", children, ...props }, ref) => {
105
- return React14.createElement(
213
+ var CardDescription = React.forwardRef(({ className, as: Tag = "p", children, ...props }, ref) => {
214
+ return React.createElement(
106
215
  Tag,
107
216
  {
108
217
  ref,
@@ -121,7 +230,7 @@ var Card = Object.assign(CardRoot, {
121
230
  Title: CardTitle,
122
231
  Description: CardDescription
123
232
  });
124
- var CommandBox = React14.forwardRef(
233
+ var CommandBox = React.forwardRef(
125
234
  ({
126
235
  className,
127
236
  command,
@@ -131,20 +240,23 @@ var CommandBox = React14.forwardRef(
131
240
  onCopy,
132
241
  ...props
133
242
  }, ref) => {
134
- const [copied, setCopied] = React14.useState(false);
135
- const handleCopy = React14.useCallback(async () => {
243
+ const [copied, setCopied] = React.useState(false);
244
+ const handleCopy = React.useCallback(async () => {
136
245
  try {
137
246
  await navigator.clipboard.writeText(command);
138
247
  setCopied(true);
139
248
  onCopy?.();
140
249
  setTimeout(() => setCopied(false), 2e3);
141
- } catch (_err) {
250
+ } catch (err) {
251
+ if (process.env.NODE_ENV !== "production") {
252
+ console.error("[CommandBox] clipboard write failed:", err);
253
+ }
142
254
  }
143
255
  }, [command, onCopy]);
144
256
  const variantStyles3 = {
145
- default: "bg-[var(--neutral-2)] border border-[var(--neutral-7)] rounded-[var(--radius-lg)]",
146
- minimal: "bg-[var(--neutral-1)] border border-[var(--neutral-7)] rounded-[var(--radius-md)]",
147
- pill: "bg-[var(--neutral-2)] border border-[var(--neutral-7)] rounded-full"
257
+ default: "bg-muted border border-border rounded-[var(--radius-lg)]",
258
+ minimal: "bg-background border border-border rounded-[var(--radius-md)]",
259
+ pill: "bg-muted border border-border rounded-full"
148
260
  };
149
261
  return (
150
262
  // biome-ignore lint/a11y/useSemanticElements: ARIA pattern
@@ -153,7 +265,7 @@ var CommandBox = React14.forwardRef(
153
265
  {
154
266
  ref,
155
267
  className: cn(
156
- "group relative flex items-center gap-3 px-4 py-2.5 font-mono text-sm cursor-pointer transition-all hover:bg-[var(--neutral-3)]",
268
+ "group relative flex items-center gap-3 px-4 py-2.5 font-mono text-sm cursor-pointer transition-colors hover:bg-muted",
157
269
  variantStyles3[variant],
158
270
  className
159
271
  ),
@@ -170,13 +282,13 @@ var CommandBox = React14.forwardRef(
170
282
  ...props,
171
283
  children: [
172
284
  /* @__PURE__ */ jsx("span", { className: "text-emerald-400 shrink-0 select-none", children: prefix }),
173
- /* @__PURE__ */ jsx("span", { className: "flex-1 text-[var(--neutral-11)] truncate", children: command }),
285
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-muted-foreground truncate", children: command }),
174
286
  showCopyButton && /* @__PURE__ */ jsx(
175
287
  "span",
176
288
  {
177
289
  className: cn(
178
290
  "shrink-0 text-xs transition-colors",
179
- copied ? "text-emerald-400" : "text-[var(--neutral-9)] group-hover:text-[var(--neutral-11)]"
291
+ copied ? "text-emerald-400" : "text-muted-foreground group-hover:text-muted-foreground"
180
292
  ),
181
293
  children: copied ? /* @__PURE__ */ jsx(CopiedIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx(CopyIcon, { className: "w-4 h-4" })
182
294
  }
@@ -185,7 +297,7 @@ var CommandBox = React14.forwardRef(
185
297
  "span",
186
298
  {
187
299
  className: cn(
188
- "absolute -top-8 left-1/2 -translate-x-1/2 px-2 py-1 text-xs rounded bg-zinc-700 text-[var(--neutral-11)] opacity-0 transition-opacity pointer-events-none",
300
+ "absolute -top-8 left-1/2 -translate-x-1/2 px-2 py-1 text-xs rounded bg-zinc-700 text-muted-foreground opacity-0 transition-opacity pointer-events-none",
189
301
  "group-hover:opacity-100",
190
302
  copied && "opacity-100"
191
303
  ),
@@ -236,13 +348,139 @@ function CopiedIcon({ className }) {
236
348
  }
237
349
  );
238
350
  }
351
+ var metricToneClasses = {
352
+ neutral: "bg-muted/70 text-muted-foreground ring-border",
353
+ blue: "bg-info/10 text-info ring-info/20",
354
+ green: "bg-success/10 text-success ring-success/20",
355
+ amber: "bg-warning/10 text-warning ring-warning/20"
356
+ };
357
+ function DashboardCommandSurface({
358
+ status,
359
+ title,
360
+ description,
361
+ actions,
362
+ children,
363
+ className
364
+ }) {
365
+ return /* @__PURE__ */ jsxs(
366
+ "section",
367
+ {
368
+ "data-pattern": "nebutra-dashboard-command",
369
+ className: cn(
370
+ "relative overflow-hidden rounded-[var(--radius-lg)] border border-border bg-card p-4 text-card-foreground shadow-sm",
371
+ "before:pointer-events-none before:absolute before:inset-x-0 before:top-0 before:h-px before:bg-[linear-gradient(90deg,transparent,hsl(var(--primary)/0.58),transparent)]",
372
+ "after:pointer-events-none after:absolute after:inset-0 after:bg-[radial-gradient(circle_at_top_left,hsl(var(--primary)/0.08),transparent_42%)]",
373
+ "sm:p-5",
374
+ className
375
+ ),
376
+ children: [
377
+ /* @__PURE__ */ jsxs("div", { className: "relative z-10 flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between", children: [
378
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
379
+ status ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
380
+ /* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-success shadow-[0_0_0_3px_hsl(var(--success)/0.18)]" }),
381
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] font-medium uppercase text-muted-foreground", children: status })
382
+ ] }) : null,
383
+ /* @__PURE__ */ jsx("h1", { className: "mt-2 text-2xl font-semibold tracking-normal text-card-foreground sm:text-[28px]", children: title }),
384
+ description ? /* @__PURE__ */ jsx("p", { className: "mt-2 max-w-2xl text-[13px] leading-5 text-muted-foreground", children: description }) : null
385
+ ] }),
386
+ actions ? /* @__PURE__ */ jsx("div", { className: "flex shrink-0 flex-wrap items-center gap-1.5", children: actions }) : null
387
+ ] }),
388
+ children ? /* @__PURE__ */ jsx("div", { className: "relative z-10 mt-4", children }) : null
389
+ ]
390
+ }
391
+ );
392
+ }
393
+ function DashboardPanel({
394
+ title,
395
+ description,
396
+ meta,
397
+ action,
398
+ children,
399
+ className,
400
+ headerClassName
401
+ }) {
402
+ return /* @__PURE__ */ jsxs(
403
+ "section",
404
+ {
405
+ "data-pattern": "nebutra-dashboard-panel",
406
+ className: cn(
407
+ "rounded-[var(--radius-lg)] border border-border bg-card p-3.5 text-card-foreground shadow-sm sm:p-4",
408
+ className
409
+ ),
410
+ children: [
411
+ /* @__PURE__ */ jsxs(
412
+ "div",
413
+ {
414
+ className: cn(
415
+ "mb-3 flex flex-col gap-2.5 border-b border-border pb-3 lg:flex-row lg:items-start lg:justify-between",
416
+ headerClassName
417
+ ),
418
+ children: [
419
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
420
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold tracking-normal text-card-foreground", children: title }),
421
+ description ? /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs leading-5 text-muted-foreground", children: description }) : null
422
+ ] }),
423
+ (meta || action) && /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2 lg:justify-end", children: [
424
+ meta,
425
+ action
426
+ ] })
427
+ ]
428
+ }
429
+ ),
430
+ children
431
+ ]
432
+ }
433
+ );
434
+ }
435
+ function DashboardMetricTile({
436
+ label,
437
+ value,
438
+ detail,
439
+ source,
440
+ icon: Icon,
441
+ tone = "neutral",
442
+ className
443
+ }) {
444
+ return /* @__PURE__ */ jsxs(
445
+ "div",
446
+ {
447
+ "data-pattern": "nebutra-dashboard-metric",
448
+ className: cn(
449
+ "group h-full rounded-[var(--radius-lg)] border border-border bg-muted/40 p-3 transition-colors duration-micro",
450
+ "hover:border-muted-foreground/30 hover:bg-muted/65",
451
+ className
452
+ ),
453
+ children: [
454
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
455
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-xs font-medium text-muted-foreground", children: label }),
456
+ Icon ? /* @__PURE__ */ jsx(
457
+ "span",
458
+ {
459
+ className: cn(
460
+ "inline-flex size-6 shrink-0 items-center justify-center rounded-[var(--radius-sm)] ring-1",
461
+ metricToneClasses[tone]
462
+ ),
463
+ children: /* @__PURE__ */ jsx(Icon, { className: "size-3.5", "aria-hidden": true })
464
+ }
465
+ ) : null
466
+ ] }),
467
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-2xl font-semibold tabular-nums tracking-normal text-card-foreground", children: value }),
468
+ (detail || source) && /* @__PURE__ */ jsxs("div", { className: "mt-1.5 space-y-0.5 text-xs leading-5 text-muted-foreground", children: [
469
+ detail ? /* @__PURE__ */ jsx("span", { className: "block", children: detail }) : null,
470
+ source ? /* @__PURE__ */ jsx("span", { className: "block text-[11px] text-muted-foreground/70", children: source }) : null
471
+ ] })
472
+ ]
473
+ }
474
+ );
475
+ }
239
476
  var badgeVariants = cva(
240
- "inline-flex justify-center items-center align-middle shrink-0 rounded-full font-sans font-medium whitespace-nowrap tabular-nums transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 border border-transparent",
477
+ "inline-flex justify-center items-center align-middle shrink-0 rounded-full font-sans font-medium whitespace-nowrap tabular-nums transition-colors focus-visible:outline-none border border-transparent",
241
478
  {
242
479
  variants: {
243
480
  variant: {
244
481
  // ─── Semantic / brand variants ────────────────────────────────────────
245
- default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
482
+ // Recipe-driven default (solid | outline | … via --badge-default-*)
483
+ default: "badge-brand-default border",
246
484
  secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
247
485
  destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
248
486
  outline: "border-border text-foreground",
@@ -250,32 +488,43 @@ var badgeVariants = cva(
250
488
  warning: "border-transparent bg-warning text-warning-foreground hover:bg-warning/80",
251
489
  info: "border-transparent bg-info text-info-foreground hover:bg-info/80",
252
490
  error: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
253
- // ─── Geist-style color palette ────────────────────────────────────────
254
- gray: "bg-geist-gray-700 text-white fill-white",
255
- "gray-subtle": "bg-geist-gray-200 text-geist-gray-1000 fill-geist-gray-1000 border-transparent",
256
- blue: "bg-blue-700 text-white fill-white",
257
- "blue-subtle": "bg-blue-200 text-blue-900 fill-blue-900 border-transparent",
258
- purple: "bg-purple-700 text-white fill-white",
259
- "purple-subtle": "bg-purple-200 text-purple-900 fill-purple-900 border-transparent",
260
- amber: "bg-amber-700 text-black fill-black",
261
- "amber-subtle": "bg-amber-200 text-amber-900 fill-amber-900 border-transparent",
262
- red: "bg-red-700 text-white fill-white",
263
- "red-subtle": "bg-red-200 text-red-900 fill-red-900 border-transparent",
264
- pink: "bg-pink-700 text-white fill-white",
265
- "pink-subtle": "bg-pink-300 text-pink-900 fill-pink-900 border-transparent",
266
- green: "bg-green-700 text-white fill-white",
267
- "green-subtle": "bg-green-200 text-green-900 fill-green-900 border-transparent",
268
- teal: "bg-teal-700 text-white fill-white",
269
- "teal-subtle": "bg-teal-300 text-teal-900 fill-teal-900 border-transparent",
270
- inverted: "bg-geist-gray-1000 text-geist-gray-100 fill-geist-gray-100",
271
- trial: "bg-gradient-to-br from-trial-start to-trial-end text-white fill-white",
272
- turbo: "bg-gradient-to-br from-turbo-start to-turbo-end text-white fill-white",
273
- pill: "bg-background text-foreground fill-foreground !border-gray-alpha-400 hover:bg-muted/50 focus-visible:bg-muted/50 dark:!border-border",
274
- // ─── Semantic tone variants (nav badges, ownership, featured) ─────────
491
+ // ─── Palette accents (decorative scale — not product chrome CTAs) ────
492
+ gray: "bg-muted text-muted-foreground fill-current",
493
+ "gray-subtle": "bg-muted/60 text-muted-foreground fill-current border-transparent",
494
+ blue: "bg-primary text-primary-foreground fill-current",
495
+ "blue-subtle": "bg-primary/10 text-primary fill-current border-transparent",
496
+ purple: "bg-secondary text-secondary-foreground fill-current",
497
+ "purple-subtle": "bg-secondary/40 text-secondary-foreground fill-current border-transparent",
498
+ amber: "bg-warning text-warning-foreground fill-current",
499
+ "amber-subtle": (
500
+ // --warning is a FILL (2.13:1). As ink on its own tint it measured 1.91:1.
501
+ // --warning-strong is the AA-safe amber foreground: 5.01:1 light / 6.20:1 dark.
502
+ "bg-warning/10 text-[hsl(var(--warning-strong))] fill-current border-transparent"
503
+ ),
504
+ red: "bg-destructive text-destructive-foreground fill-current",
505
+ "red-subtle": (
506
+ // --destructive is fill-only in dark (2.01:1 as ink on its own tint).
507
+ // --destructive-strong: 4.58:1 light / 4.97:1 dark.
508
+ "bg-destructive/10 text-[hsl(var(--destructive-strong))] fill-current border-transparent"
509
+ ),
510
+ pink: "bg-accent text-accent-foreground fill-current",
511
+ "pink-subtle": "bg-accent/40 text-accent-foreground fill-current border-transparent",
512
+ green: "bg-success text-success-foreground fill-current",
513
+ "green-subtle": (
514
+ // --success-strong closes the 4.49:1 light gap: 4.99:1 light / 4.83:1 dark.
515
+ "bg-success/10 text-[hsl(var(--success-strong))] fill-current border-transparent"
516
+ ),
517
+ teal: "bg-info text-info-foreground fill-current",
518
+ "teal-subtle": "bg-info/10 text-info fill-current border-transparent",
519
+ inverted: "bg-foreground text-background fill-current",
520
+ // Special visual treatments (intentional product design, not brand hex)
521
+ trial: "bg-gradient-to-br from-trial-start to-trial-end text-primary-foreground fill-current",
522
+ turbo: "bg-gradient-to-br from-turbo-start to-turbo-end text-primary-foreground fill-current",
523
+ pill: "bg-background text-foreground fill-foreground border-border hover:bg-muted/50 focus-visible:bg-muted/50",
275
524
  beta: "border-transparent bg-muted text-muted-foreground",
276
- new: "border-transparent bg-blue-100 text-blue-700 dark:bg-blue-950/50 dark:text-blue-300",
525
+ new: "border-transparent bg-primary/10 text-primary",
277
526
  owner: "border-border bg-transparent text-foreground",
278
- featured: "border-transparent text-white bg-[image:var(--brand-gradient)] [text-shadow:0_0_1px_rgba(0,0,0,0.2)]",
527
+ featured: "badge-brand-default border [text-shadow:0_0_1px_hsl(var(--background)/0.2)]",
279
528
  "coming-soon": "border-transparent bg-muted/60 text-muted-foreground italic"
280
529
  },
281
530
  size: {
@@ -296,15 +545,16 @@ var dotColorMap = {
296
545
  info: "bg-info-foreground",
297
546
  error: "bg-destructive-foreground",
298
547
  destructive: "bg-destructive-foreground",
299
- "gray-subtle": "bg-geist-gray-500",
300
- "green-subtle": "bg-green-500",
301
- "amber-subtle": "bg-amber-500",
302
- "red-subtle": "bg-red-500",
303
- "blue-subtle": "bg-blue-500",
304
- "purple-subtle": "bg-purple-500",
305
- "pink-subtle": "bg-pink-500",
306
- "teal-subtle": "bg-teal-500",
307
- default: "bg-primary-foreground",
548
+ "gray-subtle": "bg-muted-foreground",
549
+ "green-subtle": "bg-success",
550
+ "amber-subtle": "bg-warning",
551
+ "red-subtle": "bg-destructive",
552
+ "blue-subtle": "bg-primary",
553
+ "purple-subtle": "bg-secondary-foreground",
554
+ "pink-subtle": "bg-accent-foreground",
555
+ "teal-subtle": "bg-info",
556
+ default: "bg-brand-mark-foreground",
557
+ featured: "bg-brand-mark-foreground",
308
558
  secondary: "bg-secondary-foreground",
309
559
  outline: "bg-muted-foreground"
310
560
  };
@@ -319,7 +569,7 @@ function Badge({
319
569
  ...props
320
570
  }) {
321
571
  const badgeClassName = cn(badgeVariants({ variant, size }), className);
322
- const renderContent = (label) => /* @__PURE__ */ jsxs(Fragment, { children: [
572
+ const renderContent = (label) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
323
573
  dot && /* @__PURE__ */ jsx(
324
574
  "span",
325
575
  {
@@ -334,11 +584,11 @@ function Badge({
334
584
  label
335
585
  ] });
336
586
  if (asChild) {
337
- const childArray = React14.Children.toArray(children);
587
+ const childArray = React.Children.toArray(children);
338
588
  const child = childArray.length === 1 ? childArray[0] : null;
339
- if (React14.isValidElement(child)) {
589
+ if (React.isValidElement(child)) {
340
590
  const childProps = child.props;
341
- return React14.cloneElement(child, {
591
+ return React.cloneElement(child, {
342
592
  ...props,
343
593
  ...childProps,
344
594
  "data-slot": "badge",
@@ -350,133 +600,244 @@ function Badge({
350
600
  }
351
601
  return /* @__PURE__ */ jsx("span", { "data-slot": "badge", className: badgeClassName, ...props, children: renderContent(children) });
352
602
  }
353
- var DropdownMenu = Menu.Root;
354
- var DropdownMenuTrigger = React14.forwardRef(
355
- ({ asChild, children, render, ...props }, ref) => {
356
- const renderElement = asChild && React14.isValidElement(children) ? children : render;
357
- return /* @__PURE__ */ jsx(
358
- Menu.Trigger,
359
- {
360
- ref,
361
- render: renderElement,
362
- ...renderElement ? props : { ...props, children }
363
- }
364
- );
603
+ ({
604
+ // Nebutra Blue (云毓蓝) — technology & trust — VI: #0033FE
605
+ blue50: colors.primary[50],
606
+ blue100: colors.primary[100],
607
+ blue200: colors.primary[200],
608
+ blue300: colors.primary[300],
609
+ blue400: colors.primary[400],
610
+ blue500: colors.primary[500],
611
+ // brand primary
612
+ blue600: colors.primary[600],
613
+ blue700: colors.primary[700],
614
+ blue800: colors.primary[800],
615
+ blue900: colors.primary[900],
616
+ blue950: colors.primary[950],
617
+ // Nebutra Cyan (云毓青) — data flow & intelligence — VI: #0BF1C3
618
+ cyan50: colors.accent[50],
619
+ cyan100: colors.accent[100],
620
+ cyan200: colors.accent[200],
621
+ cyan300: colors.accent[300],
622
+ cyan400: colors.accent[400],
623
+ cyan500: colors.accent[500],
624
+ // brand secondary
625
+ cyan600: colors.accent[600],
626
+ cyan700: colors.accent[700],
627
+ cyan800: colors.accent[800],
628
+ cyan900: colors.accent[900],
629
+ cyan950: colors.accent[950],
630
+ // Neutral (blue-undertone gray scale)
631
+ neutral50: colors.neutral[50],
632
+ neutral100: colors.neutral[100],
633
+ neutral200: colors.neutral[200],
634
+ neutral300: colors.neutral[300],
635
+ neutral400: colors.neutral[400],
636
+ neutral500: colors.neutral[500],
637
+ neutral600: colors.neutral[600],
638
+ neutral700: colors.neutral[700],
639
+ neutral800: colors.neutral[800],
640
+ neutral900: colors.neutral[900],
641
+ neutral950: colors.neutral[950],
642
+ white: colors.white,
643
+ black: colors.black
644
+ });
645
+ ({
646
+ /** Hero sections, primary CTA buttons, logo fills — VI signature gradient */
647
+ primary: colors.gradient.primary,
648
+ /** Hover states, secondary gradient elements */
649
+ reverse: colors.gradient.primaryReverse,
650
+ /** Vertical layout dividers, page section separators */
651
+ vertical: colors.gradient.primaryVertical,
652
+ /** Background halos, focus glow effects, radial emphasis */
653
+ radial: colors.gradient.primaryRadial});
654
+ var primitiveSpacing = {
655
+ 1: 4,
656
+ 2: 8,
657
+ 3: 12,
658
+ 4: 16,
659
+ 5: 20,
660
+ 20: 80,
661
+ 24: 96
662
+ };
663
+ var primitiveSizing = {
664
+ /** Geist button-specific size (24px). Larger than xs by design. */
665
+ tiny: 24,
666
+ sm: 32,
667
+ md: 40,
668
+ lg: 48};
669
+ var primitiveRadius = {
670
+ md: 6,
671
+ // Geist default — slightly more rounded than 4px
672
+ lg: 8,
673
+ full: 9999
674
+ };
675
+ var primitiveFontSize = {
676
+ xs: 12,
677
+ sm: 14,
678
+ base: 16,
679
+ lg: 18};
680
+ var primitiveTransition = {
681
+ duration: {
682
+ // hover, focus, small state changes
683
+ flow: 200},
684
+ easing: {
685
+ inOut: "cubic-bezier(0.4, 0, 0.2, 1)"
365
686
  }
366
- );
367
- DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
368
- Menu.Group;
369
- Menu.Portal;
370
- Menu.SubmenuRoot;
371
- Menu.RadioGroup;
372
- var DropdownMenuSubTrigger = React14.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(
373
- Menu.SubmenuTrigger,
374
- {
375
- ref,
376
- className: cn(
377
- "flex cursor-default select-none items-center rounded-[var(--radius-md)] px-2 py-1.5 text-sm outline-none focus:bg-accent data-[popup-open]:bg-accent",
378
- inset && "pl-8",
379
- className
380
- ),
381
- ...props,
382
- children: [
383
- children,
384
- /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto size-4" })
385
- ]
687
+ };
688
+ var primitiveFocusRing = {
689
+ width: 2,
690
+ // px
691
+ offset: 2
692
+ // px — gap between element and ring
693
+ };
694
+
695
+ // src/tokens/shadows.ts
696
+ var shadowClasses = {
697
+ md: "shadow-md",
698
+ xl: "shadow-xl"};
699
+ var overlayZIndex = {
700
+ popover: 1060,
701
+ tooltip: 1070
702
+ };
703
+ var overlayClassNames = {
704
+ menuSurface: [
705
+ "min-w-32 overflow-hidden rounded-[var(--radius-lg)] border border-border/70 bg-popover/95 p-1 text-popover-foreground backdrop-blur-md",
706
+ shadowClasses.xl,
707
+ "outline-none transition-[opacity,transform,display] duration-[var(--motion-duration-flow)] ease-[var(--ease-out)]",
708
+ "data-[starting-style]:scale-95 data-[starting-style]:opacity-0 data-[ending-style]:scale-95 data-[ending-style]:opacity-0",
709
+ "motion-reduce:transition-none motion-reduce:data-[starting-style]:transform-none motion-reduce:data-[ending-style]:transform-none"
710
+ ].join(" "),
711
+ tooltipSurface: [
712
+ "overflow-hidden rounded-[var(--radius-md)] border border-border/70 bg-popover/95 px-3 py-1.5 text-sm text-popover-foreground backdrop-blur-md",
713
+ shadowClasses.md,
714
+ "transition-[opacity,transform,display] duration-[var(--motion-duration-flow)] ease-[var(--ease-out)]",
715
+ "data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0",
716
+ "motion-reduce:transition-none motion-reduce:data-starting-style:transform-none motion-reduce:data-ending-style:transform-none"
717
+ ].join(" ")};
718
+
719
+ // src/primitives/overlay.ts
720
+ var menuItemBaseClassName = [
721
+ "relative flex cursor-default select-none items-center rounded-[var(--radius-sm)] px-2 py-1.5 text-sm",
722
+ "outline-none transition-colors duration-micro ease-out",
723
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-60"
724
+ ].join(" ");
725
+ var menuHighlightedClassName = "data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground";
726
+ var overlayPrimitiveClassNames = {
727
+ menuSurface: "rounded-[var(--radius-md)] border-border/70 bg-popover/95 shadow-md",
728
+ menuItem: [menuItemBaseClassName, menuHighlightedClassName].join(" ")};
729
+ var DropdownMenuContext = React.createContext(null);
730
+ function DropdownMenu({
731
+ open: controlledOpen,
732
+ defaultOpen = false,
733
+ onOpenChange,
734
+ children,
735
+ ...props
736
+ }) {
737
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
738
+ const open = controlledOpen ?? uncontrolledOpen;
739
+ function setOpen(nextOpen, eventDetails) {
740
+ if (controlledOpen === void 0) {
741
+ setUncontrolledOpen(nextOpen);
742
+ }
743
+ onOpenChange?.(nextOpen, eventDetails);
386
744
  }
387
- ));
388
- DropdownMenuSubTrigger.displayName = "DropdownMenuSubTrigger";
389
- var DropdownMenuSubContent = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, { children: /* @__PURE__ */ jsx(
390
- Menu.Popup,
391
- {
392
- ref,
393
- className: cn(
394
- "z-50 min-w-32 overflow-hidden rounded-xl border bg-background/90 backdrop-blur-md p-1 text-popover-foreground shadow-xl transition-[opacity,transform,display] duration-flow ease-out data-[starting-style]:zoom-out-95 data-[ending-style]:zoom-out-95 data-[starting-style]:fade-out-0 data-[ending-style]:fade-out-0",
395
- className
396
- ),
397
- ...props
745
+ const contextValue = { setOpen };
746
+ return /* @__PURE__ */ jsx(DropdownMenuContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(Menu.Root, { open, onOpenChange: setOpen, ...props, children }) });
747
+ }
748
+ DropdownMenu.displayName = "DropdownMenu";
749
+ var DropdownMenuTrigger = ({
750
+ asChild,
751
+ children,
752
+ render,
753
+ ref,
754
+ ...props
755
+ }) => {
756
+ const context = React.use(DropdownMenuContext);
757
+ function openFromTrigger() {
758
+ context?.setOpen(true);
398
759
  }
399
- ) }) }));
400
- DropdownMenuSubContent.displayName = "DropdownMenuSubContent";
401
- var DropdownMenuContent = React14.forwardRef(
402
- ({ className, sideOffset = 4, align = "center", alignOffset = 0, side = "bottom", ...props }, ref) => /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(
403
- Menu.Positioner,
760
+ const childRenderElement = asChild && React.isValidElement(children) ? React.cloneElement(children, {
761
+ onMouseDown: (event) => {
762
+ children.props.onMouseDown?.(event);
763
+ if (!event.defaultPrevented) {
764
+ openFromTrigger();
765
+ }
766
+ },
767
+ onKeyDown: (event) => {
768
+ children.props.onKeyDown?.(event);
769
+ if (!event.defaultPrevented && (event.key === "Enter" || event.key === " ")) {
770
+ openFromTrigger();
771
+ }
772
+ }
773
+ }) : null;
774
+ const renderElement = childRenderElement ?? render;
775
+ return /* @__PURE__ */ jsx(
776
+ Menu.Trigger,
404
777
  {
405
- sideOffset,
406
- align,
407
- alignOffset,
408
- side,
409
- children: /* @__PURE__ */ jsx(
410
- Menu.Popup,
411
- {
412
- ref,
413
- className: cn(
414
- "z-50 min-w-32 overflow-hidden rounded-xl border bg-background/90 backdrop-blur-md p-1 text-popover-foreground shadow-xl transition-[opacity,transform,display] duration-flow ease-out outline-none data-[starting-style]:zoom-out-95 data-[ending-style]:zoom-out-95 data-[starting-style]:fade-out-0 data-[ending-style]:fade-out-0",
415
- className
416
- ),
417
- ...props
418
- }
419
- )
778
+ ref,
779
+ render: renderElement,
780
+ ...renderElement ? props : { ...props, children }
420
781
  }
421
- ) })
422
- );
782
+ );
783
+ };
784
+ DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
785
+ Menu.Group;
786
+ Menu.Portal;
787
+ Menu.SubmenuRoot;
788
+ Menu.RadioGroup;
789
+ var DropdownMenuContent = ({
790
+ className,
791
+ style,
792
+ sideOffset = 4,
793
+ align = "center",
794
+ alignOffset = 0,
795
+ side = "bottom",
796
+ ref,
797
+ ...props
798
+ }) => /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(
799
+ Menu.Positioner,
800
+ {
801
+ sideOffset,
802
+ align,
803
+ alignOffset,
804
+ side,
805
+ children: /* @__PURE__ */ jsx(
806
+ Menu.Popup,
807
+ {
808
+ ref,
809
+ className: cn(
810
+ overlayClassNames.menuSurface,
811
+ overlayPrimitiveClassNames.menuSurface,
812
+ className
813
+ ),
814
+ style: { zIndex: overlayZIndex.popover, ...style },
815
+ ...props
816
+ }
817
+ )
818
+ }
819
+ ) });
423
820
  DropdownMenuContent.displayName = "DropdownMenuContent";
424
- var DropdownMenuItem = React14.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
821
+ var DropdownMenuItem = ({
822
+ className,
823
+ inset,
824
+ ref,
825
+ ...props
826
+ }) => /* @__PURE__ */ jsx(
425
827
  Menu.Item,
426
828
  {
427
829
  ref,
428
- className: cn(
429
- "relative flex cursor-default select-none items-center rounded-[var(--radius-md)] px-2 py-1.5 text-sm outline-none transition-colors data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
430
- inset && "pl-8",
431
- className
432
- ),
830
+ className: cn(overlayPrimitiveClassNames.menuItem, inset && "pl-8", className),
433
831
  ...props
434
832
  }
435
- ));
833
+ );
436
834
  DropdownMenuItem.displayName = "DropdownMenuItem";
437
- var DropdownMenuCheckboxItem = React14.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(
438
- Menu.CheckboxItem,
439
- {
440
- ref,
441
- className: cn(
442
- "relative flex cursor-default select-none items-center rounded-[var(--radius-md)] py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
443
- className
444
- ),
445
- ...checked !== void 0 && { checked },
446
- ...props,
447
- children: [
448
- /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(Menu.CheckboxItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "size-4" }) }) }),
449
- children
450
- ]
451
- }
452
- ));
453
- DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem";
454
- var DropdownMenuRadioItem = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
455
- Menu.RadioItem,
456
- {
457
- ref,
458
- className: cn(
459
- "relative flex cursor-default select-none items-center rounded-[var(--radius-md)] py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
460
- className
461
- ),
462
- ...props,
463
- children: [
464
- /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(Menu.RadioItemIndicator, { children: /* @__PURE__ */ jsx(Status, { className: "size-2 fill-current" }) }) }),
465
- children
466
- ]
467
- }
468
- ));
469
- DropdownMenuRadioItem.displayName = "DropdownMenuRadioItem";
470
- var DropdownMenuLabel = React14.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
471
- Menu.GroupLabel,
472
- {
473
- ref,
474
- className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
475
- ...props
476
- }
477
- ));
478
- DropdownMenuLabel.displayName = "DropdownMenuLabel";
479
- var DropdownMenuSeparator = React14.forwardRef(({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ jsx(
835
+ var DropdownMenuSeparator = ({
836
+ className,
837
+ orientation = "horizontal",
838
+ ref,
839
+ ...props
840
+ }) => /* @__PURE__ */ jsx(
480
841
  Menu.Separator,
481
842
  {
482
843
  ref,
@@ -484,7 +845,7 @@ var DropdownMenuSeparator = React14.forwardRef(({ className, orientation = "hori
484
845
  className: cn("-mx-1 my-1 h-px bg-muted", className),
485
846
  ...props
486
847
  }
487
- ));
848
+ );
488
849
  DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
489
850
  var iconToneStyles = {
490
851
  neutral: "bg-muted text-muted-foreground",
@@ -503,15 +864,15 @@ var badgeToneToVariant = {
503
864
  "coming-soon": "coming-soon"
504
865
  };
505
866
  var cardClassName = cn(
506
- "group relative block rounded-xl border border-border bg-card text-card-foreground p-5 text-left",
507
- "transition-all duration-150",
508
- "hover:border-neutral-7 hover:shadow-sm hover:-translate-y-px",
509
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
867
+ "group relative block rounded-[var(--radius-xl)] border border-border bg-card text-card-foreground p-5 text-left",
868
+ "transition-[border-color,box-shadow,transform] duration-micro motion-reduce:transition-none motion-reduce:transform-none",
869
+ "hover:border-neutral-7 hover:shadow-sm hover:-translate-y-px motion-reduce:hover:translate-y-0",
870
+ "focus-visible:outline-none"
510
871
  );
511
872
  function GalleryCardActionsMenu({ actions, title }) {
512
- const stop = React14.useCallback((event) => {
873
+ function stop(event) {
513
874
  event.stopPropagation();
514
- }, []);
875
+ }
515
876
  return /* @__PURE__ */ jsx("div", { onClickCapture: stop, onPointerDownCapture: stop, children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
516
877
  /* @__PURE__ */ jsx(
517
878
  DropdownMenuTrigger,
@@ -522,10 +883,10 @@ function GalleryCardActionsMenu({ actions, title }) {
522
883
  type: "button",
523
884
  "aria-label": `Actions for ${title}`,
524
885
  className: cn(
525
- "inline-flex h-7 w-7 items-center justify-center rounded-md",
886
+ "inline-flex h-7 w-7 items-center justify-center rounded-[var(--radius-md)]",
526
887
  "text-muted-foreground transition-colors",
527
888
  "hover:bg-accent hover:text-accent-foreground",
528
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
889
+ "focus-visible:outline-none"
529
890
  ),
530
891
  children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-4 w-4" })
531
892
  }
@@ -560,13 +921,13 @@ function GalleryCardBody({
560
921
  }) {
561
922
  const hasActions = Boolean(actions && actions.length > 0);
562
923
  const hasMetadataStrip = Boolean(metadata?.author || metadata?.metric || metadata?.trailing);
563
- return /* @__PURE__ */ jsxs(Fragment, { children: [
924
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
564
925
  /* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-start justify-between gap-2", children: [
565
926
  icon ? /* @__PURE__ */ jsx(
566
927
  "div",
567
928
  {
568
929
  className: cn(
569
- "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-base",
930
+ "flex h-10 w-10 shrink-0 items-center justify-center rounded-[var(--radius-lg)] text-base",
570
931
  iconToneStyles[iconTone]
571
932
  ),
572
933
  "aria-hidden": "true",
@@ -620,36 +981,418 @@ function GalleryCard(props) {
620
981
  actions
621
982
  }
622
983
  );
623
- const composedClassName = cn(cardClassName, "cursor-pointer", className);
624
- if (href) {
625
- if (renderLink) {
626
- return renderLink({
627
- href,
628
- className: composedClassName,
629
- "aria-label": title,
630
- children: body
631
- });
984
+ const composedClassName = cn(cardClassName, "cursor-pointer", className);
985
+ if (href) {
986
+ if (renderLink) {
987
+ return renderLink({
988
+ href,
989
+ className: composedClassName,
990
+ "aria-label": title,
991
+ children: body
992
+ });
993
+ }
994
+ return /* @__PURE__ */ jsx("a", { href, "aria-label": title, className: composedClassName, onClick, children: body });
995
+ }
996
+ if (onClick) {
997
+ return /* @__PURE__ */ jsx("button", { type: "button", "aria-label": title, className: composedClassName, onClick, children: body });
998
+ }
999
+ return /* @__PURE__ */ jsx("div", { className: cn(cardClassName, "cursor-default", className), children: body });
1000
+ }
1001
+ GalleryCard.displayName = "GalleryCard";
1002
+ function lineTone(line) {
1003
+ const trimmed = line.trim();
1004
+ if (trimmed.startsWith("//") || trimmed.startsWith("--")) {
1005
+ return "text-muted-foreground/55 italic";
1006
+ }
1007
+ if (/\b(await|const|export|return|CREATE|ALTER|POLICY|USING|ENABLE|TABLE)\b/.test(trimmed)) {
1008
+ return "text-primary font-medium";
1009
+ }
1010
+ if (trimmed.includes(":")) {
1011
+ return "text-emerald-600 dark:text-emerald-400";
1012
+ }
1013
+ return "text-foreground/78";
1014
+ }
1015
+ function renderIcon(icon) {
1016
+ if (!icon) {
1017
+ return null;
1018
+ }
1019
+ if (typeof icon === "function") {
1020
+ const Icon = icon;
1021
+ return /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, className: "size-7 text-primary" });
1022
+ }
1023
+ if (isValidElement(icon)) {
1024
+ return /* @__PURE__ */ jsx(
1025
+ "span",
1026
+ {
1027
+ "aria-hidden": true,
1028
+ className: "inline-grid place-items-center text-primary [&_svg]:size-7 [&_svg]:text-primary",
1029
+ children: icon
1030
+ }
1031
+ );
1032
+ }
1033
+ return icon;
1034
+ }
1035
+ function KineticFeatureCard({
1036
+ icon,
1037
+ eyebrow,
1038
+ title,
1039
+ description,
1040
+ children,
1041
+ className,
1042
+ ...props
1043
+ }) {
1044
+ const renderedIcon = renderIcon(icon);
1045
+ return /* @__PURE__ */ jsxs(
1046
+ "article",
1047
+ {
1048
+ className: cn(
1049
+ "group/kinetic relative flex h-full min-h-[540px] flex-col overflow-hidden rounded-[var(--radius-panel)] border border-border/65 bg-background/82 p-6 shadow-glass-md backdrop-blur-2xl transition-[transform,border-color,box-shadow,background-color] duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] hover:-translate-y-1 hover:border-foreground/25 hover:bg-background/94 hover:shadow-glass-lg focus-within:-translate-y-1 focus-within:border-foreground/25 sm:p-7",
1050
+ className
1051
+ ),
1052
+ "data-taste": "nebutra-texture-cutout-card",
1053
+ ...props,
1054
+ children: [
1055
+ /* @__PURE__ */ jsx(
1056
+ "div",
1057
+ {
1058
+ "aria-hidden": "true",
1059
+ className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_1px_1px,var(--neutral-8)_1px,transparent_0)] bg-[length:18px_18px] opacity-[0.12]"
1060
+ }
1061
+ ),
1062
+ /* @__PURE__ */ jsx(
1063
+ "div",
1064
+ {
1065
+ "aria-hidden": "true",
1066
+ className: "pointer-events-none absolute inset-x-0 top-0 h-40 bg-gradient-to-b from-primary/12 via-primary/5 to-transparent",
1067
+ style: { maskImage: "linear-gradient(to bottom, black 45%, transparent 100%)" }
1068
+ }
1069
+ ),
1070
+ /* @__PURE__ */ jsx("div", { className: "absolute right-0 top-0 z-10 rounded-bl-[2rem] border-b border-l border-border/60 bg-muted/55 px-4 py-2 backdrop-blur-xl", children: /* @__PURE__ */ jsx("span", { className: "font-mono text-[10px] font-semibold uppercase tracking-[0.18em] text-muted-foreground", children: eyebrow }) }),
1071
+ /* @__PURE__ */ jsxs("div", { className: "relative z-10 flex h-full flex-col", children: [
1072
+ /* @__PURE__ */ jsx("div", { className: "mb-8 flex items-start justify-between gap-4 pr-16", children: renderedIcon && /* @__PURE__ */ jsx("div", { className: "grid size-14 place-items-center rounded-[var(--radius-xl)] border border-border/65 bg-background/75 shadow-glass-sm transition-transform duration-500 group-hover/kinetic:-translate-y-1", children: renderedIcon }) }),
1073
+ /* @__PURE__ */ jsx(
1074
+ "h3",
1075
+ {
1076
+ className: "text-2xl font-semibold text-foreground text-balance",
1077
+ style: { letterSpacing: "var(--tracking-heading)", lineHeight: "var(--leading-heading)" },
1078
+ children: title
1079
+ }
1080
+ ),
1081
+ /* @__PURE__ */ jsx("p", { className: "mt-4 text-base font-medium leading-7 text-muted-foreground text-balance", children: description }),
1082
+ /* @__PURE__ */ jsx("div", { className: "mt-auto pt-8", children })
1083
+ ] })
1084
+ ]
1085
+ }
1086
+ );
1087
+ }
1088
+ function KineticCodePreview({
1089
+ filename = "artifact.ts",
1090
+ language = "ts",
1091
+ lines,
1092
+ className,
1093
+ ...props
1094
+ }) {
1095
+ return /* @__PURE__ */ jsxs(
1096
+ "div",
1097
+ {
1098
+ className: cn(
1099
+ "relative overflow-hidden rounded-[var(--radius-xl)] border border-border/60 bg-muted/30 shadow-ambient-md transition-[transform,border-color,box-shadow] duration-500 group-hover/kinetic:-translate-y-2 group-hover/kinetic:border-foreground/20 group-hover/kinetic:shadow-ambient-lg",
1100
+ className
1101
+ ),
1102
+ ...props,
1103
+ children: [
1104
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-border/60 bg-background/70 px-4 py-3 backdrop-blur-xl", children: [
1105
+ /* @__PURE__ */ jsx("span", { className: "size-2.5 rounded-full bg-border/90", "aria-hidden": true }),
1106
+ /* @__PURE__ */ jsx("span", { className: "size-2.5 rounded-full bg-border/80", "aria-hidden": true }),
1107
+ /* @__PURE__ */ jsx("span", { className: "size-2.5 rounded-full bg-border/70", "aria-hidden": true }),
1108
+ /* @__PURE__ */ jsx(
1109
+ "span",
1110
+ {
1111
+ className: "ml-3 min-w-0 truncate font-mono text-[11px] text-muted-foreground",
1112
+ translate: "no",
1113
+ children: filename
1114
+ }
1115
+ ),
1116
+ /* @__PURE__ */ jsx("span", { className: "ml-auto rounded-full border border-border/60 bg-background/60 px-2 py-0.5 font-mono text-[10px] uppercase text-muted-foreground", children: language })
1117
+ ] }),
1118
+ /* @__PURE__ */ jsx("pre", { className: "relative max-h-[190px] overflow-hidden p-4 font-mono text-[12px] leading-5", children: lines.map((line, index) => /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 gap-3", children: [
1119
+ /* @__PURE__ */ jsx("span", { className: "w-5 shrink-0 text-right text-muted-foreground/45 tabular-nums", children: index + 1 }),
1120
+ /* @__PURE__ */ jsx("code", { className: cn("min-w-0 truncate", lineTone(line)), translate: "no", children: line || " " })
1121
+ ] }, `${line}-${index}`)) })
1122
+ ]
1123
+ }
1124
+ );
1125
+ }
1126
+ function KineticConsoleFrame({
1127
+ title = "operator@nebutra-sailor: ~",
1128
+ status,
1129
+ children,
1130
+ className,
1131
+ ...props
1132
+ }) {
1133
+ return /* @__PURE__ */ jsxs(
1134
+ "div",
1135
+ {
1136
+ className: cn(
1137
+ "group/kinetic relative flex h-full min-h-[460px] w-full flex-col overflow-hidden rounded-[2rem] border border-border/65 bg-background/84 shadow-glass-md backdrop-blur-3xl transition-[transform,border-color,box-shadow] duration-500 hover:-translate-y-1 hover:border-foreground/25 hover:shadow-glass-lg",
1138
+ className
1139
+ ),
1140
+ "data-taste": "nebutra-terminal-animation",
1141
+ ...props,
1142
+ children: [
1143
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 flex-none items-center gap-4 border-b border-border/60 bg-background/70 px-5 backdrop-blur-xl", children: [
1144
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", "aria-hidden": true, children: [
1145
+ /* @__PURE__ */ jsx("span", { className: "size-3 rounded-full border border-border/80 bg-muted shadow-sm transition-colors group-hover/kinetic:bg-red-400/80" }),
1146
+ /* @__PURE__ */ jsx("span", { className: "size-3 rounded-full border border-border/80 bg-muted shadow-sm transition-colors group-hover/kinetic:bg-amber-400/80" }),
1147
+ /* @__PURE__ */ jsx("span", { className: "size-3 rounded-full border border-border/80 bg-muted shadow-sm transition-colors group-hover/kinetic:bg-emerald-400/80" })
1148
+ ] }),
1149
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 text-center", children: /* @__PURE__ */ jsx("span", { className: "inline-flex max-w-full items-center rounded-[var(--radius-md)] border border-border/50 bg-muted/35 px-4 py-1 font-mono text-[10px] font-semibold uppercase tracking-[0.16em] text-muted-foreground", children: /* @__PURE__ */ jsx("span", { className: "truncate", translate: "no", children: title }) }) }),
1150
+ /* @__PURE__ */ jsx("div", { className: "hidden min-w-20 justify-end sm:flex", children: status && /* @__PURE__ */ jsx("span", { className: "rounded-full border border-border/55 bg-background/65 px-2 py-0.5 font-mono text-[10px] uppercase text-muted-foreground", children: status }) })
1151
+ ] }),
1152
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1 overflow-hidden bg-gradient-to-br from-background/55 via-background/25 to-muted/28 p-6 sm:p-8", children: [
1153
+ /* @__PURE__ */ jsx(
1154
+ "div",
1155
+ {
1156
+ "aria-hidden": "true",
1157
+ className: "pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,var(--neutral-6)_1px,transparent_1px),linear-gradient(to_bottom,var(--neutral-6)_1px,transparent_1px)] bg-[size:16px_24px] opacity-45"
1158
+ }
1159
+ ),
1160
+ /* @__PURE__ */ jsx(
1161
+ "div",
1162
+ {
1163
+ "aria-hidden": "true",
1164
+ className: "pointer-events-none absolute inset-x-0 bottom-0 h-28 bg-gradient-to-t from-background/80 to-transparent"
1165
+ }
1166
+ ),
1167
+ /* @__PURE__ */ jsx("div", { className: "relative z-10 h-full w-full", children })
1168
+ ] })
1169
+ ]
1170
+ }
1171
+ );
1172
+ }
1173
+ function KineticMorphSurface({
1174
+ activeKey,
1175
+ className,
1176
+ children,
1177
+ ...props
1178
+ }) {
1179
+ return /* @__PURE__ */ jsxs(
1180
+ "div",
1181
+ {
1182
+ className: cn(
1183
+ "group/kinetic relative overflow-hidden rounded-[var(--radius-panel)] border border-border/65 bg-background/80 p-3 shadow-glass-md backdrop-blur-2xl transition-[border-color,box-shadow,background-color] duration-500 hover:border-foreground/20 hover:bg-background/92 hover:shadow-glass-lg sm:p-4 lg:p-5",
1184
+ className
1185
+ ),
1186
+ "data-active-key": activeKey,
1187
+ "data-taste": "nebutra-morph-surface",
1188
+ ...props,
1189
+ children: [
1190
+ /* @__PURE__ */ jsx(
1191
+ "div",
1192
+ {
1193
+ "aria-hidden": "true",
1194
+ className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_1px_1px,var(--neutral-8)_1px,transparent_0)] bg-[length:20px_20px] opacity-[0.10]"
1195
+ }
1196
+ ),
1197
+ /* @__PURE__ */ jsx(
1198
+ "div",
1199
+ {
1200
+ "aria-hidden": "true",
1201
+ className: "pointer-events-none absolute inset-x-0 top-0 h-36 bg-gradient-to-b from-primary/12 via-primary/4 to-transparent",
1202
+ style: { maskImage: "linear-gradient(to bottom, black 45%, transparent 100%)" }
1203
+ }
1204
+ ),
1205
+ /* @__PURE__ */ jsx("div", { className: "relative z-10", children })
1206
+ ]
1207
+ }
1208
+ );
1209
+ }
1210
+ function KineticSignalMarquee({
1211
+ eyebrow,
1212
+ className,
1213
+ children,
1214
+ ...props
1215
+ }) {
1216
+ return /* @__PURE__ */ jsxs(
1217
+ "div",
1218
+ {
1219
+ className: cn(
1220
+ "group/kinetic relative mx-auto overflow-hidden rounded-[var(--radius-panel)] border border-border/55 bg-background/72 px-3 py-8 shadow-glass-md backdrop-blur-2xl sm:px-5",
1221
+ className
1222
+ ),
1223
+ "data-taste": "nebutra-provider-grid",
1224
+ ...props,
1225
+ children: [
1226
+ /* @__PURE__ */ jsx(
1227
+ "div",
1228
+ {
1229
+ "aria-hidden": "true",
1230
+ className: "pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,var(--neutral-6)_1px,transparent_1px),linear-gradient(to_bottom,var(--neutral-6)_1px,transparent_1px)] bg-[size:32px_32px] opacity-25"
1231
+ }
1232
+ ),
1233
+ /* @__PURE__ */ jsx(
1234
+ "div",
1235
+ {
1236
+ "aria-hidden": "true",
1237
+ className: "pointer-events-none absolute inset-y-0 left-0 w-28 bg-gradient-to-r from-background via-background/90 to-transparent z-20"
1238
+ }
1239
+ ),
1240
+ /* @__PURE__ */ jsx(
1241
+ "div",
1242
+ {
1243
+ "aria-hidden": "true",
1244
+ className: "pointer-events-none absolute inset-y-0 right-0 w-28 bg-gradient-to-l from-background via-background/90 to-transparent z-20"
1245
+ }
1246
+ ),
1247
+ eyebrow && /* @__PURE__ */ jsx("div", { className: "relative z-30 mb-6 text-center font-mono text-[10px] font-semibold uppercase tracking-[0.2em] text-muted-foreground", children: eyebrow }),
1248
+ /* @__PURE__ */ jsx("div", { className: "relative z-10", children })
1249
+ ]
1250
+ }
1251
+ );
1252
+ }
1253
+ function KineticCommandBox({
1254
+ command,
1255
+ copyLabel,
1256
+ copiedLabel,
1257
+ className,
1258
+ ...props
1259
+ }) {
1260
+ const [copied, setCopied] = useState(false);
1261
+ const handleCopy = async () => {
1262
+ await navigator.clipboard.writeText(command);
1263
+ setCopied(true);
1264
+ window.setTimeout(() => setCopied(false), 2e3);
1265
+ };
1266
+ return /* @__PURE__ */ jsxs(
1267
+ "div",
1268
+ {
1269
+ className: cn(
1270
+ "group/kinetic relative flex flex-col items-stretch overflow-hidden rounded-[var(--radius-xl)] border border-border/65 bg-background/82 p-1.5 shadow-glass-sm backdrop-blur-2xl transition-[transform,border-color,box-shadow,background-color] duration-500 hover:-translate-y-1 hover:border-foreground/25 hover:bg-background/92 hover:shadow-glass-md sm:flex-row sm:items-center",
1271
+ className
1272
+ ),
1273
+ "data-taste": "nebutra-texture-command",
1274
+ ...props,
1275
+ children: [
1276
+ /* @__PURE__ */ jsx(
1277
+ "div",
1278
+ {
1279
+ "aria-hidden": "true",
1280
+ className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_1px_1px,var(--neutral-8)_1px,transparent_0)] bg-[length:16px_16px] opacity-[0.10]"
1281
+ }
1282
+ ),
1283
+ /* @__PURE__ */ jsxs("code", { className: "relative z-10 flex-1 overflow-x-auto whitespace-nowrap px-4 py-3.5 font-mono text-xs text-foreground sm:px-5 sm:text-sm md:text-base", children: [
1284
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "$" }),
1285
+ " ",
1286
+ command
1287
+ ] }),
1288
+ /* @__PURE__ */ jsxs(
1289
+ "button",
1290
+ {
1291
+ type: "button",
1292
+ onClick: handleCopy,
1293
+ className: "relative z-10 mt-2 flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-[var(--radius-lg)] border border-primary/20 bg-foreground px-5 py-2.5 text-sm font-medium text-background shadow-sheen transition-[transform,opacity] hover:-translate-y-px hover:opacity-90 sm:mt-0",
1294
+ children: [
1295
+ copied ? /* @__PURE__ */ jsx(Check, { className: "size-4" }) : /* @__PURE__ */ jsx(Copy, { className: "size-4" }),
1296
+ copied ? copiedLabel : copyLabel
1297
+ ]
1298
+ }
1299
+ )
1300
+ ]
1301
+ }
1302
+ );
1303
+ }
1304
+ function KineticStepRail({ className, children, ...props }) {
1305
+ return /* @__PURE__ */ jsxs(
1306
+ "div",
1307
+ {
1308
+ className: cn(
1309
+ "relative overflow-hidden rounded-[var(--radius-panel)] border border-border/65 bg-background/78 p-6 shadow-glass-md backdrop-blur-2xl md:p-10",
1310
+ className
1311
+ ),
1312
+ "data-taste": "nebutra-grid-beam",
1313
+ ...props,
1314
+ children: [
1315
+ /* @__PURE__ */ jsx(
1316
+ "div",
1317
+ {
1318
+ "aria-hidden": "true",
1319
+ className: "pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,var(--neutral-6)_1px,transparent_1px),linear-gradient(to_bottom,var(--neutral-6)_1px,transparent_1px)] bg-[size:36px_36px] opacity-30"
1320
+ }
1321
+ ),
1322
+ /* @__PURE__ */ jsx(
1323
+ "div",
1324
+ {
1325
+ "aria-hidden": "true",
1326
+ className: "pointer-events-none absolute left-8 right-8 top-[5.7rem] hidden h-px bg-gradient-to-r from-transparent via-primary/45 to-transparent md:block"
1327
+ }
1328
+ ),
1329
+ /* @__PURE__ */ jsx(
1330
+ "div",
1331
+ {
1332
+ "aria-hidden": "true",
1333
+ className: "pointer-events-none absolute left-1/2 top-8 bottom-8 w-px -translate-x-1/2 bg-gradient-to-b from-transparent via-primary/35 to-transparent md:hidden"
1334
+ }
1335
+ ),
1336
+ /* @__PURE__ */ jsx("div", { className: "relative z-10", children })
1337
+ ]
1338
+ }
1339
+ );
1340
+ }
1341
+ function KineticStep({
1342
+ icon: Icon,
1343
+ index,
1344
+ title,
1345
+ description,
1346
+ phaseLabel,
1347
+ className,
1348
+ ...props
1349
+ }) {
1350
+ const formatted = String(index).padStart(2, "0");
1351
+ return /* @__PURE__ */ jsxs(
1352
+ "article",
1353
+ {
1354
+ className: cn(
1355
+ "group/kinetic relative flex h-full flex-col items-center rounded-[var(--radius-xl)] border border-border/60 bg-background/82 p-5 text-center shadow-ambient-md backdrop-blur-xl transition-[transform,border-color,box-shadow] duration-500 hover:-translate-y-1 hover:border-foreground/25 hover:shadow-ambient-lg",
1356
+ className
1357
+ ),
1358
+ ...props,
1359
+ children: [
1360
+ /* @__PURE__ */ jsxs("div", { className: "relative mb-6 grid size-16 place-items-center rounded-[var(--radius-xl)] border border-border/65 bg-background shadow-glass-sm", children: [
1361
+ /* @__PURE__ */ jsx(
1362
+ "span",
1363
+ {
1364
+ className: "absolute -right-2 -top-2 rounded-full border border-border/60 bg-muted px-2 py-0.5 font-mono text-[10px] text-muted-foreground",
1365
+ "aria-hidden": true,
1366
+ children: formatted
1367
+ }
1368
+ ),
1369
+ Icon && /* @__PURE__ */ jsx(
1370
+ Icon,
1371
+ {
1372
+ "aria-hidden": true,
1373
+ className: "size-7 text-primary transition-colors group-hover/kinetic:text-foreground"
1374
+ }
1375
+ )
1376
+ ] }),
1377
+ /* @__PURE__ */ jsx("span", { className: "mb-4 rounded-full border border-primary/20 bg-primary/7 px-3 py-1 font-mono text-[10px] font-semibold uppercase tracking-[0.16em] text-primary", children: phaseLabel ?? `Phase ${formatted}` }),
1378
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground", children: title }),
1379
+ /* @__PURE__ */ jsx("p", { className: "mt-3 text-sm leading-6 text-muted-foreground text-balance", children: description })
1380
+ ]
632
1381
  }
633
- return /* @__PURE__ */ jsx("a", { href, "aria-label": title, className: composedClassName, onClick, children: body });
634
- }
635
- if (onClick) {
636
- return /* @__PURE__ */ jsx("button", { type: "button", "aria-label": title, className: composedClassName, onClick, children: body });
637
- }
638
- return /* @__PURE__ */ jsx("div", { className: cn(cardClassName, "cursor-default", className), children: body });
1382
+ );
639
1383
  }
640
- GalleryCard.displayName = "GalleryCard";
641
- var Slot = React14.forwardRef(
1384
+ var Slot = React.forwardRef(
642
1385
  ({ children, className, style, ...props }, ref) => {
643
- const childArray = React14.Children.toArray(children);
1386
+ const childArray = React.Children.toArray(children);
644
1387
  const child = childArray.length === 1 ? childArray[0] : null;
645
- if (child == null || !React14.isValidElement(child)) {
1388
+ if (child == null || !React.isValidElement(child)) {
646
1389
  return /* @__PURE__ */ jsx("span", { ref, className, style, ...props, children });
647
1390
  }
648
1391
  const childProps = child.props;
649
1392
  const mergedRef = (node) => {
650
1393
  if (typeof ref === "function") ref(node);
651
1394
  else if (ref) ref.current = node;
652
- const childRef = child.ref;
1395
+ const childRef = childProps.ref;
653
1396
  if (typeof childRef === "function") childRef(node);
654
1397
  else if (childRef && "current" in childRef) {
655
1398
  childRef.current = node;
@@ -663,7 +1406,7 @@ var Slot = React14.forwardRef(
663
1406
  className: mergedClass,
664
1407
  style: { ...childProps.style, ...style }
665
1408
  };
666
- return React14.cloneElement(
1409
+ return React.cloneElement(
667
1410
  child,
668
1411
  merged
669
1412
  );
@@ -673,17 +1416,18 @@ Slot.displayName = "Slot";
673
1416
  var buttonVariants = cva(
674
1417
  [
675
1418
  "inline-flex items-center justify-center gap-2 whitespace-nowrap",
676
- "rounded-[var(--radius-md)] text-sm font-medium",
677
- "transition-colors duration-150 ease-out",
678
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
1419
+ "rounded-[var(--btn-default-radius,var(--radius-md))]",
1420
+ "text-[length:var(--control-font-size-md,0.875rem)] font-[number:var(--font-weight-medium,500)]",
1421
+ "transition-colors duration-micro ease-out",
679
1422
  "disabled:pointer-events-none disabled:opacity-50",
680
1423
  "aria-busy:cursor-wait"
681
1424
  ].join(" "),
682
1425
  {
683
1426
  variants: {
684
1427
  variant: {
685
- default: "bg-primary text-primary-foreground hover:bg-primary/90",
686
- ink: "bg-[var(--neutral-12)] text-[var(--neutral-1)] ring-1 ring-inset ring-white/[0.04] hover:bg-[var(--neutral-11)] hover:-translate-y-px active:translate-y-0 transition-[transform,background-color] duration-150",
1428
+ // Recipe-driven via packages/design/tokens/recipe.css (.btn-brand-default)
1429
+ default: "btn-brand-default",
1430
+ ink: "bg-[var(--neutral-12)] text-[var(--neutral-1)] ring-1 ring-inset ring-[color:var(--neutral-1)]/5 hover:bg-[var(--neutral-11)] hover:-translate-y-px active:translate-y-0 transition-[transform,background-color] duration-micro",
687
1431
  destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
688
1432
  outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
689
1433
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
@@ -693,34 +1437,99 @@ var buttonVariants = cva(
693
1437
  warning: "bg-warning text-warning-foreground hover:bg-warning/90"
694
1438
  },
695
1439
  size: {
696
- tiny: "h-6 rounded-[var(--radius-sm)] px-2 text-[11px]",
697
- // 24px
698
- sm: "h-8 rounded-[var(--radius-sm)] px-3 text-xs",
699
- // 32px
700
- default: "h-10 px-4 py-2",
701
- // 40px
702
- lg: "h-12 rounded-[var(--radius-lg)] px-5 text-base",
703
- // 48px
704
- icon: "h-10 w-10"
705
- // 40×40px (kept for backward compat)
1440
+ tiny: "h-[var(--control-height-tiny,1.5rem)] rounded-[var(--radius-sm)] px-2 text-[length:var(--control-font-size-tiny,0.6875rem)]",
1441
+ sm: "h-[var(--control-height-sm,2rem)] rounded-[var(--radius-sm)] px-3 text-[length:var(--control-font-size-sm,0.75rem)]",
1442
+ default: "h-[var(--control-height-md,2.5rem)] px-[var(--btn-default-padding-x,1rem)] py-[var(--btn-default-padding-y,0.5rem)]",
1443
+ lg: "h-[var(--control-height-lg,3rem)] rounded-[var(--radius-lg)] px-5 text-[length:var(--control-font-size-lg,1rem)]",
1444
+ icon: "h-[var(--control-height-md,2.5rem)] w-[var(--control-height-md,2.5rem)]"
706
1445
  },
707
1446
  shape: {
708
1447
  default: "",
709
- square: "",
710
- circle: ""
1448
+ // Radius from --btn-default-radius / --radius-md — brand-switchable.
1449
+ // Do not hardcode rounded-md here; a language must be able to retarget
1450
+ // the corner treatment of every icon trigger at once.
1451
+ square: "rounded-[var(--btn-default-radius,var(--radius-md))]",
1452
+ // Pill radius token, not Tailwind rounded-full — same 9999px default,
1453
+ // but a brand that ships a softer "circle" can override --radius-pill.
1454
+ circle: "rounded-[var(--radius-pill,9999px)]",
1455
+ pill: "rounded-[var(--radius-pill,9999px)]"
1456
+ },
1457
+ // Icon-only box size — orthogonal to `size` (which tunes text-button
1458
+ // height/padding/font together) and to `shape` (which picks the
1459
+ // corner treatment). Only takes effect combined with shape="square"
1460
+ // or shape="circle" (see compoundVariants below); every other
1461
+ // combination ignores it. 28/32/36 cover the icon-trigger sizes that
1462
+ // actually occur in the app — 24/40/48 are already reachable via
1463
+ // shape + size (tiny/default/lg). Heights read --control-height-icon-*
1464
+ // so density-aware Brand Packages can scale them with the ladder.
1465
+ iconSize: {
1466
+ sm: "",
1467
+ // 28px default
1468
+ md: "",
1469
+ // 32px default
1470
+ lg: ""
1471
+ // 36px default
711
1472
  }
712
1473
  },
713
1474
  compoundVariants: [
714
- // shape="square" — width = height, no horizontal padding
715
- { shape: "square", size: "tiny", className: "w-6 px-0" },
716
- { shape: "square", size: "sm", className: "w-8 px-0" },
717
- { shape: "square", size: "default", className: "w-10 px-0" },
718
- { shape: "square", size: "lg", className: "w-12 px-0" },
719
- // shape="circle" — width = height + rounded-full
720
- { shape: "circle", size: "tiny", className: "w-6 px-0 rounded-full" },
721
- { shape: "circle", size: "sm", className: "w-8 px-0 rounded-full" },
722
- { shape: "circle", size: "default", className: "w-10 px-0 rounded-full" },
723
- { shape: "circle", size: "lg", className: "w-12 px-0 rounded-full" }
1475
+ { shape: "square", size: "tiny", className: "w-[var(--control-height-tiny,1.5rem)] px-0" },
1476
+ { shape: "square", size: "sm", className: "w-[var(--control-height-sm,2rem)] px-0" },
1477
+ { shape: "square", size: "default", className: "w-[var(--control-height-md,2.5rem)] px-0" },
1478
+ { shape: "square", size: "lg", className: "w-[var(--control-height-lg,3rem)] px-0" },
1479
+ {
1480
+ shape: "circle",
1481
+ size: "tiny",
1482
+ className: "w-[var(--control-height-tiny,1.5rem)] px-0"
1483
+ },
1484
+ {
1485
+ shape: "circle",
1486
+ size: "sm",
1487
+ className: "w-[var(--control-height-sm,2rem)] px-0"
1488
+ },
1489
+ {
1490
+ shape: "circle",
1491
+ size: "default",
1492
+ className: "w-[var(--control-height-md,2.5rem)] px-0"
1493
+ },
1494
+ {
1495
+ shape: "circle",
1496
+ size: "lg",
1497
+ className: "w-[var(--control-height-lg,3rem)] px-0"
1498
+ },
1499
+ // iconSize wins over the size-driven box above — matched on shape +
1500
+ // iconSize only, so it applies regardless of whatever `size` was
1501
+ // passed (or left at its "default" fallback). Corner treatment stays
1502
+ // on the shape variant (token-backed); only the box is set here.
1503
+ {
1504
+ shape: "square",
1505
+ iconSize: "sm",
1506
+ className: "h-[var(--control-height-icon-sm,1.75rem)] w-[var(--control-height-icon-sm,1.75rem)] px-0"
1507
+ },
1508
+ {
1509
+ shape: "square",
1510
+ iconSize: "md",
1511
+ className: "h-[var(--control-height-icon-md,2rem)] w-[var(--control-height-icon-md,2rem)] px-0"
1512
+ },
1513
+ {
1514
+ shape: "square",
1515
+ iconSize: "lg",
1516
+ className: "h-[var(--control-height-icon-lg,2.25rem)] w-[var(--control-height-icon-lg,2.25rem)] px-0"
1517
+ },
1518
+ {
1519
+ shape: "circle",
1520
+ iconSize: "sm",
1521
+ className: "h-[var(--control-height-icon-sm,1.75rem)] w-[var(--control-height-icon-sm,1.75rem)] px-0"
1522
+ },
1523
+ {
1524
+ shape: "circle",
1525
+ iconSize: "md",
1526
+ className: "h-[var(--control-height-icon-md,2rem)] w-[var(--control-height-icon-md,2rem)] px-0"
1527
+ },
1528
+ {
1529
+ shape: "circle",
1530
+ iconSize: "lg",
1531
+ className: "h-[var(--control-height-icon-lg,2.25rem)] w-[var(--control-height-icon-lg,2.25rem)] px-0"
1532
+ }
724
1533
  ],
725
1534
  defaultVariants: {
726
1535
  variant: "default",
@@ -741,7 +1550,10 @@ function Spinner({ className }) {
741
1550
  }
742
1551
  );
743
1552
  }
744
- function getIconSizeClass(size) {
1553
+ function getIconSizeClass(size, iconSize) {
1554
+ if (iconSize === "sm") return "[&>svg]:size-3.5";
1555
+ if (iconSize === "md") return "[&>svg]:size-3.5";
1556
+ if (iconSize === "lg") return "[&>svg]:size-4";
745
1557
  switch (size) {
746
1558
  case "tiny":
747
1559
  return "[&>svg]:size-3";
@@ -756,7 +1568,10 @@ function getIconSizeClass(size) {
756
1568
  return "[&>svg]:size-4";
757
1569
  }
758
1570
  }
759
- function getSpinnerSizeClass(size) {
1571
+ function getSpinnerSizeClass(size, iconSize) {
1572
+ if (iconSize === "sm") return "size-3.5";
1573
+ if (iconSize === "md") return "size-3.5";
1574
+ if (iconSize === "lg") return "size-4";
760
1575
  switch (size) {
761
1576
  case "tiny":
762
1577
  return "size-3";
@@ -774,182 +1589,64 @@ function getSpinnerSizeClass(size) {
774
1589
  var SHADOW_CLASSES = {
775
1590
  sm: "shadow-sm",
776
1591
  md: "shadow-md",
777
- lg: "shadow-lg"
1592
+ lg: "shadow-md"
778
1593
  };
779
1594
  function resolveShadowClass(shadow) {
780
1595
  if (!shadow) return void 0;
781
1596
  const level = shadow === true ? "md" : shadow;
782
1597
  return SHADOW_CLASSES[level];
783
1598
  }
784
- function ButtonContent({ loading, prefix, suffix, size, children }) {
785
- const iconSizeClass = getIconSizeClass(size);
786
- return /* @__PURE__ */ jsxs(Fragment, { children: [
787
- loading && /* @__PURE__ */ jsx(Spinner, { className: getSpinnerSizeClass(size) }),
1599
+ function ButtonContent({ loading, prefix, suffix, size, iconSize, children }) {
1600
+ const iconSizeClass = getIconSizeClass(size, iconSize);
1601
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1602
+ loading && /* @__PURE__ */ jsx(Spinner, { className: getSpinnerSizeClass(size, iconSize) }),
788
1603
  prefix != null && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("shrink-0", iconSizeClass), children: prefix }),
789
1604
  children,
790
1605
  suffix != null && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("shrink-0", iconSizeClass), children: suffix })
791
1606
  ] });
792
1607
  }
793
- var Button = React14.forwardRef(
794
- ({
795
- className,
796
- variant,
797
- size,
798
- shape,
799
- asChild = false,
800
- loading = false,
801
- disabled,
802
- prefix,
803
- suffix,
804
- shadow,
805
- children,
806
- ...props
807
- }, ref) => {
808
- const Comp = asChild ? Slot : "button";
809
- const isDisabled = disabled ?? loading;
810
- const shadowClass = resolveShadowClass(shadow);
811
- return /* @__PURE__ */ jsx(
812
- Comp,
813
- {
814
- ref,
815
- className: cn(buttonVariants({ variant, size, shape }), shadowClass, className),
816
- disabled: isDisabled,
817
- "aria-busy": loading || void 0,
818
- ...props,
819
- children: asChild ? children : /* @__PURE__ */ jsx(ButtonContent, { loading, prefix, suffix, size, children })
820
- }
821
- );
822
- }
823
- );
824
- Button.displayName = "Button";
825
- var ButtonLink = React14.forwardRef(
826
- ({
827
- className,
828
- variant,
829
- size,
830
- shape,
831
- prefix,
832
- suffix,
833
- shadow,
834
- loading = false,
835
- children,
836
- ...props
837
- }, ref) => {
838
- const shadowClass = resolveShadowClass(shadow);
839
- const loadingProps = loading ? {
840
- "aria-busy": "true",
841
- "aria-disabled": "true",
842
- tabIndex: -1
843
- } : {};
844
- return /* @__PURE__ */ jsx(
845
- "a",
846
- {
847
- ref,
848
- className: cn(
849
- buttonVariants({ variant, size, shape }),
850
- shadowClass,
851
- loading && "pointer-events-none opacity-50",
852
- className
853
- ),
854
- ...loadingProps,
855
- ...props,
856
- children: /* @__PURE__ */ jsx(ButtonContent, { loading, prefix, suffix, size, children })
857
- }
858
- );
859
- }
860
- );
861
- ButtonLink.displayName = "ButtonLink";
862
- ({
863
- // Nebutra Blue (云毓蓝) — technology & trust — VI: #0033FE
864
- blue50: colors.primary[50],
865
- blue100: colors.primary[100],
866
- blue200: colors.primary[200],
867
- blue300: colors.primary[300],
868
- blue400: colors.primary[400],
869
- blue500: colors.primary[500],
870
- // brand primary
871
- blue600: colors.primary[600],
872
- blue700: colors.primary[700],
873
- blue800: colors.primary[800],
874
- blue900: colors.primary[900],
875
- blue950: colors.primary[950],
876
- // Nebutra Cyan (云毓青) — data flow & intelligence — VI: #0BF1C3
877
- cyan50: colors.accent[50],
878
- cyan100: colors.accent[100],
879
- cyan200: colors.accent[200],
880
- cyan300: colors.accent[300],
881
- cyan400: colors.accent[400],
882
- cyan500: colors.accent[500],
883
- // brand secondary
884
- cyan600: colors.accent[600],
885
- cyan700: colors.accent[700],
886
- cyan800: colors.accent[800],
887
- cyan900: colors.accent[900],
888
- cyan950: colors.accent[950],
889
- // Neutral (blue-undertone gray scale)
890
- neutral50: colors.neutral[50],
891
- neutral100: colors.neutral[100],
892
- neutral200: colors.neutral[200],
893
- neutral300: colors.neutral[300],
894
- neutral400: colors.neutral[400],
895
- neutral500: colors.neutral[500],
896
- neutral600: colors.neutral[600],
897
- neutral700: colors.neutral[700],
898
- neutral800: colors.neutral[800],
899
- neutral900: colors.neutral[900],
900
- neutral950: colors.neutral[950],
901
- white: colors.white,
902
- black: colors.black
903
- });
904
- ({
905
- /** Hero sections, primary CTA buttons, logo fills — VI signature gradient */
906
- primary: colors.gradient.primary,
907
- /** Hover states, secondary gradient elements */
908
- reverse: colors.gradient.primaryReverse,
909
- /** Vertical layout dividers, page section separators */
910
- vertical: colors.gradient.primaryVertical,
911
- /** Background halos, focus glow effects, radial emphasis */
912
- radial: colors.gradient.primaryRadial});
913
- var primitiveSpacing = {
914
- 1: 4,
915
- 2: 8,
916
- 3: 12,
917
- 4: 16,
918
- 5: 20,
919
- 20: 80,
920
- 24: 96
921
- };
922
- var primitiveSizing = {
923
- /** Geist button-specific size (24px). Larger than xs by design. */
924
- tiny: 24,
925
- sm: 32,
926
- md: 40,
927
- lg: 48};
928
- var primitiveRadius = {
929
- md: 6,
930
- // Geist default — slightly more rounded than 4px
931
- lg: 8,
932
- full: 9999
933
- };
934
- var primitiveFontSize = {
935
- xs: 12,
936
- sm: 14,
937
- base: 16,
938
- lg: 18};
939
- var primitiveTransition = {
940
- duration: {
941
- // hover, focus, small state changes
942
- flow: 200},
943
- easing: {
944
- inOut: "cubic-bezier(0.4, 0, 0.2, 1)"
945
- }
946
- };
947
- var primitiveFocusRing = {
948
- width: 2,
949
- // px
950
- offset: 2
951
- // px — gap between element and ring
1608
+ var Button = ({
1609
+ className,
1610
+ variant,
1611
+ size,
1612
+ shape,
1613
+ iconSize,
1614
+ asChild = false,
1615
+ loading = false,
1616
+ disabled,
1617
+ prefix,
1618
+ suffix,
1619
+ shadow,
1620
+ children,
1621
+ ref,
1622
+ ...props
1623
+ }) => {
1624
+ const Comp = asChild ? Slot : "button";
1625
+ const isDisabled = Boolean(disabled || loading);
1626
+ const shadowClass = resolveShadowClass(shadow);
1627
+ return /* @__PURE__ */ jsx(
1628
+ Comp,
1629
+ {
1630
+ ref,
1631
+ className: cn(buttonVariants({ variant, size, shape, iconSize }), shadowClass, className),
1632
+ disabled: isDisabled,
1633
+ "aria-busy": loading || void 0,
1634
+ ...props,
1635
+ children: asChild ? children : /* @__PURE__ */ jsx(
1636
+ ButtonContent,
1637
+ {
1638
+ loading,
1639
+ prefix,
1640
+ suffix,
1641
+ size,
1642
+ iconSize,
1643
+ children
1644
+ }
1645
+ )
1646
+ }
1647
+ );
952
1648
  };
1649
+ Button.displayName = "Button";
953
1650
 
954
1651
  // src/tokens/components/tabs.ts
955
1652
  var tabsSizes = {
@@ -1012,6 +1709,10 @@ var tabsTokens = {
1012
1709
  };
1013
1710
 
1014
1711
  // src/utils/primitive-props.ts
1712
+ function asPlainStyle(style) {
1713
+ if (style == null || typeof style === "function") return {};
1714
+ return style;
1715
+ }
1015
1716
  function withHtmlProps(Component) {
1016
1717
  return Component;
1017
1718
  }
@@ -1030,8 +1731,13 @@ var Tooltip = ({
1030
1731
  const delay = delayDuration ?? DEFAULT_TOOLTIP_DELAY_MS;
1031
1732
  return /* @__PURE__ */ jsx(Tooltip$1.Provider, { delay, children: /* @__PURE__ */ jsx(Tooltip$1.Root, { ...props, children }) });
1032
1733
  };
1033
- var TooltipTrigger = React14.forwardRef(({ asChild, children, ...props }, ref) => {
1034
- if (asChild && React14.isValidElement(children)) {
1734
+ var TooltipTrigger = ({
1735
+ asChild,
1736
+ children,
1737
+ ref,
1738
+ ...props
1739
+ }) => {
1740
+ if (asChild && React.isValidElement(children)) {
1035
1741
  return /* @__PURE__ */ jsx(
1036
1742
  Tooltip$1.Trigger,
1037
1743
  {
@@ -1042,31 +1748,36 @@ var TooltipTrigger = React14.forwardRef(({ asChild, children, ...props }, ref) =
1042
1748
  );
1043
1749
  }
1044
1750
  return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { ref, ...props, children });
1045
- });
1751
+ };
1046
1752
  TooltipTrigger.displayName = "TooltipTrigger";
1047
- var TooltipContent = React14.forwardRef(
1048
- ({ className, side = "top", align = "center", sideOffset = 4, alignOffset = 0, ...props }, ref) => /* @__PURE__ */ jsx(Tooltip$1.Portal, { children: /* @__PURE__ */ jsx(
1049
- Tooltip$1.Positioner,
1050
- {
1051
- side,
1052
- align,
1053
- sideOffset,
1054
- alignOffset,
1055
- className: "z-50",
1056
- children: /* @__PURE__ */ jsx(
1057
- Tooltip$1.Popup,
1058
- {
1059
- ref,
1060
- className: cn(
1061
- "z-50 overflow-hidden rounded-xl border bg-background/90 backdrop-blur-md px-3 py-1.5 text-sm text-popover-foreground shadow-xl transition-[opacity,transform,display] duration-200 data-starting-style:animate-in data-starting-style:fade-in-0 data-starting-style:zoom-in-95 data-ending-style:animate-out data-ending-style:fade-out-0 data-ending-style:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
1062
- className
1063
- ),
1064
- ...props
1065
- }
1066
- )
1067
- }
1068
- ) })
1069
- );
1753
+ var TooltipContent = ({
1754
+ className,
1755
+ style,
1756
+ side = "top",
1757
+ align = "center",
1758
+ sideOffset = 4,
1759
+ alignOffset = 0,
1760
+ ref,
1761
+ ...props
1762
+ }) => /* @__PURE__ */ jsx(Tooltip$1.Portal, { children: /* @__PURE__ */ jsx(
1763
+ Tooltip$1.Positioner,
1764
+ {
1765
+ side,
1766
+ align,
1767
+ sideOffset,
1768
+ alignOffset,
1769
+ style: { zIndex: overlayZIndex.tooltip },
1770
+ children: /* @__PURE__ */ jsx(
1771
+ Tooltip$1.Popup,
1772
+ {
1773
+ ref,
1774
+ className: cn(overlayClassNames.tooltipSurface, className),
1775
+ style: { zIndex: overlayZIndex.tooltip, ...style },
1776
+ ...props
1777
+ }
1778
+ )
1779
+ }
1780
+ ) });
1070
1781
  TooltipContent.displayName = "TooltipContent";
1071
1782
  var BaseRoot = withHtmlProps(Tabs$1.Root);
1072
1783
  var BaseList = withHtmlProps(Tabs$1.List);
@@ -1112,12 +1823,12 @@ var tabsListVariants = cva(
1112
1823
  }
1113
1824
  );
1114
1825
  var tabsTriggerVariants = cva(
1115
- "relative inline-flex h-[calc(var(--tabs-height)-var(--tabs-padding)*2)] min-w-[var(--tabs-trigger-min-width)] shrink-0 cursor-pointer items-center justify-center gap-[var(--tabs-trigger-gap)] whitespace-nowrap rounded-[var(--tabs-trigger-radius)] px-[var(--tabs-trigger-padding-x)] font-medium text-[length:var(--tabs-font-size)] outline-none transition-[background-color,border-color,box-shadow,color,opacity] duration-[var(--tabs-duration)] ease-[var(--tabs-easing)] focus-visible:ring-[length:var(--tabs-focus-ring-width)] focus-visible:ring-ring focus-visible:ring-offset-[length:var(--tabs-focus-ring-offset)] focus-visible:ring-offset-background disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 [&_svg]:size-[var(--tabs-icon-size)] [&_svg]:shrink-0",
1826
+ "relative inline-flex h-[calc(var(--tabs-height)-var(--tabs-padding)*2)] min-w-[var(--tabs-trigger-min-width)] shrink-0 cursor-pointer items-center justify-center gap-[var(--tabs-trigger-gap)] whitespace-nowrap rounded-[var(--tabs-trigger-radius)] px-[var(--tabs-trigger-padding-x)] font-medium text-[length:var(--tabs-font-size)] outline-none transition-[background-color,border-color,box-shadow,color,opacity] duration-[var(--tabs-duration)] ease-[var(--tabs-easing)] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 [&_svg]:size-[var(--tabs-icon-size)] [&_svg]:shrink-0",
1116
1827
  {
1117
1828
  variants: {
1118
1829
  variant: {
1119
1830
  default: "hover:text-foreground data-[active]:text-foreground",
1120
- button: "border border-border bg-background text-muted-foreground shadow-[var(--shadow-xs)] hover:border-ring/40 hover:text-foreground data-[active]:border-ring/40 data-[active]:text-foreground",
1831
+ button: "border border-border bg-background text-muted-foreground shadow-xs hover:border-ring/40 hover:text-foreground data-[active]:border-ring/40 data-[active]:text-foreground",
1121
1832
  line: "min-w-0 rounded-none px-0 hover:text-foreground data-[active]:text-foreground",
1122
1833
  secondary: "hover:bg-muted hover:text-foreground data-[active]:bg-muted data-[active]:text-foreground"
1123
1834
  }
@@ -1132,7 +1843,7 @@ var tabsIndicatorVariants = cva(
1132
1843
  {
1133
1844
  variants: {
1134
1845
  variant: {
1135
- default: "z-[-1] rounded-[var(--tabs-trigger-radius)] bg-background shadow-[var(--shadow-xs)]",
1846
+ default: "z-[-1] rounded-[var(--tabs-trigger-radius)] bg-background shadow-xs",
1136
1847
  button: "z-[-1] rounded-[var(--tabs-trigger-radius)] bg-muted",
1137
1848
  line: "bottom-0 h-[var(--tabs-line-thickness)] rounded-[var(--tabs-pill-radius)] bg-foreground",
1138
1849
  secondary: "z-[-1] rounded-[var(--tabs-trigger-radius)] bg-muted"
@@ -1149,7 +1860,7 @@ var tabsIndicatorVariants = cva(
1149
1860
  }
1150
1861
  );
1151
1862
  var tabsContentVariants = cva(
1152
- "mt-[var(--tabs-panel-gap)] text-[length:var(--tabs-font-size)] text-muted-foreground focus-visible:outline-none focus-visible:ring-[length:var(--tabs-focus-ring-width)] focus-visible:ring-ring focus-visible:ring-offset-[length:var(--tabs-focus-ring-offset)] focus-visible:ring-offset-background",
1863
+ "mt-[var(--tabs-panel-gap)] text-[length:var(--tabs-font-size)] text-muted-foreground focus-visible:outline-none",
1153
1864
  {
1154
1865
  variants: {
1155
1866
  variant: {
@@ -1161,7 +1872,7 @@ var tabsContentVariants = cva(
1161
1872
  }
1162
1873
  }
1163
1874
  );
1164
- var TabsContext = React14.createContext({
1875
+ var TabsContext = React.createContext({
1165
1876
  activationMode: "manual",
1166
1877
  disabled: false,
1167
1878
  shape: "default",
@@ -1191,7 +1902,7 @@ function getTabsStyle(size, style) {
1191
1902
  "--tabs-badge-font-size": `${tabsTokens.badgeFontSize}px`,
1192
1903
  "--tabs-duration": `${tabsTokens.motion.duration}ms`,
1193
1904
  "--tabs-easing": tabsTokens.motion.easing,
1194
- ...style
1905
+ ...asPlainStyle(style)
1195
1906
  };
1196
1907
  }
1197
1908
  function getFirstEnabledValue(tabs) {
@@ -1219,7 +1930,7 @@ function Tabs({
1219
1930
  }) {
1220
1931
  const rootValue = selected ?? value;
1221
1932
  const rootDefaultValue = defaultValue ?? getFirstEnabledValue(tabs);
1222
- const context = React14.useMemo(
1933
+ const context = React.useMemo(
1223
1934
  () => ({ activationMode, disabled, shape, size, variant }),
1224
1935
  [activationMode, disabled, shape, size, variant]
1225
1936
  );
@@ -1272,7 +1983,7 @@ function TabsCollection({
1272
1983
  children: tabs.map((tab) => /* @__PURE__ */ jsx(TabsCollectionTrigger, { disabled, tab }, tab.value))
1273
1984
  }
1274
1985
  );
1275
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1986
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1276
1987
  hasTooltip ? /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 150, children: list }) : list,
1277
1988
  tabs.map(
1278
1989
  (tab) => tab.content === void 0 ? null : /* @__PURE__ */ jsx(TabsContent, { value: tab.value, children: tab.content }, tab.value)
@@ -1305,11 +2016,11 @@ function TabsList({
1305
2016
  children,
1306
2017
  ...props
1307
2018
  }) {
1308
- const context = React14.useContext(TabsContext);
2019
+ const context = React.use(TabsContext);
1309
2020
  const resolvedVariant = variant ?? context.variant;
1310
2021
  const resolvedShape = shape ?? context.shape;
1311
2022
  const resolvedActivateOnFocus = activateOnFocus ?? context.activationMode === "automatic";
1312
- const listContext = React14.useMemo(
2023
+ const listContext = React.useMemo(
1313
2024
  () => ({ ...context, shape: resolvedShape, variant: resolvedVariant }),
1314
2025
  [context, resolvedShape, resolvedVariant]
1315
2026
  );
@@ -1346,7 +2057,7 @@ function TabsList({
1346
2057
  ) });
1347
2058
  }
1348
2059
  function TabsTrigger({ badge, children, className, disabled, icon, ...props }) {
1349
- const context = React14.useContext(TabsContext);
2060
+ const context = React.use(TabsContext);
1350
2061
  const isDisabled = disabled ?? context.disabled;
1351
2062
  return /* @__PURE__ */ jsxs(
1352
2063
  BaseTrigger,
@@ -1403,6 +2114,12 @@ var textareaTokens = {
1403
2114
  labelSize: primitiveFontSize.sm,
1404
2115
  focusRingWidth: 3,
1405
2116
  fieldGap: primitiveSpacing[2] - primitiveSpacing[1] / 2};
2117
+
2118
+ // src/primitives/form-control.ts
2119
+ var formControlFocusClassNames = {
2120
+ textarea: "outline-none focus:border-ring focus:ring-[length:var(--textarea-focus-ring-width)] focus:ring-ring/30"};
2121
+ var formControlInvalidClassNames = {
2122
+ textarea: "aria-invalid:border-destructive/60 aria-invalid:focus:border-destructive aria-invalid:focus:ring-destructive/20"};
1406
2123
  var fieldMessageClassName = "text-xs text-muted-foreground";
1407
2124
  var fieldErrorClassName = "text-xs font-medium text-destructive";
1408
2125
  function getTextareaStyle(size, style) {
@@ -1416,7 +2133,7 @@ function getTextareaStyle(size, style) {
1416
2133
  "--textarea-focus-ring-width": `${textareaTokens.focusRingWidth}px`,
1417
2134
  borderRadius: "var(--textarea-radius)",
1418
2135
  outline: "none",
1419
- ...style
2136
+ ...asPlainStyle(style)
1420
2137
  };
1421
2138
  }
1422
2139
  function getTextareaFieldStyle() {
@@ -1427,86 +2144,85 @@ function getTextareaFieldStyle() {
1427
2144
  }
1428
2145
  function joinDescriptionIds(...ids) {
1429
2146
  return ids.filter(Boolean).join(" ") || void 0;
1430
- }
1431
- function isInvalid(error, ariaInvalid) {
1432
- return error === true || typeof error === "string" || ariaInvalid === true || ariaInvalid === "true";
1433
- }
1434
- var Textarea = React14.forwardRef(
1435
- ({
1436
- className,
1437
- style,
1438
- size = "md",
1439
- label,
1440
- description,
1441
- error,
1442
- fieldClassName,
1443
- id,
1444
- onChange,
1445
- onValueChange,
1446
- "aria-describedby": ariaDescribedBy,
1447
- "aria-invalid": ariaInvalid,
1448
- ...props
1449
- }, ref) => {
1450
- const baseId = React14.useId();
1451
- const textareaId = id ?? (label || description || typeof error === "string" ? baseId : void 0);
1452
- const resolvedInvalid = isInvalid(error, ariaInvalid);
1453
- const descriptionId = description && textareaId ? `${textareaId}-description` : void 0;
1454
- const errorId = typeof error === "string" && textareaId ? `${textareaId}-error` : void 0;
1455
- const describedBy = joinDescriptionIds(ariaDescribedBy, descriptionId, errorId);
1456
- const handleChange = React14.useCallback(
1457
- (event) => {
1458
- onValueChange?.(event.currentTarget.value);
1459
- onChange?.(event);
1460
- },
1461
- [onChange, onValueChange]
1462
- );
1463
- const control = /* @__PURE__ */ jsx(
1464
- "textarea",
1465
- {
1466
- className: cn(
1467
- "flex min-h-[var(--textarea-min-height)] w-full resize-y rounded-[var(--textarea-radius)] border border-input bg-background",
1468
- "px-[var(--textarea-padding-x)] py-[var(--textarea-padding-y)] text-[length:var(--textarea-font-size)] text-foreground shadow-[var(--shadow-xs)]",
1469
- "transition-[background-color,border-color,box-shadow,color] duration-micro ease-out placeholder:text-muted-foreground",
1470
- "outline-none focus:border-ring focus:ring-[length:var(--textarea-focus-ring-width)] focus:ring-ring/30",
1471
- "disabled:cursor-not-allowed disabled:opacity-50 read-only:cursor-default read-only:bg-muted/70",
1472
- "aria-invalid:border-destructive/60 aria-invalid:focus:border-destructive aria-invalid:focus:ring-destructive/20",
1473
- className
1474
- ),
1475
- ref,
1476
- id: textareaId,
1477
- "aria-invalid": resolvedInvalid || void 0,
1478
- "aria-describedby": describedBy,
1479
- style: getTextareaStyle(size, style),
1480
- onChange: handleChange,
1481
- ...props
1482
- }
1483
- );
1484
- if (!label && !description && typeof error !== "string" && !fieldClassName) {
1485
- return control;
2147
+ }
2148
+ function isInvalid(error, ariaInvalid) {
2149
+ return error === true || typeof error === "string" || ariaInvalid === true || ariaInvalid === "true";
2150
+ }
2151
+ var Textarea = ({
2152
+ className,
2153
+ style,
2154
+ size = "md",
2155
+ label,
2156
+ description,
2157
+ error,
2158
+ fieldClassName,
2159
+ id,
2160
+ onChange,
2161
+ onValueChange,
2162
+ "aria-describedby": ariaDescribedBy,
2163
+ "aria-invalid": ariaInvalid,
2164
+ ref,
2165
+ ...props
2166
+ }) => {
2167
+ const baseId = React.useId();
2168
+ const textareaId = id ?? (label || description || typeof error === "string" ? baseId : void 0);
2169
+ const resolvedInvalid = isInvalid(error, ariaInvalid);
2170
+ const descriptionId = description && textareaId ? `${textareaId}-description` : void 0;
2171
+ const errorId = typeof error === "string" && textareaId ? `${textareaId}-error` : void 0;
2172
+ const describedBy = joinDescriptionIds(ariaDescribedBy, descriptionId, errorId);
2173
+ const handleChange = React.useCallback(
2174
+ (event) => {
2175
+ onValueChange?.(event.currentTarget.value);
2176
+ onChange?.(event);
2177
+ },
2178
+ [onChange, onValueChange]
2179
+ );
2180
+ const control = /* @__PURE__ */ jsx(
2181
+ "textarea",
2182
+ {
2183
+ className: cn(
2184
+ "flex min-h-[var(--textarea-min-height)] w-full resize-y rounded-[var(--textarea-radius)] border border-input bg-background",
2185
+ "px-[var(--textarea-padding-x)] py-[var(--textarea-padding-y)] text-[length:var(--textarea-font-size)] text-foreground shadow-xs",
2186
+ "transition-[background-color,border-color,box-shadow,color] duration-micro ease-out placeholder:text-muted-foreground",
2187
+ formControlFocusClassNames.textarea,
2188
+ "disabled:cursor-not-allowed disabled:opacity-50 read-only:cursor-default read-only:bg-muted/70",
2189
+ formControlInvalidClassNames.textarea,
2190
+ className
2191
+ ),
2192
+ ref,
2193
+ id: textareaId,
2194
+ "aria-invalid": resolvedInvalid || void 0,
2195
+ "aria-describedby": describedBy,
2196
+ style: getTextareaStyle(size, style),
2197
+ onChange: handleChange,
2198
+ ...props
1486
2199
  }
1487
- return /* @__PURE__ */ jsxs(
1488
- "div",
1489
- {
1490
- "data-slot": "textarea-field",
1491
- className: cn("grid gap-[var(--textarea-field-gap)]", fieldClassName),
1492
- style: getTextareaFieldStyle(),
1493
- children: [
1494
- label && /* @__PURE__ */ jsx(
1495
- "label",
1496
- {
1497
- htmlFor: textareaId,
1498
- className: "text-[length:var(--textarea-label-size)] font-medium text-foreground",
1499
- children: label
1500
- }
1501
- ),
1502
- control,
1503
- description && !error && /* @__PURE__ */ jsx("p", { id: descriptionId, className: fieldMessageClassName, children: description }),
1504
- typeof error === "string" && /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: fieldErrorClassName, children: error })
1505
- ]
1506
- }
1507
- );
2200
+ );
2201
+ if (!label && !description && typeof error !== "string" && !fieldClassName) {
2202
+ return control;
1508
2203
  }
1509
- );
2204
+ return /* @__PURE__ */ jsxs(
2205
+ "div",
2206
+ {
2207
+ "data-slot": "textarea-field",
2208
+ className: cn("grid gap-[var(--textarea-field-gap)]", fieldClassName),
2209
+ style: getTextareaFieldStyle(),
2210
+ children: [
2211
+ label && /* @__PURE__ */ jsx(
2212
+ "label",
2213
+ {
2214
+ htmlFor: textareaId,
2215
+ className: "text-[length:var(--textarea-label-size)] font-medium text-foreground",
2216
+ children: label
2217
+ }
2218
+ ),
2219
+ control,
2220
+ description && !error && /* @__PURE__ */ jsx("p", { id: descriptionId, className: fieldMessageClassName, children: description }),
2221
+ typeof error === "string" && /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: fieldErrorClassName, children: error })
2222
+ ]
2223
+ }
2224
+ );
2225
+ };
1510
2226
  Textarea.displayName = "Textarea";
1511
2227
  function MarkdownRenderer({ content, className }) {
1512
2228
  return /* @__PURE__ */ jsx("div", { className: cn("prose prose-sm dark:prose-invert max-w-none", className), children: /* @__PURE__ */ jsx(
@@ -1665,7 +2381,7 @@ function MarkdownEditor({
1665
2381
  value,
1666
2382
  onChange: (e) => onChange(e.target.value),
1667
2383
  placeholder,
1668
- className: "resize-none rounded-none border-0 font-mono text-sm shadow-none focus-visible:ring-0",
2384
+ className: "resize-none rounded-none border-0 font-mono text-sm shadow-none",
1669
2385
  style: { minHeight }
1670
2386
  }
1671
2387
  ) }),
@@ -1700,53 +2416,41 @@ function ToolbarButton({
1700
2416
  }
1701
2417
  );
1702
2418
  }
1703
- var Card2 = React14.forwardRef(
1704
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1705
- "div",
1706
- {
1707
- ref,
1708
- className: cn(
1709
- "rounded-[var(--radius-lg)] border border-border bg-card text-card-foreground shadow-sm",
1710
- className
1711
- ),
1712
- ...props
1713
- }
1714
- )
1715
- );
1716
- Card2.displayName = "Card";
1717
- var CardHeader2 = React14.forwardRef(
1718
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props })
1719
- );
1720
- CardHeader2.displayName = "CardHeader";
1721
- var CardTitle2 = React14.forwardRef(
1722
- ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
1723
- "h3",
1724
- {
1725
- ref,
1726
- className: cn("text-2xl font-semibold leading-none tracking-tight", className),
1727
- ...props,
1728
- children
1729
- }
1730
- )
1731
- );
1732
- CardTitle2.displayName = "CardTitle";
1733
- var CardDescription2 = React14.forwardRef(({ className, as: Tag = "p", ...props }, ref) => {
1734
- return React14.createElement(Tag, {
2419
+ var Card2 = ({
2420
+ className,
2421
+ ref,
2422
+ ...props
2423
+ }) => /* @__PURE__ */ jsx(
2424
+ "div",
2425
+ {
1735
2426
  ref,
1736
- className: cn("text-sm text-muted-foreground", className),
2427
+ className: cn(
2428
+ "rounded-[var(--radius-lg)] border border-border bg-card text-card-foreground shadow-sm",
2429
+ className
2430
+ ),
1737
2431
  ...props
1738
- });
1739
- });
1740
- CardDescription2.displayName = "CardDescription";
1741
- var CardContent = React14.forwardRef(
1742
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props })
2432
+ }
1743
2433
  );
2434
+ Card2.displayName = "Card";
2435
+ var CardHeader2 = ({
2436
+ className,
2437
+ ref,
2438
+ ...props
2439
+ }) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props });
2440
+ CardHeader2.displayName = "CardHeader";
2441
+ var CardContent = ({
2442
+ className,
2443
+ ref,
2444
+ ...props
2445
+ }) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props });
1744
2446
  CardContent.displayName = "CardContent";
1745
- var CardFooter2 = React14.forwardRef(
1746
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center p-6 pt-0", className), ...props })
1747
- );
1748
- CardFooter2.displayName = "CardFooter";
1749
- var Separator = React14.forwardRef(({ className, orientation = "horizontal", decorative: _decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
2447
+ var Separator = ({
2448
+ className,
2449
+ orientation = "horizontal",
2450
+ decorative: _decorative = true,
2451
+ ref,
2452
+ ...props
2453
+ }) => /* @__PURE__ */ jsx(
1750
2454
  Separator$1,
1751
2455
  {
1752
2456
  ref,
@@ -1758,7 +2462,7 @@ var Separator = React14.forwardRef(({ className, orientation = "horizontal", dec
1758
2462
  ),
1759
2463
  ...props
1760
2464
  }
1761
- ));
2465
+ );
1762
2466
  Separator.displayName = "Separator";
1763
2467
  var sizeClasses = {
1764
2468
  xs: { root: "h-5 w-5", fallback: "text-[8px]" },
@@ -1768,7 +2472,7 @@ var sizeClasses = {
1768
2472
  xl: { root: "h-20 w-20", fallback: "text-2xl" }
1769
2473
  };
1770
2474
  var numericAvatarClass = "h-[var(--avatar-size)] w-[var(--avatar-size)]";
1771
- var AvatarContext = React14.createContext(null);
2475
+ var AvatarContext = React.createContext(null);
1772
2476
  function isPresetSize(size) {
1773
2477
  return typeof size === "string";
1774
2478
  }
@@ -1780,9 +2484,18 @@ function getAvatarFallbackClass(size) {
1780
2484
  }
1781
2485
  function getAvatarStyle(size, style) {
1782
2486
  if (typeof size !== "number") return style;
1783
- return {
2487
+ const numericVars = {
1784
2488
  "--avatar-size": `${size}px`,
1785
- "--avatar-font-size": `${Math.max(10, Math.round(size * 0.375))}px`,
2489
+ "--avatar-font-size": `${Math.max(10, Math.round(size * 0.375))}px`
2490
+ };
2491
+ if (typeof style === "function") {
2492
+ return (state) => ({
2493
+ ...numericVars,
2494
+ ...style(state)
2495
+ });
2496
+ }
2497
+ return {
2498
+ ...numericVars,
1786
2499
  ...style
1787
2500
  };
1788
2501
  }
@@ -1800,77 +2513,86 @@ function normalizeAvatarLabel({
1800
2513
  }) {
1801
2514
  return title ?? alt ?? username ?? "Avatar";
1802
2515
  }
1803
- var Avatar = React14.forwardRef(
1804
- ({
1805
- className,
1806
- size = "md",
1807
- src,
1808
- alt,
1809
- title,
1810
- letter,
1811
- username,
1812
- placeholder,
1813
- fallbackDelayMs,
1814
- children,
1815
- style,
1816
- ...props
1817
- }, ref) => {
1818
- const label = normalizeAvatarLabel({ alt, title, username });
1819
- const fallback = letter ?? getAvatarInitials(title ?? username ?? alt ?? "");
1820
- const contextTitle = title ?? alt ?? username;
1821
- const contextValue = contextTitle === void 0 ? { size } : { size, title: contextTitle };
1822
- const shouldRenderConvenienceContent = children === void 0 && (src !== void 0 || placeholder === true || fallback.length > 0);
1823
- return /* @__PURE__ */ jsx(AvatarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
1824
- Avatar$1.Root,
1825
- {
1826
- ref,
1827
- className: cn(
1828
- "relative flex shrink-0 overflow-hidden rounded-full bg-muted",
1829
- getAvatarRootClass(size),
1830
- className
1831
- ),
1832
- style: getAvatarStyle(size, style),
1833
- ...props,
1834
- children: shouldRenderConvenienceContent ? /* @__PURE__ */ jsxs(Fragment, { children: [
1835
- src && /* @__PURE__ */ jsx(AvatarImage, { src, alt: label }),
1836
- /* @__PURE__ */ jsx(AvatarFallback, { size, delay: fallbackDelayMs, children: placeholder ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading avatar" }) : fallback })
1837
- ] }) : children
1838
- }
1839
- ) });
1840
- }
1841
- );
2516
+ var Avatar = ({
2517
+ className,
2518
+ size = "md",
2519
+ src,
2520
+ alt,
2521
+ title,
2522
+ letter,
2523
+ username,
2524
+ placeholder,
2525
+ fallbackDelayMs,
2526
+ children,
2527
+ style,
2528
+ ref,
2529
+ ...props
2530
+ }) => {
2531
+ const label = normalizeAvatarLabel({ alt, title, username });
2532
+ const fallback = letter ?? getAvatarInitials(title ?? username ?? alt ?? "");
2533
+ const contextTitle = title ?? alt ?? username;
2534
+ const contextValue = contextTitle === void 0 ? { size } : { size, title: contextTitle };
2535
+ const shouldRenderConvenienceContent = children === void 0 && (src !== void 0 || placeholder === true || fallback.length > 0);
2536
+ return /* @__PURE__ */ jsx(AvatarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
2537
+ Avatar$1.Root,
2538
+ {
2539
+ ref,
2540
+ className: cn(
2541
+ "relative flex shrink-0 overflow-hidden rounded-full bg-muted",
2542
+ getAvatarRootClass(size),
2543
+ className
2544
+ ),
2545
+ style: getAvatarStyle(size, style),
2546
+ ...props,
2547
+ children: shouldRenderConvenienceContent ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
2548
+ src && /* @__PURE__ */ jsx(AvatarImage, { src, alt: label }),
2549
+ /* @__PURE__ */ jsx(AvatarFallback, { size, delay: fallbackDelayMs, children: placeholder ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading avatar" }) : fallback })
2550
+ ] }) : children
2551
+ }
2552
+ ) });
2553
+ };
1842
2554
  Avatar.displayName = "Avatar";
1843
- var AvatarImage = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2555
+ var AvatarImage = ({
2556
+ className,
2557
+ ref,
2558
+ ...props
2559
+ }) => /* @__PURE__ */ jsx(
1844
2560
  Avatar$1.Image,
1845
2561
  {
1846
2562
  ref,
1847
2563
  className: cn("aspect-square h-full w-full object-cover", className),
1848
2564
  ...props
1849
2565
  }
1850
- ));
1851
- AvatarImage.displayName = "AvatarImage";
1852
- var AvatarFallback = React14.forwardRef(
1853
- ({ className, size, children, "aria-label": ariaLabel, style, ...props }, ref) => {
1854
- const context = React14.useContext(AvatarContext);
1855
- const resolvedSize = size ?? context?.size ?? "md";
1856
- const fallbackLabel = ariaLabel ?? (typeof children === "string" && children.trim().length > 0 ? `Avatar with initials: ${children}` : context?.title);
1857
- return /* @__PURE__ */ jsx(
1858
- Avatar$1.Fallback,
1859
- {
1860
- ref,
1861
- "aria-label": fallbackLabel,
1862
- className: cn(
1863
- "flex h-full w-full items-center justify-center rounded-full bg-muted font-medium text-muted-foreground",
1864
- getAvatarFallbackClass(resolvedSize),
1865
- className
1866
- ),
1867
- style: getAvatarStyle(resolvedSize, style),
1868
- ...props,
1869
- children
1870
- }
1871
- );
1872
- }
1873
2566
  );
2567
+ AvatarImage.displayName = "AvatarImage";
2568
+ var AvatarFallback = ({
2569
+ className,
2570
+ size,
2571
+ children,
2572
+ "aria-label": ariaLabel,
2573
+ style,
2574
+ ref,
2575
+ ...props
2576
+ }) => {
2577
+ const context = React.use(AvatarContext);
2578
+ const resolvedSize = size ?? context?.size ?? "md";
2579
+ const fallbackLabel = ariaLabel ?? (typeof children === "string" && children.trim().length > 0 ? `Avatar with initials: ${children}` : context?.title);
2580
+ return /* @__PURE__ */ jsx(
2581
+ Avatar$1.Fallback,
2582
+ {
2583
+ ref,
2584
+ "aria-label": fallbackLabel,
2585
+ className: cn(
2586
+ "flex h-full w-full items-center justify-center rounded-full bg-muted font-medium text-muted-foreground",
2587
+ getAvatarFallbackClass(resolvedSize),
2588
+ className
2589
+ ),
2590
+ style: getAvatarStyle(resolvedSize, style),
2591
+ ...props,
2592
+ children
2593
+ }
2594
+ );
2595
+ };
1874
2596
  AvatarFallback.displayName = "AvatarFallback";
1875
2597
  function initials(name) {
1876
2598
  return name.split(/\s+/).map((part) => part.charAt(0).toUpperCase()).join("").slice(0, 2);
@@ -2048,7 +2770,7 @@ function QAPage({
2048
2770
  return bScore - aScore;
2049
2771
  });
2050
2772
  }, [answers]);
2051
- return /* @__PURE__ */ jsxs("div", { className: cn("mx-auto w-full max-w-5xl p-4 md:p-6", className), children: [
2773
+ return /* @__PURE__ */ jsxs("div", { className: cn("mx-auto w-full max-w-[var(--container-content)] p-4 md:p-6", className), children: [
2052
2774
  /* @__PURE__ */ jsxs("header", { className: "mb-6", children: [
2053
2775
  /* @__PURE__ */ jsx("h1", { className: "mb-4 font-bold text-2xl leading-tight text-foreground", children: question.title }),
2054
2776
  /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center gap-4 text-muted-foreground text-sm", children: [
@@ -2113,7 +2835,7 @@ function QAPage({
2113
2835
  " ",
2114
2836
  answers.length === 1 ? "Answer" : "Answers"
2115
2837
  ] }) }),
2116
- /* @__PURE__ */ jsx("div", { className: "mb-8", children: sortedAnswers.map((answer, index) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
2838
+ /* @__PURE__ */ jsx("div", { className: "mb-8", children: sortedAnswers.map((answer, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
2117
2839
  /* @__PURE__ */ jsx(Card2, { className: cn("mb-6", answer.isAccepted && "ring-2 ring-success/40"), children: /* @__PURE__ */ jsxs(CardContent, { className: "flex gap-6 p-6", children: [
2118
2840
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4", children: [
2119
2841
  /* @__PURE__ */ jsx(
@@ -2213,12 +2935,21 @@ function PostActions({
2213
2935
  /* @__PURE__ */ jsx(UserInfo, { author, timestamp, verb })
2214
2936
  ] });
2215
2937
  }
2216
- var CollapsibleContext = React14.createContext({});
2217
- var Collapsible = React14.forwardRef(({ className, open: openProp, defaultOpen, onOpenChange, disabled, children, ...props }, ref) => {
2218
- const [uncontrolledOpen, setUncontrolledOpen] = React14.useState(defaultOpen || false);
2938
+ var CollapsibleContext = React.createContext({});
2939
+ var Collapsible = ({
2940
+ className,
2941
+ open: openProp,
2942
+ defaultOpen,
2943
+ onOpenChange,
2944
+ disabled,
2945
+ children,
2946
+ ref,
2947
+ ...props
2948
+ }) => {
2949
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen || false);
2219
2950
  const isControlled = openProp !== void 0;
2220
2951
  const open = isControlled ? openProp : uncontrolledOpen;
2221
- const handleOpenChange = React14.useCallback(
2952
+ const handleOpenChange = React.useCallback(
2222
2953
  (nextOpen) => {
2223
2954
  if (!isControlled) {
2224
2955
  setUncontrolledOpen(nextOpen);
@@ -2238,11 +2969,17 @@ var Collapsible = React14.forwardRef(({ className, open: openProp, defaultOpen,
2238
2969
  children
2239
2970
  }
2240
2971
  ) });
2241
- });
2972
+ };
2242
2973
  Collapsible.displayName = "Collapsible";
2243
- var CollapsibleTrigger = React14.forwardRef(({ className, asChild, children, ...props }, ref) => {
2244
- const { open, onOpenChange, disabled } = React14.useContext(CollapsibleContext);
2245
- const handleClick = React14.useCallback(
2974
+ var CollapsibleTrigger = ({
2975
+ className,
2976
+ asChild,
2977
+ children,
2978
+ ref,
2979
+ ...props
2980
+ }) => {
2981
+ const { open, onOpenChange, disabled } = React.use(CollapsibleContext);
2982
+ const handleClick = React.useCallback(
2246
2983
  (e) => {
2247
2984
  if (disabled) return;
2248
2985
  onOpenChange?.(!open);
@@ -2250,8 +2987,8 @@ var CollapsibleTrigger = React14.forwardRef(({ className, asChild, children, ...
2250
2987
  },
2251
2988
  [disabled, open, onOpenChange, props.onClick]
2252
2989
  );
2253
- if (asChild && React14.isValidElement(children)) {
2254
- return React14.cloneElement(children, {
2990
+ if (asChild && React.isValidElement(children)) {
2991
+ return React.cloneElement(children, {
2255
2992
  ref,
2256
2993
  onClick: handleClick,
2257
2994
  "data-state": open ? "open" : "closed",
@@ -2277,36 +3014,40 @@ var CollapsibleTrigger = React14.forwardRef(({ className, asChild, children, ...
2277
3014
  children
2278
3015
  }
2279
3016
  );
2280
- });
3017
+ };
2281
3018
  CollapsibleTrigger.displayName = "CollapsibleTrigger";
2282
- var CollapsibleContent = React14.forwardRef(
2283
- ({ className, children, ...props }, ref) => {
2284
- const { open } = React14.useContext(CollapsibleContext);
2285
- return /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: open && /* @__PURE__ */ jsx(
2286
- motion.div,
2287
- {
2288
- initial: "collapsed",
2289
- animate: "open",
2290
- exit: "collapsed",
2291
- variants: {
2292
- open: { opacity: 1, height: "auto" },
2293
- collapsed: { opacity: 0, height: 0 }
2294
- },
2295
- transition: { duration: 0.3, ease: [0.04, 0.62, 0.23, 0.98] },
2296
- className: "overflow-hidden",
2297
- children: /* @__PURE__ */ jsx("div", { ref, "data-state": "open", className: cn("", className), ...props, children })
3019
+ var CollapsibleContent = ({
3020
+ className,
3021
+ children,
3022
+ ref,
3023
+ ...props
3024
+ }) => {
3025
+ const { open } = React.use(CollapsibleContext);
3026
+ const shouldReduceMotion = useReducedMotion();
3027
+ return /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: open && /* @__PURE__ */ jsx(
3028
+ motion.div,
3029
+ {
3030
+ initial: "collapsed",
3031
+ animate: "open",
3032
+ exit: "collapsed",
3033
+ variants: {
3034
+ open: { opacity: 1, height: "auto" },
3035
+ collapsed: { opacity: 0, height: 0 }
2298
3036
  },
2299
- "content"
2300
- ) });
2301
- }
2302
- );
3037
+ transition: shouldReduceMotion ? { duration: 0 } : { duration: 0.3, ease: [0.04, 0.62, 0.23, 0.98] },
3038
+ className: "overflow-hidden",
3039
+ children: /* @__PURE__ */ jsx("div", { ref, "data-state": "open", className: cn("", className), ...props, children })
3040
+ },
3041
+ "content"
3042
+ ) });
3043
+ };
2303
3044
  CollapsibleContent.displayName = "CollapsibleContent";
2304
- var ITEM_BASE_CLASSES = "flex items-center gap-2 rounded-md px-2.5 py-1.5 text-[13px] leading-5 transition-colors";
2305
- var ITEM_DEFAULT_CLASSES = "text-foreground hover:bg-accent hover:text-accent-foreground";
2306
- var ITEM_ACTIVE_CLASSES = "bg-accent text-accent-foreground font-medium";
3045
+ var ITEM_BASE_CLASSES = "group flex min-h-8 items-center gap-2 rounded-[var(--radius-md)] px-2.5 py-1.5 text-[13px] leading-5 transition-[background-color,color,box-shadow,transform]";
3046
+ var ITEM_DEFAULT_CLASSES = "text-sidebar-foreground/72 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground";
3047
+ var ITEM_ACTIVE_CLASSES = "bg-sidebar-primary text-sidebar-primary-foreground font-medium shadow-sm shadow-sidebar-primary/10 hover:bg-sidebar-primary hover:text-sidebar-primary-foreground";
2307
3048
  var ITEM_DISABLED_CLASSES = "opacity-50 pointer-events-none";
2308
3049
  var ITEM_COLLAPSED_CLASSES = "justify-center px-0 size-8 mx-auto";
2309
- var ICON_CLASSES = "size-3.5 shrink-0";
3050
+ var ICON_CLASSES = "size-4 shrink-0";
2310
3051
  function defaultRenderLink({
2311
3052
  href,
2312
3053
  children,
@@ -2335,12 +3076,12 @@ function ItemContent({
2335
3076
  }) {
2336
3077
  const Icon = item.icon;
2337
3078
  if (collapsed) {
2338
- return /* @__PURE__ */ jsxs(Fragment, { children: [
3079
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
2339
3080
  Icon ? /* @__PURE__ */ jsx(Icon, { className: ICON_CLASSES }) : null,
2340
3081
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: item.label })
2341
3082
  ] });
2342
3083
  }
2343
- return /* @__PURE__ */ jsxs(Fragment, { children: [
3084
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
2344
3085
  Icon ? /* @__PURE__ */ jsx(Icon, { className: ICON_CLASSES }) : null,
2345
3086
  /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: item.label }),
2346
3087
  item.badge ? /* @__PURE__ */ jsx(Badge, { variant: item.badge.tone, size: "sm", children: item.badge.label }) : null,
@@ -2348,7 +3089,7 @@ function ItemContent({
2348
3089
  ChevronRight,
2349
3090
  {
2350
3091
  className: cn(
2351
- "h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform",
3092
+ "size-3.5 shrink-0 text-muted-foreground transition-transform",
2352
3093
  chevronOpen && "rotate-90"
2353
3094
  ),
2354
3095
  "aria-hidden": "true"
@@ -2431,11 +3172,22 @@ function ParentItem({
2431
3172
  itemClassName,
2432
3173
  renderLink
2433
3174
  }) {
2434
- const hasActiveChild = React14.useMemo(
2435
- () => item.children?.some((c) => c.isActive === true) ?? false,
2436
- [item.children]
3175
+ const hasActiveChild = item.children?.some((c) => c.isActive === true) ?? false;
3176
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(
3177
+ item.isActive === true || hasActiveChild
3178
+ );
3179
+ const isControlled = item.expanded !== void 0 && item.onExpandedChange !== void 0;
3180
+ const open = isControlled ? item.expanded : uncontrolledOpen;
3181
+ const setOpen = React.useCallback(
3182
+ (next) => {
3183
+ if (isControlled) {
3184
+ item.onExpandedChange?.(next);
3185
+ } else {
3186
+ setUncontrolledOpen(next);
3187
+ }
3188
+ },
3189
+ [isControlled, item.onExpandedChange]
2437
3190
  );
2438
- const [open, setOpen] = React14.useState(item.isActive === true || hasActiveChild);
2439
3191
  if (collapsed) {
2440
3192
  return /* @__PURE__ */ jsx(
2441
3193
  InteractiveItem,
@@ -2491,48 +3243,69 @@ function SidebarNav({
2491
3243
  "nav",
2492
3244
  {
2493
3245
  "aria-label": "Sidebar",
3246
+ "data-ui": "nebutra-sidebar-nav",
2494
3247
  className: cn(
2495
- "flex h-full flex-col gap-4",
2496
- collapsed ? "px-2 py-2.5" : "px-2.5 py-3",
3248
+ "flex h-full flex-col",
3249
+ collapsed ? "gap-3 px-2 py-3" : "gap-5 px-3 py-4",
2497
3250
  className
2498
3251
  ),
2499
3252
  children: [
2500
3253
  header ? /* @__PURE__ */ jsx("div", { className: "shrink-0", children: header }) : null,
2501
- /* @__PURE__ */ jsx("div", { className: "flex-1 space-y-4 overflow-y-auto", children: sections.map((section) => /* @__PURE__ */ jsxs("div", { children: [
2502
- section.label && !collapsed ? /* @__PURE__ */ jsx("div", { className: "mb-1.5 px-2.5 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: section.label }) : null,
2503
- /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-0.5", children: section.items.map((item) => {
2504
- const hasChildren = Array.isArray(item.children) && item.children.length > 0;
2505
- return /* @__PURE__ */ jsx("li", { children: hasChildren ? /* @__PURE__ */ jsx(
2506
- ParentItem,
2507
- {
2508
- item,
2509
- collapsed,
2510
- itemClassName,
2511
- renderLink
2512
- }
2513
- ) : /* @__PURE__ */ jsx(
2514
- InteractiveItem,
2515
- {
2516
- item,
2517
- collapsed,
2518
- itemClassName,
2519
- renderLink
2520
- }
2521
- ) }, item.id);
2522
- }) })
2523
- ] }, section.id)) }),
2524
- footer ? /* @__PURE__ */ jsx("div", { className: "shrink-0 border-t border-border pt-3", children: footer }) : null
3254
+ /* @__PURE__ */ jsx("div", { className: "flex-1 space-y-4 overflow-y-auto", children: sections.map((section) => {
3255
+ const visibleActions = !collapsed && section.actions && section.actions.length > 0 ? section.actions.slice(0, 3) : null;
3256
+ return /* @__PURE__ */ jsxs("section", { className: "group/section", children: [
3257
+ section.label && !collapsed ? /* @__PURE__ */ jsxs("div", { className: "mb-1.5 flex items-center justify-between px-2.5", children: [
3258
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-semibold uppercase tracking-[0.18em] text-sidebar-foreground/45", children: section.label }),
3259
+ visibleActions ? /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0.5 opacity-0 transition-opacity duration-micro group-hover/section:opacity-100 focus-within:opacity-100", children: visibleActions.map((action) => {
3260
+ const ActionIcon = action.icon;
3261
+ const defaultButton = /* @__PURE__ */ jsx(
3262
+ "button",
3263
+ {
3264
+ type: "button",
3265
+ "aria-label": action.label,
3266
+ title: action.label,
3267
+ onClick: action.onClick,
3268
+ className: "inline-flex size-4 items-center justify-center rounded text-sidebar-foreground/50 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:outline-none",
3269
+ children: /* @__PURE__ */ jsx(ActionIcon, { className: "size-3" })
3270
+ }
3271
+ );
3272
+ return /* @__PURE__ */ jsx("span", { className: "contents", children: action.render ? action.render(defaultButton) : defaultButton }, action.id);
3273
+ }) }) : null
3274
+ ] }) : null,
3275
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-0.5", children: section.items.map((item) => {
3276
+ const hasChildren = Array.isArray(item.children) && item.children.length > 0;
3277
+ return /* @__PURE__ */ jsx("li", { children: hasChildren ? /* @__PURE__ */ jsx(
3278
+ ParentItem,
3279
+ {
3280
+ item,
3281
+ collapsed,
3282
+ itemClassName,
3283
+ renderLink
3284
+ }
3285
+ ) : /* @__PURE__ */ jsx(
3286
+ InteractiveItem,
3287
+ {
3288
+ item,
3289
+ collapsed,
3290
+ itemClassName,
3291
+ renderLink
3292
+ }
3293
+ ) }, item.id);
3294
+ }) })
3295
+ ] }, section.id);
3296
+ }) }),
3297
+ footer ? /* @__PURE__ */ jsx("div", { className: "shrink-0 border-t border-sidebar-border pt-3", children: footer }) : null
2525
3298
  ]
2526
3299
  }
2527
3300
  ) });
2528
3301
  }
2529
- var TerminalContext = React14.createContext(null);
3302
+ var TerminalContext = React.createContext(null);
2530
3303
  var variantStyles2 = {
2531
- default: "bg-[var(--neutral-2)] border border-[var(--neutral-7)]",
2532
- minimal: "bg-[var(--neutral-1)] border border-[var(--neutral-7)]",
2533
- glass: "bg-[var(--neutral-2)] backdrop-blur-md border border-[var(--neutral-7)]"
3304
+ default: "bg-muted border border-border",
3305
+ minimal: "bg-background border border-border",
3306
+ glass: "bg-muted backdrop-blur-md border border-border"
2534
3307
  };
2535
- var TerminalRoot = React14.forwardRef(
3308
+ var TerminalRoot = React.forwardRef(
2536
3309
  ({ className, variant = "default", children, ...props }, ref) => {
2537
3310
  return /* @__PURE__ */ jsx(TerminalContext.Provider, { value: { variant }, children: /* @__PURE__ */ jsx(
2538
3311
  "div",
@@ -2550,14 +3323,14 @@ var TerminalRoot = React14.forwardRef(
2550
3323
  }
2551
3324
  );
2552
3325
  TerminalRoot.displayName = "Terminal";
2553
- var TerminalHeader = React14.forwardRef(
3326
+ var TerminalHeader = React.forwardRef(
2554
3327
  ({ className, title, showControls = true, children, ...props }, ref) => {
2555
3328
  return /* @__PURE__ */ jsxs(
2556
3329
  "div",
2557
3330
  {
2558
3331
  ref,
2559
3332
  className: cn(
2560
- "flex items-center gap-2 px-4 py-3 border-b border-[var(--neutral-7)] bg-[var(--neutral-3)]",
3333
+ "flex items-center gap-2 px-4 py-3 border-b border-border bg-muted",
2561
3334
  className
2562
3335
  ),
2563
3336
  ...props,
@@ -2567,7 +3340,7 @@ var TerminalHeader = React14.forwardRef(
2567
3340
  /* @__PURE__ */ jsx("span", { className: "w-3 h-3 rounded-full bg-yellow-500/80", "aria-hidden": true }),
2568
3341
  /* @__PURE__ */ jsx("span", { className: "w-3 h-3 rounded-full bg-green-500/80", "aria-hidden": true })
2569
3342
  ] }),
2570
- title && /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-[var(--neutral-9)]", children: title }),
3343
+ title && /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: title }),
2571
3344
  children
2572
3345
  ]
2573
3346
  }
@@ -2575,13 +3348,13 @@ var TerminalHeader = React14.forwardRef(
2575
3348
  }
2576
3349
  );
2577
3350
  TerminalHeader.displayName = "Terminal.Header";
2578
- var TerminalBody = React14.forwardRef(
3351
+ var TerminalBody = React.forwardRef(
2579
3352
  ({ className, children, ...props }, ref) => {
2580
3353
  return /* @__PURE__ */ jsx("div", { ref, className: cn("p-4 space-y-1", className), ...props, children });
2581
3354
  }
2582
3355
  );
2583
3356
  TerminalBody.displayName = "Terminal.Body";
2584
- var TerminalLine = React14.forwardRef(
3357
+ var TerminalLine = React.forwardRef(
2585
3358
  ({ className, prompt = "$", output = false, highlight = false, children, ...props }, ref) => {
2586
3359
  return /* @__PURE__ */ jsxs(
2587
3360
  "div",
@@ -2589,19 +3362,13 @@ var TerminalLine = React14.forwardRef(
2589
3362
  ref,
2590
3363
  className: cn(
2591
3364
  "flex items-start gap-2",
2592
- highlight && "bg-[var(--neutral-3)] -mx-2 px-2 py-0.5 rounded",
3365
+ highlight && "bg-muted -mx-2 px-2 py-0.5 rounded",
2593
3366
  className
2594
3367
  ),
2595
3368
  ...props,
2596
3369
  children: [
2597
3370
  !output && /* @__PURE__ */ jsx("span", { className: "text-emerald-400 shrink-0 select-none", children: prompt }),
2598
- /* @__PURE__ */ jsx(
2599
- "span",
2600
- {
2601
- className: cn("flex-1", output ? "text-[var(--neutral-9)]" : "text-[var(--neutral-11)]"),
2602
- children
2603
- }
2604
- )
3371
+ /* @__PURE__ */ jsx("span", { className: cn("flex-1", output ? "text-muted-foreground" : "text-muted-foreground"), children })
2605
3372
  ]
2606
3373
  }
2607
3374
  );
@@ -2642,7 +3409,7 @@ function subscribePlatform() {
2642
3409
  return () => void 0;
2643
3410
  }
2644
3411
  function usePlatform() {
2645
- return React14.useSyncExternalStore(subscribePlatform, getClientPlatform, () => "apple");
3412
+ return React.useSyncExternalStore(subscribePlatform, getClientPlatform, () => "apple");
2646
3413
  }
2647
3414
  function normalizeKey(children) {
2648
3415
  if (typeof children !== "string") {
@@ -2657,41 +3424,50 @@ function normalizeKey(children) {
2657
3424
  function getModifierSymbols(platform) {
2658
3425
  return platform === "apple" ? appleModifierSymbols : otherModifierSymbols;
2659
3426
  }
2660
- var Kbd = React14.forwardRef(
2661
- ({ meta, shift, alt, ctrl, small, children, className, "aria-label": ariaLabel, ...props }, ref) => {
2662
- const platform = usePlatform();
2663
- const symbols = getModifierSymbols(platform);
2664
- const activeModifiers = modifierOrder.filter((modifier) => {
2665
- if (modifier === "meta") return meta;
2666
- if (modifier === "shift") return shift;
2667
- if (modifier === "alt") return alt;
2668
- return ctrl;
2669
- });
2670
- const normalizedKey = normalizeKey(children);
2671
- const visualParts = [
2672
- ...activeModifiers.map((modifier) => symbols[modifier]),
2673
- normalizedKey
2674
- ].filter(Boolean);
2675
- const accessibleName = ariaLabel ?? [
2676
- ...activeModifiers.map((modifier) => modifierLabels[modifier]),
2677
- typeof normalizedKey === "string" ? normalizedKey : void 0
2678
- ].filter(Boolean).join(" ");
2679
- return /* @__PURE__ */ jsx(
2680
- "kbd",
2681
- {
2682
- ref,
2683
- "aria-label": accessibleName || void 0,
2684
- className: cn(
2685
- "inline-flex select-none items-center justify-center gap-0.5 rounded-[var(--radius-sm)] border border-border bg-muted font-mono font-medium leading-none text-muted-foreground tabular-nums",
2686
- small ? "min-h-4 min-w-4 px-1 py-0 text-xs" : "min-h-5 min-w-5 px-1.5 py-0.5 text-xs",
2687
- className
2688
- ),
2689
- ...props,
2690
- children: visualParts.join("")
2691
- }
2692
- );
2693
- }
2694
- );
3427
+ var Kbd = ({
3428
+ meta,
3429
+ shift,
3430
+ alt,
3431
+ ctrl,
3432
+ small,
3433
+ children,
3434
+ className,
3435
+ "aria-label": ariaLabel,
3436
+ ref,
3437
+ ...props
3438
+ }) => {
3439
+ const platform = usePlatform();
3440
+ const symbols = getModifierSymbols(platform);
3441
+ const activeModifiers = modifierOrder.filter((modifier) => {
3442
+ if (modifier === "meta") return meta;
3443
+ if (modifier === "shift") return shift;
3444
+ if (modifier === "alt") return alt;
3445
+ return ctrl;
3446
+ });
3447
+ const normalizedKey = normalizeKey(children);
3448
+ const visualParts = [
3449
+ ...activeModifiers.map((modifier) => symbols[modifier]),
3450
+ normalizedKey
3451
+ ].filter(Boolean);
3452
+ const accessibleName = ariaLabel ?? [
3453
+ ...activeModifiers.map((modifier) => modifierLabels[modifier]),
3454
+ typeof normalizedKey === "string" ? normalizedKey : void 0
3455
+ ].filter(Boolean).join(" ");
3456
+ return /* @__PURE__ */ jsx(
3457
+ "kbd",
3458
+ {
3459
+ ref,
3460
+ "aria-label": accessibleName || void 0,
3461
+ className: cn(
3462
+ "inline-flex select-none items-center justify-center gap-0.5 rounded-[var(--radius-sm)] border border-border bg-muted font-mono font-medium leading-none text-muted-foreground tabular-nums",
3463
+ small ? "min-h-4 min-w-4 px-1 py-0 text-xs" : "min-h-5 min-w-5 px-1.5 py-0.5 text-xs",
3464
+ className
3465
+ ),
3466
+ ...props,
3467
+ children: visualParts.join("")
3468
+ }
3469
+ );
3470
+ };
2695
3471
  Kbd.displayName = "Kbd";
2696
3472
  function computeInitials(user) {
2697
3473
  if (user.initials && user.initials.trim().length > 0) {
@@ -2716,20 +3492,20 @@ function DefaultTrigger({ user }) {
2716
3492
  "aria-label": "Open user menu",
2717
3493
  className: cn(
2718
3494
  "inline-flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full",
2719
- "outline-none transition-all hover:opacity-90",
2720
- "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
3495
+ "outline-none transition-[box-shadow,opacity] hover:opacity-90",
3496
+ "",
2721
3497
  "hover:ring-1 hover:ring-border"
2722
3498
  ),
2723
3499
  children: /* @__PURE__ */ jsxs(Avatar, { size: "sm", children: [
2724
3500
  user.avatarUrl ? /* @__PURE__ */ jsx(AvatarImage, { src: user.avatarUrl, alt: user.name }) : null,
2725
- /* @__PURE__ */ jsx(AvatarFallback, { size: "sm", className: "bg-[image:var(--brand-gradient)] text-white", children: initials2 })
3501
+ /* @__PURE__ */ jsx(AvatarFallback, { size: "sm", className: "bg-primary text-white", children: initials2 })
2726
3502
  ] })
2727
3503
  }
2728
3504
  );
2729
3505
  }
2730
3506
  function UserMenuItemContent({ item }) {
2731
3507
  const Icon = item.icon;
2732
- return /* @__PURE__ */ jsxs(Fragment, { children: [
3508
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
2733
3509
  Icon ? /* @__PURE__ */ jsx(Icon, { className: "mr-2 h-4 w-4 shrink-0", "aria-hidden": true }) : null,
2734
3510
  /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: item.label }),
2735
3511
  item.shortcut ? /* @__PURE__ */ jsx(Kbd, { className: "ml-2", small: true, children: item.shortcut }) : null
@@ -2752,7 +3528,7 @@ function UserMenu(props) {
2752
3528
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 p-3", children: [
2753
3529
  /* @__PURE__ */ jsxs(Avatar, { size: "md", children: [
2754
3530
  user.avatarUrl ? /* @__PURE__ */ jsx(AvatarImage, { src: user.avatarUrl, alt: user.name }) : null,
2755
- /* @__PURE__ */ jsx(AvatarFallback, { size: "md", className: "bg-[image:var(--brand-gradient)] text-white", children: initials2 })
3531
+ /* @__PURE__ */ jsx(AvatarFallback, { size: "md", className: "bg-primary text-white", children: initials2 })
2756
3532
  ] }),
2757
3533
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
2758
3534
  /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium text-foreground", children: user.name }),
@@ -2760,13 +3536,13 @@ function UserMenu(props) {
2760
3536
  ] })
2761
3537
  ] }),
2762
3538
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2763
- workspaceSlot ? /* @__PURE__ */ jsxs(Fragment, { children: [
3539
+ workspaceSlot ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
2764
3540
  /* @__PURE__ */ jsx("div", { className: "px-1 py-1", children: workspaceSlot }),
2765
3541
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {})
2766
3542
  ] }) : null,
2767
3543
  groups.map((group, groupIndex) => {
2768
3544
  const isLastGroup = groupIndex === groups.length - 1;
2769
- return /* @__PURE__ */ jsxs(React14.Fragment, { children: [
3545
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
2770
3546
  group.label ? /* @__PURE__ */ jsx("div", { className: "px-2 py-1 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: group.label }) : null,
2771
3547
  group.items.map((item) => {
2772
3548
  const itemClassName = cn(
@@ -2812,7 +3588,7 @@ function getInitials(workspace) {
2812
3588
  if (!trimmed) return "??";
2813
3589
  const parts = trimmed.split(/\s+/).filter(Boolean);
2814
3590
  if (parts.length >= 2) {
2815
- return `${parts[0][0] ?? ""}${parts[1][0] ?? ""}`.toUpperCase();
3591
+ return `${parts[0]?.[0] ?? ""}${parts[1]?.[0] ?? ""}`.toUpperCase();
2816
3592
  }
2817
3593
  return trimmed.slice(0, 2).toUpperCase();
2818
3594
  }
@@ -2830,43 +3606,35 @@ function roleLabel(role) {
2830
3606
  }
2831
3607
  function WorkspaceAvatar({ workspace, size = "sm", className }) {
2832
3608
  const initials2 = getInitials(workspace);
2833
- return /* @__PURE__ */ jsxs(Avatar, { size, className: cn("rounded-md", className), children: [
2834
- workspace.avatarUrl && /* @__PURE__ */ jsx(AvatarImage, { src: workspace.avatarUrl, alt: workspace.name, className: "rounded-md" }),
3609
+ return /* @__PURE__ */ jsxs(Avatar, { size, className: cn("rounded-[var(--radius-md)]", className), children: [
3610
+ workspace.avatarUrl && /* @__PURE__ */ jsx(
3611
+ AvatarImage,
3612
+ {
3613
+ src: workspace.avatarUrl,
3614
+ alt: workspace.name,
3615
+ className: "rounded-[var(--radius-md)]"
3616
+ }
3617
+ ),
2835
3618
  /* @__PURE__ */ jsx(
2836
3619
  AvatarFallback,
2837
3620
  {
2838
3621
  size,
2839
- className: "rounded-md bg-[image:var(--brand-gradient)] text-white font-semibold",
3622
+ className: "rounded-[var(--radius-md)] bg-primary text-white font-semibold",
2840
3623
  children: initials2
2841
3624
  }
2842
3625
  )
2843
3626
  ] });
2844
3627
  }
2845
- var TriggerButton = React14.forwardRef(
2846
- ({ activeWorkspace, variant, showRoleBadge, disabled, className }, ref) => {
2847
- const isOwner = activeWorkspace.role === "owner";
2848
- if (variant === "compact") {
2849
- return /* @__PURE__ */ jsxs(
2850
- "button",
2851
- {
2852
- ref,
2853
- type: "button",
2854
- "aria-label": "Switch workspace",
2855
- disabled,
2856
- className: cn(
2857
- "inline-flex items-center gap-1 rounded-md p-1 outline-none transition-colors",
2858
- "hover:bg-accent hover:text-accent-foreground",
2859
- "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
2860
- "disabled:cursor-not-allowed disabled:opacity-50",
2861
- className
2862
- ),
2863
- children: [
2864
- /* @__PURE__ */ jsx(WorkspaceAvatar, { workspace: activeWorkspace, size: "sm" }),
2865
- /* @__PURE__ */ jsx(ChevronUpDown, { "aria-hidden": "true", className: "h-3.5 w-3.5 text-muted-foreground" })
2866
- ]
2867
- }
2868
- );
2869
- }
3628
+ function TriggerButton({
3629
+ activeWorkspace,
3630
+ variant,
3631
+ showRoleBadge,
3632
+ disabled,
3633
+ className,
3634
+ ref
3635
+ }) {
3636
+ const isOwner = activeWorkspace.role === "owner";
3637
+ if (variant === "compact") {
2870
3638
  return /* @__PURE__ */ jsxs(
2871
3639
  "button",
2872
3640
  {
@@ -2875,24 +3643,44 @@ var TriggerButton = React14.forwardRef(
2875
3643
  "aria-label": "Switch workspace",
2876
3644
  disabled,
2877
3645
  className: cn(
2878
- "inline-flex w-full items-center gap-2 rounded-md border border-border bg-background px-2 py-1 text-left outline-none transition-colors",
3646
+ "inline-flex items-center gap-1 rounded-[var(--radius-md)] p-1 outline-none transition-colors",
2879
3647
  "hover:bg-accent hover:text-accent-foreground",
2880
- "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
3648
+ "",
2881
3649
  "disabled:cursor-not-allowed disabled:opacity-50",
2882
3650
  className
2883
3651
  ),
2884
3652
  children: [
2885
3653
  /* @__PURE__ */ jsx(WorkspaceAvatar, { workspace: activeWorkspace, size: "sm" }),
2886
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
2887
- /* @__PURE__ */ jsx("span", { className: "truncate font-medium text-[13px] text-foreground", children: activeWorkspace.name }),
2888
- showRoleBadge && isOwner && /* @__PURE__ */ jsx(Badge, { variant: "owner", size: "sm", children: "Owner" })
2889
- ] }),
2890
- /* @__PURE__ */ jsx(ChevronUpDown, { "aria-hidden": "true", className: "size-3.5 shrink-0 text-muted-foreground" })
3654
+ /* @__PURE__ */ jsx(ChevronUpDown, { "aria-hidden": "true", className: "h-3.5 w-3.5 text-muted-foreground" })
2891
3655
  ]
2892
3656
  }
2893
3657
  );
2894
3658
  }
2895
- );
3659
+ return /* @__PURE__ */ jsxs(
3660
+ "button",
3661
+ {
3662
+ ref,
3663
+ type: "button",
3664
+ "aria-label": "Switch workspace",
3665
+ disabled,
3666
+ className: cn(
3667
+ "inline-flex w-full items-center gap-2 rounded-[var(--radius-md)] border border-border bg-background px-2 py-1 text-left outline-none transition-colors",
3668
+ "hover:bg-accent hover:text-accent-foreground",
3669
+ "",
3670
+ "disabled:cursor-not-allowed disabled:opacity-50",
3671
+ className
3672
+ ),
3673
+ children: [
3674
+ /* @__PURE__ */ jsx(WorkspaceAvatar, { workspace: activeWorkspace, size: "sm" }),
3675
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
3676
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium text-[13px] text-foreground", children: activeWorkspace.name }),
3677
+ showRoleBadge && isOwner && /* @__PURE__ */ jsx(Badge, { variant: "owner", size: "sm", children: "Owner" })
3678
+ ] }),
3679
+ /* @__PURE__ */ jsx(ChevronUpDown, { "aria-hidden": "true", className: "size-3.5 shrink-0 text-muted-foreground" })
3680
+ ]
3681
+ }
3682
+ );
3683
+ }
2896
3684
  TriggerButton.displayName = "WorkspaceSwitcherTrigger";
2897
3685
  function WorkspaceItem({ workspace, isActive, onSelect }) {
2898
3686
  return /* @__PURE__ */ jsxs(
@@ -2950,7 +3738,7 @@ function WorkspaceSwitcher({
2950
3738
  "div",
2951
3739
  {
2952
3740
  className: cn(
2953
- "inline-flex items-center gap-2 rounded-md border border-dashed border-border px-2 py-1.5 text-sm text-muted-foreground",
3741
+ "inline-flex items-center gap-2 rounded-[var(--radius-md)] border border-dashed border-border px-2 py-1.5 text-sm text-muted-foreground",
2954
3742
  className
2955
3743
  ),
2956
3744
  children: "No workspaces"
@@ -2975,7 +3763,7 @@ function WorkspaceSwitcher({
2975
3763
  sideOffset: 6,
2976
3764
  className: "w-[min(20rem,calc(100vw-2rem))] p-1",
2977
3765
  children: [
2978
- headerSlot && /* @__PURE__ */ jsxs(Fragment, { children: [
3766
+ headerSlot && /* @__PURE__ */ jsxs(Fragment$1, { children: [
2979
3767
  /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5", children: headerSlot }),
2980
3768
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {})
2981
3769
  ] }),
@@ -2989,7 +3777,7 @@ function WorkspaceSwitcher({
2989
3777
  },
2990
3778
  ws.id
2991
3779
  )) }),
2992
- footerSlot && /* @__PURE__ */ jsxs(Fragment, { children: [
3780
+ footerSlot && /* @__PURE__ */ jsxs(Fragment$1, { children: [
2993
3781
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2994
3782
  /* @__PURE__ */ jsx("div", { className: "px-1 py-0.5", children: footerSlot })
2995
3783
  ] })
@@ -2999,6 +3787,6 @@ function WorkspaceSwitcher({
2999
3787
  ] });
3000
3788
  }
3001
3789
 
3002
- export { Card, CardBody, CardDescription, CardFooter, CardHeader, CardIcon, CardRoot, CardTitle, CommandBox, GalleryCard, MarkdownEditor, MarkdownRenderer, QAPage, SidebarNav, Terminal, TerminalBody, TerminalHeader, TerminalLine, TerminalRoot, UserInfo, UserMenu, VoteButtons, WorkspaceSwitcher };
3790
+ export { ArtifactShiftCard, ArtifactShiftCardFooter, ArtifactShiftCardPreview, Card, CardBody, CardDescription, CardFooter, CardHeader, CardIcon, CardRoot, CardTitle, CommandBox, DashboardCommandSurface, DashboardMetricTile, DashboardPanel, GalleryCard, KineticCodePreview, KineticCommandBox, KineticConsoleFrame, KineticFeatureCard, KineticMorphSurface, KineticSignalMarquee, KineticStep, KineticStepRail, MarkdownEditor, MarkdownRenderer, QAPage, SidebarNav, Terminal, TerminalBody, TerminalHeader, TerminalLine, TerminalRoot, UserInfo, UserMenu, VoteButtons, WorkspaceSwitcher };
3003
3791
  //# sourceMappingURL=index.js.map
3004
3792
  //# sourceMappingURL=index.js.map