diff --git a/core/epistemic_state.py b/core/epistemic_state.py
index f40b9566..751bfdb8 100644
--- a/core/epistemic_state.py
+++ b/core/epistemic_state.py
@@ -9,7 +9,17 @@ serialize stably into JSONL, metadata dictionaries, and test fixtures.
from __future__ import annotations
from enum import Enum, unique
-from typing import Any
+from typing import Any, Literal
+
+
+GroundingSource = Literal["pack", "teaching", "vault", "partial", "oov", "none"]
+"""Ratified grounding-source labels.
+
+Single source of truth for the values ``epistemic_state_for_grounding_source``
+maps, the cold-start-grounding lane validates, and the Workbench UI badges
+bind to (ADR-0162 ยง3d). Adding a value here without adding a corresponding
+badge fails the build-time enum coverage test under ``workbench-ui/``.
+"""
@unique
@@ -136,6 +146,7 @@ def epistemic_state_for_grounding_source(source: str | None) -> EpistemicState:
__all__ = [
"EpistemicState",
+ "GroundingSource",
"NormativeClearance",
"clearance_from_verdicts",
"coerce_epistemic_state",
diff --git a/docs/workbench/design-system.md b/docs/workbench/design-system.md
new file mode 100644
index 00000000..a7054c13
--- /dev/null
+++ b/docs/workbench/design-system.md
@@ -0,0 +1,61 @@
+# Workbench Design System v1
+
+This document records the Branch 1 substrate for ADR-0162, cross-referenced with
+[ADR-0160](../decisions/ADR-0160-core-workbench-v1.md) and
+[ADR-0161](../decisions/ADR-0161-hitl-async-queue.md).
+
+The implementation lives in `workbench-ui/`. The preview page is `/preview`:
+
+```bash
+cd workbench-ui && pnpm install && pnpm preview
+```
+
+Branch 1 is intentionally static and read-only. It adds no backend, no API
+client, no route shell beyond `/preview`, and no runtime mutation surface.
+
+## Token Substrate
+
+Tokens are defined in `workbench-ui/src/design/tokens/tokens.css` and mirrored
+to typed TypeScript by `workbench-ui/scripts/generate-tokens.ts`. The build
+prehook regenerates `tokens.ts`; the token test fails if CSS and TypeScript
+diverge.
+
+The theme is dark-only. Fonts are self-hosted from `workbench-ui/public/fonts/`
+and referenced through local `@font-face` rules only.
+
+## Badge Tables
+
+Badge components live under `workbench-ui/src/design/components/badges/`.
+Each component accepts a typed enum value, never an arbitrary string.
+
+| Badge | Values | Source |
+|---|---:|---|
+| `EpistemicStateBadge` | 15 | `core/epistemic_state.py` |
+| `NormativeClearanceBadge` | 4 | `core/epistemic_state.py` |
+| `ReviewStateBadge` | 4 | `teaching/proposals.py` |
+| `GroundingSourceBadge` | 6 | ADR-0162 Branch 1 contract |
+| `TraceHashBadge` | copyable digest | ADR-0153 / ADR-0160 |
+
+`scripts/dump-enums.py` performs a read-only AST walk over the Python enum
+sources. `pnpm test:enum-coverage` regenerates `workbench-ui/enum-snapshot.json`
+and asserts exact UI coverage so engine enum drift fails loudly at build/test
+time.
+
+## JSON Viewer
+
+`StableJsonViewer` preserves raw source spans for strings and numbers, renders
+object keys in deterministic lexicographic order, copies JSON Pointer paths,
+renders a source-byte SHA-256 badge, supports side-by-side leaf diffs, and
+refuses inline rendering above 16 MiB.
+
+## Motion And Keyboard
+
+All motion uses tokenized durations/easing. `prefers-reduced-motion: reduce`
+collapses tokenized durations to instant.
+
+The preview page installs the Branch 1 keyboard baseline:
+
+- `Cmd+K` / `Ctrl+K` opens the stub command palette.
+- `Esc` closes overlays.
+- Interactive primitives use `--color-focus-ring`.
+- Preview tab order follows DOM order.
diff --git a/scripts/dump-enums.py b/scripts/dump-enums.py
new file mode 100644
index 00000000..f0dda58c
--- /dev/null
+++ b/scripts/dump-enums.py
@@ -0,0 +1,60 @@
+"""Dump ratified engine enum values for Workbench UI coverage tests.
+
+Read-only helper: parses source with Python AST and writes JSON to stdout.
+"""
+
+from __future__ import annotations
+
+import ast
+import json
+from pathlib import Path
+
+
+ROOT = Path(__file__).resolve().parents[1]
+
+
+def enum_values(path: Path, class_name: str) -> list[str]:
+ module = ast.parse(path.read_text(encoding="utf-8"))
+ for node in module.body:
+ if isinstance(node, ast.ClassDef) and node.name == class_name:
+ values: list[str] = []
+ for statement in node.body:
+ if (
+ isinstance(statement, ast.Assign)
+ and isinstance(statement.value, ast.Constant)
+ and isinstance(statement.value.value, str)
+ ):
+ values.append(statement.value.value)
+ return values
+ raise SystemExit(f"enum class not found: {class_name}")
+
+
+def literal_values(path: Path, name: str) -> list[str]:
+ module = ast.parse(path.read_text(encoding="utf-8"))
+ for node in module.body:
+ if isinstance(node, ast.Assign):
+ if not any(isinstance(target, ast.Name) and target.id == name for target in node.targets):
+ continue
+ value = node.value
+ if (
+ isinstance(value, ast.Subscript)
+ and isinstance(value.value, ast.Name)
+ and value.value.id == "Literal"
+ ):
+ items = value.slice.elts if isinstance(value.slice, ast.Tuple) else [value.slice]
+ return [
+ item.value
+ for item in items
+ if isinstance(item, ast.Constant) and isinstance(item.value, str)
+ ]
+ raise SystemExit(f"literal alias not found: {name}")
+
+
+snapshot = {
+ "EpistemicState": enum_values(ROOT / "core" / "epistemic_state.py", "EpistemicState"),
+ "GroundingSource": literal_values(ROOT / "core" / "epistemic_state.py", "GroundingSource"),
+ "NormativeClearance": enum_values(ROOT / "core" / "epistemic_state.py", "NormativeClearance"),
+ "ReviewState": literal_values(ROOT / "teaching" / "proposals.py", "ReviewState"),
+}
+
+print(json.dumps(snapshot, indent=2, sort_keys=True))
diff --git a/workbench-ui/.gitignore b/workbench-ui/.gitignore
new file mode 100644
index 00000000..4812e78d
--- /dev/null
+++ b/workbench-ui/.gitignore
@@ -0,0 +1,7 @@
+node_modules/
+dist/
+*.tsbuildinfo
+vite.config.js
+vite.config.d.ts
+scripts/*.js
+scripts/*.d.ts
diff --git a/workbench-ui/enum-snapshot.json b/workbench-ui/enum-snapshot.json
new file mode 100644
index 00000000..7d2e04a9
--- /dev/null
+++ b/workbench-ui/enum-snapshot.json
@@ -0,0 +1,39 @@
+{
+ "EpistemicState": [
+ "perceived",
+ "evidenced",
+ "evidenced_incomplete",
+ "verified",
+ "decoded",
+ "decoded_unarticulated",
+ "inferred",
+ "unverified_possible",
+ "unverified_novel",
+ "contradicted",
+ "ambiguous",
+ "undetermined",
+ "scope_boundary",
+ "computationally_bounded",
+ "epistemic_state_needed"
+ ],
+ "GroundingSource": [
+ "pack",
+ "teaching",
+ "vault",
+ "partial",
+ "oov",
+ "none"
+ ],
+ "NormativeClearance": [
+ "cleared",
+ "violated",
+ "unassessable",
+ "suppressed"
+ ],
+ "ReviewState": [
+ "pending",
+ "accepted",
+ "rejected",
+ "withdrawn"
+ ]
+}
diff --git a/workbench-ui/index.html b/workbench-ui/index.html
new file mode 100644
index 00000000..1b408b32
--- /dev/null
+++ b/workbench-ui/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ CORE Workbench Preview
+
+
+
+
+
+
diff --git a/workbench-ui/package.json b/workbench-ui/package.json
new file mode 100644
index 00000000..11b43eb7
--- /dev/null
+++ b/workbench-ui/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "core-workbench-ui",
+ "version": "0.1.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "prebuild": "pnpm generate:tokens",
+ "build": "tsc -b && vite build",
+ "dev": "vite --host 127.0.0.1",
+ "preview": "vite preview --host 127.0.0.1",
+ "test": "vitest run",
+ "test:enum-coverage": "pnpm enum:snapshot && vitest run src/design/components/badges/enumCoverage.test.ts",
+ "generate:tokens": "tsx scripts/generate-tokens.ts",
+ "enum:snapshot": "cd .. && uv run python scripts/dump-enums.py > workbench-ui/enum-snapshot.json"
+ },
+ "dependencies": {
+ "@radix-ui/react-dialog": "1.1.15",
+ "@radix-ui/react-popover": "1.1.15",
+ "@radix-ui/react-slot": "1.2.3",
+ "class-variance-authority": "0.7.1",
+ "clsx": "2.1.1",
+ "lucide-react": "0.468.0",
+ "react": "18.3.1",
+ "react-dom": "18.3.1",
+ "tailwind-merge": "2.6.0"
+ },
+ "devDependencies": {
+ "@testing-library/jest-dom": "6.6.3",
+ "@testing-library/react": "16.1.0",
+ "@testing-library/user-event": "14.5.2",
+ "@types/node": "22.10.2",
+ "@types/react": "18.3.17",
+ "@types/react-dom": "18.3.5",
+ "@vitejs/plugin-react": "4.3.4",
+ "autoprefixer": "10.4.20",
+ "happy-dom": "15.11.7",
+ "postcss": "8.4.49",
+ "tailwindcss": "3.4.17",
+ "tsx": "4.19.2",
+ "typescript": "5.7.2",
+ "vite": "5.4.11",
+ "vitest": "2.1.8"
+ },
+ "packageManager": "pnpm@9.15.0"
+}
diff --git a/workbench-ui/pnpm-lock.yaml b/workbench-ui/pnpm-lock.yaml
new file mode 100644
index 00000000..2acb0a13
--- /dev/null
+++ b/workbench-ui/pnpm-lock.yaml
@@ -0,0 +1,3113 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@radix-ui/react-dialog':
+ specifier: 1.1.15
+ version: 1.1.15(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-popover':
+ specifier: 1.1.15
+ version: 1.1.15(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot':
+ specifier: 1.2.3
+ version: 1.2.3(@types/react@18.3.17)(react@18.3.1)
+ class-variance-authority:
+ specifier: 0.7.1
+ version: 0.7.1
+ clsx:
+ specifier: 2.1.1
+ version: 2.1.1
+ lucide-react:
+ specifier: 0.468.0
+ version: 0.468.0(react@18.3.1)
+ react:
+ specifier: 18.3.1
+ version: 18.3.1
+ react-dom:
+ specifier: 18.3.1
+ version: 18.3.1(react@18.3.1)
+ tailwind-merge:
+ specifier: 2.6.0
+ version: 2.6.0
+ devDependencies:
+ '@testing-library/jest-dom':
+ specifier: 6.6.3
+ version: 6.6.3
+ '@testing-library/react':
+ specifier: 16.1.0
+ version: 16.1.0(@testing-library/dom@10.4.1)(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@testing-library/user-event':
+ specifier: 14.5.2
+ version: 14.5.2(@testing-library/dom@10.4.1)
+ '@types/node':
+ specifier: 22.10.2
+ version: 22.10.2
+ '@types/react':
+ specifier: 18.3.17
+ version: 18.3.17
+ '@types/react-dom':
+ specifier: 18.3.5
+ version: 18.3.5(@types/react@18.3.17)
+ '@vitejs/plugin-react':
+ specifier: 4.3.4
+ version: 4.3.4(vite@5.4.11(@types/node@22.10.2))
+ autoprefixer:
+ specifier: 10.4.20
+ version: 10.4.20(postcss@8.4.49)
+ happy-dom:
+ specifier: 15.11.7
+ version: 15.11.7
+ postcss:
+ specifier: 8.4.49
+ version: 8.4.49
+ tailwindcss:
+ specifier: 3.4.17
+ version: 3.4.17
+ tsx:
+ specifier: 4.19.2
+ version: 4.19.2
+ typescript:
+ specifier: 5.7.2
+ version: 5.7.2
+ vite:
+ specifier: 5.4.11
+ version: 5.4.11(@types/node@22.10.2)
+ vitest:
+ specifier: 2.1.8
+ version: 2.1.8(@types/node@22.10.2)(happy-dom@15.11.7)
+
+packages:
+
+ '@adobe/css-tools@4.5.0':
+ resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==}
+
+ '@alloc/quick-lru@5.2.0':
+ resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
+ engines: {node: '>=10'}
+
+ '@babel/code-frame@7.29.7':
+ resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.29.7':
+ resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.29.7':
+ resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.29.7':
+ resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.29.7':
+ resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-globals@7.29.7':
+ resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.29.7':
+ resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.29.7':
+ resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-plugin-utils@7.29.7':
+ resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.29.7':
+ resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.29.7':
+ resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.29.7':
+ resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.29.7':
+ resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.29.7':
+ resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-transform-react-jsx-self@7.29.7':
+ resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-source@7.29.7':
+ resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/runtime@7.29.7':
+ resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/template@7.29.7':
+ resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.29.7':
+ resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.29.7':
+ resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==}
+ engines: {node: '>=6.9.0'}
+
+ '@esbuild/aix-ppc64@0.21.5':
+ resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/aix-ppc64@0.23.1':
+ resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.21.5':
+ resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm64@0.23.1':
+ resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.21.5':
+ resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-arm@0.23.1':
+ resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.21.5':
+ resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/android-x64@0.23.1':
+ resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.21.5':
+ resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-arm64@0.23.1':
+ resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.21.5':
+ resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.23.1':
+ resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.21.5':
+ resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-arm64@0.23.1':
+ resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.21.5':
+ resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.23.1':
+ resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.21.5':
+ resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm64@0.23.1':
+ resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.21.5':
+ resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.23.1':
+ resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.21.5':
+ resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.23.1':
+ resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.21.5':
+ resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.23.1':
+ resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.21.5':
+ resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.23.1':
+ resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.21.5':
+ resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.23.1':
+ resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.21.5':
+ resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.23.1':
+ resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.21.5':
+ resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.23.1':
+ resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.21.5':
+ resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.23.1':
+ resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-x64@0.21.5':
+ resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.23.1':
+ resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.23.1':
+ resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.21.5':
+ resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.23.1':
+ resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/sunos-x64@0.21.5':
+ resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/sunos-x64@0.23.1':
+ resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.21.5':
+ resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-arm64@0.23.1':
+ resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.21.5':
+ resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.23.1':
+ resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.21.5':
+ resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.23.1':
+ resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@floating-ui/core@1.7.5':
+ resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==}
+
+ '@floating-ui/dom@1.7.6':
+ resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==}
+
+ '@floating-ui/react-dom@2.1.8':
+ resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==}
+ peerDependencies:
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
+
+ '@floating-ui/utils@0.2.11':
+ resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@radix-ui/primitive@1.1.3':
+ resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
+
+ '@radix-ui/react-arrow@1.1.7':
+ resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==}
+ 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
+
+ '@radix-ui/react-compose-refs@1.1.2':
+ resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-context@1.1.2':
+ resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-dialog@1.1.15':
+ resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==}
+ 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
+
+ '@radix-ui/react-dismissable-layer@1.1.11':
+ resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==}
+ 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
+
+ '@radix-ui/react-focus-guards@1.1.3':
+ resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-focus-scope@1.1.7':
+ resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==}
+ 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
+
+ '@radix-ui/react-id@1.1.1':
+ resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-popover@1.1.15':
+ resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==}
+ 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
+
+ '@radix-ui/react-popper@1.2.8':
+ resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==}
+ 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
+
+ '@radix-ui/react-portal@1.1.9':
+ resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==}
+ 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
+
+ '@radix-ui/react-presence@1.1.5':
+ resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==}
+ 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
+
+ '@radix-ui/react-primitive@2.1.3':
+ resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==}
+ 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
+
+ '@radix-ui/react-slot@1.2.3':
+ resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-callback-ref@1.1.1':
+ resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-controllable-state@1.2.2':
+ resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-effect-event@0.0.2':
+ resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-escape-keydown@1.1.1':
+ resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-layout-effect@1.1.1':
+ resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-rect@1.1.1':
+ resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-size@1.1.1':
+ resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/rect@1.1.1':
+ resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
+
+ '@rollup/rollup-android-arm-eabi@4.60.4':
+ resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.60.4':
+ resolution: {integrity: sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.60.4':
+ resolution: {integrity: sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.60.4':
+ resolution: {integrity: sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.60.4':
+ resolution: {integrity: sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.60.4':
+ resolution: {integrity: sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.60.4':
+ resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.60.4':
+ resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.60.4':
+ resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.60.4':
+ resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-gnu@4.60.4':
+ resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-musl@4.60.4':
+ resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.60.4':
+ resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-musl@4.60.4':
+ resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.60.4':
+ resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.60.4':
+ resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.60.4':
+ resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.60.4':
+ resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.60.4':
+ resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-openbsd-x64@4.60.4':
+ resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@rollup/rollup-openharmony-arm64@4.60.4':
+ resolution: {integrity: sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.60.4':
+ resolution: {integrity: sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.60.4':
+ resolution: {integrity: sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.60.4':
+ resolution: {integrity: sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.60.4':
+ resolution: {integrity: sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==}
+ cpu: [x64]
+ os: [win32]
+
+ '@testing-library/dom@10.4.1':
+ resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
+ engines: {node: '>=18'}
+
+ '@testing-library/jest-dom@6.6.3':
+ resolution: {integrity: sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==}
+ engines: {node: '>=14', npm: '>=6', yarn: '>=1'}
+
+ '@testing-library/react@16.1.0':
+ resolution: {integrity: sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@testing-library/dom': ^10.0.0
+ '@types/react': ^18.0.0 || ^19.0.0
+ '@types/react-dom': ^18.0.0 || ^19.0.0
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@testing-library/user-event@14.5.2':
+ resolution: {integrity: sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==}
+ engines: {node: '>=12', npm: '>=6'}
+ peerDependencies:
+ '@testing-library/dom': '>=7.21.4'
+
+ '@types/aria-query@5.0.4':
+ resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
+
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.28.0':
+ resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+
+ '@types/estree@1.0.8':
+ resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+ '@types/estree@1.0.9':
+ resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+
+ '@types/node@22.10.2':
+ resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==}
+
+ '@types/prop-types@15.7.15':
+ resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
+
+ '@types/react-dom@18.3.5':
+ resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==}
+ peerDependencies:
+ '@types/react': ^18.0.0
+
+ '@types/react@18.3.17':
+ resolution: {integrity: sha512-opAQ5no6LqJNo9TqnxBKsgnkIYHozW9KSTlFVoSUJYh1Fl/sswkEoqIugRSm7tbh6pABtYjGAjW+GOS23j8qbw==}
+
+ '@vitejs/plugin-react@4.3.4':
+ resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0
+
+ '@vitest/expect@2.1.8':
+ resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==}
+
+ '@vitest/mocker@2.1.8':
+ resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^5.0.0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
+ '@vitest/pretty-format@2.1.8':
+ resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==}
+
+ '@vitest/pretty-format@2.1.9':
+ resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==}
+
+ '@vitest/runner@2.1.8':
+ resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==}
+
+ '@vitest/snapshot@2.1.8':
+ resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==}
+
+ '@vitest/spy@2.1.8':
+ resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==}
+
+ '@vitest/utils@2.1.8':
+ resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ ansi-styles@5.2.0:
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+ engines: {node: '>=10'}
+
+ any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
+ arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+
+ aria-hidden@1.2.6:
+ resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
+ engines: {node: '>=10'}
+
+ aria-query@5.3.0:
+ resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
+
+ aria-query@5.3.2:
+ resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
+ engines: {node: '>= 0.4'}
+
+ assertion-error@2.0.1:
+ resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
+ engines: {node: '>=12'}
+
+ autoprefixer@10.4.20:
+ resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+
+ baseline-browser-mapping@2.10.32:
+ resolution: {integrity: sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ binary-extensions@2.3.0:
+ resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+ engines: {node: '>=8'}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ browserslist@4.28.2:
+ resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+
+ camelcase-css@2.0.1:
+ resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
+ engines: {node: '>= 6'}
+
+ caniuse-lite@1.0.30001793:
+ resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==}
+
+ chai@5.3.3:
+ resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
+ engines: {node: '>=18'}
+
+ chalk@3.0.0:
+ resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==}
+ engines: {node: '>=8'}
+
+ check-error@2.1.3:
+ resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==}
+ engines: {node: '>= 16'}
+
+ chokidar@3.6.0:
+ resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+ engines: {node: '>= 8.10.0'}
+
+ class-variance-authority@0.7.1:
+ resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
+
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+ css.escape@1.5.1:
+ resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
+
+ cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ deep-eql@5.0.2:
+ resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
+ engines: {node: '>=6'}
+
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
+ detect-node-es@1.1.0:
+ resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
+
+ didyoumean@1.2.2:
+ resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+
+ dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+
+ dom-accessibility-api@0.5.16:
+ resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
+
+ dom-accessibility-api@0.6.3:
+ resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
+
+ electron-to-chromium@1.5.361:
+ resolution: {integrity: sha512-Q6Hts7N9FnJc5LeGRINFvLhCI9xZmNtTDe5ZbcVezQz7cU4a8Aua3GH1b8J2XY8Al9PF+OCwYqhgsOOheMdvkA==}
+
+ entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-module-lexer@1.7.0:
+ resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
+
+ esbuild@0.21.5:
+ resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ esbuild@0.23.1:
+ resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ expect-type@1.3.0:
+ resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
+ engines: {node: '>=12.0.0'}
+
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+
+ fastq@1.20.1:
+ resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ fraction.js@4.3.7:
+ resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ get-nonce@1.0.1:
+ resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
+ engines: {node: '>=6'}
+
+ get-tsconfig@4.14.0:
+ resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+
+ happy-dom@15.11.7:
+ resolution: {integrity: sha512-KyrFvnl+J9US63TEzwoiJOQzZBJY7KgBushJA8X61DMbNsH+2ONkDuLDnCnwUiPTF42tLoEmrPyoqbenVA5zrg==}
+ engines: {node: '>=18.0.0'}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ hasown@2.0.3:
+ resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==}
+ engines: {node: '>= 0.4'}
+
+ indent-string@4.0.0:
+ resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+ engines: {node: '>=8'}
+
+ is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+
+ is-core-module@2.16.2:
+ resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==}
+ engines: {node: '>= 0.4'}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ jiti@1.21.7:
+ resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
+ hasBin: true
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ lilconfig@3.1.3:
+ resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
+ engines: {node: '>=14'}
+
+ lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ lodash@4.18.1:
+ resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ loupe@3.2.1:
+ resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+ lucide-react@0.468.0:
+ resolution: {integrity: sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==}
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc
+
+ lz-string@1.5.0:
+ resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
+ hasBin: true
+
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ min-indent@1.0.1:
+ resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+ engines: {node: '>=4'}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+
+ nanoid@3.3.12:
+ resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ node-releases@2.0.46:
+ resolution: {integrity: sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==}
+ engines: {node: '>=18'}
+
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ normalize-range@0.1.2:
+ resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
+ engines: {node: '>=0.10.0'}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+
+ path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ pathe@1.1.2:
+ resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
+
+ pathval@2.0.1:
+ resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
+ engines: {node: '>= 14.16'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@2.3.2:
+ resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==}
+ engines: {node: '>=8.6'}
+
+ picomatch@4.0.4:
+ resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
+ engines: {node: '>=12'}
+
+ pify@2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+
+ pirates@4.0.7:
+ resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
+ engines: {node: '>= 6'}
+
+ postcss-import@15.1.0:
+ resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+
+ postcss-js@4.1.0:
+ resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==}
+ engines: {node: ^12 || ^14 || >= 16}
+ peerDependencies:
+ postcss: ^8.4.21
+
+ postcss-load-config@4.0.2:
+ resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+
+ postcss-nested@6.2.0:
+ resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+
+ postcss-selector-parser@6.1.2:
+ resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
+ engines: {node: '>=4'}
+
+ postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
+ postcss@8.4.49:
+ resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ pretty-format@27.5.1:
+ resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
+ engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ react-dom@18.3.1:
+ resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
+ peerDependencies:
+ react: ^18.3.1
+
+ react-is@17.0.2:
+ resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
+
+ react-refresh@0.14.2:
+ resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
+ engines: {node: '>=0.10.0'}
+
+ react-remove-scroll-bar@2.3.8:
+ resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react-remove-scroll@2.7.2:
+ resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react-style-singleton@2.2.3:
+ resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react@18.3.1:
+ resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+ engines: {node: '>=0.10.0'}
+
+ read-cache@1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+
+ readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+
+ redent@3.0.0:
+ resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
+ engines: {node: '>=8'}
+
+ resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
+ resolve@1.22.12:
+ resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rollup@4.60.4:
+ resolution: {integrity: sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ scheduler@0.23.2:
+ resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ siginfo@2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ stackback@0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+
+ std-env@3.10.0:
+ resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+
+ strip-indent@3.0.0:
+ resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+ engines: {node: '>=8'}
+
+ sucrase@3.35.1:
+ resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
+ supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ tailwind-merge@2.6.0:
+ resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==}
+
+ tailwindcss@3.4.17:
+ resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+
+ thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+
+ thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+
+ tinybench@2.9.0:
+ resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+
+ tinyexec@0.3.2:
+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+
+ tinyglobby@0.2.16:
+ resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
+ engines: {node: '>=12.0.0'}
+
+ tinypool@1.1.1:
+ resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+
+ tinyrainbow@1.2.0:
+ resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
+ engines: {node: '>=14.0.0'}
+
+ tinyspy@3.0.2:
+ resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
+ engines: {node: '>=14.0.0'}
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ tsx@4.19.2:
+ resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==}
+ engines: {node: '>=18.0.0'}
+ hasBin: true
+
+ typescript@5.7.2:
+ resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ undici-types@6.20.0:
+ resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
+
+ update-browserslist-db@1.2.3:
+ resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ use-callback-ref@1.3.3:
+ resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ use-sidecar@1.1.3:
+ resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ vite-node@2.1.8:
+ resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+
+ vite@5.4.11:
+ resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+
+ vitest@2.1.8:
+ resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/node': ^18.0.0 || >=20.0.0
+ '@vitest/browser': 2.1.8
+ '@vitest/ui': 2.1.8
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ webidl-conversions@7.0.0:
+ resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
+ engines: {node: '>=12'}
+
+ whatwg-mimetype@3.0.0:
+ resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==}
+ engines: {node: '>=12'}
+
+ why-is-node-running@2.3.0:
+ resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
+ engines: {node: '>=8'}
+ hasBin: true
+
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+ yaml@2.9.0:
+ resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==}
+ engines: {node: '>= 14.6'}
+ hasBin: true
+
+snapshots:
+
+ '@adobe/css-tools@4.5.0': {}
+
+ '@alloc/quick-lru@5.2.0': {}
+
+ '@babel/code-frame@7.29.7':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.29.7
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.29.7': {}
+
+ '@babel/core@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helpers': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.29.7':
+ dependencies:
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
+ '@babel/helper-compilation-targets@7.29.7':
+ dependencies:
+ '@babel/compat-data': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ browserslist: 4.28.2
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-globals@7.29.7': {}
+
+ '@babel/helper-module-imports@7.29.7':
+ dependencies:
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-plugin-utils@7.29.7': {}
+
+ '@babel/helper-string-parser@7.29.7': {}
+
+ '@babel/helper-validator-identifier@7.29.7': {}
+
+ '@babel/helper-validator-option@7.29.7': {}
+
+ '@babel/helpers@7.29.7':
+ dependencies:
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
+
+ '@babel/parser@7.29.7':
+ dependencies:
+ '@babel/types': 7.29.7
+
+ '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/runtime@7.29.7': {}
+
+ '@babel/template@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+
+ '@babel/traverse@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-globals': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.29.7':
+ dependencies:
+ '@babel/helper-string-parser': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+
+ '@esbuild/aix-ppc64@0.21.5':
+ optional: true
+
+ '@esbuild/aix-ppc64@0.23.1':
+ optional: true
+
+ '@esbuild/android-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/android-arm64@0.23.1':
+ optional: true
+
+ '@esbuild/android-arm@0.21.5':
+ optional: true
+
+ '@esbuild/android-arm@0.23.1':
+ optional: true
+
+ '@esbuild/android-x64@0.21.5':
+ optional: true
+
+ '@esbuild/android-x64@0.23.1':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.23.1':
+ optional: true
+
+ '@esbuild/darwin-x64@0.21.5':
+ optional: true
+
+ '@esbuild/darwin-x64@0.23.1':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.23.1':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.23.1':
+ optional: true
+
+ '@esbuild/linux-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-arm64@0.23.1':
+ optional: true
+
+ '@esbuild/linux-arm@0.21.5':
+ optional: true
+
+ '@esbuild/linux-arm@0.23.1':
+ optional: true
+
+ '@esbuild/linux-ia32@0.21.5':
+ optional: true
+
+ '@esbuild/linux-ia32@0.23.1':
+ optional: true
+
+ '@esbuild/linux-loong64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-loong64@0.23.1':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.21.5':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.23.1':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.23.1':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.23.1':
+ optional: true
+
+ '@esbuild/linux-s390x@0.21.5':
+ optional: true
+
+ '@esbuild/linux-s390x@0.23.1':
+ optional: true
+
+ '@esbuild/linux-x64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-x64@0.23.1':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.23.1':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.23.1':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.23.1':
+ optional: true
+
+ '@esbuild/sunos-x64@0.21.5':
+ optional: true
+
+ '@esbuild/sunos-x64@0.23.1':
+ optional: true
+
+ '@esbuild/win32-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/win32-arm64@0.23.1':
+ optional: true
+
+ '@esbuild/win32-ia32@0.21.5':
+ optional: true
+
+ '@esbuild/win32-ia32@0.23.1':
+ optional: true
+
+ '@esbuild/win32-x64@0.21.5':
+ optional: true
+
+ '@esbuild/win32-x64@0.23.1':
+ optional: true
+
+ '@floating-ui/core@1.7.5':
+ dependencies:
+ '@floating-ui/utils': 0.2.11
+
+ '@floating-ui/dom@1.7.6':
+ dependencies:
+ '@floating-ui/core': 1.7.5
+ '@floating-ui/utils': 0.2.11
+
+ '@floating-ui/react-dom@2.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@floating-ui/dom': 1.7.6
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
+ '@floating-ui/utils@0.2.11': {}
+
+ '@jridgewell/gen-mapping@0.3.13':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.20.1
+
+ '@radix-ui/primitive@1.1.3': {}
+
+ '@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-context@1.1.2(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-dialog@1.1.15(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.17)(react@18.3.1)
+ aria-hidden: 1.2.6
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-remove-scroll: 2.7.2(@types/react@18.3.17)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@radix-ui/react-focus-guards@1.1.3(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@radix-ui/react-id@1.1.1(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.17)(react@18.3.1)
+ aria-hidden: 1.2.6
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-remove-scroll: 2.7.2(@types/react@18.3.17)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@radix-ui/react-popper@1.2.8(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@floating-ui/react-dom': 2.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-arrow': 1.1.7(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/rect': 1.1.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@radix-ui/react-portal@1.1.9(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@radix-ui/react-presence@1.1.5(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@radix-ui/react-primitive@2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@radix-ui/react-slot@1.2.3(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.17)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-use-rect@1.1.1(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ '@radix-ui/rect': 1.1.1
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/react-use-size@1.1.1(@types/react@18.3.17)(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.17)(react@18.3.1)
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ '@radix-ui/rect@1.1.1': {}
+
+ '@rollup/rollup-android-arm-eabi@4.60.4':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.60.4':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.60.4':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.60.4':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.60.4':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-musl@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-musl@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.60.4':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.60.4':
+ optional: true
+
+ '@rollup/rollup-openbsd-x64@4.60.4':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.60.4':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.60.4':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.60.4':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.60.4':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.60.4':
+ optional: true
+
+ '@testing-library/dom@10.4.1':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/runtime': 7.29.7
+ '@types/aria-query': 5.0.4
+ aria-query: 5.3.0
+ dom-accessibility-api: 0.5.16
+ lz-string: 1.5.0
+ picocolors: 1.1.1
+ pretty-format: 27.5.1
+
+ '@testing-library/jest-dom@6.6.3':
+ dependencies:
+ '@adobe/css-tools': 4.5.0
+ aria-query: 5.3.2
+ chalk: 3.0.0
+ css.escape: 1.5.1
+ dom-accessibility-api: 0.6.3
+ lodash: 4.18.1
+ redent: 3.0.0
+
+ '@testing-library/react@16.1.0(@testing-library/dom@10.4.1)(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.29.7
+ '@testing-library/dom': 10.4.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+ '@types/react-dom': 18.3.5(@types/react@18.3.17)
+
+ '@testing-library/user-event@14.5.2(@testing-library/dom@10.4.1)':
+ dependencies:
+ '@testing-library/dom': 10.4.1
+
+ '@types/aria-query@5.0.4': {}
+
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+ '@types/babel__generator': 7.27.0
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.28.0
+
+ '@types/babel__generator@7.27.0':
+ dependencies:
+ '@babel/types': 7.29.7
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+
+ '@types/babel__traverse@7.28.0':
+ dependencies:
+ '@babel/types': 7.29.7
+
+ '@types/estree@1.0.8': {}
+
+ '@types/estree@1.0.9': {}
+
+ '@types/node@22.10.2':
+ dependencies:
+ undici-types: 6.20.0
+
+ '@types/prop-types@15.7.15': {}
+
+ '@types/react-dom@18.3.5(@types/react@18.3.17)':
+ dependencies:
+ '@types/react': 18.3.17
+
+ '@types/react@18.3.17':
+ dependencies:
+ '@types/prop-types': 15.7.15
+ csstype: 3.2.3
+
+ '@vitejs/plugin-react@4.3.4(vite@5.4.11(@types/node@22.10.2))':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7)
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.14.2
+ vite: 5.4.11(@types/node@22.10.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@vitest/expect@2.1.8':
+ dependencies:
+ '@vitest/spy': 2.1.8
+ '@vitest/utils': 2.1.8
+ chai: 5.3.3
+ tinyrainbow: 1.2.0
+
+ '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.2))':
+ dependencies:
+ '@vitest/spy': 2.1.8
+ estree-walker: 3.0.3
+ magic-string: 0.30.21
+ optionalDependencies:
+ vite: 5.4.11(@types/node@22.10.2)
+
+ '@vitest/pretty-format@2.1.8':
+ dependencies:
+ tinyrainbow: 1.2.0
+
+ '@vitest/pretty-format@2.1.9':
+ dependencies:
+ tinyrainbow: 1.2.0
+
+ '@vitest/runner@2.1.8':
+ dependencies:
+ '@vitest/utils': 2.1.8
+ pathe: 1.1.2
+
+ '@vitest/snapshot@2.1.8':
+ dependencies:
+ '@vitest/pretty-format': 2.1.8
+ magic-string: 0.30.21
+ pathe: 1.1.2
+
+ '@vitest/spy@2.1.8':
+ dependencies:
+ tinyspy: 3.0.2
+
+ '@vitest/utils@2.1.8':
+ dependencies:
+ '@vitest/pretty-format': 2.1.8
+ loupe: 3.2.1
+ tinyrainbow: 1.2.0
+
+ ansi-regex@5.0.1: {}
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ ansi-styles@5.2.0: {}
+
+ any-promise@1.3.0: {}
+
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.2
+
+ arg@5.0.2: {}
+
+ aria-hidden@1.2.6:
+ dependencies:
+ tslib: 2.8.1
+
+ aria-query@5.3.0:
+ dependencies:
+ dequal: 2.0.3
+
+ aria-query@5.3.2: {}
+
+ assertion-error@2.0.1: {}
+
+ autoprefixer@10.4.20(postcss@8.4.49):
+ dependencies:
+ browserslist: 4.28.2
+ caniuse-lite: 1.0.30001793
+ fraction.js: 4.3.7
+ normalize-range: 0.1.2
+ picocolors: 1.1.1
+ postcss: 8.4.49
+ postcss-value-parser: 4.2.0
+
+ baseline-browser-mapping@2.10.32: {}
+
+ binary-extensions@2.3.0: {}
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ browserslist@4.28.2:
+ dependencies:
+ baseline-browser-mapping: 2.10.32
+ caniuse-lite: 1.0.30001793
+ electron-to-chromium: 1.5.361
+ node-releases: 2.0.46
+ update-browserslist-db: 1.2.3(browserslist@4.28.2)
+
+ cac@6.7.14: {}
+
+ camelcase-css@2.0.1: {}
+
+ caniuse-lite@1.0.30001793: {}
+
+ chai@5.3.3:
+ dependencies:
+ assertion-error: 2.0.1
+ check-error: 2.1.3
+ deep-eql: 5.0.2
+ loupe: 3.2.1
+ pathval: 2.0.1
+
+ chalk@3.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
+ check-error@2.1.3: {}
+
+ chokidar@3.6.0:
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.3
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ class-variance-authority@0.7.1:
+ dependencies:
+ clsx: 2.1.1
+
+ clsx@2.1.1: {}
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.4: {}
+
+ commander@4.1.1: {}
+
+ convert-source-map@2.0.0: {}
+
+ css.escape@1.5.1: {}
+
+ cssesc@3.0.0: {}
+
+ csstype@3.2.3: {}
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ deep-eql@5.0.2: {}
+
+ dequal@2.0.3: {}
+
+ detect-node-es@1.1.0: {}
+
+ didyoumean@1.2.2: {}
+
+ dlv@1.1.3: {}
+
+ dom-accessibility-api@0.5.16: {}
+
+ dom-accessibility-api@0.6.3: {}
+
+ electron-to-chromium@1.5.361: {}
+
+ entities@4.5.0: {}
+
+ es-errors@1.3.0: {}
+
+ es-module-lexer@1.7.0: {}
+
+ esbuild@0.21.5:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.21.5
+ '@esbuild/android-arm': 0.21.5
+ '@esbuild/android-arm64': 0.21.5
+ '@esbuild/android-x64': 0.21.5
+ '@esbuild/darwin-arm64': 0.21.5
+ '@esbuild/darwin-x64': 0.21.5
+ '@esbuild/freebsd-arm64': 0.21.5
+ '@esbuild/freebsd-x64': 0.21.5
+ '@esbuild/linux-arm': 0.21.5
+ '@esbuild/linux-arm64': 0.21.5
+ '@esbuild/linux-ia32': 0.21.5
+ '@esbuild/linux-loong64': 0.21.5
+ '@esbuild/linux-mips64el': 0.21.5
+ '@esbuild/linux-ppc64': 0.21.5
+ '@esbuild/linux-riscv64': 0.21.5
+ '@esbuild/linux-s390x': 0.21.5
+ '@esbuild/linux-x64': 0.21.5
+ '@esbuild/netbsd-x64': 0.21.5
+ '@esbuild/openbsd-x64': 0.21.5
+ '@esbuild/sunos-x64': 0.21.5
+ '@esbuild/win32-arm64': 0.21.5
+ '@esbuild/win32-ia32': 0.21.5
+ '@esbuild/win32-x64': 0.21.5
+
+ esbuild@0.23.1:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.23.1
+ '@esbuild/android-arm': 0.23.1
+ '@esbuild/android-arm64': 0.23.1
+ '@esbuild/android-x64': 0.23.1
+ '@esbuild/darwin-arm64': 0.23.1
+ '@esbuild/darwin-x64': 0.23.1
+ '@esbuild/freebsd-arm64': 0.23.1
+ '@esbuild/freebsd-x64': 0.23.1
+ '@esbuild/linux-arm': 0.23.1
+ '@esbuild/linux-arm64': 0.23.1
+ '@esbuild/linux-ia32': 0.23.1
+ '@esbuild/linux-loong64': 0.23.1
+ '@esbuild/linux-mips64el': 0.23.1
+ '@esbuild/linux-ppc64': 0.23.1
+ '@esbuild/linux-riscv64': 0.23.1
+ '@esbuild/linux-s390x': 0.23.1
+ '@esbuild/linux-x64': 0.23.1
+ '@esbuild/netbsd-x64': 0.23.1
+ '@esbuild/openbsd-arm64': 0.23.1
+ '@esbuild/openbsd-x64': 0.23.1
+ '@esbuild/sunos-x64': 0.23.1
+ '@esbuild/win32-arm64': 0.23.1
+ '@esbuild/win32-ia32': 0.23.1
+ '@esbuild/win32-x64': 0.23.1
+
+ escalade@3.2.0: {}
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.9
+
+ expect-type@1.3.0: {}
+
+ fast-glob@3.3.3:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
+ fastq@1.20.1:
+ dependencies:
+ reusify: 1.1.0
+
+ fdir@6.5.0(picomatch@4.0.4):
+ optionalDependencies:
+ picomatch: 4.0.4
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ fraction.js@4.3.7: {}
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ gensync@1.0.0-beta.2: {}
+
+ get-nonce@1.0.1: {}
+
+ get-tsconfig@4.14.0:
+ dependencies:
+ resolve-pkg-maps: 1.0.0
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-parent@6.0.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ happy-dom@15.11.7:
+ dependencies:
+ entities: 4.5.0
+ webidl-conversions: 7.0.0
+ whatwg-mimetype: 3.0.0
+
+ has-flag@4.0.0: {}
+
+ hasown@2.0.3:
+ dependencies:
+ function-bind: 1.1.2
+
+ indent-string@4.0.0: {}
+
+ is-binary-path@2.1.0:
+ dependencies:
+ binary-extensions: 2.3.0
+
+ is-core-module@2.16.2:
+ dependencies:
+ hasown: 2.0.3
+
+ is-extglob@2.1.1: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-number@7.0.0: {}
+
+ jiti@1.21.7: {}
+
+ js-tokens@4.0.0: {}
+
+ jsesc@3.1.0: {}
+
+ json5@2.2.3: {}
+
+ lilconfig@3.1.3: {}
+
+ lines-and-columns@1.2.4: {}
+
+ lodash@4.18.1: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ loupe@3.2.1: {}
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
+ lucide-react@0.468.0(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
+ lz-string@1.5.0: {}
+
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ merge2@1.4.1: {}
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.2
+
+ min-indent@1.0.1: {}
+
+ ms@2.1.3: {}
+
+ mz@2.7.0:
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+
+ nanoid@3.3.12: {}
+
+ node-releases@2.0.46: {}
+
+ normalize-path@3.0.0: {}
+
+ normalize-range@0.1.2: {}
+
+ object-assign@4.1.1: {}
+
+ object-hash@3.0.0: {}
+
+ path-parse@1.0.7: {}
+
+ pathe@1.1.2: {}
+
+ pathval@2.0.1: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@2.3.2: {}
+
+ picomatch@4.0.4: {}
+
+ pify@2.3.0: {}
+
+ pirates@4.0.7: {}
+
+ postcss-import@15.1.0(postcss@8.4.49):
+ dependencies:
+ postcss: 8.4.49
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.12
+
+ postcss-js@4.1.0(postcss@8.4.49):
+ dependencies:
+ camelcase-css: 2.0.1
+ postcss: 8.4.49
+
+ postcss-load-config@4.0.2(postcss@8.4.49):
+ dependencies:
+ lilconfig: 3.1.3
+ yaml: 2.9.0
+ optionalDependencies:
+ postcss: 8.4.49
+
+ postcss-nested@6.2.0(postcss@8.4.49):
+ dependencies:
+ postcss: 8.4.49
+ postcss-selector-parser: 6.1.2
+
+ postcss-selector-parser@6.1.2:
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ postcss-value-parser@4.2.0: {}
+
+ postcss@8.4.49:
+ dependencies:
+ nanoid: 3.3.12
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ pretty-format@27.5.1:
+ dependencies:
+ ansi-regex: 5.0.1
+ ansi-styles: 5.2.0
+ react-is: 17.0.2
+
+ queue-microtask@1.2.3: {}
+
+ react-dom@18.3.1(react@18.3.1):
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.3.1
+ scheduler: 0.23.2
+
+ react-is@17.0.2: {}
+
+ react-refresh@0.14.2: {}
+
+ react-remove-scroll-bar@2.3.8(@types/react@18.3.17)(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-style-singleton: 2.2.3(@types/react@18.3.17)(react@18.3.1)
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ react-remove-scroll@2.7.2(@types/react@18.3.17)(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-remove-scroll-bar: 2.3.8(@types/react@18.3.17)(react@18.3.1)
+ react-style-singleton: 2.2.3(@types/react@18.3.17)(react@18.3.1)
+ tslib: 2.8.1
+ use-callback-ref: 1.3.3(@types/react@18.3.17)(react@18.3.1)
+ use-sidecar: 1.1.3(@types/react@18.3.17)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ react-style-singleton@2.2.3(@types/react@18.3.17)(react@18.3.1):
+ dependencies:
+ get-nonce: 1.0.1
+ react: 18.3.1
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ react@18.3.1:
+ dependencies:
+ loose-envify: 1.4.0
+
+ read-cache@1.0.0:
+ dependencies:
+ pify: 2.3.0
+
+ readdirp@3.6.0:
+ dependencies:
+ picomatch: 2.3.2
+
+ redent@3.0.0:
+ dependencies:
+ indent-string: 4.0.0
+ strip-indent: 3.0.0
+
+ resolve-pkg-maps@1.0.0: {}
+
+ resolve@1.22.12:
+ dependencies:
+ es-errors: 1.3.0
+ is-core-module: 2.16.2
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ reusify@1.1.0: {}
+
+ rollup@4.60.4:
+ dependencies:
+ '@types/estree': 1.0.8
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.60.4
+ '@rollup/rollup-android-arm64': 4.60.4
+ '@rollup/rollup-darwin-arm64': 4.60.4
+ '@rollup/rollup-darwin-x64': 4.60.4
+ '@rollup/rollup-freebsd-arm64': 4.60.4
+ '@rollup/rollup-freebsd-x64': 4.60.4
+ '@rollup/rollup-linux-arm-gnueabihf': 4.60.4
+ '@rollup/rollup-linux-arm-musleabihf': 4.60.4
+ '@rollup/rollup-linux-arm64-gnu': 4.60.4
+ '@rollup/rollup-linux-arm64-musl': 4.60.4
+ '@rollup/rollup-linux-loong64-gnu': 4.60.4
+ '@rollup/rollup-linux-loong64-musl': 4.60.4
+ '@rollup/rollup-linux-ppc64-gnu': 4.60.4
+ '@rollup/rollup-linux-ppc64-musl': 4.60.4
+ '@rollup/rollup-linux-riscv64-gnu': 4.60.4
+ '@rollup/rollup-linux-riscv64-musl': 4.60.4
+ '@rollup/rollup-linux-s390x-gnu': 4.60.4
+ '@rollup/rollup-linux-x64-gnu': 4.60.4
+ '@rollup/rollup-linux-x64-musl': 4.60.4
+ '@rollup/rollup-openbsd-x64': 4.60.4
+ '@rollup/rollup-openharmony-arm64': 4.60.4
+ '@rollup/rollup-win32-arm64-msvc': 4.60.4
+ '@rollup/rollup-win32-ia32-msvc': 4.60.4
+ '@rollup/rollup-win32-x64-gnu': 4.60.4
+ '@rollup/rollup-win32-x64-msvc': 4.60.4
+ fsevents: 2.3.3
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ scheduler@0.23.2:
+ dependencies:
+ loose-envify: 1.4.0
+
+ semver@6.3.1: {}
+
+ siginfo@2.0.0: {}
+
+ source-map-js@1.2.1: {}
+
+ stackback@0.0.2: {}
+
+ std-env@3.10.0: {}
+
+ strip-indent@3.0.0:
+ dependencies:
+ min-indent: 1.0.1
+
+ sucrase@3.35.1:
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ commander: 4.1.1
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.7
+ tinyglobby: 0.2.16
+ ts-interface-checker: 0.1.13
+
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
+ supports-preserve-symlinks-flag@1.0.0: {}
+
+ tailwind-merge@2.6.0: {}
+
+ tailwindcss@3.4.17:
+ dependencies:
+ '@alloc/quick-lru': 5.2.0
+ arg: 5.0.2
+ chokidar: 3.6.0
+ didyoumean: 1.2.2
+ dlv: 1.1.3
+ fast-glob: 3.3.3
+ glob-parent: 6.0.2
+ is-glob: 4.0.3
+ jiti: 1.21.7
+ lilconfig: 3.1.3
+ micromatch: 4.0.8
+ normalize-path: 3.0.0
+ object-hash: 3.0.0
+ picocolors: 1.1.1
+ postcss: 8.4.49
+ postcss-import: 15.1.0(postcss@8.4.49)
+ postcss-js: 4.1.0(postcss@8.4.49)
+ postcss-load-config: 4.0.2(postcss@8.4.49)
+ postcss-nested: 6.2.0(postcss@8.4.49)
+ postcss-selector-parser: 6.1.2
+ resolve: 1.22.12
+ sucrase: 3.35.1
+ transitivePeerDependencies:
+ - ts-node
+
+ thenify-all@1.6.0:
+ dependencies:
+ thenify: 3.3.1
+
+ thenify@3.3.1:
+ dependencies:
+ any-promise: 1.3.0
+
+ tinybench@2.9.0: {}
+
+ tinyexec@0.3.2: {}
+
+ tinyglobby@0.2.16:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.4)
+ picomatch: 4.0.4
+
+ tinypool@1.1.1: {}
+
+ tinyrainbow@1.2.0: {}
+
+ tinyspy@3.0.2: {}
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ ts-interface-checker@0.1.13: {}
+
+ tslib@2.8.1: {}
+
+ tsx@4.19.2:
+ dependencies:
+ esbuild: 0.23.1
+ get-tsconfig: 4.14.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ typescript@5.7.2: {}
+
+ undici-types@6.20.0: {}
+
+ update-browserslist-db@1.2.3(browserslist@4.28.2):
+ dependencies:
+ browserslist: 4.28.2
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
+ use-callback-ref@1.3.3(@types/react@18.3.17)(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ use-sidecar@1.1.3(@types/react@18.3.17)(react@18.3.1):
+ dependencies:
+ detect-node-es: 1.1.0
+ react: 18.3.1
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 18.3.17
+
+ util-deprecate@1.0.2: {}
+
+ vite-node@2.1.8(@types/node@22.10.2):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.3
+ es-module-lexer: 1.7.0
+ pathe: 1.1.2
+ vite: 5.4.11(@types/node@22.10.2)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
+ vite@5.4.11(@types/node@22.10.2):
+ dependencies:
+ esbuild: 0.21.5
+ postcss: 8.4.49
+ rollup: 4.60.4
+ optionalDependencies:
+ '@types/node': 22.10.2
+ fsevents: 2.3.3
+
+ vitest@2.1.8(@types/node@22.10.2)(happy-dom@15.11.7):
+ dependencies:
+ '@vitest/expect': 2.1.8
+ '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.2))
+ '@vitest/pretty-format': 2.1.9
+ '@vitest/runner': 2.1.8
+ '@vitest/snapshot': 2.1.8
+ '@vitest/spy': 2.1.8
+ '@vitest/utils': 2.1.8
+ chai: 5.3.3
+ debug: 4.4.3
+ expect-type: 1.3.0
+ magic-string: 0.30.21
+ pathe: 1.1.2
+ std-env: 3.10.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinypool: 1.1.1
+ tinyrainbow: 1.2.0
+ vite: 5.4.11(@types/node@22.10.2)
+ vite-node: 2.1.8(@types/node@22.10.2)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/node': 22.10.2
+ happy-dom: 15.11.7
+ transitivePeerDependencies:
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
+ webidl-conversions@7.0.0: {}
+
+ whatwg-mimetype@3.0.0: {}
+
+ why-is-node-running@2.3.0:
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
+
+ yallist@3.1.1: {}
+
+ yaml@2.9.0: {}
diff --git a/workbench-ui/postcss.config.js b/workbench-ui/postcss.config.js
new file mode 100644
index 00000000..2aa7205d
--- /dev/null
+++ b/workbench-ui/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/workbench-ui/preview/README.md b/workbench-ui/preview/README.md
new file mode 100644
index 00000000..1cf46de6
--- /dev/null
+++ b/workbench-ui/preview/README.md
@@ -0,0 +1,8 @@
+# Preview
+
+The Vite route at `/preview` renders the Branch 1 design substrate.
+
+```bash
+pnpm build
+pnpm preview
+```
diff --git a/workbench-ui/preview/preview.png b/workbench-ui/preview/preview.png
new file mode 100644
index 00000000..6c57c90e
Binary files /dev/null and b/workbench-ui/preview/preview.png differ
diff --git a/workbench-ui/public/fonts/Inter-Regular.woff2 b/workbench-ui/public/fonts/Inter-Regular.woff2
new file mode 100644
index 00000000..5a8d3e72
Binary files /dev/null and b/workbench-ui/public/fonts/Inter-Regular.woff2 differ
diff --git a/workbench-ui/public/fonts/JetBrainsMono-Regular.woff2 b/workbench-ui/public/fonts/JetBrainsMono-Regular.woff2
new file mode 100644
index 00000000..66c54672
Binary files /dev/null and b/workbench-ui/public/fonts/JetBrainsMono-Regular.woff2 differ
diff --git a/workbench-ui/scripts/generate-tokens.ts b/workbench-ui/scripts/generate-tokens.ts
new file mode 100644
index 00000000..a07b38be
--- /dev/null
+++ b/workbench-ui/scripts/generate-tokens.ts
@@ -0,0 +1,22 @@
+import { readFileSync, writeFileSync } from "node:fs";
+import { dirname, resolve } from "node:path";
+import { fileURLToPath } from "node:url";
+
+const here = dirname(fileURLToPath(import.meta.url));
+const cssPath = resolve(here, "../src/design/tokens/tokens.css");
+const outPath = resolve(here, "../src/design/tokens/tokens.ts");
+
+const css = readFileSync(cssPath, "utf8");
+const tokenMatches = [...css.matchAll(/--([a-z0-9-]+):\s*([^;]+);/g)];
+const tokens = Object.fromEntries(
+ tokenMatches.map(([, name, value]) => [name, value.trim()]),
+);
+
+const body = `// Generated by scripts/generate-tokens.ts. Do not edit by hand.
+export const tokens = ${JSON.stringify(tokens, null, 2)} as const;
+
+export type DesignTokenName = keyof typeof tokens;
+export type DesignTokenValue = (typeof tokens)[DesignTokenName];
+`;
+
+writeFileSync(outPath, body);
diff --git a/workbench-ui/src/design/components/StableJsonViewer/StableJsonViewer.test.tsx b/workbench-ui/src/design/components/StableJsonViewer/StableJsonViewer.test.tsx
new file mode 100644
index 00000000..961d1289
--- /dev/null
+++ b/workbench-ui/src/design/components/StableJsonViewer/StableJsonViewer.test.tsx
@@ -0,0 +1,88 @@
+import { render, screen, waitFor, within } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { describe, expect, it } from "vitest";
+import { StableJsonViewer } from "./StableJsonViewer";
+import { diffLeaves, leaves, parseJsonSource } from "./jsonModel";
+
+async function sha256Hex(source: string): Promise {
+ const bytes = new TextEncoder().encode(source);
+ const hash = await crypto.subtle.digest("SHA-256", bytes);
+ return [...new Uint8Array(hash)].map((b) => b.toString(16).padStart(2, "0")).join("");
+}
+
+describe("StableJsonViewer invariants", () => {
+ it("renders object keys in deterministic lexicographic order", () => {
+ render();
+ const rows = within(screen.getByTestId("json-rows")).getAllByRole("button");
+ expect(rows.map((row) => row.textContent)).toEqual(["/a 2", "/z 1"]);
+ });
+
+ it("preserves source string bytes without smart quotes or entity coercion", () => {
+ const source = "{\"quote\":\"a \\\"raw\\\" & \"}";
+ render();
+ expect(screen.getByText(/"a \\"raw\\" & "/)).toBeInTheDocument();
+ });
+
+ it("preserves numeric notation and int/float distinction", () => {
+ render();
+ expect(screen.getByText((_, node) => node?.textContent === "/epsilon 1e-6")).toBeInTheDocument();
+ expect(screen.getByText((_, node) => node?.textContent === "/int 1")).toBeInTheDocument();
+ expect(screen.getByText((_, node) => node?.textContent === "/float 1.0")).toBeInTheDocument();
+ });
+
+ it("copy-path returns a JSON Pointer", async () => {
+ const user = userEvent.setup();
+ const writeText = vi.fn().mockResolvedValue(undefined);
+ Object.defineProperty(navigator, "clipboard", {
+ configurable: true,
+ value: { writeText },
+ });
+ render();
+ await user.click(screen.getByText(/\/scenes\/3\/detail\/object/));
+ expect(writeText).toHaveBeenCalledWith("/scenes/3/detail/object");
+ });
+
+ it("diff mode is side-by-side and marks only changed leaves with glyphs", () => {
+ render();
+ expect(screen.getByTestId("json-diff")).toBeInTheDocument();
+ expect(screen.getAllByLabelText("changed")).toHaveLength(2);
+ expect(screen.getAllByLabelText("added")).toHaveLength(2);
+ expect(screen.getAllByLabelText("same")).toHaveLength(2);
+
+ const modelDiff = diffLeaves(leaves(parseJsonSource('{"a":1}')), leaves(parseJsonSource('{"a":2}')));
+ expect(modelDiff).toMatchObject([{ pointer: "/a", kind: "changed" }]);
+ });
+
+ it("virtualizes large documents and refuses inline render above 16 MiB", () => {
+ const manyLeaves = `{"items":[${Array.from({ length: 1001 }, (_, i) => i).join(",")}]}`;
+ const { rerender } = render();
+ expect(screen.getByTestId("virtualized-json")).toHaveTextContent("virtualized 1000 of 1001 leaves");
+
+ rerender();
+ expect(screen.getByText(/larger than 16 MiB/)).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: /Open in external viewer/ })).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: /Copy path/ })).toBeInTheDocument();
+ });
+
+ it("renders a sha256 digest badge over the source bytes and copies the full digest on click", async () => {
+ const user = userEvent.setup();
+ const writeText = vi.fn().mockResolvedValue(undefined);
+ Object.defineProperty(navigator, "clipboard", {
+ configurable: true,
+ value: { writeText },
+ });
+ const source = '{"a":1}';
+ const expectedDigest = await sha256Hex(source);
+
+ render();
+
+ const digestButton = await screen.findByRole("button", { name: /sha256:/ });
+ // The badge displays the truncated prefix.
+ await waitFor(() => {
+ expect(digestButton.textContent).toBe(`sha256:${expectedDigest.slice(0, 12)}`);
+ });
+ // Clicking the badge copies the FULL digest, not the truncated prefix.
+ await user.click(digestButton);
+ expect(writeText).toHaveBeenCalledWith(expectedDigest);
+ });
+});
diff --git a/workbench-ui/src/design/components/StableJsonViewer/StableJsonViewer.tsx b/workbench-ui/src/design/components/StableJsonViewer/StableJsonViewer.tsx
new file mode 100644
index 00000000..a81102de
--- /dev/null
+++ b/workbench-ui/src/design/components/StableJsonViewer/StableJsonViewer.tsx
@@ -0,0 +1,136 @@
+import { Copy, ExternalLink } from "lucide-react";
+import { useEffect, useMemo, useState } from "react";
+import { Button } from "../primitives/Button";
+import { copyText, cn } from "../../lib";
+import { countLeaves, diffLeaves, leaves, parseJsonSource, type DiffKind, type JsonNode } from "./jsonModel";
+
+const MAX_INLINE_BYTES = 16 * 1024 * 1024;
+const VIRTUALIZE_LEAVES = 1000;
+
+function bytes(source: string) {
+ return new TextEncoder().encode(source);
+}
+
+async function sha256(source: string) {
+ const hash = await crypto.subtle.digest("SHA-256", bytes(source));
+ return [...new Uint8Array(hash)].map((b) => b.toString(16).padStart(2, "0")).join("");
+}
+
+function nodeRows(node: JsonNode, pointer = "", depth = 0): { pointer: string; depth: number; label: string; raw?: string }[] {
+ if (node.kind === "literal") return [{ pointer, depth, label: pointer.split("/").at(-1) || "/", raw: node.raw }];
+ if (node.kind === "array") {
+ return node.items.flatMap((item, index) => nodeRows(item, `${pointer}/${index}`, depth + 1));
+ }
+ return node.entries.flatMap((entry) => nodeRows(entry.value, `${pointer}/${entry.key.replaceAll("~", "~0").replaceAll("/", "~1")}`, depth + 1));
+}
+
+function DigestBadge({ source }: { source: string }) {
+ const [digest, setDigest] = useState("");
+ useEffect(() => {
+ void sha256(source).then(setDigest);
+ }, [source]);
+ return (
+
+ );
+}
+
+function ChangeGlyph({ kind }: { kind: DiffKind }) {
+ const glyph = kind === "added" ? "+" : kind === "removed" ? "-" : kind === "changed" ? "~" : " ";
+ return {glyph};
+}
+
+export function StableJsonViewer({
+ source,
+ compareSource,
+}: {
+ source: string;
+ compareSource?: string;
+}) {
+ const rawBytes = bytes(source).byteLength;
+ const parsed = useMemo(() => (rawBytes <= MAX_INLINE_BYTES ? parseJsonSource(source) : null), [rawBytes, source]);
+ const leafCount = parsed ? countLeaves(parsed) : 0;
+
+ if (rawBytes > MAX_INLINE_BYTES) {
+ return (
+
+
+
+
+ JSON is larger than 16 MiB and was not rendered inline.
+
+
+
+ );
+ }
+
+ if (compareSource) {
+ const right = parseJsonSource(compareSource);
+ const rows = diffLeaves(leaves(parsed!), leaves(right));
+ return (
+
+
+
+ diff mode
+
+
+ {rows.map((row) => (
+
+
+
+
+ ))}
+
+
+ );
+ }
+
+ const rows = nodeRows(parsed!);
+ const visibleRows = leafCount > VIRTUALIZE_LEAVES ? rows.slice(0, VIRTUALIZE_LEAVES) : rows;
+ return (
+
+
+
+ {leafCount > VIRTUALIZE_LEAVES ? virtualized {VIRTUALIZE_LEAVES} of {leafCount} leaves : null}
+
+
+ {visibleRows.map((row) => (
+
+ ))}
+
+
+ );
+}
diff --git a/workbench-ui/src/design/components/StableJsonViewer/index.ts b/workbench-ui/src/design/components/StableJsonViewer/index.ts
new file mode 100644
index 00000000..eaabb8c7
--- /dev/null
+++ b/workbench-ui/src/design/components/StableJsonViewer/index.ts
@@ -0,0 +1,2 @@
+export { StableJsonViewer } from "./StableJsonViewer";
+export { parseJsonSource, leaves, diffLeaves } from "./jsonModel";
diff --git a/workbench-ui/src/design/components/StableJsonViewer/jsonModel.ts b/workbench-ui/src/design/components/StableJsonViewer/jsonModel.ts
new file mode 100644
index 00000000..bdcba06e
--- /dev/null
+++ b/workbench-ui/src/design/components/StableJsonViewer/jsonModel.ts
@@ -0,0 +1,155 @@
+export type JsonNode =
+ | { kind: "object"; entries: { key: string; keyRaw: string; value: JsonNode }[] }
+ | { kind: "array"; items: JsonNode[] }
+ | { kind: "literal"; raw: string; valueKind: "string" | "number" | "boolean" | "null" };
+
+export type Leaf = { pointer: string; raw: string; valueKind: string };
+
+class Parser {
+ private index = 0;
+
+ constructor(private readonly source: string) {}
+
+ parse(): JsonNode {
+ this.ws();
+ const node = this.value();
+ this.ws();
+ if (this.index !== this.source.length) throw new Error("Unexpected trailing JSON content.");
+ return node;
+ }
+
+ private value(): JsonNode {
+ this.ws();
+ const ch = this.source[this.index];
+ if (ch === "{") return this.object();
+ if (ch === "[") return this.array();
+ if (ch === '"') return { kind: "literal", raw: this.stringRaw(), valueKind: "string" };
+ if (ch === "-" || /\d/.test(ch)) return { kind: "literal", raw: this.numberRaw(), valueKind: "number" };
+ for (const word of ["true", "false", "null"] as const) {
+ if (this.source.startsWith(word, this.index)) {
+ this.index += word.length;
+ return { kind: "literal", raw: word, valueKind: word === "null" ? "null" : "boolean" };
+ }
+ }
+ throw new Error(`Unexpected JSON token at ${this.index}.`);
+ }
+
+ private object(): JsonNode {
+ this.index++;
+ this.ws();
+ const entries: { key: string; keyRaw: string; value: JsonNode }[] = [];
+ if (this.source[this.index] === "}") {
+ this.index++;
+ return { kind: "object", entries };
+ }
+ while (this.index < this.source.length) {
+ const keyRaw = this.stringRaw();
+ const key = JSON.parse(keyRaw) as string;
+ this.ws();
+ this.expect(":");
+ const value = this.value();
+ entries.push({ key, keyRaw, value });
+ this.ws();
+ if (this.source[this.index] === "}") {
+ this.index++;
+ break;
+ }
+ this.expect(",");
+ this.ws();
+ }
+ entries.sort((a, b) => a.key.localeCompare(b.key));
+ return { kind: "object", entries };
+ }
+
+ private array(): JsonNode {
+ this.index++;
+ this.ws();
+ const items: JsonNode[] = [];
+ if (this.source[this.index] === "]") {
+ this.index++;
+ return { kind: "array", items };
+ }
+ while (this.index < this.source.length) {
+ items.push(this.value());
+ this.ws();
+ if (this.source[this.index] === "]") {
+ this.index++;
+ break;
+ }
+ this.expect(",");
+ this.ws();
+ }
+ return { kind: "array", items };
+ }
+
+ private stringRaw(): string {
+ const start = this.index;
+ this.expect('"');
+ while (this.index < this.source.length) {
+ const ch = this.source[this.index++];
+ if (ch === "\\") {
+ this.index++;
+ } else if (ch === '"') {
+ return this.source.slice(start, this.index);
+ }
+ }
+ throw new Error("Unterminated string.");
+ }
+
+ private numberRaw(): string {
+ const start = this.index;
+ if (this.source[this.index] === "-") this.index++;
+ while (/\d/.test(this.source[this.index] ?? "")) this.index++;
+ if (this.source[this.index] === ".") {
+ this.index++;
+ while (/\d/.test(this.source[this.index] ?? "")) this.index++;
+ }
+ if ((this.source[this.index] ?? "").toLowerCase() === "e") {
+ this.index++;
+ if (["+", "-"].includes(this.source[this.index] ?? "")) this.index++;
+ while (/\d/.test(this.source[this.index] ?? "")) this.index++;
+ }
+ return this.source.slice(start, this.index);
+ }
+
+ private ws() {
+ while (/\s/.test(this.source[this.index] ?? "")) this.index++;
+ }
+
+ private expect(ch: string) {
+ if (this.source[this.index] !== ch) throw new Error(`Expected ${ch} at ${this.index}.`);
+ this.index++;
+ }
+}
+
+export function parseJsonSource(source: string): JsonNode {
+ return new Parser(source).parse();
+}
+
+export function pointerPart(value: string) {
+ return value.replaceAll("~", "~0").replaceAll("/", "~1");
+}
+
+export function leaves(node: JsonNode, pointer = ""): Leaf[] {
+ if (node.kind === "literal") return [{ pointer, raw: node.raw, valueKind: node.valueKind }];
+ if (node.kind === "array") return node.items.flatMap((item, index) => leaves(item, `${pointer}/${index}`));
+ return node.entries.flatMap((entry) => leaves(entry.value, `${pointer}/${pointerPart(entry.key)}`));
+}
+
+export function countLeaves(node: JsonNode) {
+ return leaves(node).length;
+}
+
+export type DiffKind = "added" | "removed" | "changed" | "same";
+
+export function diffLeaves(left: Leaf[], right: Leaf[]) {
+ const l = new Map(left.map((leaf) => [leaf.pointer, leaf]));
+ const r = new Map(right.map((leaf) => [leaf.pointer, leaf]));
+ const pointers = [...new Set([...l.keys(), ...r.keys()])].toSorted();
+ return pointers.map((pointer) => {
+ const before = l.get(pointer);
+ const after = r.get(pointer);
+ const kind: DiffKind = before && after ? (before.raw === after.raw ? "same" : "changed") : before ? "removed" : "added";
+ return { pointer, before, after, kind };
+ });
+}
diff --git a/workbench-ui/src/design/components/badges/Badge.tsx b/workbench-ui/src/design/components/badges/Badge.tsx
new file mode 100644
index 00000000..bb79a0b9
--- /dev/null
+++ b/workbench-ui/src/design/components/badges/Badge.tsx
@@ -0,0 +1,67 @@
+import * as Popover from "@radix-ui/react-popover";
+import { Copy } from "lucide-react";
+import type { CSSProperties } from "react";
+import { copyText, cn } from "../../lib";
+
+export function InfoBadge({
+ label,
+ colorToken,
+ meaning,
+ adr,
+ evidence,
+ mono = false,
+ onCopy,
+}: {
+ label: string;
+ colorToken: string;
+ meaning: string;
+ adr: string;
+ evidence: string;
+ mono?: boolean;
+ onCopy?: string;
+}) {
+ const style = {
+ backgroundColor: `color-mix(in srgb, var(${colorToken}) 18%, transparent)`,
+ borderColor: `var(${colorToken})`,
+ color: `var(${colorToken})`,
+ } as CSSProperties;
+
+ return (
+
+
+ {label}
+
+
+
+ {label}
+ {meaning}
+
+ - Pinned by
+ - {adr}
+ - Evidence example
+ - {evidence}
+
+ {onCopy ? (
+
+ ) : null}
+
+
+
+ );
+}
diff --git a/workbench-ui/src/design/components/badges/enumCoverage.test.ts b/workbench-ui/src/design/components/badges/enumCoverage.test.ts
new file mode 100644
index 00000000..52d1ae8b
--- /dev/null
+++ b/workbench-ui/src/design/components/badges/enumCoverage.test.ts
@@ -0,0 +1,46 @@
+import { describe, expect, it } from "vitest";
+import snapshot from "../../../../enum-snapshot.json";
+import {
+ epistemicStateMeta,
+ groundingSourceMeta,
+ normativeClearanceMeta,
+ reviewStateMeta,
+} from "./mappings";
+
+function expectExactCoverage(name: string, engineValues: string[], uiValues: string[]) {
+ expect(
+ uiValues.toSorted(),
+ `${name} badge mapping must exactly match engine enum values`,
+ ).toEqual(engineValues.toSorted());
+ expect(new Set(uiValues).size, `${name} badge mapping has duplicate values`).toBe(uiValues.length);
+}
+
+describe("build-time enum coverage", () => {
+ it("tracks every ratified EpistemicState value exactly once", () => {
+ expectExactCoverage(
+ "EpistemicState",
+ snapshot.EpistemicState,
+ Object.keys(epistemicStateMeta),
+ );
+ });
+
+ it("tracks every ratified NormativeClearance value exactly once", () => {
+ expectExactCoverage(
+ "NormativeClearance",
+ snapshot.NormativeClearance,
+ Object.keys(normativeClearanceMeta),
+ );
+ });
+
+ it("tracks every ratified ReviewState value exactly once", () => {
+ expectExactCoverage("ReviewState", snapshot.ReviewState, Object.keys(reviewStateMeta));
+ });
+
+ it("tracks every ratified GroundingSource value exactly once", () => {
+ expectExactCoverage(
+ "GroundingSource",
+ snapshot.GroundingSource,
+ Object.keys(groundingSourceMeta),
+ );
+ });
+});
diff --git a/workbench-ui/src/design/components/badges/index.tsx b/workbench-ui/src/design/components/badges/index.tsx
new file mode 100644
index 00000000..f2ec8562
--- /dev/null
+++ b/workbench-ui/src/design/components/badges/index.tsx
@@ -0,0 +1,47 @@
+import {
+ epistemicStateMeta,
+ groundingSourceMeta,
+ normativeClearanceMeta,
+ reviewStateMeta,
+} from "./mappings";
+import { InfoBadge } from "./Badge";
+import { EpistemicState, GroundingSource, NormativeClearance, ReviewState } from "./types";
+
+export { EpistemicState, GroundingSource, NormativeClearance, ReviewState };
+
+export function EpistemicStateBadge({ value }: { value: EpistemicState }) {
+ return ;
+}
+
+export function NormativeClearanceBadge({ value }: { value: NormativeClearance }) {
+ return ;
+}
+
+export function ReviewStateBadge({ value }: { value: ReviewState }) {
+ return ;
+}
+
+export function GroundingSourceBadge({ value }: { value: GroundingSource }) {
+ return ;
+}
+
+export function TraceHashBadge({
+ value,
+ truncate = 12,
+}: {
+ value: string;
+ truncate?: number;
+}) {
+ const label = value.slice(0, truncate);
+ return (
+
+ );
+}
diff --git a/workbench-ui/src/design/components/badges/mappings.ts b/workbench-ui/src/design/components/badges/mappings.ts
new file mode 100644
index 00000000..2f7f1a4d
--- /dev/null
+++ b/workbench-ui/src/design/components/badges/mappings.ts
@@ -0,0 +1,48 @@
+import {
+ EpistemicState,
+ GroundingSource,
+ NormativeClearance,
+ ReviewState,
+ type BadgeMeta,
+} from "./types";
+
+export const epistemicStateMeta = {
+ [EpistemicState.PERCEIVED]: { label: "Perceived", colorToken: "--color-state-perceived", meaning: "Observed at the surface but not yet independently evidenced.", adr: "ADR-0142 / ADR-0162", evidence: "A trace carries raw input evidence." },
+ [EpistemicState.EVIDENCED]: { label: "Evidenced", colorToken: "--color-state-evidenced", meaning: "Supported by explicit evidence.", adr: "ADR-0142 / ADR-0162", evidence: "A proposition cites a supporting artifact." },
+ [EpistemicState.EVIDENCED_INCOMPLETE]: { label: "Evidenced incomplete", colorToken: "--color-state-evidenced-muted", meaning: "Some evidence exists, but coverage is partial.", adr: "ADR-0142 / ADR-0162", evidence: "Grounding source is partial." },
+ [EpistemicState.VERIFIED]: { label: "Verified", colorToken: "--color-state-verified", meaning: "Checked against an authoritative deterministic lane.", adr: "ADR-0142 / ADR-0162", evidence: "Replay hash matches original." },
+ [EpistemicState.DECODED]: { label: "Decoded", colorToken: "--color-state-decoded", meaning: "Mapped through ratified semantic structure.", adr: "ADR-0142 / ADR-0162", evidence: "Grounding source is pack, teaching, or vault." },
+ [EpistemicState.DECODED_UNARTICULATED]: { label: "Decoded unarticulated", colorToken: "--color-state-decoded-muted", meaning: "Structured internally but not surfaced.", adr: "ADR-0142 / ADR-0162", evidence: "Graph node exists without realized sentence." },
+ [EpistemicState.INFERRED]: { label: "Inferred", colorToken: "--color-state-inferred", meaning: "Derived from available structure.", adr: "ADR-0142 / ADR-0162", evidence: "Planner derives a relation from linked propositions." },
+ [EpistemicState.UNVERIFIED_POSSIBLE]: { label: "Unverified possible", colorToken: "--color-state-unverified", meaning: "Plausible but not verified.", adr: "ADR-0142 / ADR-0162", evidence: "Candidate has no ratified support yet." },
+ [EpistemicState.UNVERIFIED_NOVEL]: { label: "Unverified novel", colorToken: "--color-state-unverified-warm", meaning: "New or OOV content without ratified grounding.", adr: "ADR-0142 / ADR-0162", evidence: "Grounding source is oov." },
+ [EpistemicState.CONTRADICTED]: { label: "Contradicted", colorToken: "--color-state-contradicted", meaning: "Evidence conflicts with the proposition.", adr: "ADR-0142 / ADR-0162", evidence: "A boundary or claim rejects the assertion." },
+ [EpistemicState.AMBIGUOUS]: { label: "Ambiguous", colorToken: "--color-state-ambiguous", meaning: "Multiple readings remain live.", adr: "ADR-0142 / ADR-0162", evidence: "Parser retains competing interpretations." },
+ [EpistemicState.UNDETERMINED]: { label: "Undetermined", colorToken: "--color-state-undetermined", meaning: "No stronger epistemic state is justified.", adr: "ADR-0142 / ADR-0162", evidence: "No grounding source is present." },
+ [EpistemicState.SCOPE_BOUNDARY]: { label: "Scope boundary", colorToken: "--color-state-scope", meaning: "The claim is outside the active scope.", adr: "ADR-0142 / ADR-0162", evidence: "Runtime declines to classify beyond scope." },
+ [EpistemicState.COMPUTATIONALLY_BOUNDED]: { label: "Computationally bounded", colorToken: "--color-state-bounded", meaning: "The answer is limited by bounded computation.", adr: "ADR-0142 / ADR-0162", evidence: "Eval lane reports a bounded operator." },
+ [EpistemicState.EPISTEMIC_STATE_NEEDED]: { label: "State needed", colorToken: "--color-state-needed", meaning: "A missing state must be assigned before trust display.", adr: "ADR-0142 / ADR-0162", evidence: "Unknown grounding source reached UI mapping." },
+} satisfies BadgeMeta;
+
+export const normativeClearanceMeta = {
+ [NormativeClearance.CLEARED]: { label: "Cleared", colorToken: "--color-clearance-cleared", meaning: "Runtime-checkable normative gates passed.", adr: "ADR-0142 / ADR-0162", evidence: "Safety and ethics verdicts upheld." },
+ [NormativeClearance.VIOLATED]: { label: "Violated", colorToken: "--color-clearance-violated", meaning: "A runtime-checkable boundary failed.", adr: "ADR-0142 / ADR-0162", evidence: "Boundary id appears in normative detail." },
+ [NormativeClearance.UNASSESSABLE]: { label: "Unassessable", colorToken: "--color-clearance-unassessable", meaning: "No positive clearance can be asserted.", adr: "ADR-0142 / ADR-0162", evidence: "No runtime-checkable verdict exists." },
+ [NormativeClearance.SUPPRESSED]: { label: "Suppressed", colorToken: "--color-clearance-suppressed", meaning: "A refusal surface replaced unsafe output.", adr: "ADR-0142 / ADR-0162", evidence: "refusal_emitted is true." },
+} satisfies BadgeMeta;
+
+export const reviewStateMeta = {
+ [ReviewState.PENDING]: { label: "Pending", colorToken: "--color-review-pending", meaning: "Proposal awaits operator review.", adr: "ADR-0057 / ADR-0161 / ADR-0162", evidence: "No terminal transition exists." },
+ [ReviewState.ACCEPTED]: { label: "Accepted", colorToken: "--color-review-accepted", meaning: "Operator ratified the proposal.", adr: "ADR-0057 / ADR-0161 / ADR-0162", evidence: "transition.to is accepted." },
+ [ReviewState.REJECTED]: { label: "Rejected", colorToken: "--color-review-rejected", meaning: "Operator rejected the proposal.", adr: "ADR-0057 / ADR-0161 / ADR-0162", evidence: "transition.to is rejected." },
+ [ReviewState.WITHDRAWN]: { label: "Withdrawn", colorToken: "--color-review-withdrawn", meaning: "Proposal was withdrawn without ratification.", adr: "ADR-0057 / ADR-0161 / ADR-0162", evidence: "transition.to is withdrawn." },
+} satisfies BadgeMeta;
+
+export const groundingSourceMeta = {
+ [GroundingSource.PACK]: { label: "Pack", colorToken: "--color-grounding-pack", meaning: "Grounded in a curated semantic pack.", adr: "ADR-0160 / ADR-0162", evidence: "grounding_source is pack." },
+ [GroundingSource.TEACHING]: { label: "Teaching", colorToken: "--color-grounding-teaching", meaning: "Grounded in reviewed teaching memory.", adr: "ADR-0160 / ADR-0162", evidence: "grounding_source is teaching." },
+ [GroundingSource.VAULT]: { label: "Vault", colorToken: "--color-grounding-vault", meaning: "Grounded in deterministic vault recall.", adr: "ADR-0160 / ADR-0162", evidence: "grounding_source is vault." },
+ [GroundingSource.PARTIAL]: { label: "Partial", colorToken: "--color-grounding-partial", meaning: "Only partial grounding was available.", adr: "ADR-0160 / ADR-0162", evidence: "grounding_source is partial." },
+ [GroundingSource.OOV]: { label: "OOV", colorToken: "--color-grounding-oov", meaning: "Out-of-vocabulary grounding was encountered.", adr: "ADR-0160 / ADR-0162", evidence: "grounding_source is oov." },
+ [GroundingSource.NONE]: { label: "None", colorToken: "--color-grounding-none", meaning: "No grounding source was present.", adr: "ADR-0160 / ADR-0162", evidence: "grounding_source is none." },
+} satisfies BadgeMeta;
diff --git a/workbench-ui/src/design/components/badges/types.ts b/workbench-ui/src/design/components/badges/types.ts
new file mode 100644
index 00000000..7b895820
--- /dev/null
+++ b/workbench-ui/src/design/components/badges/types.ts
@@ -0,0 +1,51 @@
+export enum EpistemicState {
+ PERCEIVED = "perceived",
+ EVIDENCED = "evidenced",
+ EVIDENCED_INCOMPLETE = "evidenced_incomplete",
+ VERIFIED = "verified",
+ DECODED = "decoded",
+ DECODED_UNARTICULATED = "decoded_unarticulated",
+ INFERRED = "inferred",
+ UNVERIFIED_POSSIBLE = "unverified_possible",
+ UNVERIFIED_NOVEL = "unverified_novel",
+ CONTRADICTED = "contradicted",
+ AMBIGUOUS = "ambiguous",
+ UNDETERMINED = "undetermined",
+ SCOPE_BOUNDARY = "scope_boundary",
+ COMPUTATIONALLY_BOUNDED = "computationally_bounded",
+ EPISTEMIC_STATE_NEEDED = "epistemic_state_needed",
+}
+
+export enum NormativeClearance {
+ CLEARED = "cleared",
+ VIOLATED = "violated",
+ UNASSESSABLE = "unassessable",
+ SUPPRESSED = "suppressed",
+}
+
+export enum ReviewState {
+ PENDING = "pending",
+ ACCEPTED = "accepted",
+ REJECTED = "rejected",
+ WITHDRAWN = "withdrawn",
+}
+
+export enum GroundingSource {
+ PACK = "pack",
+ TEACHING = "teaching",
+ VAULT = "vault",
+ PARTIAL = "partial",
+ OOV = "oov",
+ NONE = "none",
+}
+
+export type BadgeMeta = Record<
+ T,
+ {
+ label: string;
+ colorToken: string;
+ meaning: string;
+ adr: string;
+ evidence: string;
+ }
+>;
diff --git a/workbench-ui/src/design/components/primitives/Button.tsx b/workbench-ui/src/design/components/primitives/Button.tsx
new file mode 100644
index 00000000..b0a0b9f6
--- /dev/null
+++ b/workbench-ui/src/design/components/primitives/Button.tsx
@@ -0,0 +1,30 @@
+import { Slot } from "@radix-ui/react-slot";
+import { cva, type VariantProps } from "class-variance-authority";
+import type { ButtonHTMLAttributes } from "react";
+import { cn } from "../../lib";
+
+const buttonVariants = cva(
+ "inline-flex h-9 items-center justify-center gap-2 rounded-md border px-3 text-sm font-medium transition-colors motion-standard focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-focus-ring)] disabled:pointer-events-none disabled:opacity-50",
+ {
+ variants: {
+ variant: {
+ primary:
+ "border-[var(--color-border-strong)] bg-[var(--color-surface-overlay)] text-[var(--color-text-primary)] hover:bg-[var(--color-surface-raised)]",
+ quiet:
+ "border-[var(--color-border-subtle)] bg-transparent text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)]",
+ },
+ },
+ defaultVariants: { variant: "primary" },
+ },
+);
+
+export interface ButtonProps
+ extends ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean;
+}
+
+export function Button({ className, variant, asChild, ...props }: ButtonProps) {
+ const Comp = asChild ? Slot : "button";
+ return ;
+}
diff --git a/workbench-ui/src/design/components/primitives/CommandPalette.tsx b/workbench-ui/src/design/components/primitives/CommandPalette.tsx
new file mode 100644
index 00000000..bb2c91c6
--- /dev/null
+++ b/workbench-ui/src/design/components/primitives/CommandPalette.tsx
@@ -0,0 +1,32 @@
+import * as Dialog from "@radix-ui/react-dialog";
+import { Search } from "lucide-react";
+import { EmptyState } from "../states/EmptyState";
+
+export function CommandPalette({
+ open,
+ onOpenChange,
+}: {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+}) {
+ return (
+
+
+
+
+
+
+ Command Palette
+
+
+ Empty command palette stub for the Branch 1 keyboard contract.
+
+
+
+
+
+ );
+}
diff --git a/workbench-ui/src/design/components/states/EmptyState.tsx b/workbench-ui/src/design/components/states/EmptyState.tsx
new file mode 100644
index 00000000..3a299fcc
--- /dev/null
+++ b/workbench-ui/src/design/components/states/EmptyState.tsx
@@ -0,0 +1,18 @@
+import { Button } from "../primitives/Button";
+
+export function EmptyState({
+ statement,
+ nextAction,
+}: {
+ statement: string;
+ nextAction: string;
+}) {
+ return (
+
+ {statement}
+
+
+ );
+}
diff --git a/workbench-ui/src/design/components/states/ErrorState.tsx b/workbench-ui/src/design/components/states/ErrorState.tsx
new file mode 100644
index 00000000..ef7dc6b1
--- /dev/null
+++ b/workbench-ui/src/design/components/states/ErrorState.tsx
@@ -0,0 +1,34 @@
+export function ErrorState({
+ whatFailed,
+ mutationStatus,
+ reproducer,
+ retrySafety,
+}: {
+ whatFailed: string;
+ mutationStatus: string;
+ reproducer: string;
+ retrySafety: string;
+}) {
+ return (
+
+
+
+
- What failed
+ - {whatFailed}
+
+
+
- Mutation status
+ - {mutationStatus}
+
+
+
- Reproducer
+ - {reproducer}
+
+
+
- Retry safety
+ - {retrySafety}
+
+
+
+ );
+}
diff --git a/workbench-ui/src/design/components/states/LoadingState.tsx b/workbench-ui/src/design/components/states/LoadingState.tsx
new file mode 100644
index 00000000..91005ee2
--- /dev/null
+++ b/workbench-ui/src/design/components/states/LoadingState.tsx
@@ -0,0 +1,16 @@
+export function LoadingState({ label }: { label: string }) {
+ if (label.trim().toLowerCase() === "thinking...") {
+ throw new Error('LoadingState label must be specific; "Thinking..." is forbidden.');
+ }
+
+ return (
+
+ );
+}
diff --git a/workbench-ui/src/design/components/states/states.test.tsx b/workbench-ui/src/design/components/states/states.test.tsx
new file mode 100644
index 00000000..1c41efd8
--- /dev/null
+++ b/workbench-ui/src/design/components/states/states.test.tsx
@@ -0,0 +1,37 @@
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it } from "vitest";
+import { EmptyState } from "./EmptyState";
+import { ErrorState } from "./ErrorState";
+import { LoadingState } from "./LoadingState";
+
+describe("state components", () => {
+ it("requires empty-state statement and next action", () => {
+ render();
+ expect(screen.getByText("No trace selected.")).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: "Select a trace." })).toBeInTheDocument();
+ });
+
+ it("renders every error-state contract field", () => {
+ render(
+ ,
+ );
+ expect(screen.getByText("What failed")).toBeInTheDocument();
+ expect(screen.getByText("Mutation status")).toBeInTheDocument();
+ expect(screen.getByText("Reproducer")).toBeInTheDocument();
+ expect(screen.getByText("Retry safety")).toBeInTheDocument();
+ });
+
+ it("requires a specific loading label and caps shimmer cycles", () => {
+ const consoleError = vi.spyOn(console, "error").mockImplementation(() => undefined);
+ expect(() => render()).toThrow();
+ consoleError.mockRestore();
+ render();
+ expect(screen.getByText("Loading trace fixture.")).toBeInTheDocument();
+ expect(document.querySelector("[data-shimmer-cycles='2']")).toBeInTheDocument();
+ });
+});
diff --git a/workbench-ui/src/design/lib.ts b/workbench-ui/src/design/lib.ts
new file mode 100644
index 00000000..97a64d12
--- /dev/null
+++ b/workbench-ui/src/design/lib.ts
@@ -0,0 +1,10 @@
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
+
+export async function copyText(value: string) {
+ await navigator.clipboard?.writeText(value);
+}
diff --git a/workbench-ui/src/design/tokens/tokens.css b/workbench-ui/src/design/tokens/tokens.css
new file mode 100644
index 00000000..1daa0915
--- /dev/null
+++ b/workbench-ui/src/design/tokens/tokens.css
@@ -0,0 +1,146 @@
+@font-face {
+ font-family: "Inter";
+ src: url("/fonts/Inter-Regular.woff2") format("woff2");
+ font-weight: 400 800;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "JetBrains Mono";
+ src: url("/fonts/JetBrainsMono-Regular.woff2") format("woff2");
+ font-weight: 400 800;
+ font-display: swap;
+}
+
+:root,
+.dark {
+ color-scheme: dark;
+ --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
+ --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
+
+ --color-surface-base: #0d1117;
+ --color-surface-raised: #131923;
+ --color-surface-overlay: #191f2a;
+ --color-surface-inset: #070a0f;
+ --color-border-subtle: #252d3a;
+ --color-border-strong: #3a4556;
+ --color-text-primary: #eef2f7;
+ --color-text-secondary: #aeb8c7;
+ --color-text-mono: #d8e2ef;
+ --color-text-muted: #788395;
+ --color-focus-ring: #7dd3fc;
+ --color-link: #8bd3ff;
+
+ --color-state-decoded: #4fc3b4;
+ --color-state-decoded-muted: #3d8f86;
+ --color-state-verified: #67d391;
+ --color-state-evidenced: #38bfa7;
+ --color-state-evidenced-muted: #2f8175;
+ --color-state-inferred: #8d8cff;
+ --color-state-unverified: #8aa0b8;
+ --color-state-unverified-warm: #d39b4f;
+ --color-state-perceived: #5ec8f2;
+ --color-state-contradicted: #f07178;
+ --color-state-ambiguous: #b18cff;
+ --color-state-undetermined: #77808f;
+ --color-state-scope: #64748b;
+ --color-state-bounded: #e59f48;
+ --color-state-needed: #f3c45b;
+
+ --color-clearance-cleared: #74d99f;
+ --color-clearance-violated: #f25f6f;
+ --color-clearance-unassessable: #7f8998;
+ --color-clearance-suppressed: #bd5b68;
+
+ --color-review-pending: #e8b94e;
+ --color-review-accepted: #57c989;
+ --color-review-rejected: #cf6470;
+ --color-review-withdrawn: #858d9b;
+
+ --color-grounding-teaching: #61d394;
+ --color-grounding-pack: #42c7b5;
+ --color-grounding-vault: #7f95ff;
+ --color-grounding-partial: #6faea4;
+ --color-grounding-oov: #e9a94f;
+ --color-grounding-none: #6f7b8c;
+
+ --color-state-info-bg: #10253a;
+ --color-state-info-border: #23648e;
+ --color-state-info-text: #bde8ff;
+ --color-state-success-bg: #10291e;
+ --color-state-success-border: #2d7a55;
+ --color-state-success-text: #b9f3d3;
+ --color-state-warning-bg: #31240c;
+ --color-state-warning-border: #9c6a1b;
+ --color-state-warning-text: #ffd89a;
+ --color-state-danger-bg: #351419;
+ --color-state-danger-border: #9f3848;
+ --color-state-danger-text: #ffc3ca;
+ --color-state-neutral-bg: #1b212c;
+ --color-state-neutral-border: #465164;
+ --color-state-neutral-text: #d4dbe7;
+ --color-state-purple-bg: #241a34;
+ --color-state-purple-border: #7655a2;
+ --color-state-purple-text: #dec8ff;
+
+ --space-1: 0.25rem;
+ --space-2: 0.5rem;
+ --space-3: 0.75rem;
+ --space-4: 1rem;
+ --space-5: 1.25rem;
+ --space-6: 1.5rem;
+ --space-8: 2rem;
+ --space-10: 2.5rem;
+ --space-12: 3rem;
+ --radius-sm: 0.25rem;
+ --radius-md: 0.375rem;
+ --radius-lg: 0.5rem;
+ --radius-1: var(--radius-sm);
+ --radius-2: var(--radius-md);
+ --radius-3: var(--radius-lg);
+ --shadow-panel: 0 10px 35px rgb(0 0 0 / 0.28);
+ --shadow-floating: 0 18px 60px rgb(0 0 0 / 0.45);
+ --shadow-overlay: var(--shadow-floating);
+
+ --font-size-display: 1.75rem;
+ --font-size-h1: 1.375rem;
+ --font-size-h2: 1rem;
+ --font-size-body: 0.875rem;
+ --font-size-meta: 0.75rem;
+ --font-size-mono: 0.75rem;
+ --font-weight-regular: 400;
+ --font-weight-medium: 500;
+ --font-weight-semibold: 650;
+ --line-height-tight: 1.2;
+ --line-height-base: 1.5;
+ --text-xs: var(--font-size-meta);
+ --text-sm: var(--font-size-body);
+ --text-md: 1rem;
+ --text-lg: 1.125rem;
+ --text-xl: var(--font-size-h1);
+ --line-tight: var(--line-height-tight);
+ --line-normal: var(--line-height-base);
+
+ --motion-instant: 0ms;
+ --motion-fast: 120ms;
+ --motion-base: 180ms;
+ --motion-slow: 1200ms;
+ --motion-ease-out: cubic-bezier(0.2, 0, 0, 1);
+ --motion-ease-spring: cubic-bezier(0.16, 1, 0.3, 1);
+ --motion-duration-instant: var(--motion-instant);
+ --motion-duration-fast: var(--motion-fast);
+ --motion-duration-standard: var(--motion-base);
+ --motion-duration-slow: var(--motion-slow);
+ --motion-ease-standard: var(--motion-ease-out);
+ --motion-ease-emphasized: var(--motion-ease-spring);
+}
+
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: var(--motion-duration-instant) !important;
+ transition-duration: var(--motion-duration-instant) !important;
+ animation-iteration-count: 1 !important;
+ }
+}
diff --git a/workbench-ui/src/design/tokens/tokens.test.ts b/workbench-ui/src/design/tokens/tokens.test.ts
new file mode 100644
index 00000000..4062ac82
--- /dev/null
+++ b/workbench-ui/src/design/tokens/tokens.test.ts
@@ -0,0 +1,37 @@
+import { readFileSync } from "node:fs";
+import { resolve } from "node:path";
+import { describe, expect, it } from "vitest";
+import { tokens } from "./tokens";
+
+function parseCssTokens() {
+ const css = readFileSync(resolve(process.cwd(), "src/design/tokens/tokens.css"), "utf8");
+ return Object.fromEntries(
+ [...css.matchAll(/--([a-z0-9-]+):\s*([^;]+);/g)].map(([, name, value]) => [
+ name,
+ value.trim(),
+ ]),
+ );
+}
+
+describe("design tokens", () => {
+ it("keeps tokens.css and generated tokens.ts synchronized", () => {
+ expect(tokens).toEqual(parseCssTokens());
+ });
+
+ it("collapses tokenized motion under reduced motion", () => {
+ const reduced = true;
+ vi.stubGlobal("matchMedia", (query: string) => ({
+ matches: reduced && query.includes("prefers-reduced-motion"),
+ media: query,
+ onchange: null,
+ addListener: vi.fn(),
+ removeListener: vi.fn(),
+ addEventListener: vi.fn(),
+ removeEventListener: vi.fn(),
+ dispatchEvent: vi.fn(),
+ }));
+
+ expect(window.matchMedia("(prefers-reduced-motion: reduce)").matches).toBe(true);
+ expect(tokens["motion-instant"]).toBe("0ms");
+ });
+});
diff --git a/workbench-ui/src/design/tokens/tokens.ts b/workbench-ui/src/design/tokens/tokens.ts
new file mode 100644
index 00000000..e81893c7
--- /dev/null
+++ b/workbench-ui/src/design/tokens/tokens.ts
@@ -0,0 +1,115 @@
+// Generated by scripts/generate-tokens.ts. Do not edit by hand.
+export const tokens = {
+ "font-sans": "\"Inter\", ui-sans-serif, system-ui, sans-serif",
+ "font-mono": "\"JetBrains Mono\", ui-monospace, SFMono-Regular, monospace",
+ "color-surface-base": "#0d1117",
+ "color-surface-raised": "#131923",
+ "color-surface-overlay": "#191f2a",
+ "color-surface-inset": "#070a0f",
+ "color-border-subtle": "#252d3a",
+ "color-border-strong": "#3a4556",
+ "color-text-primary": "#eef2f7",
+ "color-text-secondary": "#aeb8c7",
+ "color-text-mono": "#d8e2ef",
+ "color-text-muted": "#788395",
+ "color-focus-ring": "#7dd3fc",
+ "color-link": "#8bd3ff",
+ "color-state-decoded": "#4fc3b4",
+ "color-state-decoded-muted": "#3d8f86",
+ "color-state-verified": "#67d391",
+ "color-state-evidenced": "#38bfa7",
+ "color-state-evidenced-muted": "#2f8175",
+ "color-state-inferred": "#8d8cff",
+ "color-state-unverified": "#8aa0b8",
+ "color-state-unverified-warm": "#d39b4f",
+ "color-state-perceived": "#5ec8f2",
+ "color-state-contradicted": "#f07178",
+ "color-state-ambiguous": "#b18cff",
+ "color-state-undetermined": "#77808f",
+ "color-state-scope": "#64748b",
+ "color-state-bounded": "#e59f48",
+ "color-state-needed": "#f3c45b",
+ "color-clearance-cleared": "#74d99f",
+ "color-clearance-violated": "#f25f6f",
+ "color-clearance-unassessable": "#7f8998",
+ "color-clearance-suppressed": "#bd5b68",
+ "color-review-pending": "#e8b94e",
+ "color-review-accepted": "#57c989",
+ "color-review-rejected": "#cf6470",
+ "color-review-withdrawn": "#858d9b",
+ "color-grounding-teaching": "#61d394",
+ "color-grounding-pack": "#42c7b5",
+ "color-grounding-vault": "#7f95ff",
+ "color-grounding-partial": "#6faea4",
+ "color-grounding-oov": "#e9a94f",
+ "color-grounding-none": "#6f7b8c",
+ "color-state-info-bg": "#10253a",
+ "color-state-info-border": "#23648e",
+ "color-state-info-text": "#bde8ff",
+ "color-state-success-bg": "#10291e",
+ "color-state-success-border": "#2d7a55",
+ "color-state-success-text": "#b9f3d3",
+ "color-state-warning-bg": "#31240c",
+ "color-state-warning-border": "#9c6a1b",
+ "color-state-warning-text": "#ffd89a",
+ "color-state-danger-bg": "#351419",
+ "color-state-danger-border": "#9f3848",
+ "color-state-danger-text": "#ffc3ca",
+ "color-state-neutral-bg": "#1b212c",
+ "color-state-neutral-border": "#465164",
+ "color-state-neutral-text": "#d4dbe7",
+ "color-state-purple-bg": "#241a34",
+ "color-state-purple-border": "#7655a2",
+ "color-state-purple-text": "#dec8ff",
+ "space-1": "0.25rem",
+ "space-2": "0.5rem",
+ "space-3": "0.75rem",
+ "space-4": "1rem",
+ "space-5": "1.25rem",
+ "space-6": "1.5rem",
+ "space-8": "2rem",
+ "space-10": "2.5rem",
+ "space-12": "3rem",
+ "radius-sm": "0.25rem",
+ "radius-md": "0.375rem",
+ "radius-lg": "0.5rem",
+ "radius-1": "var(--radius-sm)",
+ "radius-2": "var(--radius-md)",
+ "radius-3": "var(--radius-lg)",
+ "shadow-panel": "0 10px 35px rgb(0 0 0 / 0.28)",
+ "shadow-floating": "0 18px 60px rgb(0 0 0 / 0.45)",
+ "shadow-overlay": "var(--shadow-floating)",
+ "font-size-display": "1.75rem",
+ "font-size-h1": "1.375rem",
+ "font-size-h2": "1rem",
+ "font-size-body": "0.875rem",
+ "font-size-meta": "0.75rem",
+ "font-size-mono": "0.75rem",
+ "font-weight-regular": "400",
+ "font-weight-medium": "500",
+ "font-weight-semibold": "650",
+ "line-height-tight": "1.2",
+ "line-height-base": "1.5",
+ "text-xs": "var(--font-size-meta)",
+ "text-sm": "var(--font-size-body)",
+ "text-md": "1rem",
+ "text-lg": "1.125rem",
+ "text-xl": "var(--font-size-h1)",
+ "line-tight": "var(--line-height-tight)",
+ "line-normal": "var(--line-height-base)",
+ "motion-instant": "0ms",
+ "motion-fast": "120ms",
+ "motion-base": "180ms",
+ "motion-slow": "1200ms",
+ "motion-ease-out": "cubic-bezier(0.2, 0, 0, 1)",
+ "motion-ease-spring": "cubic-bezier(0.16, 1, 0.3, 1)",
+ "motion-duration-instant": "var(--motion-instant)",
+ "motion-duration-fast": "var(--motion-fast)",
+ "motion-duration-standard": "var(--motion-base)",
+ "motion-duration-slow": "var(--motion-slow)",
+ "motion-ease-standard": "var(--motion-ease-out)",
+ "motion-ease-emphasized": "var(--motion-ease-spring)"
+} as const;
+
+export type DesignTokenName = keyof typeof tokens;
+export type DesignTokenValue = (typeof tokens)[DesignTokenName];
diff --git a/workbench-ui/src/index.css b/workbench-ui/src/index.css
new file mode 100644
index 00000000..8ddb265b
--- /dev/null
+++ b/workbench-ui/src/index.css
@@ -0,0 +1,35 @@
+@import "./design/tokens/tokens.css";
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+* {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ min-width: 320px;
+ min-height: 100vh;
+ background: var(--color-surface-base);
+ color: var(--color-text-primary);
+ font-family: var(--font-sans);
+ line-height: var(--line-normal);
+}
+
+button,
+a,
+[tabindex]:not([tabindex="-1"]) {
+ outline: none;
+}
+
+:focus-visible {
+ outline: 2px solid var(--color-focus-ring);
+ outline-offset: 2px;
+}
+
+.motion-standard {
+ transition-duration: var(--motion-duration-standard);
+ transition-timing-function: var(--motion-ease-standard);
+}
diff --git a/workbench-ui/src/main.tsx b/workbench-ui/src/main.tsx
new file mode 100644
index 00000000..e86d0f79
--- /dev/null
+++ b/workbench-ui/src/main.tsx
@@ -0,0 +1,14 @@
+import React from "react";
+import ReactDOM from "react-dom/client";
+import "./index.css";
+import { PreviewPage } from "./preview/PreviewPage";
+
+function App() {
+ return window.location.pathname === "/preview" ? : ;
+}
+
+ReactDOM.createRoot(document.getElementById("root")!).render(
+
+
+ ,
+);
diff --git a/workbench-ui/src/preview/PreviewPage.test.tsx b/workbench-ui/src/preview/PreviewPage.test.tsx
new file mode 100644
index 00000000..7630a15f
--- /dev/null
+++ b/workbench-ui/src/preview/PreviewPage.test.tsx
@@ -0,0 +1,35 @@
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { describe, expect, it } from "vitest";
+import { PreviewPage } from "./PreviewPage";
+
+describe("/preview", () => {
+ it("renders every primitive with network unavailable", () => {
+ vi.stubGlobal("fetch", vi.fn(() => Promise.reject(new Error("network blocked"))));
+ render();
+ expect(screen.getByRole("heading", { name: "CORE Workbench Design System v1" })).toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: "Primitives" })).toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: "Badges" })).toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: "States" })).toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: "Stable JSON Viewer" })).toBeInTheDocument();
+ expect(fetch).not.toHaveBeenCalled();
+ });
+
+ it("opens CommandPalette with mod+k and closes overlays with Escape", async () => {
+ const user = userEvent.setup();
+ render();
+ await user.keyboard("{Control>}k{/Control}");
+ expect(screen.getByRole("dialog", { name: "Command Palette" })).toBeInTheDocument();
+ await user.keyboard("{Escape}");
+ expect(screen.queryByRole("dialog", { name: "Command Palette" })).not.toBeInTheDocument();
+ });
+
+ it("keeps tab order in DOM order for preview actions", async () => {
+ const user = userEvent.setup();
+ render();
+ await user.tab();
+ expect(screen.getByRole("button", { name: "Primary action" })).toHaveFocus();
+ await user.tab();
+ expect(screen.getByRole("button", { name: "Quiet action" })).toHaveFocus();
+ });
+});
diff --git a/workbench-ui/src/preview/PreviewPage.tsx b/workbench-ui/src/preview/PreviewPage.tsx
new file mode 100644
index 00000000..1009339e
--- /dev/null
+++ b/workbench-ui/src/preview/PreviewPage.tsx
@@ -0,0 +1,85 @@
+import { useEffect, useState } from "react";
+import { StableJsonViewer } from "../design/components/StableJsonViewer";
+import {
+ EpistemicState,
+ EpistemicStateBadge,
+ GroundingSource,
+ GroundingSourceBadge,
+ NormativeClearance,
+ NormativeClearanceBadge,
+ ReviewState,
+ ReviewStateBadge,
+ TraceHashBadge,
+} from "../design/components/badges";
+import { Button } from "../design/components/primitives/Button";
+import { CommandPalette } from "../design/components/primitives/CommandPalette";
+import { EmptyState } from "../design/components/states/EmptyState";
+import { ErrorState } from "../design/components/states/ErrorState";
+import { LoadingState } from "../design/components/states/LoadingState";
+
+export function PreviewPage() {
+ const [paletteOpen, setPaletteOpen] = useState(false);
+
+ useEffect(() => {
+ const onKeyDown = (event: KeyboardEvent) => {
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
+ event.preventDefault();
+ setPaletteOpen(true);
+ }
+ if (event.key === "Escape") setPaletteOpen(false);
+ };
+ window.addEventListener("keydown", onKeyDown);
+ return () => window.removeEventListener("keydown", onKeyDown);
+ }, []);
+
+ return (
+
+
+
+
+ Primitives
+
+
+
+
+
+
+
+ Badges
+
+ {Object.values(EpistemicState).map((value) => )}
+ {Object.values(NormativeClearance).map((value) => )}
+ {Object.values(ReviewState).map((value) => )}
+ {Object.values(GroundingSource).map((value) => )}
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/workbench-ui/src/test/setup.ts b/workbench-ui/src/test/setup.ts
new file mode 100644
index 00000000..08fce702
--- /dev/null
+++ b/workbench-ui/src/test/setup.ts
@@ -0,0 +1,8 @@
+import "@testing-library/jest-dom/vitest";
+
+Object.defineProperty(navigator, "clipboard", {
+ configurable: true,
+ value: {
+ writeText: vi.fn().mockResolvedValue(undefined),
+ },
+});
diff --git a/workbench-ui/tailwind.config.ts b/workbench-ui/tailwind.config.ts
new file mode 100644
index 00000000..12a777c2
--- /dev/null
+++ b/workbench-ui/tailwind.config.ts
@@ -0,0 +1,15 @@
+import type { Config } from "tailwindcss";
+
+export default {
+ darkMode: "class",
+ content: ["./index.html", "./src/**/*.{ts,tsx}"],
+ theme: {
+ extend: {
+ fontFamily: {
+ sans: ["Inter", "ui-sans-serif", "system-ui", "sans-serif"],
+ mono: ["JetBrains Mono", "ui-monospace", "SFMono-Regular", "monospace"],
+ },
+ },
+ },
+ plugins: [],
+} satisfies Config;
diff --git a/workbench-ui/tsconfig.json b/workbench-ui/tsconfig.json
new file mode 100644
index 00000000..39136000
--- /dev/null
+++ b/workbench-ui/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "target": "ES2023",
+ "useDefineForClassFields": true,
+ "lib": ["DOM", "DOM.Iterable", "ES2023"],
+ "types": ["vitest/globals"],
+ "allowJs": false,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx"
+ },
+ "include": ["src", "scripts"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/workbench-ui/tsconfig.node.json b/workbench-ui/tsconfig.node.json
new file mode 100644
index 00000000..f25d7bb5
--- /dev/null
+++ b/workbench-ui/tsconfig.node.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "target": "ES2023",
+ "lib": ["ES2023"],
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts", "scripts/*.ts"]
+}
diff --git a/workbench-ui/vite.config.ts b/workbench-ui/vite.config.ts
new file mode 100644
index 00000000..722961b7
--- /dev/null
+++ b/workbench-ui/vite.config.ts
@@ -0,0 +1,11 @@
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+ plugins: [react()],
+ test: {
+ environment: "happy-dom",
+ setupFiles: ["./src/test/setup.ts"],
+ globals: true,
+ },
+});