diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index fcf4e68..dbf449c 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -3,9 +3,9 @@ name: Documentation
on:
push:
branches: [main]
- paths: ['apps/**', 'packages/**', 'package.json', 'package-lock.json', '.github/workflows/docs.yml']
+ paths: ['apps/**', 'packages/**', 'vendor/**', 'hig-drift.json', 'package.json', 'package-lock.json', '.github/workflows/docs.yml']
pull_request:
- paths: ['apps/**', 'packages/**', 'package.json', 'package-lock.json', '.github/workflows/docs.yml']
+ paths: ['apps/**', 'packages/**', 'vendor/**', 'hig-drift.json', 'package.json', 'package-lock.json', '.github/workflows/docs.yml']
workflow_dispatch:
permissions:
@@ -33,6 +33,17 @@ jobs:
- run: npm run docs:build
- run: npm run docs:check
- run: npm run lint
+ # Scoped HIG anti-drift check from the same HIG commit as vendor/bloxwap-hig (bloxwap/hig#58).
+ - uses: actions/checkout@v7
+ with:
+ repository: bloxwap/hig
+ ref: 19c75619fa5020c015aa639172c83fd02f2bc0a2
+ path: .hig
+ sparse-checkout: scripts/drift.mjs
+ sparse-checkout-cone-mode: false
+ - run: node .hig/scripts/drift.mjs --root . --config hig-drift.json
+ - run: npx playwright install --with-deps chromium
+ - run: npm run docs:smoke
- uses: actions/upload-pages-artifact@v5
with:
path: apps/docs/out
diff --git a/.gitignore b/.gitignore
index b9ad226..91be0ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,5 @@ binaries/
out/
*.tsbuildinfo
apps/docs/next-env.d.ts
+.hig/
+!vendor/bloxwap-hig/*.tgz
diff --git a/apps/docs/README.md b/apps/docs/README.md
index da455f9..5ea1107 100644
--- a/apps/docs/README.md
+++ b/apps/docs/README.md
@@ -34,14 +34,21 @@ uses a static `search.json` index in the browser. `llms.txt`, robots, and sitema
are generated for the configured deployment URL. The Pages workflow builds and
checks PRs and deploys only main.
-The design mirrors Chart's dark surfaces, green accents, typography, navigation,
-footer, and HIG controls. `app/global.css`, `styles/hig.generated.css`, and
-`vendor/hig/` are copied from Chart, including the upstream license and provenance.
-`hig-tokens.mjs --check` verifies the pinned hashes and adapter; update vendor files
-from the upstream source rather than hand-editing generated tokens.
+The design mirrors Chart's dark surfaces, green accents, typography, navigation and
+footer. Shared presentation comes from the Bloxwap HIG packages, installed from the
+packed candidates in [`vendor/bloxwap-hig/`](../../vendor/bloxwap-hig/README.md):
+`@bloxwap/hig-tokens/css` and `@bloxwap/hig-react/css` supply the `--hig-*` roles and
+control recipes, and the install tabs, copy buttons, search states and MDX callouts
+use HIG `Tabs`, `InstallCommand`, `IconButton`, `Alert`, `EmptyState` and `Callout`.
+`app/global.css` maps Fumadocs onto the HIG roles and keeps only site layout. Never
+copy HIG CSS, palettes or fonts into this app. `hig-tokens.mjs --check` (part of
+`docs:check`) verifies the vendored hashes, the installed versions and the few
+JS-only HIG values `global.css` repeats. CI also runs HIG's scoped drift check
+(`hig-drift.json`) and `npm run docs:smoke`, a Playwright pass over install/copy,
+keyboard, search, 404 and 390 px navigation against the static export.
Bloxwap Sans and Mono are self-hosted by `@bloxwap/font@0.1.2`. The social renderer
-uses local Bold/Black TTF instances; see `fonts/README.md` and the font license.
+uses the static Bold/Black instances shipped in `@bloxwap/hig-tokens/fonts`.
Brand marks in `public/logos/` are supplied artwork, never typeset replacements.
Every MDX page receives a static social card via `app/og/[...slug]/route.tsx`.
diff --git a/apps/docs/app/global.css b/apps/docs/app/global.css
index 97b48ac..8fcb20a 100644
--- a/apps/docs/app/global.css
+++ b/apps/docs/app/global.css
@@ -1,34 +1,62 @@
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
-@import '../vendor/hig/tokens.css';
-@import '../styles/hig.generated.css';
+@import '@bloxwap/hig-tokens/css';
+@import '@bloxwap/hig-react/css';
@theme inline {
--font-sans: var(--font-bloxwap-sans), ui-rounded, system-ui, sans-serif;
--font-mono: var(--font-bloxwap-mono), ui-monospace, monospace;
+ --text-3xs: 0.625rem;
+ --text-2xs: 0.6875rem;
}
-/* Keep Fumadocs surfaces and states on the shared Bloxwap palette. */
+/*
+ * Colors, spacing and control heights come from @bloxwap/hig-tokens/css as --hig-* roles. The package
+ * publishes radius, motion, type and compact density only in JS (`tokens`), so this host copies those
+ * numbers once; `scripts/hig-tokens.mjs --check` fails if they stop matching the installed package.
+ */
+:root {
+ --docs-radius: 14px; /* tokens.radius.xl */
+ --docs-radius-pill: 9999px; /* tokens.radius.pill */
+ --docs-duration: 180ms; /* tokens.motion.fast */
+ --docs-ease: cubic-bezier(0.22, 1, 0.36, 1);
+ --docs-control-compact: 36px; /* tokens.density.compact.control */
+ --docs-control-touch: 48px; /* tokens.density.comfortable.control */
+ --docs-control-min: 6rem;
+ --docs-icon: 16px;
+ --docs-type-caption: 0.75rem; /* tokens.type.caption.size */
+ --docs-type-body: 1rem; /* tokens.type.body.size */
+ --docs-type-body-line: 1.5rem; /* tokens.type.body.lineHeight */
+ --docs-type-title: 1.5rem; /* tokens.type.title.size */
+ --docs-type-title-line: 1.875rem; /* tokens.type.title.lineHeight */
+ --docs-type-display: 3rem; /* tokens.type.display.size */
+ --docs-type-weight: 600; /* tokens.type.title.weight and tokens.type.display.weight */
+}
+@media (prefers-reduced-motion: reduce) {
+ :root { --docs-duration: 0ms; }
+}
+
+/* Fumadocs surfaces and states read the HIG semantic roles directly. */
:root,
.dark,
.dark #nd-sidebar {
- --color-fd-background: var(--bloxwap-black);
- --color-fd-foreground: var(--foreground);
- --color-fd-card: var(--bloxwap-black);
- --color-fd-card-foreground: var(--foreground);
- --color-fd-popover: var(--popover);
- --color-fd-popover-foreground: var(--popover-foreground);
- --color-fd-muted: var(--muted);
- --color-fd-muted-foreground: var(--muted-foreground);
- --color-fd-secondary: var(--card);
- --color-fd-secondary-foreground: var(--foreground);
- --color-fd-border: var(--border);
- --color-fd-primary: var(--bloxwap-green);
- --color-fd-primary-foreground: var(--bloxwap-black);
- --color-fd-accent: var(--card);
- --color-fd-accent-foreground: var(--foreground);
- --color-fd-ring: var(--bloxwap-green);
+ --color-fd-background: var(--hig-background);
+ --color-fd-foreground: var(--hig-text);
+ --color-fd-card: var(--hig-background);
+ --color-fd-card-foreground: var(--hig-text);
+ --color-fd-popover: var(--hig-nested);
+ --color-fd-popover-foreground: var(--hig-text);
+ --color-fd-muted: var(--hig-nested);
+ --color-fd-muted-foreground: var(--hig-muted);
+ --color-fd-secondary: var(--hig-surface);
+ --color-fd-secondary-foreground: var(--hig-text);
+ --color-fd-border: var(--hig-border);
+ --color-fd-primary: var(--hig-action);
+ --color-fd-primary-foreground: var(--hig-onAction);
+ --color-fd-accent: var(--hig-surface);
+ --color-fd-accent-foreground: var(--hig-text);
+ --color-fd-ring: var(--hig-focus);
}
html {
@@ -45,13 +73,8 @@ html > body[data-scroll-locked] {
}
::selection {
- background: color-mix(in srgb, var(--bloxwap-green) 25%, transparent);
- color: var(--foreground);
-}
-
-:focus-visible {
- outline: 2px solid var(--bloxwap-green);
- outline-offset: 3px;
+ background: color-mix(in srgb, var(--hig-action) 25%, transparent);
+ color: var(--hig-text);
}
#nd-page {
@@ -71,8 +94,8 @@ html > body[data-scroll-locked] {
}
#nd-page > p {
- font-size: var(--type-body-size);
- line-height: var(--type-body-line);
+ font-size: var(--docs-type-body);
+ line-height: var(--docs-type-body-line);
}
.prose {
@@ -96,7 +119,7 @@ html > body[data-scroll-locked] {
}
.prose a:not([data-card]):hover {
- color: var(--bloxwap-green);
+ color: var(--hig-action);
}
.prose [data-card='true'] {
@@ -105,7 +128,7 @@ html > body[data-scroll-locked] {
}
.prose [data-card='true']:hover {
- border-color: color-mix(in srgb, var(--bloxwap-green) 40%, var(--border));
+ border-color: color-mix(in srgb, var(--hig-action) 40%, var(--hig-border));
}
.prose [data-card='true'] h3 {
@@ -114,12 +137,12 @@ html > body[data-scroll-locked] {
}
#nd-sidebar {
- border-color: var(--border);
+ border-color: var(--hig-border);
}
#nd-sidebar a[data-active='true'] {
- background: color-mix(in srgb, var(--bloxwap-green) 8%, transparent);
- color: var(--bloxwap-green);
+ background: color-mix(in srgb, var(--hig-action) 8%, transparent);
+ color: var(--hig-action);
}
/* Fumadocs' sidebar icon-link bar ships as a stroked box; with GitHub its only link, drop the box and keep the icon. */
@@ -129,7 +152,7 @@ html > body[data-scroll-locked] {
}
.docs-sidebar-footer {
- padding-top: var(--space-xs);
+ padding-top: var(--hig-space-xs);
}
.docs-app-link {
@@ -138,122 +161,88 @@ html > body[data-scroll-locked] {
justify-content: space-between;
min-height: 2.5rem;
padding: 0.5rem 0.75rem;
- border-radius: var(--radius-full);
- transition: background-color var(--duration-fast) var(--ease-spring), color var(--duration-fast) var(--ease-spring);
+ border-radius: var(--docs-radius-pill);
+ transition: background-color var(--docs-duration) var(--docs-ease), color var(--docs-duration) var(--docs-ease);
font-size: 0.875rem;
font-weight: 600;
}
.docs-app-link:hover {
- background: var(--card);
- color: var(--bloxwap-green);
+ background: var(--hig-surface);
+ color: var(--hig-action);
}
/*
- * Buttons: plain-UI's .btn family (www button.tsx: pill, h-12, text-base semibold, pressed scale).
- * The primary fill is brand green with black text, as in www's .nav-cta/.submit and the app's CTAs.
+ * HIG buttons (@bloxwap/hig-react/css) supply paint, height and states. The host adds layout only: icon
+ * slots, anchors rendered as buttons, and the font loader's family names. @bloxwap/font registers
+ * Bloxwap Sans under a generated name, so the recipe's 'Bloxwap Sans' family is mapped to its variable.
*/
-.btn {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- gap: var(--space-sm);
- min-height: var(--control-h);
- min-width: var(--control-min-w);
- padding: 0 var(--space-xl);
- border: 1px solid transparent;
- border-radius: var(--radius-full);
- background: var(--bloxwap-green);
- color: var(--bloxwap-black);
- font: 600 var(--text-base) / 1 var(--font-sans);
- white-space: normal;
- overflow-wrap: anywhere;
- cursor: pointer;
- text-decoration: none;
- touch-action: manipulation;
- transition:
- background-color var(--duration-fast) var(--ease-spring),
- color var(--duration-fast) var(--ease-spring),
- border-color var(--duration-fast) var(--ease-spring),
- transform var(--duration-fast) var(--ease-spring);
-}
-.btn:hover { background: color-mix(in oklab, var(--bloxwap-green) 90%, transparent); color: var(--bloxwap-black); }
-.btn:active { transform: scale(0.98); }
-.btn:disabled, .btn[aria-disabled='true'] { opacity: 0.5; pointer-events: none; }
-.btn svg { flex: none; width: var(--icon-md); height: var(--icon-md); }
-.btn--secondary { background: var(--card); color: var(--foreground); }
-.btn--secondary:hover { background: var(--muted); color: var(--foreground); }
-.btn--ghost { background: transparent; color: var(--muted-foreground); min-width: 0; }
-.btn--ghost:hover { background: var(--card); color: var(--foreground); }
-.btn--sm { height: var(--control-h-sm); min-width: 5rem; padding: 0 var(--space-md); font-size: var(--text-sm); }
-.btn--ghost.btn--sm { min-width: 0; padding: 0 var(--space-sm); }
-.btn--icon { width: var(--control-h-sm); height: var(--control-h-sm); min-width: 0; padding: 0; }
+.hig-button {
+ display: inline-flex; align-items: center; justify-content: center; gap: var(--hig-space-sm);
+ font-family: var(--font-sans); text-decoration: none; touch-action: manipulation;
+}
+.hig-button svg { flex: none; width: var(--docs-icon); height: var(--docs-icon); }
+.hig-button[data-shape='icon'] { width: var(--hig-control); min-width: 0; padding: 0; }
+.hig-button[data-shape='icon'] > span { display: inline-flex; }
+.hig-number { font-family: var(--font-mono); }
/* Chart-specific layout on the scale above; typography, surfaces, and states follow workers/docs. */
-.brand { display: inline-flex; align-items: center; gap: var(--space-md); }
+.brand { display: inline-flex; align-items: center; gap: var(--hig-space-md); }
.brand img { flex: none; width: 28px; height: 28px; }
-.brand-product { border-left: 1px solid var(--border); padding-left: var(--space-md); color: var(--muted-foreground); font-size: var(--text-sm); }
+.brand-product { border-left: 1px solid var(--hig-border); padding-left: var(--hig-space-md); color: var(--hig-muted); font-size: var(--text-sm); }
.hero h1, .principles h2, .start-grid h2, .guide-links h3, .not-found h1 {
font-family: var(--font-sans);
}
/* Same box as the Fumadocs header (max-w --fd-layout-width, 16px padding), so content lines up with the nav. */
-.home { width: 100%; max-width: var(--fd-layout-width, 1400px); padding: var(--space-5xl) var(--space-lg) 0; margin: 0 auto; }
-.hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: var(--space-6xl); padding-bottom: var(--space-5xl); }
+.home { width: 100%; max-width: var(--fd-layout-width, 1400px); padding: var(--hig-space-section) var(--hig-space-lg) 0; margin: 0 auto; }
+.hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: var(--hig-space-section); padding-bottom: var(--hig-space-section); }
.hero--single { grid-template-columns: minmax(0, 1fr); max-width: 47.5rem; }
.hero-copy { min-width: 0; }
-.eyebrow { display: flex; align-items: center; gap: var(--space-sm); color: var(--color-fd-muted-foreground); font: var(--text-2xs) / 1.5 var(--font-mono); letter-spacing: .09em; }
-.status-dot { width: 6px; height: 6px; border-radius: var(--radius-full); background: var(--color-fd-primary); }
-.hero h1 { margin: var(--space-xl) 0 0; font-size: clamp(var(--text-5xl), 4.4vw, 4rem); line-height: 1.07; font-weight: 600; letter-spacing: -.04em; }
+.eyebrow { display: flex; align-items: center; gap: var(--hig-space-sm); color: var(--color-fd-muted-foreground); font: var(--text-2xs) / 1.5 var(--font-mono); letter-spacing: .09em; }
+.status-dot { width: 6px; height: 6px; border-radius: var(--docs-radius-pill); background: var(--color-fd-primary); }
+.hero h1 { margin: var(--hig-space-xl) 0 0; font-size: clamp(var(--text-5xl), 4.4vw, 4rem); line-height: 1.07; font-weight: 600; letter-spacing: -.04em; }
.hero h1 span { color: var(--color-fd-foreground); }
-.hero-description { max-width: 35rem; margin-top: var(--space-xl); color: var(--color-fd-muted-foreground); line-height: 1.5; font-size: var(--text-lg); }
-.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-md); margin: var(--space-2xl) 0 var(--space-xl); }
-.package-install { width: fit-content; max-width: 100%; margin-top: var(--space-2xl); }
-.install-tabs { display: inline-flex; max-width: 100%; gap: var(--space-xs); padding: var(--space-xs); border-radius: var(--radius-full); background: var(--card); }
-.install-tabs button {
- min-width: 0; height: 2rem; padding: 0 var(--space-lg); border-radius: var(--radius-full);
- color: var(--muted-foreground); font: 600 var(--text-sm) / 1 var(--font-mono); cursor: pointer;
- transition: background-color var(--duration-fast) var(--ease-spring), color var(--duration-fast) var(--ease-spring);
-}
-.install-tabs button:hover { color: var(--foreground); }
-.install-tabs button[aria-selected='true'] { background: var(--muted); color: var(--foreground); }
-.install-command {
- display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--space-lg); min-width: 0; margin-top: var(--space-md);
- padding: var(--space-xs) var(--space-xs) var(--space-xs) var(--space-xl); border-radius: var(--radius-full);
- background: var(--card); font: 600 var(--text-sm) / 1.5 var(--font-mono);
-}
-.install-prompt { flex: none; color: var(--muted-foreground); user-select: none; }
-.install-command code { min-width: 0; overflow-wrap: anywhere; user-select: all; }
-.install-command .btn { margin-left: auto; }
-.install-platforms, .install-feedback { margin-top: var(--space-lg); color: var(--muted-foreground); font-size: var(--text-sm); line-height: 1.5; }
-.install-feedback { display: block; }
+.hero-description { max-width: 35rem; margin-top: var(--hig-space-xl); color: var(--color-fd-muted-foreground); line-height: 1.5; font-size: var(--text-lg); }
+.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--hig-space-md); margin: var(--hig-space-xxl) 0 var(--hig-space-xl); }
+.package-install { width: fit-content; max-width: 100%; margin-top: var(--hig-space-xxl); }
+.package-install [role='tablist'] { gap: var(--hig-space-xs); }
+.package-install [role='tab'] { min-width: 4.5rem; font-family: var(--font-mono); }
+.package-install [role='tabpanel'] { margin-top: var(--hig-space-md); border-radius: var(--docs-radius); }
+/* Layout for the HIG InstallCommand recipe (surface, command, copy button, status). */
+.package-install .hig-surface { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--hig-space-md) var(--hig-space-lg); }
+.package-install pre { margin: 0; font: 600 var(--text-sm) / 1.5 var(--font-mono); white-space: pre-wrap; overflow-wrap: anywhere; }
+.package-install pre code::before { content: '$ '; color: var(--hig-muted); user-select: none; }
+.package-install [role='status'] { grid-column: 1 / -1; margin: 0; color: var(--hig-muted); font-size: var(--docs-type-caption); }
+.package-install [role='status']:empty { display: none; }
+.install-platforms { margin-top: var(--hig-space-lg); color: var(--hig-muted); font-size: var(--text-sm); line-height: 1.5; }
/* Hero code window: zero-stroke fill card with the Bloxwap code palette (as on the Hyperliquid SDK site). */
.code-window {
- --code-keyword: color-mix(in oklab, #ff479c 70%, var(--foreground));
- --code-type: color-mix(in oklab, var(--hig-info) 60%, var(--foreground));
- min-width: 0; margin: 0; overflow: hidden; border-radius: var(--radius-xl); background: var(--card); color: var(--foreground);
+ --code-keyword: color-mix(in oklab, #ff479c 70%, var(--hig-text));
+ --code-type: color-mix(in oklab, var(--hig-info) 60%, var(--hig-text));
+ min-width: 0; margin: 0; overflow: hidden; border-radius: var(--docs-radius); background: var(--hig-surface); color: var(--hig-text);
}
.code-toolbar {
- display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--space-md);
- padding: var(--space-md) var(--space-2xl) 0; font: var(--text-2xs) / 1.5 var(--font-mono); color: var(--muted-foreground);
+ display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--hig-space-md);
+ padding: var(--hig-space-md) var(--hig-space-xxl) 0; font: var(--text-2xs) / 1.5 var(--font-mono); color: var(--hig-muted);
}
-.window-dots { display: flex; gap: var(--space-xs); }
-.window-dots > i { width: 6px; height: 6px; border-radius: var(--radius-full); background: var(--muted); }
+.window-dots { display: flex; gap: var(--hig-space-xs); }
+.window-dots > i { width: 6px; height: 6px; border-radius: var(--docs-radius-pill); background: var(--hig-nested); }
.code-caption { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.code-language { color: var(--code-type); }
-.code-actions { display: flex; align-items: center; gap: var(--space-xs); margin-right: calc(-1 * var(--space-md)); }
-.code-toolbar { min-height: var(--control-h-sm); }
-.code-window pre { margin: 0; overflow-x: auto; padding: var(--space-xl) var(--space-2xl); font: var(--text-xs) / 1.85 var(--font-mono); tab-size: 2; scrollbar-width: none; }
+.code-actions { display: flex; align-items: center; gap: var(--hig-space-xs); margin-right: calc(-1 * var(--hig-space-md)); }
+.code-toolbar { min-height: var(--docs-control-compact); }
+.code-window pre { margin: 0; overflow-x: auto; padding: var(--hig-space-xl) var(--hig-space-xxl); font: var(--text-xs) / 1.85 var(--font-mono); tab-size: 2; scrollbar-width: none; }
.code-window pre::-webkit-scrollbar { display: none; }
.syntax-keyword { color: var(--code-keyword); }
-.syntax-string { color: var(--bloxwap-green); }
+.syntax-string { color: var(--hig-action); }
.syntax-type { color: var(--code-type); }
-.syntax-muted { color: var(--muted-foreground); }
+.syntax-muted { color: var(--hig-muted); }
.code-status {
- display: flex; align-items: center; gap: var(--space-sm); margin: 0;
- padding: 0 var(--space-2xl) var(--space-lg); font: var(--text-2xs) / 1.5 var(--font-mono); color: var(--muted-foreground);
+ display: flex; align-items: center; gap: var(--hig-space-sm); margin: 0;
+ padding: 0 var(--hig-space-xxl) var(--hig-space-lg); font: var(--text-2xs) / 1.5 var(--font-mono); color: var(--hig-muted);
}
-.code-status > span { width: 6px; height: 6px; border-radius: var(--radius-full); background: var(--bloxwap-green); }
+.code-status > span { width: 6px; height: 6px; border-radius: var(--docs-radius-pill); background: var(--hig-action); }
/*
* Entrance: three attention layers ~200 ms apart on one curve (MOT-2), as on the Hyperliquid SDK site:
@@ -262,7 +251,7 @@ html > body[data-scroll-locked] {
@keyframes landing-rise {
from { opacity: 0; translate: 0 8px; }
}
-.hero-copy > *, .code-window, .hero-preview { animation: landing-rise 600ms var(--ease-spring) both; }
+.hero-copy > *, .code-window, .hero-preview { animation: landing-rise 600ms var(--docs-ease) both; }
.hero-copy > h1 { animation-delay: 60ms; }
.hero-copy > :not(.eyebrow, h1) { animation-delay: 200ms; }
.code-window { animation-delay: 360ms; }
@@ -273,156 +262,147 @@ html > body[data-scroll-locked] {
/* Search (header and docs sidebar): a zero-stroke filled pill at the small control height, with key chips one step lighter than the box. */
button[data-search-full] {
- height: var(--control-h-sm); gap: var(--space-sm); padding: 0 var(--space-xs) 0 var(--space-md);
- border: 0; border-radius: var(--radius-full); background: var(--card); color: var(--muted-foreground); font-size: var(--text-sm);
- transition: background-color var(--duration-fast) var(--ease-spring), color var(--duration-fast) var(--ease-spring);
+ height: var(--docs-control-compact); gap: var(--hig-space-sm); padding: 0 var(--hig-space-xs) 0 var(--hig-space-md);
+ border: 0; border-radius: var(--docs-radius-pill); background: var(--hig-surface); color: var(--hig-muted); font-size: var(--text-sm);
+ transition: background-color var(--docs-duration) var(--docs-ease), color var(--docs-duration) var(--docs-ease);
}
-button[data-search-full]:hover { background: var(--muted); color: var(--foreground); }
+button[data-search-full]:hover { background: var(--hig-nested); color: var(--hig-text); }
button[data-search-full] kbd {
- display: inline-grid; place-items: center; min-width: 1.5rem; height: 1.5rem; padding: 0 var(--space-xs);
- border: 0; border-radius: var(--radius-full); background: color-mix(in oklab, var(--card) 80%, var(--foreground)); color: var(--foreground);
+ display: inline-grid; place-items: center; min-width: 1.5rem; height: 1.5rem; padding: 0 var(--hig-space-xs);
+ border: 0; border-radius: var(--docs-radius-pill); background: color-mix(in oklab, var(--hig-surface) 80%, var(--hig-text)); color: var(--hig-text);
font: var(--text-2xs) / 1 var(--font-mono);
}
.hero-preview {
min-width: 0;
- padding-bottom: var(--space-6xl);
+ padding-bottom: var(--hig-space-section);
scroll-margin-top: 5rem;
}
-.preview-intro { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-lg); margin-bottom: var(--space-2xl); }
+.preview-intro { display: flex; flex-direction: column; align-items: flex-start; gap: var(--hig-space-lg); margin-bottom: var(--hig-space-xxl); }
.preview-intro h2 { margin: 0; font-size: var(--text-3xl); letter-spacing: -.04em; line-height: 1.2; font-weight: 600; }
.preview-intro > p:not(.eyebrow) { margin: 0; max-width: 25rem; color: var(--color-fd-muted-foreground); font-size: var(--text-sm); line-height: 1.7; }
.preview-intro--section { align-items: center; text-align: center; }
-.preview-actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-xs); }
-.preview-intro > .preview-actions:not(:first-child) { margin-top: var(--space-xs); }
+.preview-actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--hig-space-xs); }
+.preview-intro > .preview-actions:not(:first-child) { margin-top: var(--hig-space-xs); }
.chart-preview {
overflow: hidden;
width: 100%;
- border: 1px solid var(--border);
- border-radius: var(--radius-xl);
- background: var(--bloxwap-black);
- color: var(--foreground);
+ border: 1px solid var(--hig-border);
+ border-radius: var(--docs-radius);
+ background: var(--hig-background);
+ color: var(--hig-text);
font-family: var(--font-sans);
}
.chart-frame {
display: block;
width: 100%;
height: clamp(320px, 72svh, 900px);
- scroll-margin-block: var(--space-6xl) var(--space-lg);
+ scroll-margin-block: var(--hig-space-section) var(--hig-space-lg);
border: 0;
- background: var(--bloxwap-black);
+ background: var(--hig-background);
}
.chart-preview:fullscreen { display: flex; flex-direction: column; height: 100%; border: 0; border-radius: 0; }
.chart-preview:fullscreen .chart-frame { flex: 1; min-height: 0; height: 100%; }
/* Cards, not rules: zero-stroke fill cards (plain-UI .card fill, --radius-xl, --space-xl, no border); hover shifts the fill. */
-.principles { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-md); padding: var(--space-lg) 0 var(--space-3xl); }
+.principles { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--hig-space-md); padding: var(--hig-space-lg) 0 var(--hig-space-xxxl); }
.principles > div, .guide-links a {
- background: var(--card);
- border-radius: var(--radius-xl);
- padding: var(--space-xl);
+ background: var(--hig-surface);
+ border-radius: var(--docs-radius);
+ padding: var(--hig-space-xl);
}
.feature-number { color: var(--color-fd-primary); font: var(--text-2xs) var(--font-mono); }
-.principles h2 { font-size: var(--text-base); font-weight: 600; margin: var(--space-md) 0 var(--space-sm); }
+.principles h2 { font-size: var(--text-base); font-weight: 600; margin: var(--hig-space-md) 0 var(--hig-space-sm); }
.principles p { font-size: var(--text-sm); color: var(--color-fd-muted-foreground); line-height: 1.7; }
-.start-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6xl); padding: var(--space-5xl) 0 var(--space-6xl); }
-.start-grid h2 { margin: var(--space-xl) 0; font-size: var(--text-3xl); letter-spacing: -.04em; line-height: 1.2; font-weight: 600; }
+.start-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--hig-space-section); padding: var(--hig-space-section) 0 var(--hig-space-section); }
+.start-grid h2 { margin: var(--hig-space-xl) 0; font-size: var(--text-3xl); letter-spacing: -.04em; line-height: 1.2; font-weight: 600; }
.start-grid > div > p:last-child { color: var(--color-fd-muted-foreground); font-size: var(--text-sm); max-width: 25rem; line-height: 1.7; }
-.guide-links { display: grid; gap: var(--space-md); }
+.guide-links { display: grid; gap: var(--hig-space-md); }
.guide-links a {
- display: flex; align-items: center; gap: var(--space-xl);
- transition: background-color var(--duration-fast) var(--ease-spring);
+ display: flex; align-items: center; gap: var(--hig-space-xl);
+ transition: background-color var(--docs-duration) var(--docs-ease);
}
-.guide-links a:hover { background: var(--muted); }
+.guide-links a:hover { background: var(--hig-nested); }
.guide-links a > span { font: var(--text-2xs) var(--font-mono); color: var(--color-fd-muted-foreground); }
-.guide-links a > svg { flex: none; margin-left: auto; width: var(--icon-md); height: var(--icon-md); color: var(--color-fd-muted-foreground); transition: color var(--duration-fast) var(--ease-spring), transform var(--duration-fast) var(--ease-spring); }
+.guide-links a > svg { flex: none; margin-left: auto; width: var(--docs-icon); height: var(--docs-icon); color: var(--color-fd-muted-foreground); transition: color var(--docs-duration) var(--docs-ease), transform var(--docs-duration) var(--docs-ease); }
.guide-links a:hover > svg { color: var(--color-fd-primary); transform: translateX(2px); }
-.guide-links h3 { font-size: var(--text-sm); margin-bottom: var(--space-xs); font-weight: 600; transition: color var(--duration-fast) var(--ease-spring); }
+.guide-links h3 { font-size: var(--text-sm); margin-bottom: var(--hig-space-xs); font-weight: 600; transition: color var(--docs-duration) var(--docs-ease); }
.guide-links a:hover h3 { color: var(--color-fd-primary); }
.guide-links p { color: var(--color-fd-muted-foreground); font-size: var(--text-xs); }
/* Full-bleed rule; content inset to the header's box so both edges line up with the nav. */
/* The bloxwap.com footer (monorepo workers/www), inset to the header's box. The home page ends with it. */
-.site-footer { margin-top: auto; padding: var(--space-5xl) max(var(--space-lg), calc((100% - var(--fd-layout-width, 1400px)) / 2 + var(--space-lg))) var(--space-4xl); }
+.site-footer { margin-top: auto; padding: var(--hig-space-section) max(var(--hig-space-lg), calc((100% - var(--fd-layout-width, 1400px)) / 2 + var(--hig-space-lg))) var(--hig-space-section); }
/* Page end: Edit on GitHub as a quiet ghost pill, prev/next as zero-stroke fill cards (the landing's card style). */
#nd-page .edit-on-github {
- align-self: flex-start; height: var(--control-h-sm); padding: 0 var(--space-md); border: 0; border-radius: var(--radius-full);
- background: transparent; color: var(--muted-foreground); font-size: var(--text-sm);
- transition: background-color var(--duration-fast) var(--ease-spring), color var(--duration-fast) var(--ease-spring);
+ align-self: flex-start; height: var(--docs-control-compact); padding: 0 var(--hig-space-md); border: 0; border-radius: var(--docs-radius-pill);
+ background: transparent; color: var(--hig-muted); font-size: var(--text-sm);
+ transition: background-color var(--docs-duration) var(--docs-ease), color var(--docs-duration) var(--docs-ease);
}
-#nd-page .edit-on-github:hover { background: var(--card); color: var(--foreground); }
+#nd-page .edit-on-github:hover { background: var(--hig-surface); color: var(--hig-text); }
.page-nav > a {
- padding: var(--space-xl) var(--space-2xl); border: 0; border-radius: var(--radius-xl); background: var(--card);
- transition: background-color var(--duration-fast) var(--ease-spring), color var(--duration-fast) var(--ease-spring);
+ padding: var(--hig-space-xl) var(--hig-space-xxl); border: 0; border-radius: var(--docs-radius); background: var(--hig-surface);
+ transition: background-color var(--docs-duration) var(--docs-ease), color var(--docs-duration) var(--docs-ease);
}
-.page-nav > a:hover { background: var(--muted); color: var(--bloxwap-green); }
-.footer-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--space-2xl); row-gap: var(--space-4xl); }
-.footer-brand { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-md); }
+.page-nav > a:hover { background: var(--hig-nested); color: var(--hig-action); }
+.footer-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--hig-space-xxl); row-gap: var(--hig-space-section); }
+.footer-brand { display: flex; flex-direction: column; align-items: flex-start; gap: var(--hig-space-md); }
.footer-brand p { margin: 0; color: var(--color-fd-muted-foreground); font-size: var(--text-sm); }
-.footer-lockup { display: flex; align-items: center; gap: var(--space-sm); }
+.footer-lockup { display: flex; align-items: center; gap: var(--hig-space-sm); }
.footer-icon { width: 36px; height: 36px; border-radius: 10px; }
/* The wordmark's box reserves descender room for the "p"; shift it so the cap height (not the box) centers on the icon: (143/2 - (149-74.6)/2) / 223.6 of the viewBox. */
.footer-wordmark { width: auto; height: 32px; transform: translateY(15.3%); }
-.footer-col h2 { margin: 0 0 var(--space-md); color: var(--color-fd-muted-foreground); font: 700 var(--text-2xs) / 1.5 var(--font-sans); letter-spacing: .14em; text-transform: uppercase; }
-.footer-col a, .footer-base a { transition: color var(--duration-fast) var(--ease-spring), opacity var(--duration-fast) var(--ease-spring); }
-.footer-col a { display: block; width: fit-content; padding: var(--space-xs) 0; color: var(--color-fd-foreground); font-size: var(--text-sm); opacity: .8; }
+.footer-col h2 { margin: 0 0 var(--hig-space-md); color: var(--color-fd-muted-foreground); font: 700 var(--text-2xs) / 1.5 var(--font-sans); letter-spacing: .14em; text-transform: uppercase; }
+.footer-col a, .footer-base a { transition: color var(--docs-duration) var(--docs-ease), opacity var(--docs-duration) var(--docs-ease); }
+.footer-col a { display: block; width: fit-content; padding: var(--hig-space-xs) 0; color: var(--color-fd-foreground); font-size: var(--text-sm); opacity: .8; }
.footer-col a:hover, .footer-base a:hover { color: var(--color-fd-primary); opacity: 1; }
-.footer-base { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-sm); margin-top: var(--space-4xl); color: var(--color-fd-muted-foreground); font-size: var(--text-xs); }
-.footer-legal { display: inline-flex; align-items: center; gap: var(--space-sm); }
+.footer-base { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--hig-space-sm); margin-top: var(--hig-space-section); color: var(--color-fd-muted-foreground); font-size: var(--text-xs); }
+.footer-legal { display: inline-flex; align-items: center; gap: var(--hig-space-sm); }
@media (max-width: 860px) {
- .footer-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--space-xl); }
+ .footer-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--hig-space-xl); }
.footer-brand { grid-column: 1 / -1; }
- .footer-col a { padding: var(--space-md) 0; }
+ .footer-col a { padding: var(--hig-space-md) 0; }
}
@media (max-width: 480px) { .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
-.docs-sidebar-links { display: flex; align-items: center; gap: var(--space-lg); padding-top: var(--space-lg); font-size: var(--text-xs); color: var(--color-fd-muted-foreground); }
-.docs-sidebar-links a { transition: color var(--duration-fast) var(--ease-spring); }
+.docs-sidebar-links { display: flex; align-items: center; gap: var(--hig-space-lg); padding-top: var(--hig-space-lg); font-size: var(--text-xs); color: var(--color-fd-muted-foreground); }
+.docs-sidebar-links a { transition: color var(--docs-duration) var(--docs-ease); }
.docs-sidebar-links a:hover { color: var(--color-fd-foreground); }
-.not-found { max-width: 37.5rem; padding: 7.5rem var(--space-2xl); margin: 0 auto; }
-.not-found h1 { font-size: var(--text-4xl); margin: var(--space-2xl) 0; }
-.not-found .btn { margin-top: var(--space-3xl); }
-.not-found-links { display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-xl); margin-top: var(--space-3xl); font: var(--text-2xs) / 1.5 var(--font-mono); letter-spacing: .09em; }
-.not-found-links a { color: var(--color-fd-muted-foreground); transition: color var(--duration-fast) var(--ease-spring); }
+.not-found { max-width: 37.5rem; padding: 7.5rem var(--hig-space-xxl); margin: 0 auto; }
+.not-found h1 { font-size: var(--text-4xl); margin: var(--hig-space-xxl) 0; }
+.not-found .hig-button { margin-top: var(--hig-space-xxxl); }
+.not-found-links { display: flex; flex-wrap: wrap; gap: var(--hig-space-sm) var(--hig-space-xl); margin-top: var(--hig-space-xxxl); font: var(--text-2xs) / 1.5 var(--font-mono); letter-spacing: .09em; }
+.not-found-links a { color: var(--color-fd-muted-foreground); transition: color var(--docs-duration) var(--docs-ease); }
.not-found-links a:hover { color: var(--color-fd-foreground); }
@media (max-width: 800px) {
- .home { padding-top: var(--space-3xl); }
- .hero { grid-template-columns: minmax(0, 1fr); gap: var(--space-3xl); padding-bottom: var(--space-3xl); }
+ .home { padding-top: var(--hig-space-xxxl); }
+ .hero { grid-template-columns: minmax(0, 1fr); gap: var(--hig-space-xxxl); padding-bottom: var(--hig-space-xxxl); }
.hero h1 { font-size: var(--text-6xl); }
}
@media (max-width: 600px) {
- .home { padding: var(--space-3xl) var(--space-lg) 0; }
+ .home { padding: var(--hig-space-xxxl) var(--hig-space-lg) 0; }
.hero h1 { font-size: var(--text-5xl); }
/* Share the row when both fit; otherwise each takes a full-width row (app pattern: full-width primary). */
- .hero-actions > .btn { flex: 1 1 auto; }
- .install-command { gap: var(--space-sm); padding-left: var(--space-lg); font-size: clamp(var(--text-xs), 3.4vw, var(--text-sm)); }
+ .hero-actions > .hig-button { flex: 1 1 auto; }
+ .package-install { width: 100%; }
+ .package-install .hig-surface { grid-template-columns: minmax(0, 1fr); }
.principles { grid-template-columns: 1fr; }
- .start-grid { grid-template-columns: 1fr; gap: var(--space-3xl); }
- .start-grid { padding: var(--space-4xl) 0; }
+ .start-grid { grid-template-columns: 1fr; gap: var(--hig-space-xxxl); }
+ .start-grid { padding: var(--hig-space-section) 0; }
.chart-frame { height: clamp(320px, 72svh, 600px); }
}
/* HIG type roles and adaptive targets; the dense chart keeps compact controls. */
-body { font-size: var(--type-body-size); line-height: var(--type-body-line); }
-.hero h1 { font-size: clamp(var(--type-title-size), 4.4vw, var(--type-display-size)); line-height: 1.0833; font-weight: var(--type-display-weight); }
-#nd-page h1 { font-size: var(--type-title-size); line-height: var(--type-title-line); font-weight: var(--type-title-weight); }
-.install-tabs button { min-height: var(--control-h-sm); }
-.install-feedback, .copy-feedback { color: var(--destructive); font-size: var(--type-caption-size); }
-.btn--icon { min-height: var(--control-h-sm); }
+body { font-size: var(--docs-type-body); line-height: var(--docs-type-body-line); }
+.hero h1 { font-size: clamp(var(--docs-type-title), 4.4vw, var(--docs-type-display)); line-height: 1.0833; font-weight: var(--docs-type-weight); }
+#nd-page h1 { font-size: var(--docs-type-title); line-height: var(--docs-type-title-line); font-weight: var(--docs-type-weight); }
+.copy-feedback { color: var(--hig-negative); font-size: var(--docs-type-caption); }
@media (pointer: coarse) {
- .btn--sm, .btn--icon, .install-tabs button, .docs-app-link, #nd-page .edit-on-github { min-height: var(--control-h); }
- .btn--icon { min-width: var(--control-h); }
+ .docs-app-link, #nd-page .edit-on-github { min-height: var(--hig-control); }
+ /* Compact HIG controls keep the comfortable 48 px target on touch screens. */
+ [data-hig-density='compact'] { --hig-control: var(--docs-control-touch); }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: 0ms !important; transition-duration: 0ms !important; scroll-behavior: auto !important; }
- .btn:active, .guide-links a:hover > svg { transform: none; }
-}
-
-@theme inline {
- --color-background: var(--background); --color-foreground: var(--foreground);
- --color-card: var(--card); --color-card-foreground: var(--card-foreground);
- --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground);
- --color-border: var(--border); --color-primary: var(--primary);
- --color-bloxwap-green: var(--hig-action); --color-bloxwap-black: var(--hig-background);
- --text-3xs: 0.625rem; --text-2xs: 0.6875rem;
+ .guide-links a:hover > svg { transform: none; }
}
-.search-error { color: var(--destructive); padding: var(--space-lg); }
+.search-state { padding: var(--hig-space-lg); }
+.search-state p { margin: var(--hig-space-xs) 0 0; color: var(--hig-muted); }
-.install-command .copy-feedback { grid-column: 1 / -1; padding-inline-end: var(--space-lg); }
diff --git a/apps/docs/app/not-found.tsx b/apps/docs/app/not-found.tsx
index 465bd69..3a8bc79 100644
--- a/apps/docs/app/not-found.tsx
+++ b/apps/docs/app/not-found.tsx
@@ -15,7 +15,7 @@ export default function NotFound() {
404 / PAGE NOT FOUND
That page is missing.
The page you requested does not exist on this site. It may have moved, or the URL may be wrong. Head back to the documentation to find your next step, or use one of the machine-readable indexes below.
- Open documentation
+ Open documentation
{RESOURCES.map(([label, href]) => {label} )}
diff --git a/apps/docs/app/page.tsx b/apps/docs/app/page.tsx
index e7d520a..bc85067 100644
--- a/apps/docs/app/page.tsx
+++ b/apps/docs/app/page.tsx
@@ -14,7 +14,7 @@ export default function Home() {
HYPERLIQUID · AGENT CLI
Trading tools.For your agent.
JSON commands, a persistent signing runner, Privy managed agents, and Relay funding. Keep master custody in your wallet and give your agent the tools to trade.
- Get started
Command reference
+ Get started
Command reference
diff --git a/apps/docs/components/callout.tsx b/apps/docs/components/callout.tsx
new file mode 100644
index 0000000..8fa4c74
--- /dev/null
+++ b/apps/docs/components/callout.tsx
@@ -0,0 +1,13 @@
+import type { ReactNode } from 'react';
+import { Callout as HIGCallout } from '@bloxwap/hig-react/status';
+
+const severities = { info: 'info', idea: 'info', warn: 'warning', warning: 'warning', error: 'error', success: 'success' } as const;
+const titles = { info: 'Note', warning: 'Important', error: 'Error', success: 'Success' } as const;
+
+/** Fumadocs' MDX `` API, rendered with the HIG callout. Static docs content is not a live region. */
+export function Callout({ type = 'info', title, children }: { type?: keyof typeof severities; title?: ReactNode; children?: ReactNode }) {
+ const severity = severities[type] ?? 'info';
+ return
+ {children}
+
;
+}
diff --git a/apps/docs/components/copy-button.tsx b/apps/docs/components/copy-button.tsx
index e921ddf..43a3434 100644
--- a/apps/docs/components/copy-button.tsx
+++ b/apps/docs/components/copy-button.tsx
@@ -2,11 +2,11 @@
import { useEffect, useRef, useState } from 'react';
import { Check, Copy } from 'lucide-react';
+import { IconButton } from '@bloxwap/hig-react/button';
-/** A quiet icon button that copies `text`, with a check mark and a screen-reader status on success. */
+/** A compact HIG icon button that copies `text`, with a check mark and a screen-reader status on success. */
export function CopyButton({ text, label }: { text: string; label: string }) {
const pending = useRef(false);
- const [busy, setBusy] = useState(false);
const [result, setResult] = useState<'copied' | 'failed' | null>(null);
useEffect(() => {
@@ -18,7 +18,6 @@ export function CopyButton({ text, label }: { text: string; label: string }) {
async function copy() {
if (pending.current) return;
pending.current = true;
- setBusy(true);
try {
await navigator.clipboard.writeText(text);
setResult('copied');
@@ -26,15 +25,14 @@ export function CopyButton({ text, label }: { text: string; label: string }) {
setResult('failed');
} finally {
pending.current = false;
- setBusy(false);
}
}
return <>
-
- {result === 'copied' ? : }
-
-
+
+ {result === 'copied' ? : }
+
+
{result === 'copied' ? 'Code copied to clipboard.' : result === 'failed' ? 'Could not copy. Select the code to copy it manually.' : ''}
>;
diff --git a/apps/docs/components/install-command.tsx b/apps/docs/components/install-command.tsx
index 4162eb6..2627224 100644
--- a/apps/docs/components/install-command.tsx
+++ b/apps/docs/components/install-command.tsx
@@ -1,51 +1,25 @@
'use client';
-import { useId, useState } from 'react';
-import { CopyButton } from './copy-button';
+import { Tabs } from '@bloxwap/hig-react/navigation';
+import { InstallCommand as HIGInstallCommand } from '@bloxwap/hig-react/recipes';
const managers = [
{ name: 'npm', command: 'npm install -g @bloxwap/agent-cli' },
{ name: 'bun', command: 'bunx @bloxwap/agent-cli --help' },
];
+/** HIG Tabs pick the package manager (roving focus, arrow/Home/End keys); each panel is the HIG install recipe with its own copy status. */
export function InstallCommand() {
- const id = useId();
- const [selected, setSelected] = useState(0);
- const { command } = managers[selected];
-
- function select(index: number) {
- setSelected(index);
- }
-
- return
-
- {managers.map(({ name }, index) => select(index)}
- onKeyDown={(event) => {
- let next: number;
- if (event.key === 'ArrowRight') next = (index + 1) % managers.length;
- else if (event.key === 'ArrowLeft') next = (index + managers.length - 1) % managers.length;
- else if (event.key === 'Home') next = 0;
- else if (event.key === 'End') next = managers.length - 1;
- else return;
- event.preventDefault();
- select(next);
- document.getElementById(`${id}-tab-${next}`)?.focus();
- }}
- >{name} )}
-
-
- $
- {command}
-
-
+ return
+
({
+ value: name,
+ label: name,
+ content: navigator.clipboard.writeText(command)} />,
+ }))}
+ />
Node.js 22.12+ · Bun
;
}
diff --git a/apps/docs/components/search.tsx b/apps/docs/components/search.tsx
index 11d05a7..65cbd3a 100644
--- a/apps/docs/components/search.tsx
+++ b/apps/docs/components/search.tsx
@@ -7,8 +7,16 @@ import {
SearchDialogIcon, SearchDialogInput, SearchDialogList, SearchDialogOverlay,
type SharedProps,
} from 'fumadocs-ui/components/dialog/search';
+import { Alert, EmptyState } from '@bloxwap/hig-react/status';
import { assetUrl } from '@/lib/site';
+/** No-results state; the static index needs no retry, so it points at commands and the plain page list instead. */
+function NoResults() {
+ return
+
+
;
+}
+
export default function StaticSearch(props: SharedProps) {
const { search, setSearch, query } = useDocsSearch({
client: staticClient({ from: assetUrl('/search.json') }),
@@ -18,8 +26,13 @@ export default function StaticSearch(props: SharedProps) {
- {query.error && Search is unavailable. Use the documentation navigation or close search and try again.
}
-
+ {query.error
+ ?
+
+ Use the documentation navigation, or open llms.txt for a plain list of pages.
+
+
+ : }
);
diff --git a/apps/docs/fonts/Bloxwap-OFL.txt b/apps/docs/fonts/Bloxwap-OFL.txt
deleted file mode 100644
index 5acdf82..0000000
--- a/apps/docs/fonts/Bloxwap-OFL.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-Copyright 2026 Bloxwap, Inc. (https://bloxwap.com), with Reserved Font Name "Bloxwap".
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-https://openfontlicense.org
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) and the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/apps/docs/fonts/BloxwapSans-Black.ttf b/apps/docs/fonts/BloxwapSans-Black.ttf
deleted file mode 100644
index 2b61bf1..0000000
Binary files a/apps/docs/fonts/BloxwapSans-Black.ttf and /dev/null differ
diff --git a/apps/docs/fonts/BloxwapSans-Bold.ttf b/apps/docs/fonts/BloxwapSans-Bold.ttf
deleted file mode 100644
index df41fa9..0000000
Binary files a/apps/docs/fonts/BloxwapSans-Bold.ttf and /dev/null differ
diff --git a/apps/docs/fonts/README.md b/apps/docs/fonts/README.md
deleted file mode 100644
index 45fc4e5..0000000
--- a/apps/docs/fonts/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Documentation fonts
-
-Web body text uses Bloxwap Sans and code uses Bloxwap Mono from the exact
-`@bloxwap/font@0.1.2` dependency. The Next.js exports self-host variable weights
-100–900, italics, and script companions without requests to Google Fonts.
-HIG headings use Bloxwap Sans too; the unused Space Grotesk face and notice were removed.
-
-`BloxwapSans-Bold.ttf` (700) and `BloxwapSans-Black.ttf` (900) are static
-instances of `fonts/BloxwapSans/BloxwapSans-Variable.woff2` from the published
-`@bloxwap/font@0.1.2` npm tarball (byte-identical to 0.1.1, so the derived files are unchanged). FontTools 4.66.1 `instantiateVariableFont`
-sets `wght` to 700/900 and removes WOFF2 compression (`font.flavor = None`)
-for the Open Graph renderer. Keep `Bloxwap-OFL.txt` with these derived faces.
diff --git a/apps/docs/lib/og-card.tsx b/apps/docs/lib/og-card.tsx
index 5befc08..89fca65 100644
--- a/apps/docs/lib/og-card.tsx
+++ b/apps/docs/lib/og-card.tsx
@@ -1,18 +1,23 @@
-import hig from '@/vendor/hig/manifest.json';
import { readFile } from 'node:fs/promises';
+import { createRequire } from 'node:module';
import { join } from 'node:path';
+import { tokens } from '@bloxwap/hig-tokens';
import { ImageResponse } from 'next/og';
import { socialImageSize } from './social';
// Modeled on GitHub's repository cards, in the site's dark theme (the same card as bloxwap/sfx): the Bloxwap black
// canvas, owner/repo title, muted description, the logo tile top right, a stats row, and a color bar along the
-// bottom (the Bloxwap brand palette).
-const ink = hig.colors.text.srgb; // --foreground
-const muted = hig.colors.muted.srgb; // --muted-foreground
-const bar: [color: string, share: number][] = [[hig.colors.action.srgb, 62], [hig.colors.info.srgb, 14], ['#b300ff', 10], ['#ff479c', 8], ['#fffb38', 6]];
+// bottom (the Bloxwap brand palette). Shared colors come from HIG tokens; purple, pink and yellow are brand-bar
+// accents outside HIG's semantic palette.
+const { colors } = tokens;
+const ink = colors.text.srgb;
+const muted = colors.muted.srgb;
+const bar: [color: string, share: number][] = [[colors.action.srgb, 62], [colors.info.srgb, 14], ['#b300ff', 10], ['#ff479c', 8], ['#fffb38', 6]];
+// Approved static Bloxwap Sans instances (derived from @bloxwap/font 0.1.2, OFL) shipped by the HIG tokens package.
+const hig = createRequire(join(process.cwd(), 'package.json'));
const assets = Promise.all([
- readFile(join(process.cwd(), 'fonts/BloxwapSans-Bold.ttf')),
- readFile(join(process.cwd(), 'fonts/BloxwapSans-Black.ttf')),
+ readFile(hig.resolve('@bloxwap/hig-tokens/fonts/BloxwapSans-Bold.ttf')),
+ readFile(hig.resolve('@bloxwap/hig-tokens/fonts/BloxwapSans-Black.ttf')),
readFile(join(process.cwd(), '../../packages/agent-cli/package.json'), 'utf8'),
]);
@@ -62,7 +67,7 @@ export async function renderSocialCard(options: {
const fontSize = options.home || title.length <= 20 ? 84 : title.length <= 34 ? 72 : 60;
return new ImageResponse(
-
+
@@ -73,8 +78,8 @@ export async function renderSocialCard(options: {
{description}
-
-
+
+
diff --git a/apps/docs/mdx-components.tsx b/apps/docs/mdx-components.tsx
index 6b57853..afb8eb0 100644
--- a/apps/docs/mdx-components.tsx
+++ b/apps/docs/mdx-components.tsx
@@ -1,7 +1,8 @@
import defaults from 'fumadocs-ui/mdx';
import type { MDXComponents } from 'mdx/types';
+import { Callout } from '@/components/callout';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
- return { ...defaults, ...components };
+ return { ...defaults, Callout, ...components };
}
export const useMDXComponents = getMDXComponents;
diff --git a/apps/docs/package.json b/apps/docs/package.json
index 61f4e9e..8f597e0 100644
--- a/apps/docs/package.json
+++ b/apps/docs/package.json
@@ -11,10 +11,16 @@
"preview": "node scripts/preview.mjs",
"postinstall": "fumadocs-mdx",
"predev": "npm --workspace @bloxwap/agent-cli run build && node scripts/generate-content.mjs && node scripts/prepare-public.mjs",
- "prebuild": "npm --workspace @bloxwap/agent-cli run build && node scripts/generate-content.mjs && node scripts/prepare-public.mjs"
+ "prebuild": "npm --workspace @bloxwap/agent-cli run build && node scripts/generate-content.mjs && node scripts/prepare-public.mjs",
+ "smoke": "node scripts/smoke.mjs"
},
"dependencies": {
"@bloxwap/font": "0.1.2",
+ "@bloxwap/hig-contracts": "file:../../vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha19c75619.tgz",
+ "@bloxwap/hig-react": "file:../../vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha19c75619.tgz",
+ "@bloxwap/hig-tokens": "file:../../vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha19c75619.tgz",
+ "@radix-ui/react-dropdown-menu": "2.1.16",
+ "@radix-ui/react-tooltip": "1.2.8",
"fumadocs-core": "16.15.14",
"fumadocs-mdx": "15.4.5",
"fumadocs-ui": "16.15.14",
@@ -29,6 +35,7 @@
"@types/node": "^24.13.6",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
+ "playwright": "1.64.1",
"tailwindcss": "^4.2.0",
"typescript": "^6.0.3"
},
diff --git a/apps/docs/scripts/hig-tokens.mjs b/apps/docs/scripts/hig-tokens.mjs
index 0a90241..b9ea9f8 100644
--- a/apps/docs/scripts/hig-tokens.mjs
+++ b/apps/docs/scripts/hig-tokens.mjs
@@ -1,46 +1,59 @@
-import { readFile, writeFile } from 'node:fs/promises';
+// Verifies the HIG package install: vendored candidate tarballs match their recorded hashes, the docs depend on
+// exactly those files, the installed packages are the same build, and the few JS-only HIG numbers that
+// app/global.css copies (radius, motion, type, density) still equal the installed @bloxwap/hig-tokens.
+import { readFile, stat } from 'node:fs/promises';
import { createHash } from 'node:crypto';
import assert from 'node:assert/strict';
-const vendor = new URL('../vendor/hig/', import.meta.url);
-export const manifest = JSON.parse(await readFile(new URL('manifest.json', vendor), 'utf8'));
-export const colors = Object.fromEntries(Object.entries(manifest.colors).map(([key, value]) => [key, value.srgb]));
-export const chartTheme = {
- theme: { background: colors.surface, textColor: colors.text, borderColor: colors.border, fontFamily: '"Bloxwap Sans", system-ui, sans-serif', monoFamily: '"Bloxwap Mono", monospace', scaleFontFamily: '"Bloxwap Mono", monospace' },
- grid: { color: colors.border },
- crosshair: { color: colors.muted, labelBackground: colors.action, labelColor: colors.onAction },
- series: { upColor: colors.buy, downColor: colors.sell, wickUpColor: colors.buy, wickDownColor: colors.sell, borderUpColor: colors.buy, borderDownColor: colors.sell },
+import { tokens } from '@bloxwap/hig-tokens';
+
+const root = new URL('../../../', import.meta.url);
+const docs = new URL('../', import.meta.url);
+const vendor = new URL('vendor/bloxwap-hig/', root);
+const provenance = JSON.parse(await readFile(new URL('provenance.json', vendor), 'utf8'));
+const manifest = JSON.parse(await readFile(new URL('package.json', docs), 'utf8'));
+/** npm workspaces install a package in apps/docs/node_modules or hoist it to the root. */
+async function installedManifest(name) {
+ for (const base of [docs, root]) {
+ try { return JSON.parse(await readFile(new URL(`node_modules/${name}/package.json`, base), 'utf8')); } catch { /* try the next location */ }
+ }
+ throw new Error(`${name} is not installed; run npm install`);
+}
+
+for (const { package: name, file, sha256 } of provenance.artifacts) {
+ const digest = createHash('sha256').update(await readFile(new URL(file, vendor))).digest('hex');
+ assert.equal(digest, sha256, `Vendored HIG tarball changed: ${file}`);
+ assert.equal(manifest.dependencies[name], `file:../../vendor/bloxwap-hig/${file}`, `${name} must install from vendor/bloxwap-hig/${file}`);
+ const installed = await installedManifest(name);
+ assert.equal(installed.version, provenance.version, `${name}: installed ${installed.version}, vendored ${provenance.version}; run npm install`);
+}
+assert.equal(tokens.version, provenance.version.split('-')[0]);
+
+const css = await readFile(new URL('app/global.css', docs), 'utf8');
+const px = (value) => `${value}px`;
+const rem = (value) => `${value / 16}rem`;
+const expected = {
+ '--docs-radius': px(tokens.radius.xl),
+ '--docs-radius-pill': px(tokens.radius.pill),
+ '--docs-duration': `${tokens.motion.fast}ms`,
+ '--docs-control-compact': px(tokens.density.compact.control),
+ '--docs-control-touch': px(tokens.density.comfortable.control),
+ '--docs-type-caption': rem(tokens.type.caption.size),
+ '--docs-type-body': rem(tokens.type.body.size),
+ '--docs-type-body-line': rem(tokens.type.body.lineHeight),
+ '--docs-type-title': rem(tokens.type.title.size),
+ '--docs-type-title-line': rem(tokens.type.title.lineHeight),
+ '--docs-type-display': rem(tokens.type.display.size),
+ '--docs-type-weight': String(tokens.type.title.weight),
};
-const aliases = { 'bloxwap-black': 'background', 'bloxwap-green': 'action', background: 'background', foreground: 'text', card: 'surface', 'card-foreground': 'text', popover: 'nested', 'popover-foreground': 'text', primary: 'action', 'primary-foreground': 'onAction', secondary: 'nested', 'secondary-foreground': 'text', muted: 'nested', 'muted-foreground': 'muted', accent: 'nested', 'accent-foreground': 'text', destructive: 'negative', border: 'border', input: 'border', ring: 'focus' };
-const vars = Object.entries(aliases).map(([key, role]) => ` --${key}: var(--hig-${role});`);
-for (const [key, value] of Object.entries(manifest.radius)) vars.push(` --radius-${key === 'pill' ? 'full' : key}: ${value / 16}rem;`);
-vars.push(' --radius: var(--radius-lg);', ' --radius-2xl: var(--radius-xl);');
-for (const [key, role] of Object.entries({ xs:'xs', sm:'sm', md:'md', lg:'lg', xl:'xl', '2xl':'xxl', '3xl':'xxxl', '4xl':'section', '5xl':'section', '6xl':'section' })) vars.push(` --space-${key}: var(--hig-space-${role});`);
-for (const [key, value] of Object.entries(manifest.motion)) vars.push(` --duration-${key}: ${value}ms;`);
-for (const [key, role] of Object.entries(manifest.type)) {
- vars.push(` --type-${key}-size: ${role.size / 16}rem;`, ` --type-${key}-line: ${role.lineHeight / 16}rem;`, ` --type-${key}-weight: ${role.weight};`);
+assert.equal(tokens.type.display.weight, tokens.type.title.weight, '--docs-type-weight serves both title and display');
+for (const [name, value] of Object.entries(expected)) {
+ const match = css.match(new RegExp(`^\\s*${name}:\\s*([^;]+);`, 'm'));
+ assert.equal(match?.[1].trim(), value, `app/global.css ${name} must equal @bloxwap/hig-tokens (${value})`);
}
-vars.push(` --control-h: ${manifest.density.comfortable.control / 16}rem;`, ` --control-h-sm: ${manifest.density.compact.control / 16}rem;`, ' --ease-spring: cubic-bezier(0.22, 1, 0.36, 1);', ' --ease-standard: ease-out;', ' --icon-md: 16px;', ' --control-min-w: 6rem;');
-const css = `/* Generated from pinned HIG manifest by scripts/hig-tokens.mjs. */\n:root {\n${vars.join('\n')}\n}\n@media (prefers-reduced-motion: reduce) {\n :root { --duration-fast: 0ms; --duration-base: 0ms; --duration-slow: 0ms; }\n}\n`;
-const output = new URL('../styles/hig.generated.css', import.meta.url);
-if (process.argv.includes('--write')) await writeFile(output, css);
-if (process.argv.includes('--check')) {
- assert.equal(await readFile(output, 'utf8'), css, 'HIG adapter drift: run node apps/docs/scripts/hig-tokens.mjs --write');
- const provenance = JSON.parse(await readFile(new URL('provenance.json', vendor), 'utf8'));
- for (const [file, hash] of Object.entries(provenance.sha256)) assert.equal(createHash('sha256').update(await readFile(new URL(file, vendor))).digest('hex'), hash, `Pinned HIG artifact changed: ${file}`);
- const { readdir } = await import('node:fs/promises');
- assert.deepEqual((await readdir(new URL('../styles/', import.meta.url))).sort(), ['hig.generated.css']);
- const { readdir: list } = await import('node:fs/promises');
- async function checkSurface(dir) {
- for (const entry of await list(dir, { withFileTypes: true })) {
- const path = new URL(entry.name + (entry.isDirectory() ? '/' : ''), dir);
- if (entry.isDirectory()) await checkSurface(path);
- else if (/\.(css|tsx?)$/.test(entry.name)) {
- const source = await readFile(path, 'utf8');
- assert.ok(!/@workspace\/(tokens|ui)|tokens\.generated\.css|--bloxwap-\w+\s*:\s*(#|oklch|color\()/.test(source), `Obsolete imports or copied palette: ${path}`);
- }
- }
- }
- await checkSurface(new URL('../app/', import.meta.url));
- await checkSurface(new URL('../components/', import.meta.url));
- console.log('HIG provenance, generated adapter and copied-palette drift checks passed.');
+
+// The copied HIG folder, alias layer and committed fonts must not come back.
+for (const path of ['vendor/hig', 'styles', 'fonts']) {
+ await assert.rejects(stat(new URL(path, docs)), `apps/docs/${path} must not exist; use the HIG packages`);
}
+assert.ok(!/--bloxwap-[\w-]+\s*:/.test(css), 'app/global.css must not define --bloxwap-* aliases; use --hig-* roles');
+console.log(`HIG ${provenance.version}: ${provenance.artifacts.length} vendored tarballs, installed packages and ${Object.keys(expected).length} host token values verified.`);
diff --git a/apps/docs/scripts/smoke.mjs b/apps/docs/scripts/smoke.mjs
new file mode 100644
index 0000000..eaeb246
--- /dev/null
+++ b/apps/docs/scripts/smoke.mjs
@@ -0,0 +1,159 @@
+// Browser smoke test for the static export: install/copy, keyboard, search, base path and 390 px mobile navigation.
+// Run after `npm run docs:build`. Set SCREENSHOTS=
to save desktop and mobile captures (SCREENSHOT_PREFIX names them).
+import { spawn } from 'node:child_process';
+import { mkdir, readFile } from 'node:fs/promises';
+import { join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import assert from 'node:assert/strict';
+import { chromium } from 'playwright';
+
+const docs = fileURLToPath(new URL('..', import.meta.url));
+const { basePath } = JSON.parse(await readFile(join(docs, 'out/_docs-config.json'), 'utf8'));
+const port = Number(process.env.PORT ?? 3913);
+const origin = `http://127.0.0.1:${port}`;
+const url = (path) => `${origin}${basePath}${path}`;
+const shots = process.env.SCREENSHOTS;
+const prefix = process.env.SCREENSHOT_PREFIX ?? 'after';
+
+const server = spawn(process.execPath, [join(docs, 'scripts/preview.mjs')], { env: { ...process.env, PORT: String(port) }, stdio: ['ignore', 'pipe', 'inherit'] });
+await new Promise((resolve, reject) => {
+ server.stdout.on('data', (chunk) => { if (String(chunk).includes('Static docs preview')) resolve(); });
+ server.on('exit', (code) => reject(new Error(`Preview exited with ${code}`)));
+});
+
+const browser = await chromium.launch();
+const results = [];
+async function check(name, run) {
+ try { await run(); results.push(`ok ${name}`); }
+ catch (error) { results.push(`FAIL ${name}: ${error.message.split('\n')[0]}`); process.exitCode = 1; }
+}
+async function capture(page, name) {
+ if (!shots) return;
+ await mkdir(shots, { recursive: true });
+ await page.waitForTimeout(1200); // let the landing entrance animation finish
+ await page.screenshot({ path: join(shots, `${prefix}-${name}.png`), fullPage: name.startsWith('home') });
+}
+async function noHorizontalScroll(page) {
+ await page.waitForFunction(() => document.documentElement.scrollWidth <= window.innerWidth + 1, null, { timeout: 5000 });
+}
+
+try {
+ const desktop = await browser.newContext({ viewport: { width: 1440, height: 900 }, permissions: ['clipboard-read', 'clipboard-write'] });
+ const page = await desktop.newPage();
+ const errors = [];
+ page.on('pageerror', (error) => errors.push(error.message));
+
+ await check('home renders with the base path and no runtime errors', async () => {
+ const response = await page.goto(url('/'));
+ assert.equal(response?.status(), 200);
+ await page.getByRole('heading', { level: 1 }).waitFor();
+ for (const href of await page.locator('link[rel=stylesheet]').evaluateAll((links) => links.map((l) => l.getAttribute('href')))) {
+ assert.ok(href?.startsWith(`${basePath}/`), `stylesheet outside base path: ${href}`);
+ }
+ await capture(page, 'home-desktop');
+ assert.deepEqual(errors, []);
+ });
+
+ await check('install tabs: arrow/Home/End keys move selection and focus', async () => {
+ const tabs = page.getByRole('tablist', { name: 'Package manager' });
+ const npm = tabs.getByRole('tab', { name: 'npm' });
+ const bun = tabs.getByRole('tab', { name: 'bun' });
+ await npm.focus();
+ await page.keyboard.press('ArrowRight');
+ assert.equal(await bun.getAttribute('aria-selected'), 'true');
+ assert.ok(await bun.evaluate((el) => el === document.activeElement));
+ await page.keyboard.press('Home');
+ assert.equal(await npm.getAttribute('aria-selected'), 'true');
+ await page.keyboard.press('End');
+ assert.equal(await bun.getAttribute('aria-selected'), 'true');
+ assert.match(await page.getByRole('tabpanel').filter({ visible: true }).innerText(), /bunx @bloxwap\/agent-cli --help/);
+ await page.keyboard.press('Home');
+ });
+
+ await check('install command copies to the clipboard and announces the result', async () => {
+ await page.getByRole('tabpanel').filter({ visible: true }).getByRole('button', { name: /copy install command/i }).click();
+ await page.waitForFunction(() => [...document.querySelectorAll('[role=status]')].some((s) => /copied/i.test(s.textContent ?? '')));
+ assert.equal(await page.evaluate(() => navigator.clipboard.readText()), 'npm install -g @bloxwap/agent-cli');
+ });
+
+ await check('hero code window copies the workflow', async () => {
+ await page.getByRole('button', { name: 'Copy workflow commands' }).click();
+ await page.waitForFunction(async () => (await navigator.clipboard.readText()).startsWith('agent-cli schema order'));
+ });
+
+ await check('keyboard: Tab reaches the primary actions with a visible focus ring', async () => {
+ await page.goto(url('/'));
+ let outline = '';
+ for (let i = 0; i < 40 && !/Get started/.test(outline); i++) {
+ await page.keyboard.press('Tab');
+ outline = await page.evaluate(() => {
+ const el = document.activeElement;
+ if (!el) return '';
+ const style = getComputedStyle(el);
+ return `${el.textContent?.trim()}|${style.outlineStyle}|${style.outlineWidth}`;
+ });
+ }
+ assert.match(outline, /^Get started\|solid\|2px$/, `focused element: ${outline}`);
+ });
+
+ await check('search: Ctrl+K opens, finds pages, shows a no-results state and closes with Escape', async () => {
+ await page.goto(url('/docs/'));
+ await page.keyboard.press('Control+k');
+ const dialog = page.getByRole('dialog');
+ await dialog.waitFor();
+ await page.keyboard.type('runner');
+ await dialog.getByRole('option').first().waitFor();
+ await capture(page, 'search-desktop');
+ await page.keyboard.press('Control+a');
+ await page.keyboard.type('zzqxv nothing matches');
+ await dialog.getByText(/no (matching pages|results)/i).first().waitFor();
+ await capture(page, 'search-empty-desktop');
+ await page.keyboard.press('Escape');
+ await dialog.waitFor({ state: 'hidden' });
+ });
+
+ await check('docs page renders', async () => {
+ await page.goto(url('/docs/quickstart/'));
+ await page.getByRole('heading', { level: 1, name: 'Quickstart' }).waitFor();
+ await capture(page, 'quickstart-desktop');
+ await page.goto(url('/docs/errors/'));
+ await page.locator('#nd-page table').first().waitFor();
+ await capture(page, 'errors-desktop');
+ });
+
+ await check('404 explains the error and recovers inside the base path', async () => {
+ const response = await page.goto(url('/docs/missing-page/'));
+ assert.equal(response?.status(), 404);
+ const link = page.getByRole('link', { name: 'Open documentation' });
+ assert.equal(await link.getAttribute('href'), `${basePath}/docs/`);
+ await capture(page, 'not-found-desktop');
+ await link.click();
+ await page.waitForURL(new RegExp(`${basePath}/docs/?$`));
+ });
+ await desktop.close();
+
+ const mobile = await browser.newContext({ viewport: { width: 390, height: 844 }, hasTouch: true, isMobile: true });
+ const phone = await mobile.newPage();
+ await check('390 px home has no horizontal scroll', async () => {
+ await phone.goto(url('/'));
+ await noHorizontalScroll(phone);
+ await capture(phone, 'home-mobile');
+ });
+ await check('390 px sidebar navigation reaches a deep link', async () => {
+ await phone.goto(url('/docs/'));
+ await noHorizontalScroll(phone);
+ await phone.getByRole('button', { name: /open sidebar|toggle sidebar/i }).first().click();
+ const link = phone.getByRole('link', { name: 'Runner and JSON-RPC', exact: true }).filter({ visible: true }).first();
+ await link.waitFor();
+ await capture(phone, 'mobile-nav');
+ await link.click();
+ await phone.waitForURL(new RegExp(`${basePath}/docs/runner/?$`));
+ await phone.getByRole('heading', { level: 1 }).waitFor();
+ await noHorizontalScroll(phone);
+ });
+ await mobile.close();
+} finally {
+ await browser.close();
+ server.kill();
+}
+console.log(results.join('\n'));
diff --git a/apps/docs/styles/hig.generated.css b/apps/docs/styles/hig.generated.css
deleted file mode 100644
index e64f889..0000000
--- a/apps/docs/styles/hig.generated.css
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Generated from pinned HIG manifest by scripts/hig-tokens.mjs. */
-:root {
- --bloxwap-black: var(--hig-background);
- --bloxwap-green: var(--hig-action);
- --background: var(--hig-background);
- --foreground: var(--hig-text);
- --card: var(--hig-surface);
- --card-foreground: var(--hig-text);
- --popover: var(--hig-nested);
- --popover-foreground: var(--hig-text);
- --primary: var(--hig-action);
- --primary-foreground: var(--hig-onAction);
- --secondary: var(--hig-nested);
- --secondary-foreground: var(--hig-text);
- --muted: var(--hig-nested);
- --muted-foreground: var(--hig-muted);
- --accent: var(--hig-nested);
- --accent-foreground: var(--hig-text);
- --destructive: var(--hig-negative);
- --border: var(--hig-border);
- --input: var(--hig-border);
- --ring: var(--hig-focus);
- --radius-sm: 0.375rem;
- --radius-md: 0.5rem;
- --radius-lg: 0.625rem;
- --radius-xl: 0.875rem;
- --radius-full: 624.9375rem;
- --radius: var(--radius-lg);
- --radius-2xl: var(--radius-xl);
- --space-xs: var(--hig-space-xs);
- --space-sm: var(--hig-space-sm);
- --space-md: var(--hig-space-md);
- --space-lg: var(--hig-space-lg);
- --space-xl: var(--hig-space-xl);
- --space-2xl: var(--hig-space-xxl);
- --space-3xl: var(--hig-space-xxxl);
- --space-4xl: var(--hig-space-section);
- --space-5xl: var(--hig-space-section);
- --space-6xl: var(--hig-space-section);
- --duration-fast: 180ms;
- --duration-base: 260ms;
- --duration-slow: 320ms;
- --type-caption-size: 0.75rem;
- --type-caption-line: 1.125rem;
- --type-caption-weight: 500;
- --type-label-size: 0.875rem;
- --type-label-line: 1.25rem;
- --type-label-weight: 600;
- --type-body-size: 1rem;
- --type-body-line: 1.5rem;
- --type-body-weight: 400;
- --type-title-size: 1.5rem;
- --type-title-line: 1.875rem;
- --type-title-weight: 600;
- --type-display-size: 3rem;
- --type-display-line: 3.25rem;
- --type-display-weight: 600;
- --control-h: 3rem;
- --control-h-sm: 2.25rem;
- --ease-spring: cubic-bezier(0.22, 1, 0.36, 1);
- --ease-standard: ease-out;
- --icon-md: 16px;
- --control-min-w: 6rem;
-}
-@media (prefers-reduced-motion: reduce) {
- :root { --duration-fast: 0ms; --duration-base: 0ms; --duration-slow: 0ms; }
-}
diff --git a/apps/docs/vendor/hig/LICENSE b/apps/docs/vendor/hig/LICENSE
deleted file mode 100644
index daec4c1..0000000
--- a/apps/docs/vendor/hig/LICENSE
+++ /dev/null
@@ -1,5 +0,0 @@
-MIT License
-
-Copyright (c) 2026 Bloxwap
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to inclusion of this notice. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.
diff --git a/apps/docs/vendor/hig/manifest.json b/apps/docs/vendor/hig/manifest.json
deleted file mode 100644
index 2d92b5a..0000000
--- a/apps/docs/vendor/hig/manifest.json
+++ /dev/null
@@ -1,151 +0,0 @@
-{
- "version": "0.1.0",
- "mode": "dark",
- "provenance": "font/apps/docs/styles/tokens.css; monorepo inaccessible; authored OKLCH unavailable",
- "colors": {
- "background": {
- "srgb": "#0a0a0a",
- "p3": [
- 0.04,
- 0.04,
- 0.04
- ]
- },
- "surface": {
- "srgb": "#171717"
- },
- "nested": {
- "srgb": "#262626"
- },
- "text": {
- "srgb": "#fafafa"
- },
- "muted": {
- "srgb": "#a1a1a1"
- },
- "faint": {
- "srgb": "#858585"
- },
- "border": {
- "srgb": "#3a3a3a"
- },
- "action": {
- "srgb": "#00ff3f",
- "p3": [
- 0,
- 1,
- 0.24
- ]
- },
- "onAction": {
- "srgb": "#0a0a0a",
- "p3": [
- 0.04,
- 0.04,
- 0.04
- ]
- },
- "focus": {
- "srgb": "#00ff3f",
- "p3": [
- 0,
- 1,
- 0.24
- ]
- },
- "buy": {
- "srgb": "#00ff3f",
- "p3": [
- 0,
- 1,
- 0.24
- ]
- },
- "sell": {
- "srgb": "#ff5c5c"
- },
- "positive": {
- "srgb": "#00ff3f",
- "p3": [
- 0,
- 1,
- 0.24
- ]
- },
- "negative": {
- "srgb": "#ff5c5c"
- },
- "warning": {
- "srgb": "#f5b300"
- },
- "info": {
- "srgb": "#35b5ff",
- "p3": [
- 0.18,
- 0.72,
- 1
- ]
- }
- },
- "space": {
- "xs": 4,
- "sm": 8,
- "md": 12,
- "lg": 16,
- "xl": 20,
- "xxl": 24,
- "xxxl": 32,
- "section": 48
- },
- "radius": {
- "sm": 6,
- "md": 8,
- "lg": 10,
- "xl": 14,
- "pill": 9999
- },
- "density": {
- "comfortable": {
- "control": 48,
- "target": 48,
- "gap": 12
- },
- "compact": {
- "control": 36,
- "target": 36,
- "gap": 8
- }
- },
- "motion": {
- "fast": 180,
- "base": 260,
- "slow": 320
- },
- "type": {
- "caption": {
- "size": 12,
- "lineHeight": 18,
- "weight": 500
- },
- "label": {
- "size": 14,
- "lineHeight": 20,
- "weight": 600
- },
- "body": {
- "size": 16,
- "lineHeight": 24,
- "weight": 400
- },
- "title": {
- "size": 24,
- "lineHeight": 30,
- "weight": 600
- },
- "display": {
- "size": 48,
- "lineHeight": 52,
- "weight": 600
- }
- }
-}
diff --git a/apps/docs/vendor/hig/provenance.json b/apps/docs/vendor/hig/provenance.json
deleted file mode 100644
index 32d18a5..0000000
--- a/apps/docs/vendor/hig/provenance.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "repository": "bloxwap/hig",
- "commit": "1a776b9326c6ba03702894943b3edbfd178c4b40",
- "version": "0.1.0 candidate",
- "distribution": "approved plain CSS + generated manifest; no npm release exists",
- "sha256": {
- "tokens.css": "1c60086af561070fdc1ee6056d6bc43bd8eed78614c318d466ee3850dc317609",
- "manifest.json": "1f7383521cf9d3a559ae4abb91e64aa26f3fba03df22768aaeb26f6df822a454",
- "LICENSE": "3e120a937544f1299495b556d63e040f2ee4678d0def27cfbf71ac62e75b022e"
- }
-}
diff --git a/apps/docs/vendor/hig/tokens.css b/apps/docs/vendor/hig/tokens.css
deleted file mode 100644
index 3b26998..0000000
--- a/apps/docs/vendor/hig/tokens.css
+++ /dev/null
@@ -1,35 +0,0 @@
-:root { color-scheme: dark;
- --hig-background: #0a0a0a;
- --hig-surface: #171717;
- --hig-nested: #262626;
- --hig-text: #fafafa;
- --hig-muted: #a1a1a1;
- --hig-faint: #858585;
- --hig-border: #3a3a3a;
- --hig-action: #00ff3f;
- --hig-onAction: #0a0a0a;
- --hig-focus: #00ff3f;
- --hig-buy: #00ff3f;
- --hig-sell: #ff5c5c;
- --hig-positive: #00ff3f;
- --hig-negative: #ff5c5c;
- --hig-warning: #f5b300;
- --hig-info: #35b5ff;
- --hig-space-xs: 0.25rem;
- --hig-space-sm: 0.5rem;
- --hig-space-md: 0.75rem;
- --hig-space-lg: 1rem;
- --hig-space-xl: 1.25rem;
- --hig-space-xxl: 1.5rem;
- --hig-space-xxxl: 2rem;
- --hig-space-section: 3rem;
-}
-@supports (color: color(display-p3 1 1 1)) { :root {
- --hig-background: color(display-p3 0.04 0.04 0.04);
- --hig-action: color(display-p3 0 1 0.24);
- --hig-onAction: color(display-p3 0.04 0.04 0.04);
- --hig-focus: color(display-p3 0 1 0.24);
- --hig-buy: color(display-p3 0 1 0.24);
- --hig-positive: color(display-p3 0 1 0.24);
- --hig-info: color(display-p3 0.18 0.72 1);
-} }
diff --git a/evidence/hig/docs-package-migration/README.md b/evidence/hig/docs-package-migration/README.md
new file mode 100644
index 0000000..379a3f9
--- /dev/null
+++ b/evidence/hig/docs-package-migration/README.md
@@ -0,0 +1,86 @@
+# Docs: copied HIG CSS → HIG packages (bloxwap/hig#58)
+
+The agent-cli docs (`apps/docs`) now consume the HIG 0.1.0 candidate packages built from
+[bloxwap/hig@19c7561](https://github.com/bloxwap/hig/tree/19c75619fa5020c015aa639172c83fd02f2bc0a2) and vendored in
+[`vendor/bloxwap-hig/`](../../../vendor/bloxwap-hig/README.md). Nothing was published, tagged or released.
+
+## Before / after
+
+Static export with `NEXT_PUBLIC_BASE_PATH=/agent-cli`. Sizes are emitted file bytes, not transfer sizes; gzip is
+the sum of per-file gzip. Raw data: [measurements.json](measurements.json).
+
+| | Before (main 19ebad0) | After |
+| --- | ---: | ---: |
+| Docs source CSS | 3 files, 530 lines, 25,447 B | 1 file, 408 lines, 21,885 B |
+| Committed font files in `apps/docs` | 2 TTFs, 892,964 B | 0 |
+| Copied HIG files (`vendor/hig`, `styles/hig.generated.css`, `fonts/`) | 9 | 0 |
+| Emitted CSS | 142,143 B (22,554 gz) | 150,822 B (24,357 gz) |
+| Emitted JS | 1,262,320 B (404,715 gz) | 1,268,249 B (406,679 gz) |
+| Emitted fonts | 22 files, 12,965,628 B | same |
+| Total static export | 20,535,551 B | 20,552,717 B |
+| Docs direct dependencies (runtime) | 15 (8) | 21 (13) |
+| Lockfile package entries | 703 | 764 |
+
+- **CSS +8.7 KB (+1.8 KB gzip):** `@bloxwap/hig-react/css` ships every control recipe as one sheet (fields, ranges,
+ segmented controls, progress and so on). The docs use only a few. The local `.btn` family, install tabs and focus
+ ring were removed.
+- **JS +5.9 KB (+2.0 KB gzip):** HIG `Tabs`, `IconButton`, `InstallCommand`, `Alert`/`EmptyState` and the
+ context provider code.
+- **Dependencies:** +3 HIG packages (`hig-tokens`, `hig-react`, `hig-contracts`), +1 dev (`playwright` for the new
+ smoke test), and +2 Radix packages. The Radix ones are needed only because `@bloxwap/hig-react/recipes`
+ statically imports `./overlay.js`, which imports the optional peers `@radix-ui/react-dropdown-menu` and
+ `@radix-ui/react-tooltip`. Without them the build fails with "Module not found". The overlay code is
+ tree-shaken out of the docs bundle: composing the same recipe from `Surface` and `Button` produced the same JS size
+ (1,268,192 B) but 56 fewer lockfile entries. This needs an upstream HIG fix: either drop the overlay import from
+ `recipes`, or make those peers required.
+- **Optional peer mismatch:** `hig-react` pins `@radix-ui/react-dialog`/`react-popover` to exactly 1.1.15, but
+ Fumadocs installs 1.3.1. `npm ls` reports them as invalid. Unlike in sfx#50, npm did not re-resolve Fumadocs here,
+ so this adds no JS.
+- **Fonts:** the social-card renderer now reads `BloxwapSans-{Bold,Black}.ttf` from `@bloxwap/hig-tokens/fonts`. The
+ files differ in bytes from the deleted local instances, but every rendered card is byte-identical
+ (`out/og/home.png` compared with `cmp`).
+
+## Drift
+
+`node /scripts/drift.mjs --root . --config hig-drift.json`:
+
+- Before (main): 6 violations. The `vendor/hig` import in `global.css` and `og-card.tsx`, the two TTFs, and the copied
+ palette and token definitions in `vendor/hig/tokens.css`.
+- After: `Scoped anti-drift: passed (36 files, 0 dated exceptions)`. CI runs the check from the same pinned HIG commit
+ (`.github/workflows/docs.yml`).
+
+## Validation (automated and browser; local Linux x64, Node 24.22.0)
+
+- `npm run build`, `npm run lint`, `npm run typecheck` and `npm test` all pass.
+- `npm run docs:check` passes: content, HIG provenance/installed versions/host token values, Next typegen and `tsc`.
+- `NEXT_PUBLIC_BASE_PATH=/agent-cli npm run docs:build`: the postbuild checker verified 16 HTML pages, 597 local
+ links/assets, 13 social cards and the `/agent-cli` base path.
+- `npm run docs:smoke` (Playwright Chromium, against the `/agent-cli` static preview). It passes 10/10, and the same
+ script passes 10/10 on the before build:
+ - home renders with every stylesheet inside the base path and no runtime errors
+ - install tabs respond to ArrowRight/Home/End with roving focus
+ - install copy writes the clipboard and announces status
+ - hero code copy works
+ - Tab reaches "Get started" with a 2 px solid focus ring
+ - Ctrl+K search finds results, shows the no-results state and closes with Escape
+ - docs and table pages render
+ - the 404 page returns status 404 and its recovery link stays under `/agent-cli/docs/`
+ - at 390 px the home page has no horizontal scroll, and the sidebar opens and navigates to `/docs/runner/`
+
+## Visual differences (screenshots/)
+
+Each `before-*` and `after-*` pair was captured at 1440×900 or 390×844.
+
+- Install picker: HIG `Tabs`, with the selected tab filled in green. The HIG `InstallCommand` recipe (surface,
+ command, "Copy install command" button, visible status) replaces the pill and icon-only copy button.
+- Code-window copy: HIG ghost `IconButton`, a nested fill at compact density with 48 px targets on coarse pointers.
+- Search no-results: HIG `EmptyState`. Search error: HIG `Alert`.
+- Tables: HIG's global table rule adds 12 px cell padding.
+- Unchanged: Fumadocs shell, navigation, search index, base path, metadata, social cards, footer and deep links.
+
+## Not covered
+
+- Large-text and RTL checks were not run. Only Chromium was automated; Firefox and WebKit were not run.
+- No physical devices. Simulators and emulators do not apply to this static docs change.
+
+Rollback: revert the PR. That restores the copied files, the previous lockfile and the imports.
diff --git a/evidence/hig/docs-package-migration/measurements.json b/evidence/hig/docs-package-migration/measurements.json
new file mode 100644
index 0000000..b8da533
--- /dev/null
+++ b/evidence/hig/docs-package-migration/measurements.json
@@ -0,0 +1,104 @@
+{
+ "note": "Static export with NEXT_PUBLIC_BASE_PATH=/agent-cli; emitted file sizes on disk (gzip = per-file gzip -9 default level sum), not transfer sizes. Measured by a Node script over apps/docs/out, the tracked apps/docs sources and package-lock.json.",
+ "hig": {
+ "commit": "19c75619fa5020c015aa639172c83fd02f2bc0a2",
+ "version": "0.1.0-candidate.sha19c75619"
+ },
+ "before": {
+ "label": "before",
+ "commit": "19ebad0",
+ "basePath": "/agent-cli",
+ "source": {
+ "css": {
+ "files": 3,
+ "bytes": 25447,
+ "gzip": 6098,
+ "lines": 530,
+ "paths": [
+ "apps/docs/app/global.css",
+ "apps/docs/styles/hig.generated.css",
+ "apps/docs/vendor/hig/tokens.css"
+ ]
+ },
+ "fonts": {
+ "files": 2,
+ "bytes": 892964,
+ "gzip": 342654,
+ "paths": [
+ "apps/docs/fonts/BloxwapSans-Black.ttf",
+ "apps/docs/fonts/BloxwapSans-Bold.ttf"
+ ]
+ }
+ },
+ "emitted": {
+ "css": {
+ "files": 2,
+ "bytes": 142143,
+ "gzip": 22554
+ },
+ "js": {
+ "files": 27,
+ "bytes": 1262320,
+ "gzip": 404715
+ },
+ "fonts": {
+ "files": 22,
+ "bytes": 12965628,
+ "gzip": 12917806
+ },
+ "html": 16,
+ "total": 20535551
+ },
+ "dependencies": {
+ "docsDirect": 15,
+ "docsRuntime": 8,
+ "lockfilePackages": 703
+ }
+ },
+ "after": {
+ "label": "after",
+ "commit": "this PR (working tree on 19ebad0)",
+ "basePath": "/agent-cli",
+ "source": {
+ "css": {
+ "files": 1,
+ "bytes": 21885,
+ "gzip": 5235,
+ "lines": 408,
+ "paths": [
+ "apps/docs/app/global.css"
+ ]
+ },
+ "fonts": {
+ "files": 0,
+ "bytes": 0,
+ "gzip": 0,
+ "paths": []
+ }
+ },
+ "emitted": {
+ "css": {
+ "files": 2,
+ "bytes": 150822,
+ "gzip": 24357
+ },
+ "js": {
+ "files": 27,
+ "bytes": 1268249,
+ "gzip": 406679
+ },
+ "fonts": {
+ "files": 22,
+ "bytes": 12965628,
+ "gzip": 12917806
+ },
+ "html": 16,
+ "total": 20552717
+ },
+ "dependencies": {
+ "docsDirect": 21,
+ "docsRuntime": 13,
+ "lockfilePackages": 764
+ }
+ }
+}
\ No newline at end of file
diff --git a/evidence/hig/docs-package-migration/screenshots/after-errors-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/after-errors-desktop.jpg
new file mode 100644
index 0000000..22bf441
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/after-errors-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/after-home-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/after-home-desktop.jpg
new file mode 100644
index 0000000..ad47ba7
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/after-home-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/after-home-mobile.jpg b/evidence/hig/docs-package-migration/screenshots/after-home-mobile.jpg
new file mode 100644
index 0000000..b46f423
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/after-home-mobile.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/after-mobile-nav.jpg b/evidence/hig/docs-package-migration/screenshots/after-mobile-nav.jpg
new file mode 100644
index 0000000..752a79b
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/after-mobile-nav.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/after-not-found-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/after-not-found-desktop.jpg
new file mode 100644
index 0000000..0422eeb
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/after-not-found-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/after-og-home.jpg b/evidence/hig/docs-package-migration/screenshots/after-og-home.jpg
new file mode 100644
index 0000000..d99d9e8
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/after-og-home.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/after-quickstart-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/after-quickstart-desktop.jpg
new file mode 100644
index 0000000..e0133b5
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/after-quickstart-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/after-search-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/after-search-desktop.jpg
new file mode 100644
index 0000000..558e185
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/after-search-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/after-search-empty-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/after-search-empty-desktop.jpg
new file mode 100644
index 0000000..07ed215
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/after-search-empty-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/before-errors-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/before-errors-desktop.jpg
new file mode 100644
index 0000000..bd487bf
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/before-errors-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/before-home-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/before-home-desktop.jpg
new file mode 100644
index 0000000..901643b
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/before-home-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/before-home-mobile.jpg b/evidence/hig/docs-package-migration/screenshots/before-home-mobile.jpg
new file mode 100644
index 0000000..ed0c946
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/before-home-mobile.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/before-mobile-nav.jpg b/evidence/hig/docs-package-migration/screenshots/before-mobile-nav.jpg
new file mode 100644
index 0000000..f137187
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/before-mobile-nav.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/before-not-found-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/before-not-found-desktop.jpg
new file mode 100644
index 0000000..0422eeb
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/before-not-found-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/before-og-home.jpg b/evidence/hig/docs-package-migration/screenshots/before-og-home.jpg
new file mode 100644
index 0000000..d99d9e8
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/before-og-home.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/before-quickstart-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/before-quickstart-desktop.jpg
new file mode 100644
index 0000000..9cfd3e9
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/before-quickstart-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/before-search-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/before-search-desktop.jpg
new file mode 100644
index 0000000..3666dd0
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/before-search-desktop.jpg differ
diff --git a/evidence/hig/docs-package-migration/screenshots/before-search-empty-desktop.jpg b/evidence/hig/docs-package-migration/screenshots/before-search-empty-desktop.jpg
new file mode 100644
index 0000000..bcc3f95
Binary files /dev/null and b/evidence/hig/docs-package-migration/screenshots/before-search-empty-desktop.jpg differ
diff --git a/hig-drift.json b/hig-drift.json
new file mode 100644
index 0000000..8c684d5
--- /dev/null
+++ b/hig-drift.json
@@ -0,0 +1,6 @@
+{
+ "paths": ["apps/docs/app", "apps/docs/components", "apps/docs/lib", "apps/docs/mdx-components.tsx", "apps/docs/scripts", "apps/docs/public", "apps/docs/fonts", "apps/docs/styles", "apps/docs/vendor"],
+ "canonical": [],
+ "obsoleteImports": [],
+ "exceptions": []
+}
diff --git a/package-lock.json b/package-lock.json
index 64087bc..9241cc7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,6 +23,11 @@
"hasInstallScript": true,
"dependencies": {
"@bloxwap/font": "0.1.2",
+ "@bloxwap/hig-contracts": "file:../../vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha19c75619.tgz",
+ "@bloxwap/hig-react": "file:../../vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha19c75619.tgz",
+ "@bloxwap/hig-tokens": "file:../../vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha19c75619.tgz",
+ "@radix-ui/react-dropdown-menu": "2.1.16",
+ "@radix-ui/react-tooltip": "1.2.8",
"fumadocs-core": "16.15.14",
"fumadocs-mdx": "15.4.5",
"fumadocs-ui": "16.15.14",
@@ -37,6 +42,7 @@
"@types/node": "^24.13.6",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
+ "playwright": "1.64.1",
"tailwindcss": "^4.2.0",
"typescript": "^6.0.3"
},
@@ -44,6 +50,42 @@
"node": ">=24"
}
},
+ "apps/docs/node_modules/@bloxwap/hig-react": {
+ "version": "0.1.0-candidate.sha19c75619",
+ "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha19c75619.tgz",
+ "integrity": "sha512-BmUEg145HFZ25gdSxBKnoBMva2KWK0a3l38ED/vNlltlPjOBu1s7r0uWN4kYjL/6Q/Itm5TyCeehcpjanc3pog==",
+ "license": "MIT",
+ "dependencies": {
+ "@bloxwap/hig-contracts": "0.1.0-candidate.sha19c75619",
+ "@bloxwap/hig-tokens": "0.1.0-candidate.sha19c75619"
+ },
+ "peerDependencies": {
+ "@bloxwap/chart": "^0.3.0",
+ "@radix-ui/react-dialog": "1.1.15",
+ "@radix-ui/react-dropdown-menu": "2.1.16",
+ "@radix-ui/react-popover": "1.1.15",
+ "@radix-ui/react-tooltip": "1.2.8",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@bloxwap/chart": {
+ "optional": true
+ },
+ "@radix-ui/react-dialog": {
+ "optional": true
+ },
+ "@radix-ui/react-dropdown-menu": {
+ "optional": true
+ },
+ "@radix-ui/react-popover": {
+ "optional": true
+ },
+ "@radix-ui/react-tooltip": {
+ "optional": true
+ }
+ }
+ },
"apps/docs/node_modules/@types/node": {
"version": "24.19.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.2.tgz",
@@ -116,6 +158,18 @@
}
}
},
+ "node_modules/@bloxwap/hig-contracts": {
+ "version": "0.1.0-candidate.sha19c75619",
+ "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha19c75619.tgz",
+ "integrity": "sha512-twceZ7JuiC38Zv20QseKb3WRuUnrKHT0mV3cDIWhqcqcT2Bp1T238le0zy0Fehg0uvGjo2VvXhAJ5UMkE8kjmg==",
+ "license": "MIT"
+ },
+ "node_modules/@bloxwap/hig-tokens": {
+ "version": "0.1.0-candidate.sha19c75619",
+ "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha19c75619.tgz",
+ "integrity": "sha512-kk4a9nqv13yPaAQXwxvj7DHK9WXeGYPLInABAP0yplbLy/GQMx2JBDu7VKdkr73/2b1fuamdyuvk3s3pLJtAlQ==",
+ "license": "MIT"
+ },
"node_modules/@bloxwap/hyperliquid": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@bloxwap/hyperliquid/-/hyperliquid-0.6.0.tgz",
@@ -2308,17 +2362,1090 @@
}
}
},
- "node_modules/@radix-ui/react-dismissable-layer": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.2.1.tgz",
- "integrity": "sha512-KIfDcAsx+oVylFZ4xryVKusJUrLLhTQmfnJW4kwk4Km5myvhHCrj04hnWWUC166+xD4DHdH8tQGylwYX1h6+Pg==",
+ "node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.2.1.tgz",
+ "integrity": "sha512-KIfDcAsx+oVylFZ4xryVKusJUrLLhTQmfnJW4kwk4Km5myvhHCrj04hnWWUC166+xD4DHdH8tQGylwYX1h6+Pg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.2.0",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-primitive": "2.2.0",
+ "@radix-ui/react-use-callback-ref": "1.1.5",
+ "@radix-ui/react-use-effect-event": "0.0.5"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
+ "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-id": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-effect-event": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.2.0.tgz",
+ "integrity": "sha512-MPm5R0iRGUDrDnPNxmLBkv+X7pN4XKzt+MbWJEuJQsH3NFH4omrbpXpucyYCCKTSt+na/ZxGhEWQrWTZ0285cA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-scope": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.3.1.tgz",
+ "integrity": "sha512-ugeMhbXt4y5S2T1GnIqbWDKEN962PDwnX1fN0eKOOgf5f63Dh2mn8F1FUySlgW0iF6GiVsRF32DzuDIWTUyQJg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-primitive": "2.2.0",
+ "@radix-ui/react-use-callback-ref": "1.1.5"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz",
+ "integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
+ "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-arrow": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-collection": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-direction": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
+ "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
+ "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-focus-scope": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-id": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-popper": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
+ "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-rect": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1",
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-portal": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-presence": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
+ "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-effect-event": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-size": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-navigation-menu": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.4.1.tgz",
+ "integrity": "sha512-XPPZjkeyCSMNNvt0FyDv/PUauG7Ow4GwHQ/XZSwW36F/TS7rR4HFTsXH8ewLnXTOLn3x96/pmTPNQIVoTX/86g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.2.0",
+ "@radix-ui/react-collection": "1.2.0",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.3.0",
+ "@radix-ui/react-direction": "1.2.0",
+ "@radix-ui/react-dismissable-layer": "1.2.1",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-presence": "1.1.11",
+ "@radix-ui/react-primitive": "2.2.0",
+ "@radix-ui/react-slot": "1.5.0",
+ "@radix-ui/react-use-callback-ref": "1.1.5",
+ "@radix-ui/react-use-controllable-state": "1.3.0",
+ "@radix-ui/react-use-layout-effect": "1.1.4",
+ "@radix-ui/react-use-previous": "1.1.4",
+ "@radix-ui/react-visually-hidden": "1.2.13"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popover": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.3.1.tgz",
+ "integrity": "sha512-ZNxvXRx5W2Wos4fXCXb5lpdqN0Z5chf+mStOUOTr4ik7d+62MRvoe9rzCA/eGNg36lxXqSrKEKmwuZEcUrIstw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.2.0",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.3.0",
+ "@radix-ui/react-dismissable-layer": "1.2.1",
+ "@radix-ui/react-focus-guards": "1.2.0",
+ "@radix-ui/react-focus-scope": "1.3.1",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-popper": "1.4.0",
+ "@radix-ui/react-portal": "1.2.0",
+ "@radix-ui/react-presence": "1.1.11",
+ "@radix-ui/react-primitive": "2.2.0",
+ "@radix-ui/react-slot": "1.5.0",
+ "@radix-ui/react-use-controllable-state": "1.3.0",
+ "@radix-ui/react-use-layout-effect": "1.1.4",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.7.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popper": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.4.0.tgz",
+ "integrity": "sha512-yCWRvLeGv9Pz3+efwHqGPp70mZ56r3kfIgQVF56Oj2aAa4uP/Tb+IE59wNcc+758rctqbCKx4LbK8II/r7Bn0Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.1.17",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.3.0",
+ "@radix-ui/react-primitive": "2.2.0",
+ "@radix-ui/react-use-callback-ref": "1.1.5",
+ "@radix-ui/react-use-layout-effect": "1.1.4",
+ "@radix-ui/react-use-rect": "1.1.4",
+ "@radix-ui/react-use-size": "1.1.5",
+ "@radix-ui/rect": "1.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.2.0.tgz",
+ "integrity": "sha512-StX7xXnaRU41VvFtMm9zlhVGz8XF6GmWWTXftkQaY+tqVkbs/R9UmAp5mLzHHapk5hM9RMZQvO/3usyIP/g42g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.2.0",
+ "@radix-ui/react-use-layout-effect": "1.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.11.tgz",
+ "integrity": "sha512-Z7/atlkab36Z8hm+V8zYc79r0W+tiOB1o0tun1By94JyadkekLQmtEAnBSP9XKXBNQsStoStS4+gX10JpS5akA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.2.0.tgz",
+ "integrity": "sha512-HCTSPMNqv55Qk0IX4geJbpyXazmqulcimwuyjxTkKi29v+QZbG2Zho9BnbBq4YS2PF+KlNb2CXoLz66uUmblkg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.5.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.2.1.tgz",
+ "integrity": "sha512-UwraORzVUeEPMclhO1p0vz0qI+TbdDLO9i+FiOqhJyHKwdpCRCck9yVEscUnAMIzCiuNoQa8D4A9bIpOPXGt6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.2.0",
+ "@radix-ui/react-collection": "1.2.0",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.3.0",
+ "@radix-ui/react-direction": "1.2.0",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-primitive": "2.2.0",
+ "@radix-ui/react-use-callback-ref": "1.1.5",
+ "@radix-ui/react-use-controllable-state": "1.3.0",
+ "@radix-ui/react-use-is-hydrated": "0.1.3",
+ "@radix-ui/react-use-layout-effect": "1.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-scroll-area": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.4.0.tgz",
+ "integrity": "sha512-CFrLqHNejWq5FhKAcj9V/WPGRsol76HBQto81NdOBVFEOqIEkJkKIJt0Z824A/9hHLCtoiR/Kw3euRgzXP2pxg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.3",
+ "@radix-ui/primitive": "1.2.0",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.3.0",
+ "@radix-ui/react-direction": "1.2.0",
+ "@radix-ui/react-presence": "1.1.11",
+ "@radix-ui/react-primitive": "2.2.0",
+ "@radix-ui/react-slot": "1.5.0",
+ "@radix-ui/react-use-callback-ref": "1.1.5",
+ "@radix-ui/react-use-layout-effect": "1.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.5.0.tgz",
+ "integrity": "sha512-tyYd9ddPXAysAbdbD9eYxgwpCSv6f3PncqVSNKQFSR5lcJVLz3cb/pANDoYrLiHBpXv7skortyUgGUWsYuPPFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.5"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tabs": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.2.1.tgz",
+ "integrity": "sha512-hRoJlode+hg5ZNlR+3tkfkUliIybdTpD5lkAvHQ9yaXseGf7XVO9Ib2GPEIOuaJJbo7YWYbNpDDRfo8Dhf6/xA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.2.0",
+ "@radix-ui/react-context": "1.3.0",
+ "@radix-ui/react-direction": "1.2.0",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-presence": "1.1.11",
+ "@radix-ui/react-primitive": "2.2.0",
+ "@radix-ui/react-roving-focus": "1.2.1",
+ "@radix-ui/react-use-controllable-state": "1.3.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
+ "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-visually-hidden": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.2.0",
- "@radix-ui/react-compose-refs": "1.1.5",
- "@radix-ui/react-primitive": "2.2.0",
- "@radix-ui/react-use-callback-ref": "1.1.5",
- "@radix-ui/react-use-effect-event": "0.0.5"
+ "@radix-ui/react-primitive": "2.1.3"
},
"peerDependencies": {
"@types/react": "*",
@@ -2335,10 +3462,10 @@
}
}
},
- "node_modules/@radix-ui/react-focus-guards": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.2.0.tgz",
- "integrity": "sha512-MPm5R0iRGUDrDnPNxmLBkv+X7pN4XKzt+MbWJEuJQsH3NFH4omrbpXpucyYCCKTSt+na/ZxGhEWQrWTZ0285cA==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -2350,15 +3477,32 @@
}
}
},
- "node_modules/@radix-ui/react-focus-scope": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.3.1.tgz",
- "integrity": "sha512-ugeMhbXt4y5S2T1GnIqbWDKEN962PDwnX1fN0eKOOgf5f63Dh2mn8F1FUySlgW0iF6GiVsRF32DzuDIWTUyQJg==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
+ "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.5",
- "@radix-ui/react-primitive": "2.2.0",
- "@radix-ui/react-use-callback-ref": "1.1.5"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2375,13 +3519,13 @@
}
}
},
- "node_modules/@radix-ui/react-id": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz",
- "integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-id": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.4"
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2393,27 +3537,22 @@
}
}
},
- "node_modules/@radix-ui/react-navigation-menu": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.4.1.tgz",
- "integrity": "sha512-XPPZjkeyCSMNNvt0FyDv/PUauG7Ow4GwHQ/XZSwW36F/TS7rR4HFTsXH8ewLnXTOLn3x96/pmTPNQIVoTX/86g==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
+ "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.2.0",
- "@radix-ui/react-collection": "1.2.0",
- "@radix-ui/react-compose-refs": "1.1.5",
- "@radix-ui/react-context": "1.3.0",
- "@radix-ui/react-direction": "1.2.0",
- "@radix-ui/react-dismissable-layer": "1.2.1",
- "@radix-ui/react-id": "1.1.4",
- "@radix-ui/react-presence": "1.1.11",
- "@radix-ui/react-primitive": "2.2.0",
- "@radix-ui/react-slot": "1.5.0",
- "@radix-ui/react-use-callback-ref": "1.1.5",
- "@radix-ui/react-use-controllable-state": "1.3.0",
- "@radix-ui/react-use-layout-effect": "1.1.4",
- "@radix-ui/react-use-previous": "1.1.4",
- "@radix-ui/react-visually-hidden": "1.2.13"
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-rect": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1",
+ "@radix-ui/rect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2430,28 +3569,14 @@
}
}
},
- "node_modules/@radix-ui/react-popover": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.3.1.tgz",
- "integrity": "sha512-ZNxvXRx5W2Wos4fXCXb5lpdqN0Z5chf+mStOUOTr4ik7d+62MRvoe9rzCA/eGNg36lxXqSrKEKmwuZEcUrIstw==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-portal": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.2.0",
- "@radix-ui/react-compose-refs": "1.1.5",
- "@radix-ui/react-context": "1.3.0",
- "@radix-ui/react-dismissable-layer": "1.2.1",
- "@radix-ui/react-focus-guards": "1.2.0",
- "@radix-ui/react-focus-scope": "1.3.1",
- "@radix-ui/react-id": "1.1.4",
- "@radix-ui/react-popper": "1.4.0",
- "@radix-ui/react-portal": "1.2.0",
- "@radix-ui/react-presence": "1.1.11",
- "@radix-ui/react-primitive": "2.2.0",
- "@radix-ui/react-slot": "1.5.0",
- "@radix-ui/react-use-controllable-state": "1.3.0",
- "@radix-ui/react-use-layout-effect": "1.1.4",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.7.2"
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2468,22 +3593,14 @@
}
}
},
- "node_modules/@radix-ui/react-popper": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.4.0.tgz",
- "integrity": "sha512-yCWRvLeGv9Pz3+efwHqGPp70mZ56r3kfIgQVF56Oj2aAa4uP/Tb+IE59wNcc+758rctqbCKx4LbK8II/r7Bn0Q==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-presence": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
"license": "MIT",
"dependencies": {
- "@floating-ui/react-dom": "^2.0.0",
- "@radix-ui/react-arrow": "1.1.17",
- "@radix-ui/react-compose-refs": "1.1.5",
- "@radix-ui/react-context": "1.3.0",
- "@radix-ui/react-primitive": "2.2.0",
- "@radix-ui/react-use-callback-ref": "1.1.5",
- "@radix-ui/react-use-layout-effect": "1.1.4",
- "@radix-ui/react-use-rect": "1.1.4",
- "@radix-ui/react-use-size": "1.1.5",
- "@radix-ui/rect": "1.1.3"
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2500,14 +3617,13 @@
}
}
},
- "node_modules/@radix-ui/react-portal": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.2.0.tgz",
- "integrity": "sha512-StX7xXnaRU41VvFtMm9zlhVGz8XF6GmWWTXftkQaY+tqVkbs/R9UmAp5mLzHHapk5hM9RMZQvO/3usyIP/g42g==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.2.0",
- "@radix-ui/react-use-layout-effect": "1.1.4"
+ "@radix-ui/react-slot": "1.2.3"
},
"peerDependencies": {
"@types/react": "*",
@@ -2524,124 +3640,116 @@
}
}
},
- "node_modules/@radix-ui/react-presence": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.11.tgz",
- "integrity": "sha512-Z7/atlkab36Z8hm+V8zYc79r0W+tiOB1o0tun1By94JyadkekLQmtEAnBSP9XKXBNQsStoStS4+gX10JpS5akA==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.4"
+ "@radix-ui/react-compose-refs": "1.1.2"
},
"peerDependencies": {
"@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
- },
- "@types/react-dom": {
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
"optional": true
}
}
},
- "node_modules/@radix-ui/react-primitive": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.2.0.tgz",
- "integrity": "sha512-HCTSPMNqv55Qk0IX4geJbpyXazmqulcimwuyjxTkKi29v+QZbG2Zho9BnbBq4YS2PF+KlNb2CXoLz66uUmblkg==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-slot": "1.5.0"
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
- },
- "@types/react-dom": {
- "optional": true
}
}
},
- "node_modules/@radix-ui/react-roving-focus": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.2.1.tgz",
- "integrity": "sha512-UwraORzVUeEPMclhO1p0vz0qI+TbdDLO9i+FiOqhJyHKwdpCRCck9yVEscUnAMIzCiuNoQa8D4A9bIpOPXGt6Q==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-effect-event": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.2.0",
- "@radix-ui/react-collection": "1.2.0",
- "@radix-ui/react-compose-refs": "1.1.5",
- "@radix-ui/react-context": "1.3.0",
- "@radix-ui/react-direction": "1.2.0",
- "@radix-ui/react-id": "1.1.4",
- "@radix-ui/react-primitive": "2.2.0",
- "@radix-ui/react-use-callback-ref": "1.1.5",
- "@radix-ui/react-use-controllable-state": "1.3.0",
- "@radix-ui/react-use-is-hydrated": "0.1.3",
- "@radix-ui/react-use-layout-effect": "1.1.4"
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
- },
- "@types/react-dom": {
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
"optional": true
}
}
},
- "node_modules/@radix-ui/react-scroll-area": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.4.0.tgz",
- "integrity": "sha512-CFrLqHNejWq5FhKAcj9V/WPGRsol76HBQto81NdOBVFEOqIEkJkKIJt0Z824A/9hHLCtoiR/Kw3euRgzXP2pxg==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
"license": "MIT",
"dependencies": {
- "@radix-ui/number": "1.1.3",
- "@radix-ui/primitive": "1.2.0",
- "@radix-ui/react-compose-refs": "1.1.5",
- "@radix-ui/react-context": "1.3.0",
- "@radix-ui/react-direction": "1.2.0",
- "@radix-ui/react-presence": "1.1.11",
- "@radix-ui/react-primitive": "2.2.0",
- "@radix-ui/react-slot": "1.5.0",
- "@radix-ui/react-use-callback-ref": "1.1.5",
- "@radix-ui/react-use-layout-effect": "1.1.4"
+ "@radix-ui/rect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
- },
- "@types/react-dom": {
- "optional": true
}
}
},
- "node_modules/@radix-ui/react-slot": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.5.0.tgz",
- "integrity": "sha512-tyYd9ddPXAysAbdbD9eYxgwpCSv6f3PncqVSNKQFSR5lcJVLz3cb/pANDoYrLiHBpXv7skortyUgGUWsYuPPFQ==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-size": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.5"
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2653,20 +3761,13 @@
}
}
},
- "node_modules/@radix-ui/react-tabs": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.2.1.tgz",
- "integrity": "sha512-hRoJlode+hg5ZNlR+3tkfkUliIybdTpD5lkAvHQ9yaXseGf7XVO9Ib2GPEIOuaJJbo7YWYbNpDDRfo8Dhf6/xA==",
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-visually-hidden": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.2.0",
- "@radix-ui/react-context": "1.3.0",
- "@radix-ui/react-direction": "1.2.0",
- "@radix-ui/react-id": "1.1.4",
- "@radix-ui/react-presence": "1.1.11",
- "@radix-ui/react-primitive": "2.2.0",
- "@radix-ui/react-roving-focus": "1.2.1",
- "@radix-ui/react-use-controllable-state": "1.3.0"
+ "@radix-ui/react-primitive": "2.1.3"
},
"peerDependencies": {
"@types/react": "*",
@@ -2683,6 +3784,12 @@
}
}
},
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
+ "license": "MIT"
+ },
"node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.5.tgz",
@@ -2739,6 +3846,39 @@
}
}
},
+ "node_modules/@radix-ui/react-use-escape-keydown": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-escape-keydown/node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-use-is-hydrated": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.3.tgz",
@@ -8822,6 +9962,35 @@
"pathe": "^2.0.1"
}
},
+ "node_modules/playwright": {
+ "version": "1.64.1",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.1.tgz",
+ "integrity": "sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.64.1"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.64.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.64.1.tgz",
+ "integrity": "sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
"node_modules/pngjs": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
diff --git a/package.json b/package.json
index 72215ce..0045daf 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,8 @@
"docs:dev": "npm --workspace @bloxwap/agent-cli-docs run dev",
"docs:build": "npm --workspace @bloxwap/agent-cli-docs run build",
"docs:check": "npm --workspace @bloxwap/agent-cli-docs run check",
- "docs:preview": "npm --workspace @bloxwap/agent-cli-docs run preview"
+ "docs:preview": "npm --workspace @bloxwap/agent-cli-docs run preview",
+ "docs:smoke": "npm --workspace @bloxwap/agent-cli-docs run smoke"
},
"engines": {
"node": ">=24"
diff --git a/vendor/bloxwap-hig/README.md b/vendor/bloxwap-hig/README.md
new file mode 100644
index 0000000..11518f4
--- /dev/null
+++ b/vendor/bloxwap-hig/README.md
@@ -0,0 +1,44 @@
+# Vendored Bloxwap HIG candidate packages
+
+`@bloxwap/hig-*` is not on npm yet ([bloxwap/hig#56](https://github.com/bloxwap/hig/issues/56)). The docs app
+(`apps/docs`) installs these packed candidates through `file:` dependencies. Nothing here is copied source.
+
+| Tarball | Package | Bytes | sha256 |
+| --- | --- | ---: | --- |
+| `bloxwap-hig-tokens-0.1.0-candidate.sha19c75619.tgz` | `@bloxwap/hig-tokens` | 4,428,740 | `55542394d90b4b8eef0fd17c413595152032195aab24e3bcd55060041d28830e` |
+| `bloxwap-hig-react-0.1.0-candidate.sha19c75619.tgz` | `@bloxwap/hig-react` | 16,726 | `3a5e6b7a014900df339737feafa7458077aaf8a512881dc58a98a623dbd1fc3d` |
+| `bloxwap-hig-contracts-0.1.0-candidate.sha19c75619.tgz` | `@bloxwap/hig-contracts` (dependency of react) | 3,056 | `9c61c4b82f64335bb1b7ce1bfcf25e2e5f060e0e19c52fce3b99b17a96f410c7` |
+
+Source: [bloxwap/hig@19c7561](https://github.com/bloxwap/hig/tree/19c75619fa5020c015aa639172c83fd02f2bc0a2), HIG 0.1.0
+candidate. Built in a clean clone (Node 24, Python with `fonttools[woff]==4.61.1` and `brotli==1.2.0`):
+
+```sh
+npm ci && npm run generate:fonts && npm run build
+npm run release:dry-run -- --channel candidate
+```
+
+The dry run reported `published: false`, with no tags or releases. Only the three packages the docs use are
+vendored; `hig-feedback` and `hig-native` are not needed. `provenance.json` holds the same hashes in machine form,
+and `npm run docs:check` (`apps/docs/scripts/hig-tokens.mjs`) fails if a tarball, the `file:` specs or the installed
+versions drift apart.
+
+What the docs use:
+
+- `@bloxwap/hig-tokens/css` for the `--hig-*` palette, spacing and control heights; `@bloxwap/hig-react/css` for the
+ control recipes (`hig-button`, `hig-surface`, `hig-link`, `hig-sr-only`, focus ring).
+- `@bloxwap/hig-react/button` `IconButton` (code copy), `/navigation` `Tabs` and `/recipes` `InstallCommand`
+ (package-manager install), `/status` `Alert`, `EmptyState` and `Callout` (search error, no results, MDX callouts).
+- `@bloxwap/hig-tokens` `tokens` and `@bloxwap/hig-tokens/fonts/BloxwapSans-{Bold,Black}.ttf` for the Open Graph
+ renderer (approved static instances of `@bloxwap/font` 0.1.2; OFL in the package).
+
+Upgrade: rebuild the tarballs from a reviewed HIG commit, replace these files, update the three `file:` specs in
+`apps/docs/package.json`, `provenance.json`, this table and the drift checkout `ref` in
+`.github/workflows/docs.yml`, then run `npm install`. When #56 publishes, swap the `file:` specs for registry versions
+and delete this folder. Rollback is a revert of the adopting commit, which restores the previous lockfile and imports.
+
+Packaging note: `@bloxwap/hig-react` declares exact optional peers (`@radix-ui/react-dialog` and
+`@radix-ui/react-popover` 1.1.15). Fumadocs already installs 1.3.1, so `npm ls` reports those optional peers as
+invalid. The docs never render HIG's Radix-backed overlays, so nothing runs against the mismatched version. However,
+`@bloxwap/hig-react/recipes` statically imports `./overlay.js`, so the docs install the optional peers
+`@radix-ui/react-dropdown-menu@2.1.16` and `@radix-ui/react-tooltip@1.2.8`. They are only needed to resolve that
+import; the overlay code is tree-shaken out of the bundle. Remove them once HIG decouples `recipes` from `overlay`.
diff --git a/vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha19c75619.tgz b/vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha19c75619.tgz
new file mode 100644
index 0000000..23685a2
Binary files /dev/null and b/vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha19c75619.tgz differ
diff --git a/vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha19c75619.tgz b/vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha19c75619.tgz
new file mode 100644
index 0000000..bea4a92
Binary files /dev/null and b/vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha19c75619.tgz differ
diff --git a/vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha19c75619.tgz b/vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha19c75619.tgz
new file mode 100644
index 0000000..cf9b06c
Binary files /dev/null and b/vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha19c75619.tgz differ
diff --git a/vendor/bloxwap-hig/provenance.json b/vendor/bloxwap-hig/provenance.json
new file mode 100644
index 0000000..5194415
--- /dev/null
+++ b/vendor/bloxwap-hig/provenance.json
@@ -0,0 +1,31 @@
+{
+ "repository": "bloxwap/hig",
+ "commit": "19c75619fa5020c015aa639172c83fd02f2bc0a2",
+ "version": "0.1.0-candidate.sha19c75619",
+ "producedBy": "npm ci && npm run generate:fonts && npm run build && npm run release:dry-run -- --channel candidate",
+ "dryRun": {
+ "published": false,
+ "tagsCreated": false,
+ "releasesCreated": false
+ },
+ "artifacts": [
+ {
+ "package": "@bloxwap/hig-tokens",
+ "file": "bloxwap-hig-tokens-0.1.0-candidate.sha19c75619.tgz",
+ "bytes": 4428740,
+ "sha256": "55542394d90b4b8eef0fd17c413595152032195aab24e3bcd55060041d28830e"
+ },
+ {
+ "package": "@bloxwap/hig-react",
+ "file": "bloxwap-hig-react-0.1.0-candidate.sha19c75619.tgz",
+ "bytes": 16726,
+ "sha256": "3a5e6b7a014900df339737feafa7458077aaf8a512881dc58a98a623dbd1fc3d"
+ },
+ {
+ "package": "@bloxwap/hig-contracts",
+ "file": "bloxwap-hig-contracts-0.1.0-candidate.sha19c75619.tgz",
+ "bytes": 3056,
+ "sha256": "9c61c4b82f64335bb1b7ce1bfcf25e2e5f060e0e19c52fce3b99b17a96f410c7"
+ }
+ ]
+}