`, `preset url `, or `preset open `. For project-aware preset detection, use `npx shadcn@latest preset resolve`.
+- **Apply preset codes directly with the CLI.** Use `npx shadcn@latest apply ` for existing projects, or `npx shadcn@latest init --preset ` when initializing.
+
+## Key Patterns
+
+These are the most common patterns that differentiate correct shadcn/ui code. For edge cases, see the linked rule files above.
+
+```tsx
+// Form layout: FieldGroup + Field, not div + Label.
+
+
+ Email
+
+
+
+
+// Validation: data-invalid on Field, aria-invalid on the control.
+
+ Email
+
+ Invalid email.
+
+
+// Icons in buttons: data-icon, no sizing classes.
+
+
+// Spacing: gap-*, not space-y-*.
+ // correct
+ // wrong
+
+// Equal dimensions: size-*, not w-* h-*.
+ // correct
+ // wrong
+
+// Status colors: Badge variants or semantic tokens, not raw colors.
++20.1% // correct
++20.1% // wrong
+```
+
+## Component Selection
+
+| Need | Use |
+| -------------------------- | --------------------------------------------------------------------------------------------------- |
+| Button/action | `Button` with appropriate variant |
+| Form inputs | `Input`, `Select`, `Combobox`, `Switch`, `Checkbox`, `RadioGroup`, `Textarea`, `InputOTP`, `Slider` |
+| Toggle between 2–5 options | `ToggleGroup` + `ToggleGroupItem` |
+| Data display | `Table`, `Card`, `Badge`, `Avatar` |
+| Navigation | `Sidebar`, `NavigationMenu`, `Breadcrumb`, `Tabs`, `Pagination` |
+| Overlays | `Dialog` (modal), `Sheet` (side panel), `Drawer` (bottom sheet), `AlertDialog` (confirmation) |
+| Feedback | `toast` (Base UI), `sonner` (Radix/Aria), `Alert`, `Progress`, `Skeleton`, `Spinner` |
+| Command palette | `Command` inside `Dialog` |
+| Charts | `Chart` (wraps Recharts) |
+| Layout | `Card`, `Separator`, `Resizable`, `ScrollArea`, `Accordion`, `Collapsible` |
+| Empty states | `Empty` |
+| Menus | `DropdownMenu`, `ContextMenu`, `Menubar` |
+| Tooltips/info | `Tooltip`, `HoverCard`, `Popover` |
+| Chat / conversation UI | `MessageScroller`, `Message`, `Bubble`, `Attachment`, `Marker` |
+
+## Key Fields
+
+The injected project context contains these key fields:
+
+- **`aliases`** → use the actual alias prefix for imports (e.g. `@/`, `~/`), never hardcode.
+- **`isRSC`** → when `true`, components using `useState`, `useEffect`, event handlers, or browser APIs need `"use client"` at the top of the file. Always reference this field when advising on the directive.
+- **`tailwindVersion`** → `"v4"` uses `@theme inline` blocks; `"v3"` uses `tailwind.config.js`.
+- **`tailwindCssFile`** → the global CSS file where custom CSS variables are defined. Always edit this file, never create a new one.
+- **`style`** → component visual treatment (e.g. `nova`, `vega`).
+- **`base`** → primitive library (`radix` or `base`). Affects component APIs and available props.
+- **`iconLibrary`** → determines icon imports. Use `lucide-react` for `lucide`, `@tabler/icons-react` for `tabler`, etc. Never assume `lucide-react`.
+- **`resolvedPaths`** → exact file-system destinations for components, utils, hooks, etc.
+- **`framework`** → routing and file conventions (e.g. Next.js App Router vs Vite SPA).
+- **`packageManager`** → use this for any non-shadcn dependency installs (e.g. `pnpm add date-fns` vs `npm install date-fns`).
+- **`preset`** → resolved preset code and values for the current project. Use `npx shadcn@latest preset resolve --json` when you only need preset information.
+
+See [cli.md — `info` command](./cli.md) for the full field reference.
+
+## Component Docs, Examples, and Usage
+
+Run `npx shadcn@latest docs ` to get the URLs for a component's documentation, examples, and API reference. Fetch these URLs to get the actual content.
+
+```bash
+npx shadcn@latest docs button dialog select
+```
+
+**When creating, fixing, debugging, or using a component, always run `npx shadcn@latest docs` and fetch the URLs first.** This ensures you're working with the correct API and usage patterns rather than guessing.
+
+## Workflow
+
+1. **Get project context** — already injected above. Run `npx shadcn@latest info` again if you need to refresh.
+2. **Check installed components first** — before running `add`, always check the `components` list from project context or list the `resolvedPaths.ui` directory. Don't import components that haven't been added, and don't re-add ones already installed.
+3. **Find components** — `npx shadcn@latest search`.
+4. **Get docs and examples** — run `npx shadcn@latest docs ` to get URLs, then fetch them. Use `npx shadcn@latest view` to browse registry items you haven't installed. To preview changes to installed components, use `npx shadcn@latest add --diff`.
+5. **Install or update** — `npx shadcn@latest add`. When updating existing components, use `--dry-run` and `--diff` to preview changes first (see [Updating Components](#updating-components) below).
+6. **Fix imports in third-party components** — After adding components from community registries (e.g. `@bundui`, `@magicui`), check the added non-UI files for hardcoded import paths like `@/components/ui/...`. These won't match the project's actual aliases. Use `npx shadcn@latest info` to get the correct `ui` alias (e.g. `@workspace/ui/components`) and rewrite the imports accordingly. The CLI rewrites imports for its own UI files, but third-party registry components may use default paths that don't match the project.
+7. **Review added components** — After adding a component or block from any registry, **always read the added files and verify they are correct**. Check for missing sub-components (e.g. `SelectItem` without `SelectGroup`), missing imports, incorrect composition, or violations of the [Critical Rules](#critical-rules). Also replace any icon imports with the project's `iconLibrary` from the project context (e.g. if the registry item uses `lucide-react` but the project uses `hugeicons`, swap the imports and icon names accordingly). Fix all issues before moving on.
+8. **Registry must be explicit** — When the user asks to add a block or component, **do not guess the registry**. If no registry is specified (e.g. user says "add a login block" without specifying `@shadcn`, `@tailark`, `owner/repo`, etc.), ask which registry to use. Never default to a registry on behalf of the user.
+9. **Switching presets** — Ask the user first: **overwrite**, **partial**, **merge**, or **skip**?
+ - **Inspect current preset**: `npx shadcn@latest preset resolve`. Use `--json` when you need structured values.
+ - **Inspect incoming preset**: `npx shadcn@latest preset decode `. Use `preset url ` or `preset open ` to share or open the preset builder.
+ - **Overwrite**: `npx shadcn@latest apply `. Overwrites detected components, fonts, and CSS variables.
+ - **Partial**: `npx shadcn@latest apply --only theme,font`. Updates only the selected preset parts without reinstalling UI components. Supported values are `theme` and `font`; comma-separated combinations are allowed. `icon` is intentionally not supported, because icon changes may require full component reinstall and transforms.
+ - **Merge**: `npx shadcn@latest init --preset --force --no-reinstall`, then run `npx shadcn@latest info` to list installed components, then for each installed component use `--dry-run` and `--diff` to [smart merge](#updating-components) it individually.
+ - **Skip**: `npx shadcn@latest init --preset --force --no-reinstall`. Only updates config and CSS, leaves components as-is.
+ - **Important**: Always run preset commands inside the user's project directory. `apply` only works in an existing project with a `components.json` file. The CLI automatically preserves the current base (`base` vs `radix`) from `components.json`. If you must use a scratch/temp directory (e.g. for `--dry-run` comparisons), pass `--base ` explicitly — preset codes do not encode the base.
+
+## Updating Components
+
+When the user asks to update a component from upstream while keeping their local changes, use `--dry-run` and `--diff` to intelligently merge. **NEVER fetch raw files from GitHub manually — always use the CLI.**
+
+1. Run `npx shadcn@latest add --dry-run` to see all files that would be affected.
+2. For each file, run `npx shadcn@latest add --diff ` to see what changed upstream vs local.
+3. Decide per file based on the diff:
+ - No local changes → safe to overwrite.
+ - Has local changes → read the local file, analyze the diff, and apply upstream updates while preserving local modifications.
+ - User says "just update everything" → use `--overwrite`, but confirm first.
+4. **Never use `--overwrite` without the user's explicit approval.**
+
+## Quick Reference
+
+```bash
+# Create a new project.
+npx shadcn@latest init --name my-app --preset base-nova
+npx shadcn@latest init --name my-app --preset a2r6bw --template vite
+
+# Create a monorepo project.
+npx shadcn@latest init --name my-app --preset base-nova --monorepo
+npx shadcn@latest init --name my-app --preset base-nova --template next --monorepo
+
+# Initialize existing project.
+npx shadcn@latest init --preset base-nova
+npx shadcn@latest init --defaults # shortcut: --template=next --preset=nova (base style implied)
+
+# Apply a preset to an existing project.
+npx shadcn@latest apply a2r6bw
+npx shadcn@latest apply a2r6bw --only theme
+npx shadcn@latest apply a2r6bw --only font
+npx shadcn@latest apply a2r6bw --only theme,font
+
+# Inspect preset codes and project preset state.
+npx shadcn@latest preset decode a2r6bw
+npx shadcn@latest preset url a2r6bw
+npx shadcn@latest preset open a2r6bw
+npx shadcn@latest preset resolve
+npx shadcn@latest preset resolve --json
+
+# Add components.
+npx shadcn@latest add button card dialog
+npx shadcn@latest add @magicui/shimmer-button
+npx shadcn@latest add owner/repo/item
+npx shadcn@latest add --all
+
+# Preview changes before adding/updating.
+npx shadcn@latest add button --dry-run
+npx shadcn@latest add button --diff button.tsx
+npx shadcn@latest add @acme/form --view button.tsx
+npx shadcn@latest add owner/repo/item --dry-run
+
+# Search registries.
+npx shadcn@latest search @shadcn -q "sidebar"
+npx shadcn@latest search @tailark -q "stats"
+npx shadcn@latest search owner/repo -q "login"
+npx shadcn@latest search # all configured registries
+npx shadcn@latest search @shadcn -q "menu" -t ui # filter by item type
+
+# Get component docs and example URLs.
+npx shadcn@latest docs button dialog select
+
+# View registry item details (for items not yet installed).
+npx shadcn@latest view @shadcn/button
+npx shadcn@latest view owner/repo/item
+```
+
+**Named presets:** `nova`, `vega`, `maia`, `lyra`, `mira`, `luma`
+**Templates:** `next`, `vite`, `start`, `react-router`, `astro` (all support `--monorepo`) and `laravel` (not supported for monorepo)
+**Preset codes:** Version-prefixed base62 strings (e.g. `a2r6bw` or `b0`), from [ui.shadcn.com](https://ui.shadcn.com).
+
+## Detailed References
+
+- [rules/forms.md](./rules/forms.md) — FieldGroup, Field, InputGroup, ToggleGroup, FieldSet, validation states
+- [rules/composition.md](./rules/composition.md) — Groups, overlays, Card, Tabs, Avatar, Alert, Empty, Toast, Separator, Skeleton, Badge, Button loading
+- [rules/chat.md](./rules/chat.md) — MessageScroller, Message, Bubble, Attachment, Marker; streaming, anchoring, jump-to-latest
+- [rules/icons.md](./rules/icons.md) — data-icon, icon sizing, passing icons as objects
+- [rules/styling.md](./rules/styling.md) — Semantic colors, variants, className, spacing, size, truncate, dark mode, cn(), z-index
+- [rules/base-vs-radix.md](./rules/base-vs-radix.md) — asChild vs render, Select, ToggleGroup, Slider, Accordion
+- [cli.md](./cli.md) — Commands, flags, presets, templates
+- [registry.md](./registry.md) — Authoring source registries, `include`, item definitions, dependencies, GitHub registry rules
+- [customization.md](./customization.md) — Theming, CSS variables, extending components
diff --git a/distribution_fe/.agents/skills/shadcn/agents/openai.yml b/distribution_fe/.agents/skills/shadcn/agents/openai.yml
new file mode 100644
index 0000000..ab636da
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/agents/openai.yml
@@ -0,0 +1,5 @@
+interface:
+ display_name: "shadcn/ui"
+ short_description: "Manages shadcn/ui components — adding, searching, fixing, debugging, styling, and composing UI."
+ icon_small: "./assets/shadcn-small.png"
+ icon_large: "./assets/shadcn.png"
diff --git a/distribution_fe/.agents/skills/shadcn/assets/shadcn-small.png b/distribution_fe/.agents/skills/shadcn/assets/shadcn-small.png
new file mode 100644
index 0000000..547154b
Binary files /dev/null and b/distribution_fe/.agents/skills/shadcn/assets/shadcn-small.png differ
diff --git a/distribution_fe/.agents/skills/shadcn/assets/shadcn.png b/distribution_fe/.agents/skills/shadcn/assets/shadcn.png
new file mode 100644
index 0000000..b7b6814
Binary files /dev/null and b/distribution_fe/.agents/skills/shadcn/assets/shadcn.png differ
diff --git a/distribution_fe/.agents/skills/shadcn/cli.md b/distribution_fe/.agents/skills/shadcn/cli.md
new file mode 100644
index 0000000..8a1d195
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/cli.md
@@ -0,0 +1,290 @@
+# shadcn CLI Reference
+
+Configuration is read from `components.json`.
+
+> **IMPORTANT:** Always run commands using the project's package runner: `npx shadcn@latest`, `pnpm dlx shadcn@latest`, or `bunx --bun shadcn@latest`. Check `packageManager` from project context to choose the right one. Examples below use `npx shadcn@latest` but substitute the correct runner for the project.
+
+> **IMPORTANT:** Only use the flags documented below. Do not invent or guess flags — if a flag isn't listed here, it doesn't exist. The CLI auto-detects the package manager from the project's lockfile; there is no `--package-manager` flag.
+
+## Contents
+
+- Commands: init, apply, add (dry-run, smart merge), search, view, docs, info, build
+- Templates: next, vite, start, react-router, astro
+- Presets: named, code, URL formats and fields
+- Switching presets
+
+---
+
+## Commands
+
+### `init` — Initialize or create a project
+
+```bash
+npx shadcn@latest init [components...] [options]
+```
+
+Initializes shadcn/ui in an existing project or creates a new project (when `--name` is provided). Optionally installs components in the same step.
+
+| Flag | Short | Description | Default |
+| ----------------------- | ----- | --------------------------------------------------------- | ------- |
+| `--template ` | `-t` | Template (next, start, vite, next-monorepo, react-router) | — |
+| `--preset [name]` | `-p` | Preset configuration (named, code, or URL) | — |
+| `--yes` | `-y` | Skip confirmation prompt | `true` |
+| `--defaults` | `-d` | Use defaults (`--template=next --preset=base-nova`) | `false` |
+| `--force` | `-f` | Force overwrite existing configuration | `false` |
+| `--cwd ` | `-c` | Working directory | current |
+| `--name ` | `-n` | Name for new project | — |
+| `--silent` | `-s` | Mute output | `false` |
+| `--rtl` | | Enable RTL support | — |
+| `--reinstall` | | Re-install existing UI components | `false` |
+| `--monorepo` | | Scaffold a monorepo project | — |
+| `--no-monorepo` | | Skip the monorepo prompt | — |
+
+`npx shadcn@latest create` is an alias for `npx shadcn@latest init`.
+
+### `apply` — Apply a preset to an existing project
+
+```bash
+npx shadcn@latest apply [preset] [options]
+```
+
+Applies a preset to an existing project, overwriting preset-driven config, fonts, CSS variables, and detected UI components.
+
+| Flag | Short | Description | Default |
+| ------------------- | ----- | ------------------------------------------ | ------- |
+| `--preset ` | — | Preset configuration (named, code, or URL) | — |
+| `--yes` | `-y` | Skip confirmation prompt | `false` |
+| `--cwd ` | `-c` | Working directory | current |
+| `--silent` | `-s` | Mute output | `false` |
+
+`[preset]` is a shorthand for `--preset `. If both are provided, they must match.
+If no preset is provided, the CLI offers to open the custom preset builder on `ui.shadcn.com/create`.
+
+### `add` — Add components
+
+> **IMPORTANT:** To compare local components against upstream or to preview changes, ALWAYS use `npx shadcn@latest add --dry-run`, `--diff`, or `--view`. NEVER fetch raw files from GitHub or other sources manually. The CLI handles registry resolution, file paths, and CSS diffing automatically.
+
+```bash
+npx shadcn@latest add [components...] [options]
+```
+
+Accepts component names, registry-prefixed names (`@magicui/shimmer-button`),
+GitHub item addresses (`owner/repo/item`), URLs, or local paths.
+
+| Flag | Short | Description | Default |
+| --------------- | ----- | -------------------------------------------------------------------------------------------------------------------- | ------- |
+| `--yes` | `-y` | Skip confirmation prompt | `false` |
+| `--overwrite` | `-o` | Overwrite existing files | `false` |
+| `--cwd ` | `-c` | Working directory | current |
+| `--all` | `-a` | Add all available components | `false` |
+| `--path ` | `-p` | Target path for the component | — |
+| `--silent` | `-s` | Mute output | `false` |
+| `--dry-run` | | Preview all changes without writing files | `false` |
+| `--diff [path]` | | Show diffs. Without a path, shows the first 5 files. With a path, shows that file only (implies `--dry-run`) | — |
+| `--view [path]` | | Show file contents. Without a path, shows the first 5 files. With a path, shows that file only (implies `--dry-run`) | — |
+
+#### Dry-Run Mode
+
+Use `--dry-run` to preview what `add` would do without writing any files. `--diff` and `--view` both imply `--dry-run`.
+
+```bash
+# Preview all changes.
+npx shadcn@latest add button --dry-run
+
+# Show diffs for all files (top 5).
+npx shadcn@latest add button --diff
+
+# Show the diff for a specific file.
+npx shadcn@latest add button --diff button.tsx
+
+# Show contents for all files (top 5).
+npx shadcn@latest add button --view
+
+# Show the full content of a specific file.
+npx shadcn@latest add button --view button.tsx
+
+# Works with URLs too.
+npx shadcn@latest add https://api.npoint.io/abc123 --dry-run
+
+# Works with public GitHub registries too.
+npx shadcn@latest add owner/repo/item --dry-run
+
+# CSS diffs.
+npx shadcn@latest add button --diff globals.css
+```
+
+**When to use dry-run:**
+
+- When the user asks "what files will this add?" or "what will this change?" — use `--dry-run`.
+- Before overwriting existing components — use `--diff` to preview the changes first.
+- When the user wants to inspect component source code without installing — use `--view`.
+- When checking what CSS changes would be made to `globals.css` — use `--diff globals.css`.
+- When the user asks to review or audit third-party registry code before installing — use `--view` to inspect the source.
+
+> **`npx shadcn@latest add --dry-run` vs `npx shadcn@latest view`:** Prefer `npx shadcn@latest add --dry-run/--diff/--view` over `npx shadcn@latest view` when the user wants to preview changes to their project. `npx shadcn@latest view` only shows raw registry metadata. `npx shadcn@latest add --dry-run` shows exactly what would happen in the user's project: resolved file paths, diffs against existing files, and CSS updates. Use `npx shadcn@latest view` only when the user wants to browse registry info without a project context.
+
+#### Smart Merge from Upstream
+
+See [Updating Components in SKILL.md](./SKILL.md#updating-components) for the full workflow.
+
+### `search` — Search registries
+
+```bash
+npx shadcn@latest search [registries...] [options]
+```
+
+Fuzzy search across registries. Also aliased as `npx shadcn@latest list`.
+Supports namespaces (`@acme`), public GitHub registry sources (`owner/repo`),
+and registry catalog URLs. Without `-q`, lists all items. When no registries are
+passed, searches every registry configured in `components.json`.
+
+| Flag | Short | Description | Default |
+| ------------------- | ----- | ------------------------------------------------- | ------- |
+| `--query ` | `-q` | Search query | — |
+| `--type ` | `-t` | Filter by item type (e.g. `ui`, `block`, `hook`); comma-separated | — |
+| `--limit ` | `-l` | Max items to display | `100` |
+| `--offset ` | `-o` | Items to skip | `0` |
+| `--json` | | Output as JSON | `false` |
+| `--cwd ` | `-c` | Working directory | current |
+
+### `view` — View item details
+
+```bash
+npx shadcn@latest view [options]
+```
+
+Displays item info including file contents. Examples:
+`npx shadcn@latest view @shadcn/button`,
+`npx shadcn@latest view owner/repo/item`.
+
+### `docs` — Get component documentation URLs
+
+```bash
+npx shadcn@latest docs [options]
+```
+
+Outputs resolved URLs for component documentation, examples, and API references. Accepts one or more component names. Fetch the URLs to get the actual content.
+
+Example output for `npx shadcn@latest docs input button`:
+
+```
+base radix
+
+input
+ docs https://ui.shadcn.com/docs/components/radix/input
+ examples https://raw.githubusercontent.com/.../examples/input-example.tsx
+
+button
+ docs https://ui.shadcn.com/docs/components/radix/button
+ examples https://raw.githubusercontent.com/.../examples/button-example.tsx
+```
+
+Some components include an `api` link to the underlying library (e.g. `cmdk` for the command component).
+
+### `diff` — Check for updates
+
+Do not use this command. Use `npx shadcn@latest add --diff` instead.
+
+### `info` — Project information
+
+```bash
+npx shadcn@latest info [options]
+```
+
+Displays project info and `components.json` configuration. Run this first to discover the project's framework, aliases, Tailwind version, and resolved paths.
+
+| Flag | Short | Description | Default |
+| ------------- | ----- | ----------------- | ------- |
+| `--cwd ` | `-c` | Working directory | current |
+
+**Project Info fields:**
+
+| Field | Type | Meaning |
+| -------------------- | --------- | ------------------------------------------------------------------ |
+| `framework` | `string` | Detected framework (`next`, `vite`, `react-router`, `start`, etc.) |
+| `frameworkVersion` | `string` | Framework version (e.g. `15.2.4`) |
+| `isSrcDir` | `boolean` | Whether the project uses a `src/` directory |
+| `isRSC` | `boolean` | Whether React Server Components are enabled |
+| `isTsx` | `boolean` | Whether the project uses TypeScript |
+| `tailwindVersion` | `string` | `"v3"` or `"v4"` |
+| `tailwindConfigFile` | `string` | Path to the Tailwind config file |
+| `tailwindCssFile` | `string` | Path to the global CSS file |
+| `aliasPrefix` | `string` | Import alias prefix (e.g. `@`, `~`, `@/`) |
+| `packageManager` | `string` | Detected package manager (`npm`, `pnpm`, `yarn`, `bun`) |
+
+**Components.json fields:**
+
+| Field | Type | Meaning |
+| -------------------- | --------- | ------------------------------------------------------------------------------------------ |
+| `base` | `string` | Primitive library (`radix` or `base`) — determines component APIs and available props |
+| `style` | `string` | Visual style (e.g. `nova`, `vega`) |
+| `rsc` | `boolean` | RSC flag from config |
+| `tsx` | `boolean` | TypeScript flag |
+| `tailwind.config` | `string` | Tailwind config path |
+| `tailwind.css` | `string` | Global CSS path — this is where custom CSS variables go |
+| `iconLibrary` | `string` | Icon library — determines icon import package (e.g. `lucide-react`, `@tabler/icons-react`) |
+| `aliases.components` | `string` | Component import alias (e.g. `@/components`) |
+| `aliases.utils` | `string` | Utils import alias (e.g. `@/lib/utils`) |
+| `aliases.ui` | `string` | UI component alias (e.g. `@/components/ui`) |
+| `aliases.lib` | `string` | Lib alias (e.g. `@/lib`) |
+| `aliases.hooks` | `string` | Hooks alias (e.g. `@/hooks`) |
+| `resolvedPaths` | `object` | Absolute file-system paths for each alias |
+| `registries` | `object` | Configured custom registries |
+
+**Links fields:**
+
+The `info` output includes a **Links** section with templated URLs for component docs, source, and examples. For resolved URLs, use `npx shadcn@latest docs ` instead.
+
+### `build` — Build a custom registry
+
+```bash
+npx shadcn@latest build [registry] [options]
+```
+
+Builds `registry.json` into individual JSON files for distribution. Default input: `./registry.json`, default output: `./public/r`.
+
+For authoring rules, `include`, item definitions, `registryDependencies`, and
+GitHub registry behavior, see [registry.md](./registry.md).
+
+| Flag | Short | Description | Default |
+| ----------------- | ----- | ----------------- | ------------ |
+| `--output ` | `-o` | Output directory | `./public/r` |
+| `--cwd ` | `-c` | Working directory | current |
+
+---
+
+## Templates
+
+| Value | Framework | Monorepo support |
+| -------------- | -------------- | ---------------- |
+| `next` | Next.js | Yes |
+| `vite` | Vite | Yes |
+| `start` | TanStack Start | Yes |
+| `react-router` | React Router | Yes |
+| `astro` | Astro | Yes |
+| `laravel` | Laravel | No |
+
+All templates support monorepo scaffolding via the `--monorepo` flag. When passed, the CLI uses a monorepo-specific template directory (e.g. `next-monorepo`, `vite-monorepo`). When neither `--monorepo` nor `--no-monorepo` is passed, the CLI prompts interactively. Laravel does not support monorepo scaffolding.
+
+---
+
+## Presets
+
+Three ways to specify a preset via `--preset`:
+
+1. **Named:** `--preset nova` or `--preset lyra`
+2. **Code:** `--preset a2r6bw` (version-prefixed base62 string, e.g. `a2r6bw` or `b0`)
+3. **URL:** `--preset "https://ui.shadcn.com/init?base=radix&style=nova&..."`
+
+> **IMPORTANT:** Never try to decode, fetch, or resolve preset codes manually. Preset codes are opaque — pass them directly to `npx shadcn@latest init --preset ` and let the CLI handle resolution.
+> Use `npx shadcn@latest apply --preset ` when overwriting an existing project's preset.
+
+## Switching Presets
+
+Ask the user first: **overwrite**, **merge**, or **skip** existing components?
+
+- **Overwrite / Re-install** → `npx shadcn@latest apply --preset `. Overwrites all detected component files with the new preset styles. Use when the user hasn't customized components.
+- **Merge** → `npx shadcn@latest init --preset --force --no-reinstall`, then run `npx shadcn@latest info` to get the list of installed components and use the [smart merge workflow](./SKILL.md#updating-components) to update them one by one, preserving local changes. Use when the user has customized components.
+- **Skip** → `npx shadcn@latest init --preset --force --no-reinstall`. Only updates config and CSS variables, leaves existing components as-is.
+
+Always run preset commands inside the user's project directory. `apply` only works in an existing project with a `components.json` file. The CLI automatically preserves the current base (`base` vs `radix`) from `components.json`. If you must use a scratch/temp directory (e.g. for `--dry-run` comparisons), pass `--base ` explicitly — preset codes do not encode the base.
diff --git a/distribution_fe/.agents/skills/shadcn/customization.md b/distribution_fe/.agents/skills/shadcn/customization.md
new file mode 100644
index 0000000..16954f5
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/customization.md
@@ -0,0 +1,209 @@
+# Customization & Theming
+
+Components reference semantic CSS variable tokens. Change the variables to change every component.
+
+## Contents
+
+- How it works (CSS variables → Tailwind utilities → components)
+- Color variables and OKLCH format
+- Dark mode setup
+- Changing the theme (presets, CSS variables)
+- Adding custom colors (Tailwind v3 and v4)
+- Border radius
+- Customizing components (variants, className, wrappers)
+- Checking for updates
+
+---
+
+## How It Works
+
+1. CSS variables defined in `:root` (light) and `.dark` (dark mode).
+2. Tailwind maps them to utilities: `bg-primary`, `text-muted-foreground`, etc.
+3. Components use these utilities — changing a variable changes all components that reference it.
+
+---
+
+## Color Variables
+
+Every color follows the `name` / `name-foreground` convention. The base variable is for backgrounds, `-foreground` is for text/icons on that background.
+
+| Variable | Purpose |
+| -------------------------------------------- | -------------------------------- |
+| `--background` / `--foreground` | Page background and default text |
+| `--card` / `--card-foreground` | Card surfaces |
+| `--primary` / `--primary-foreground` | Primary buttons and actions |
+| `--secondary` / `--secondary-foreground` | Secondary actions |
+| `--muted` / `--muted-foreground` | Muted/disabled states |
+| `--accent` / `--accent-foreground` | Hover and accent states |
+| `--destructive` / `--destructive-foreground` | Error and destructive actions |
+| `--border` | Default border color |
+| `--input` | Form input borders |
+| `--ring` | Focus ring color |
+| `--chart-1` through `--chart-5` | Chart/data visualization |
+| `--sidebar-*` | Sidebar-specific colors |
+| `--surface` / `--surface-foreground` | Secondary surface |
+
+Colors use OKLCH: `--primary: oklch(0.205 0 0)` where values are lightness (0–1), chroma (0 = gray), and hue (0–360).
+
+---
+
+## Dark Mode
+
+Class-based toggle via `.dark` on the root element. In Next.js, use `next-themes`:
+
+```tsx
+import { ThemeProvider } from "next-themes"
+
+
+ {children}
+
+```
+
+---
+
+## Changing the Theme
+
+```bash
+# Apply a preset code from ui.shadcn.com.
+npx shadcn@latest apply --preset a2r6bw
+
+# Positional shorthand also works.
+npx shadcn@latest apply a2r6bw
+
+# Switch to a named preset and overwrite existing components.
+npx shadcn@latest apply --preset nova
+
+# Preserve existing components instead.
+npx shadcn@latest init --preset nova --force --no-reinstall
+
+# Use a custom theme URL.
+npx shadcn@latest apply --preset "https://ui.shadcn.com/init?base=radix&style=nova&theme=blue&..."
+```
+
+Or edit CSS variables directly in `globals.css`.
+
+---
+
+## Adding Custom Colors
+
+Add variables to the file at `tailwindCssFile` from `npx shadcn@latest info` (typically `globals.css`). Never create a new CSS file for this.
+
+```css
+/* 1. Define in the global CSS file. */
+:root {
+ --warning: oklch(0.84 0.16 84);
+ --warning-foreground: oklch(0.28 0.07 46);
+}
+.dark {
+ --warning: oklch(0.41 0.11 46);
+ --warning-foreground: oklch(0.99 0.02 95);
+}
+```
+
+```css
+/* 2a. Register with Tailwind v4 (@theme inline). */
+@theme inline {
+ --color-warning: var(--warning);
+ --color-warning-foreground: var(--warning-foreground);
+}
+```
+
+When `tailwindVersion` is `"v3"` (check via `npx shadcn@latest info`), register in `tailwind.config.js` instead:
+
+```js
+// 2b. Register with Tailwind v3 (tailwind.config.js).
+module.exports = {
+ theme: {
+ extend: {
+ colors: {
+ warning: "oklch(var(--warning) / )",
+ "warning-foreground":
+ "oklch(var(--warning-foreground) / )",
+ },
+ },
+ },
+}
+```
+
+```tsx
+// 3. Use in components.
+Warning
+```
+
+---
+
+## Border Radius
+
+`--radius` controls border radius globally. Components derive values from it (`rounded-lg` = `var(--radius)`, `rounded-md` = `calc(var(--radius) - 2px)`).
+
+---
+
+## Customizing Components
+
+See also: [rules/styling.md](./rules/styling.md) for Incorrect/Correct examples.
+
+Prefer these approaches in order:
+
+### 1. Built-in variants
+
+```tsx
+
+```
+
+### 2. Tailwind classes via `className`
+
+```tsx
+...
+```
+
+### 3. Add a new variant
+
+Edit the component source to add a variant via `cva`:
+
+```tsx
+// components/ui/button.tsx
+warning: "bg-warning text-warning-foreground hover:bg-warning/90",
+```
+
+### 4. Wrapper components
+
+Compose shadcn/ui primitives into higher-level components:
+
+```tsx
+export function ConfirmDialog({ title, description, onConfirm, children }) {
+ return (
+
+ {children}
+
+
+ {title}
+ {description}
+
+
+ Cancel
+ Confirm
+
+
+
+ )
+}
+```
+
+---
+
+## Checking for Updates
+
+```bash
+npx shadcn@latest add button --diff
+```
+
+To preview exactly what would change before updating, use `--dry-run` and `--diff`:
+
+```bash
+npx shadcn@latest add button --dry-run # see all affected files
+npx shadcn@latest add button --diff button.tsx # see the diff for a specific file
+```
+
+See [Updating Components in SKILL.md](./SKILL.md#updating-components) for the full smart merge workflow.
diff --git a/distribution_fe/.agents/skills/shadcn/evals/evals.json b/distribution_fe/.agents/skills/shadcn/evals/evals.json
new file mode 100644
index 0000000..c1b7bdd
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/evals/evals.json
@@ -0,0 +1,77 @@
+{
+ "skill_name": "shadcn",
+ "evals": [
+ {
+ "id": 1,
+ "prompt": "I'm building a Next.js app with shadcn/ui (base-nova preset, lucide icons). Create a settings form component with fields for: full name, email address, and notification preferences (email, SMS, push notifications as toggle options). Add validation states for required fields.",
+ "expected_output": "A React component using FieldGroup, Field, ToggleGroup, data-invalid/aria-invalid validation, gap-* spacing, and semantic colors.",
+ "files": [],
+ "expectations": [
+ "Uses FieldGroup and Field components for form layout instead of raw div with space-y",
+ "Uses Switch for independent on/off notification toggles (not looping Button with manual active state)",
+ "Uses data-invalid on Field and aria-invalid on the input control for validation states",
+ "Uses gap-* (e.g. gap-4, gap-6) instead of space-y-* or space-x-* for spacing",
+ "Uses semantic color tokens (e.g. bg-background, text-muted-foreground, text-destructive) instead of raw colors like bg-red-500",
+ "No manual dark: color overrides"
+ ]
+ },
+ {
+ "id": 2,
+ "prompt": "Create a dialog component for editing a user profile. It should have the user's avatar at the top, input fields for name and bio, and Save/Cancel buttons with appropriate icons. Using shadcn/ui with radix-nova preset and tabler icons.",
+ "expected_output": "A React component with DialogTitle, Avatar+AvatarFallback, data-icon on icon buttons, no icon sizing classes, tabler icon imports.",
+ "files": [],
+ "expectations": [
+ "Includes DialogTitle for accessibility (visible or with sr-only class)",
+ "Avatar component includes AvatarFallback",
+ "Icons on buttons use the data-icon attribute (data-icon=\"inline-start\" or data-icon=\"inline-end\")",
+ "No sizing classes on icons inside components (no size-4, w-4, h-4, etc.)",
+ "Uses tabler icons (@tabler/icons-react) instead of lucide-react",
+ "Uses asChild for custom triggers (radix preset)"
+ ]
+ },
+ {
+ "id": 3,
+ "prompt": "Create a dashboard component that shows 4 stat cards in a grid. Each card has a title, large number, percentage change badge, and a loading skeleton state. Using shadcn/ui with base-nova preset and lucide icons.",
+ "expected_output": "A React component with full Card composition, Skeleton for loading, Badge for changes, semantic colors, gap-* spacing.",
+ "files": [],
+ "expectations": [
+ "Uses full Card composition with CardHeader, CardTitle, CardContent (not dumping everything into CardContent)",
+ "Uses Skeleton component for loading placeholders instead of custom animate-pulse divs",
+ "Uses Badge component for percentage change instead of custom styled spans",
+ "Uses semantic color tokens instead of raw color values like bg-green-500 or text-red-600",
+ "Uses gap-* instead of space-y-* or space-x-* for spacing",
+ "Uses size-* when width and height are equal instead of separate w-* h-*"
+ ]
+ },
+ {
+ "id": 4,
+ "prompt": "I'm building a Next.js app with shadcn/ui (base-nova preset, lucide icons). Build a chat conversation view: a scrollable thread of messages from two different people, each with an avatar, sender name, timestamp, and message bubble. A couple of messages include an image attachment and a PDF file attachment, and there's a 'Today' divider separating the days.",
+ "expected_output": "A React component composing MessageScroller, Message, Bubble, Attachment, and Marker from the registry instead of hand-rolled bubble/divider/attachment markup.",
+ "files": [],
+ "expectations": [
+ "Uses MessageScroller (MessageScrollerProvider, MessageScrollerViewport, MessageScrollerContent, MessageScrollerItem) for the scrollable thread instead of a raw overflow-y-auto div or ScrollArea",
+ "Wraps each row in MessageScrollerItem inside MessageScrollerContent",
+ "Uses Message with MessageAvatar/MessageContent/MessageHeader for row layout instead of custom flex divs",
+ "Uses Bubble + BubbleContent for the message surface instead of a styled div with bg-muted/bg-primary",
+ "Uses Attachment (AttachmentMedia, AttachmentContent, AttachmentTitle, AttachmentDescription) for the file and image attachments instead of Item or a custom card",
+ "Uses Marker (variant=\"separator\") for the 'Today' divider instead of Separator plus a centered label",
+ "Uses semantic color tokens and gap-* spacing; no raw colors like bg-emerald-500 and no space-y-*",
+ "Includes \"use client\" when the component uses state or event handlers (isRSC)"
+ ]
+ },
+ {
+ "id": 5,
+ "prompt": "Using shadcn/ui (base-nova preset, lucide icons), build a streaming AI chat UI. The assistant's reply streams in while it generates, the view auto-scrolls to follow the latest content but stops following if the user scrolls up to read earlier messages, a 'jump to latest' button appears when the user has scrolled away from the bottom, and a subtle 'thinking…' shimmer shows while the model is generating.",
+ "expected_output": "A React component that delegates scroll/anchor behavior to MessageScroller and uses MessageScrollerButton for jump-to-latest and the shimmer utility for the thinking indicator — no hand-rolled scroll logic or custom shimmer keyframes.",
+ "files": [],
+ "expectations": [
+ "Uses MessageScroller with MessageScrollerProvider (autoScroll) and scrollAnchor on message items for the stick-to-bottom/follow behavior instead of a custom useStickToBottom hook or ResizeObserver/scrollTop wiring",
+ "Uses MessageScrollerButton for the jump-to-latest control instead of a hand-built conditional button driven by manual scroll-position state",
+ "Uses the shimmer utility class for the 'thinking…' indicator instead of a custom @keyframes or bg-clip-text gradient animation",
+ "Wraps each message row in MessageScrollerItem inside MessageScrollerContent",
+ "Uses Message + Bubble + BubbleContent for the conversation rows instead of hand-rolled bubble divs",
+ "Uses semantic color tokens and gap-* spacing; includes \"use client\" (isRSC)"
+ ]
+ }
+ ]
+}
diff --git a/distribution_fe/.agents/skills/shadcn/mcp.md b/distribution_fe/.agents/skills/shadcn/mcp.md
new file mode 100644
index 0000000..6539dda
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/mcp.md
@@ -0,0 +1,105 @@
+# shadcn MCP Server
+
+The CLI includes an MCP server that lets AI assistants search, browse, view, and install items from registries.
+
+---
+
+## Setup
+
+```bash
+shadcn mcp # start the MCP server (stdio)
+shadcn mcp init # write config for your editor
+```
+
+Editor config files:
+
+| Editor | Config file |
+| ----------- | ------------------------------- |
+| Claude Code | `.mcp.json` |
+| Cursor | `.cursor/mcp.json` |
+| VS Code | `.vscode/mcp.json` |
+| OpenCode | `opencode.json` |
+| Codex | `~/.codex/config.toml` (manual) |
+
+---
+
+## Tools
+
+> **Tip:** MCP tools handle registry operations (search, view, install). For project configuration (aliases, framework, Tailwind version), use `npx shadcn@latest info` — there is no MCP equivalent.
+
+### `shadcn:get_project_registries`
+
+Returns registry names from `components.json`. Errors if no `components.json` exists.
+
+**Input:** none
+
+### `shadcn:list_items_in_registries`
+
+Lists all items from one or more registries. Registries can be configured
+namespaces such as `@acme`, public GitHub sources such as `owner/repo`, or
+registry catalog URLs. Omit `registries` to list from every registry configured
+in `components.json`.
+
+**Input:** `registries` (string[], optional — omit for all configured), `types` (string[], optional — e.g. `["ui", "block"]`), `limit` (number, optional, defaults to 100), `offset` (number, optional)
+
+### `shadcn:search_items_in_registries`
+
+Fuzzy search across registries. Registries can be configured namespaces, public
+GitHub sources, or registry catalog URLs. Omit `registries` to search every
+registry configured in `components.json` — e.g. "find me a hero" across all
+configured registries.
+
+**Input:** `registries` (string[], optional — omit for all configured), `query` (string), `types` (string[], optional — e.g. `["ui", "block"]`), `limit` (number, optional, defaults to 100), `offset` (number, optional)
+
+### `shadcn:view_items_in_registries`
+
+View item details including full file contents.
+
+**Input:** `items` (string[]) — e.g.
+`["@shadcn/button", "@shadcn/card", "owner/repo/item"]`
+
+### `shadcn:get_item_examples_from_registries`
+
+Find usage examples and demos with source code. Omit `registries` to search
+every registry configured in `components.json`.
+
+**Input:** `registries` (string[], optional — omit for all configured), `query` (string) — e.g. `"accordion-demo"`, `"button example"`
+
+### `shadcn:get_add_command_for_items`
+
+Returns the CLI install command.
+
+**Input:** `items` (string[]) — e.g. `["@shadcn/button"]`
+
+### `shadcn:get_audit_checklist`
+
+Returns a checklist for verifying components (imports, deps, lint, TypeScript).
+
+**Input:** none
+
+---
+
+## Configuring Registries
+
+Namespaced and authenticated registries are set in `components.json`. The
+`@shadcn` registry is always built-in. Public GitHub registries can also be used
+directly as `owner/repo` registry sources when the repository has a root
+`registry.json`; they do not need `components.json` configuration.
+
+```json
+{
+ "registries": {
+ "@acme": "https://acme.com/r/{name}.json",
+ "@private": {
+ "url": "https://private.com/r/{name}.json",
+ "headers": { "Authorization": "Bearer ${MY_TOKEN}" }
+ }
+ }
+}
+```
+
+- Names must start with `@`.
+- URLs must contain `{name}`.
+- `${VAR}` references are resolved from environment variables.
+
+Community registry index: `https://ui.shadcn.com/r/registries.json`
diff --git a/distribution_fe/.agents/skills/shadcn/registry.md b/distribution_fe/.agents/skills/shadcn/registry.md
new file mode 100644
index 0000000..5369468
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/registry.md
@@ -0,0 +1,277 @@
+# Registry Authoring and Addresses
+
+Use this reference when the user wants to create, fix, publish, or reason about
+a shadcn registry.
+
+## Mental Model
+
+A registry has two forms:
+
+- **Source registry**: an authored `registry.json` in a project or repository.
+ It may use `include` and file paths that point at source files.
+- **Built registry**: generated JSON files served to CLI consumers, usually
+ from `public/r`. Use `npx shadcn@latest build` to create this form.
+
+The CLI installer consumes registry item payloads. A source registry is a way to
+author those payloads from real files.
+
+Registry items are not limited to React components. They can distribute
+components, hooks, utilities, design tokens, pages, config files, docs, rules,
+workflows, templates, MCP files, and other project files.
+
+## Root `registry.json`
+
+The root registry file should define registry metadata and either `items` or
+`include`.
+
+```json
+{
+ "$schema": "https://ui.shadcn.com/schema/registry.json",
+ "name": "acme",
+ "homepage": "https://acme.com",
+ "items": [
+ {
+ "name": "absolute-url",
+ "type": "registry:lib",
+ "title": "Absolute URL",
+ "description": "A utility to turn any path into an absolute URL.",
+ "files": [
+ {
+ "path": "lib/absolute-url.ts",
+ "type": "registry:lib"
+ }
+ ]
+ }
+ ]
+}
+```
+
+Root registry rules:
+
+- Root `registry.json` must include `name` and `homepage`.
+- `items` is an array of registry item definitions.
+- `include` may be used to split the source registry into multiple files.
+- Included registry files may omit `name` and `homepage`.
+
+## Include
+
+Use `include` to keep large registries modular.
+
+```json
+{
+ "$schema": "https://ui.shadcn.com/schema/registry.json",
+ "name": "acme",
+ "homepage": "https://acme.com",
+ "include": ["registry/ui/registry.json", "registry/blocks/registry.json"]
+}
+```
+
+Include rules:
+
+- Include paths are relative to the `registry.json` that declares them.
+- Include paths must explicitly point to a `registry.json` file.
+- Do not use remote URLs, absolute paths, or parent traversal (`..`).
+- Item file paths are relative to the registry file that declares the item.
+- Duplicate item names fail across the resolved registry.
+
+Example included file:
+
+```json
+{
+ "items": [
+ {
+ "name": "button",
+ "type": "registry:ui",
+ "files": [
+ {
+ "path": "button.tsx",
+ "type": "registry:ui"
+ }
+ ]
+ }
+ ]
+}
+```
+
+If this file is at `registry/ui/registry.json`, then `button.tsx` is read from
+`registry/ui/button.tsx`, and the built item path is emitted relative to the
+root registry.
+
+## Item Definitions
+
+Common item fields:
+
+```json
+{
+ "name": "login-form",
+ "type": "registry:block",
+ "title": "Login Form",
+ "description": "A login form with email and password fields.",
+ "dependencies": ["zod"],
+ "registryDependencies": ["button", "input", "label"],
+ "files": [
+ {
+ "path": "blocks/login-form.tsx",
+ "type": "registry:block"
+ }
+ ],
+ "cssVars": {
+ "light": {
+ "brand": "oklch(0.62 0.18 250)"
+ },
+ "dark": {
+ "brand": "oklch(0.72 0.16 250)"
+ }
+ }
+}
+```
+
+Important fields:
+
+- `name`: the installable item name. It is not necessarily a file path.
+- `type`: one of the registry item types, such as `registry:ui`,
+ `registry:block`, `registry:lib`, `registry:hook`, `registry:file`,
+ `registry:page`, `registry:theme`, `registry:style`, `registry:font`, or
+ `registry:item`.
+- `files`: source files copied or generated by the item.
+- `dependencies`: npm runtime dependencies.
+- `devDependencies`: npm development dependencies.
+- `registryDependencies`: other registry items required by this item.
+- `cssVars`, `css`, `tailwind`, `envVars`, and `docs`: optional install-time
+ additions.
+
+File rules:
+
+- File paths are relative to the declaring `registry.json`.
+- `registry:file` and `registry:page` files require a `target`.
+- Do not use remote file URLs in source registry file paths.
+- Keep source files copy-pasteable: no hidden app-only imports.
+
+## Registry Dependencies
+
+`registryDependencies` entries are item addresses, not file paths.
+
+```json
+{
+ "name": "login-form",
+ "type": "registry:block",
+ "registryDependencies": ["button", "@acme/input", "acme/ui/card#v1.2.0"],
+ "files": [
+ {
+ "path": "blocks/login-form.tsx",
+ "type": "registry:block"
+ }
+ ]
+}
+```
+
+Dependency rules:
+
+- Bare names such as `"button"` mean official shadcn items.
+- Bare names never mean same-registry or same-repository items.
+- Namespaced dependencies use `@namespace/item-name`.
+- GitHub dependencies use `owner/repo/item-name`.
+- Pin GitHub dependencies with `owner/repo/item-name#ref` when needed.
+- Refs are not inherited. If `owner/repo/foo#v2` depends on `bar` from the same
+ repo at `v2`, write `owner/repo/bar#v2`.
+- Do not use relative dependencies such as `"./bar"`.
+
+## Address Schemes
+
+When reasoning about a registry item string, classify it first.
+
+| Address | Scheme | Meaning |
+| ----------------------------------- | --------- | ------------------------------------------------------------ |
+| `button` | shadcn | Official shadcn item named `button`. |
+| `@acme/button` | namespace | Item `button` from configured registry `@acme`. |
+| `@acme/ui/button` | namespace | Item `ui/button` from configured registry `@acme`. |
+| `https://example.com/r/button.json` | url | Built registry item JSON at that URL. |
+| `./button.json` | file | Built registry item JSON on disk. |
+| `acme/ui/button` | github | Item `button` from GitHub repo `acme/ui`. |
+| `acme/ui/forms/login#main` | github | Item `forms/login` from GitHub repo `acme/ui` at ref `main`. |
+
+For namespace and GitHub addresses, slashful item names are allowed and are item
+names, not file paths. Addresses ending in `.json` keep file-address
+precedence, so `acme/ui/data/schema.json` is treated as a file path, not a
+GitHub item address.
+
+## GitHub Registries
+
+A public GitHub repository can act as a source registry when it has a root
+`registry.json`.
+
+```txt
+owner/repo/item-name[#ref]
+```
+
+Rules:
+
+- The first two path segments are GitHub owner and repo.
+- All remaining path segments are the registry item name.
+- The source entrypoint is always root `registry.json`.
+- GitHub registries are source registries consumed directly by the CLI. They do
+ not require `shadcn build` or generated item JSON files.
+- `include` follows the same source-registry rules as local registries.
+- Currently, GitHub addresses support public `github.com` repositories only.
+- Private repos and GitHub Enterprise require explicit product decisions.
+
+When implementing GitHub registry fetching, resolve refs to a commit SHA before
+reading source files. Do not read moving refs directly from
+`raw.githubusercontent.com`, because branch-like refs can be cached for several
+minutes.
+
+Preferred flow:
+
+```txt
+owner/repo[#ref]
+ -> resolve ref with git ls-remote
+ -> commit SHA
+ -> read https://raw.githubusercontent.com/{owner}/{repo}/{sha}/registry.json
+ -> read includes and item files from the same SHA
+```
+
+This keeps a command on one consistent repository snapshot.
+
+Full 40-character commit SHAs are already stable and can be used directly.
+Branches, tags, and short refs require Git so the CLI can resolve them to a
+commit SHA first.
+
+## Build and Verify
+
+Use the CLI to build source registries:
+
+```bash
+npx shadcn@latest build
+npx shadcn@latest build registry.json --output public/r
+```
+
+Use CLI commands to inspect the result:
+
+```bash
+npx shadcn@latest list @acme
+npx shadcn@latest search @acme -q "login"
+npx shadcn@latest view @acme/login-form
+npx shadcn@latest add @acme/login-form --dry-run
+npx shadcn@latest registry validate ./registry.json
+```
+
+Use GitHub addresses directly for public GitHub registries:
+
+```bash
+npx shadcn@latest list owner/repo
+npx shadcn@latest search owner/repo -q "login"
+npx shadcn@latest view owner/repo/item
+npx shadcn@latest add owner/repo/item --dry-run
+npx shadcn@latest registry validate owner/repo
+```
+
+When working on registry implementation in the shadcn/ui codebase:
+
+- Keep address parsing pure and testable.
+- Do not add side effects to validators.
+- Preserve existing behavior for official shadcn, namespace, URL, and file
+ schemes.
+- Add tests for address parsing, source loading, dependency resolution, list,
+ search, view, and add paths.
+- Prefer small source-reader abstractions over a plugin system until there are
+ multiple real providers.
diff --git a/distribution_fe/.agents/skills/shadcn/rules/base-vs-radix.md b/distribution_fe/.agents/skills/shadcn/rules/base-vs-radix.md
new file mode 100644
index 0000000..c1ed7d1
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/rules/base-vs-radix.md
@@ -0,0 +1,306 @@
+# Base vs Radix
+
+API differences between `base` and `radix`. Check the `base` field from `npx shadcn@latest info`.
+
+## Contents
+
+- Composition: asChild vs render
+- Button / trigger as non-button element
+- Select (items prop, placeholder, positioning, multiple, object values)
+- ToggleGroup (type vs multiple)
+- Slider (scalar vs array)
+- Accordion (type and defaultValue)
+
+---
+
+## Composition: asChild (radix) vs render (base)
+
+Radix uses `asChild` to replace the default element. Base uses `render`. Don't wrap triggers in extra elements.
+
+**Incorrect:**
+
+```tsx
+
+
+
+
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+
+
+```
+
+**Correct (base):**
+
+```tsx
+ }>Open
+```
+
+This applies to all trigger and close components: `DialogTrigger`, `SheetTrigger`, `AlertDialogTrigger`, `DropdownMenuTrigger`, `PopoverTrigger`, `TooltipTrigger`, `CollapsibleTrigger`, `DialogClose`, `SheetClose`, `NavigationMenuLink`, `BreadcrumbLink`, `SidebarMenuButton`, `Badge`, `Item`.
+
+---
+
+## Button / trigger as non-button element (base only)
+
+When `render` changes an element to a non-button (``, ``), add `nativeButton={false}`.
+
+**Incorrect (base):** missing `nativeButton={false}`.
+
+```tsx
+}>Read the docs
+```
+
+**Correct (base):**
+
+```tsx
+} nativeButton={false}>
+ Read the docs
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+```
+
+Same for triggers whose `render` is not a `Button`:
+
+```tsx
+// base.
+ } nativeButton={false}>
+ Pick date
+
+```
+
+---
+
+## Select
+
+**items prop (base only).** Base requires an `items` prop on the root. Radix uses inline JSX only.
+
+**Incorrect (base):**
+
+```tsx
+
+```
+
+**Correct (base):**
+
+```tsx
+const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+]
+
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+```
+
+**Placeholder.** Base uses a `{ value: null }` item in the items array. Radix uses ``.
+
+**Content positioning.** Base uses `alignItemWithTrigger`. Radix uses `position`.
+
+```tsx
+// base.
+
+
+// radix.
+
+```
+
+---
+
+## Select — multiple selection and object values (base only)
+
+Base supports `multiple`, render-function children on `SelectValue`, and object values with `itemToStringValue`. Radix is single-select with string values only.
+
+**Correct (base — multiple selection):**
+
+```tsx
+
+```
+
+**Correct (base — object values):**
+
+```tsx
+
+```
+
+---
+
+## ToggleGroup
+
+Base uses a `multiple` boolean prop. Radix uses `type="single"` or `type="multiple"`.
+
+**Incorrect (base):**
+
+```tsx
+
+ Daily
+
+```
+
+**Correct (base):**
+
+```tsx
+// Single (no prop needed), defaultValue is always an array.
+
+ Daily
+ Weekly
+
+
+// Multi-selection.
+
+ Bold
+ Italic
+
+```
+
+**Correct (radix):**
+
+```tsx
+// Single, defaultValue is a string.
+
+ Daily
+ Weekly
+
+
+// Multi-selection.
+
+ Bold
+ Italic
+
+```
+
+**Controlled single value:**
+
+```tsx
+// base — wrap/unwrap arrays.
+const [value, setValue] = React.useState("normal")
+ setValue(v[0])}>
+
+// radix — plain string.
+const [value, setValue] = React.useState("normal")
+
+```
+
+---
+
+## Slider
+
+Base accepts a plain number for a single thumb. Radix always requires an array.
+
+**Incorrect (base):**
+
+```tsx
+
+```
+
+**Correct (base):**
+
+```tsx
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+```
+
+Both use arrays for range sliders. Controlled `onValueChange` in base may need a cast:
+
+```tsx
+// base.
+const [value, setValue] = React.useState([0.3, 0.7])
+ setValue(v as number[])} />
+
+// radix.
+const [value, setValue] = React.useState([0.3, 0.7])
+
+```
+
+---
+
+## Accordion
+
+Radix requires `type="single"` or `type="multiple"` and supports `collapsible`. `defaultValue` is a string. Base uses no `type` prop, uses `multiple` boolean, and `defaultValue` is always an array.
+
+**Incorrect (base):**
+
+```tsx
+
+ ...
+
+```
+
+**Correct (base):**
+
+```tsx
+
+ ...
+
+
+// Multi-select.
+
+ ...
+ ...
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+ ...
+
+```
diff --git a/distribution_fe/.agents/skills/shadcn/rules/chat.md b/distribution_fe/.agents/skills/shadcn/rules/chat.md
new file mode 100644
index 0000000..8ce62fe
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/rules/chat.md
@@ -0,0 +1,224 @@
+# Chat & Messaging
+
+Components for conversation and chat UI. Compose these instead of hand-rolling
+bubbles, scroll containers, dividers, or attachment cards.
+
+Install: `npx shadcn@latest add message-scroller message bubble attachment marker`
+
+The same component names and props ship for both `base` and `radix`; only
+composition differs (`render` vs `asChild`). See [base-vs-radix.md](./base-vs-radix.md).
+
+## Contents
+
+- Scrollable threads use MessageScroller
+- Message rows use Message
+- Message surfaces use Bubble
+- Attachments use Attachment
+- System notes and dividers use Marker
+- Streaming, anchoring, and jump-to-latest are built in
+- Escape hatch: the scroller hooks
+
+---
+
+## Scrollable threads use MessageScroller
+
+A conversation that scrolls, follows new messages, restores position, or jumps
+to a message uses `MessageScroller`. Don't build a raw overflow container with
+manual scroll wiring, and don't reach for `ScrollArea`.
+
+The parts nest in a fixed order. Every direct child of the content is wrapped in
+a `MessageScrollerItem` so the scroller can measure, anchor, preserve position,
+track visibility, and jump to it. `MessageScrollerButton` sits inside
+`MessageScroller`, after the viewport.
+
+**Incorrect:**
+
+```tsx
+// Hand-rolled scroll container with manual stick-to-bottom logic.
+
+
+ {messages.map((m) => (
+
+ ))}
+
+
+```
+
+**Correct:**
+
+```tsx
+
+
+
+
+ {messages.map((message) => (
+
+
+ {/* ...message content... */}
+
+
+ ))}
+
+
+
+
+
+```
+
+---
+
+## Message rows use Message
+
+`Message` lays out a single row: avatar, header, content, footer, with
+alignment. Group consecutive rows from one sender with `MessageGroup`. Don't
+rebuild the row from flex divs.
+
+`align="end"` is the current user's side; `align="start"` is everyone else.
+
+```tsx
+
+
+
+
+ {initials}
+
+
+
+ {sender.name}
+
+ {text}
+
+ {time}
+
+
+```
+
+---
+
+## Message surfaces use Bubble
+
+The colored message surface is `Bubble` + `BubbleContent`, never a styled `div`
+with `bg-muted` / `bg-primary` and hand-managed corners.
+
+- `variant`: `default`, `secondary`, `muted`, `tinted`, `outline`, `ghost`, `destructive`.
+- `align`: `start` or `end` (matches the `Message` side).
+
+`BubbleReactions` renders the reaction cluster. `side` (`top` | `bottom`) and
+`align` (`start` | `end`) position it against the bubble. Don't lay reactions out
+with absolutely-positioned `Badge`s.
+
+**Incorrect:**
+
+```tsx
+
+ {text}
+
+```
+
+**Correct:**
+
+```tsx
+
+ {text}
+
+ 👍 2
+
+
+```
+
+---
+
+## Attachments use Attachment
+
+File and image attachments use `Attachment`, not `Item` or a custom card. It
+carries upload state, so wire `state` to the real status rather than rendering a
+separate spinner.
+
+- `state`: `idle`, `uploading`, `processing`, `error`, `done`. `uploading` and
+ `processing` apply the `shimmer` animation to the title automatically.
+- `size`: `default`, `sm`, `xs`. `orientation`: `horizontal`, `vertical`.
+- Use `AttachmentGroup` to lay out several attachments in a scrolling row.
+
+```tsx
+
+
+
+
+
+ homepage-feedback.pdf
+ PDF · 2.4 MB
+
+
+
+
+
+
+
+```
+
+For an image, use `` with an `img` child.
+
+---
+
+## System notes and dividers use Marker
+
+Status lines ("Sarah joined the conversation"), date dividers ("Today"), and
+labeled separators are `Marker`, not a `Separator` plus a centered span.
+
+- `variant`: `default` (plain row), `separator` (centered label with rules on
+ each side), `border` (bottom-bordered row).
+- `MarkerIcon` holds a leading icon; `MarkerContent` holds the label.
+
+**Incorrect:**
+
+```tsx
+
+
+ Today
+
+
+```
+
+**Correct:**
+
+```tsx
+
+ Today
+
+```
+
+---
+
+## Streaming, anchoring, and jump-to-latest are built in
+
+`MessageScroller` handles the behavior that chat UIs usually reinvent. Don't
+write a `useStickToBottom` hook, a `ResizeObserver`, or manual `scrollTop` math.
+
+- **Follow the live edge while streaming.** `MessageScrollerProvider` with
+ `autoScroll` keeps the view pinned to new content and yields the moment the
+ user scrolls up. Streaming token updates that grow the last message are
+ followed automatically.
+- **Anchor a turn.** `scrollAnchor` on a `MessageScrollerItem` marks the row to
+ hold in view (typically the user's message that started the turn).
+- **Jump to latest.** `MessageScrollerButton` appears when the user scrolls away
+ and scrolls back on click. `direction="end"` (default) or `direction="start"`.
+ It is a self-managing control, so don't gate it behind your own scroll-position
+ state.
+
+For a "thinking…" indicator while the model generates, apply the `shimmer`
+utility to text. Don't author a custom keyframe animation. See
+[styling.md](./styling.md).
+
+---
+
+## Escape hatch: the scroller hooks
+
+For behavior the parts don't expose, read state from the hooks rather than
+re-implementing the scroller: `useMessageScroller`,
+`useMessageScrollerVisibility`, and `useMessageScrollerScrollable`. They come
+from the auto-installed `@shadcn/react` dependency, so there's nothing extra to
+install. Reach for them only when composition can't express what you need.
diff --git a/distribution_fe/.agents/skills/shadcn/rules/composition.md b/distribution_fe/.agents/skills/shadcn/rules/composition.md
new file mode 100644
index 0000000..a8aa427
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/rules/composition.md
@@ -0,0 +1,213 @@
+# Component Composition
+
+## Contents
+
+- Items always inside their Group component
+- Callouts use Alert
+- Empty states use Empty component
+- Toast notifications follow the project base
+- Choosing between overlay components
+- Dialog, Sheet, and Drawer always need a Title
+- Card structure
+- Button has no isPending or isLoading prop
+- TabsTrigger must be inside TabsList
+- Avatar always needs AvatarFallback
+- Use Separator instead of raw hr or border divs
+- Use Skeleton for loading placeholders
+- Use Badge instead of custom styled spans
+
+---
+
+## Items always inside their Group component
+
+Never render items directly inside the content container.
+
+**Incorrect:**
+
+```tsx
+
+ Apple
+ Banana
+
+```
+
+**Correct:**
+
+```tsx
+
+
+ Apple
+ Banana
+
+
+```
+
+This applies to all group-based components:
+
+| Item | Group |
+|------|-------|
+| `SelectItem`, `SelectLabel` | `SelectGroup` |
+| `DropdownMenuItem`, `DropdownMenuLabel`, `DropdownMenuSub` | `DropdownMenuGroup` |
+| `MenubarItem` | `MenubarGroup` |
+| `ContextMenuItem` | `ContextMenuGroup` |
+| `CommandItem` | `CommandGroup` |
+| `MessageScrollerItem` | `MessageScrollerContent` |
+| `Message` (consecutive, same sender) | `MessageGroup` |
+| `Bubble` (stacked) | `BubbleGroup` |
+| `Attachment` (in a row) | `AttachmentGroup` |
+
+Chat components nest in a fixed order (`MessageScrollerProvider` → `MessageScroller` → `MessageScrollerViewport` → `MessageScrollerContent` → `MessageScrollerItem`). See [chat.md](./chat.md).
+
+---
+
+## Callouts use Alert
+
+```tsx
+
+ Warning
+ Something needs attention.
+
+```
+
+---
+
+## Empty states use Empty component
+
+```tsx
+
+
+
+ No projects yet
+ Get started by creating a new project.
+
+
+
+
+
+```
+
+---
+
+## Toast notifications follow the project base
+
+For Base UI projects, use the `toast` component:
+
+```tsx
+import { toast } from "@/components/ui/toast"
+
+toast.add({
+ title: "Changes saved.",
+})
+```
+
+For Radix and React Aria projects, use Sonner:
+
+```tsx
+import { toast } from "sonner"
+
+toast.success("Changes saved.")
+toast.error("Something went wrong.")
+toast("File deleted.", {
+ action: { label: "Undo", onClick: () => undoDelete() },
+})
+```
+
+---
+
+## Choosing between overlay components
+
+| Use case | Component |
+|----------|-----------|
+| Focused task that requires input | `Dialog` |
+| Destructive action confirmation | `AlertDialog` |
+| Side panel with details or filters | `Sheet` |
+| Mobile-first bottom panel | `Drawer` |
+| Quick info on hover | `HoverCard` |
+| Small contextual content on click | `Popover` |
+
+---
+
+## Dialog, Sheet, and Drawer always need a Title
+
+`DialogTitle`, `SheetTitle`, `DrawerTitle` are required for accessibility. Use `className="sr-only"` if visually hidden.
+
+```tsx
+
+
+ Edit Profile
+ Update your profile.
+
+ ...
+
+```
+
+---
+
+## Card structure
+
+Use full composition — don't dump everything into `CardContent`:
+
+```tsx
+
+
+ Team Members
+ Manage your team.
+
+ ...
+
+
+
+
+```
+
+---
+
+## Button has no isPending or isLoading prop
+
+Compose with `Spinner` + `data-icon` + `disabled`:
+
+```tsx
+
+```
+
+---
+
+## TabsTrigger must be inside TabsList
+
+Never render `TabsTrigger` directly inside `Tabs` — always wrap in `TabsList`:
+
+```tsx
+
+
+ Account
+ Password
+
+ ...
+
+```
+
+---
+
+## Avatar always needs AvatarFallback
+
+Always include `AvatarFallback` for when the image fails to load:
+
+```tsx
+
+
+ JD
+
+```
+
+---
+
+## Use existing components instead of custom markup
+
+| Instead of | Use |
+|---|---|
+| `
` or `` | ` ` |
+| `` with styled divs | ` ` |
+| `` | `` |
diff --git a/distribution_fe/.agents/skills/shadcn/rules/forms.md b/distribution_fe/.agents/skills/shadcn/rules/forms.md
new file mode 100644
index 0000000..f451e2f
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/rules/forms.md
@@ -0,0 +1,192 @@
+# Forms & Inputs
+
+## Contents
+
+- Forms use FieldGroup + Field
+- InputGroup requires InputGroupInput/InputGroupTextarea
+- Buttons inside inputs use InputGroup + InputGroupAddon
+- Option sets (2–7 choices) use ToggleGroup
+- FieldSet + FieldLegend for grouping related fields
+- Field validation and disabled states
+
+---
+
+## Forms use FieldGroup + Field
+
+Always use `FieldGroup` + `Field` — never raw `div` with `space-y-*`:
+
+```tsx
+
+
+ Email
+
+
+
+ Password
+
+
+
+```
+
+Use `Field orientation="horizontal"` for settings pages. Use `FieldLabel className="sr-only"` for visually hidden labels.
+
+**Choosing form controls:**
+
+- Simple text input → `Input`
+- Dropdown with predefined options → `Select`
+- Searchable dropdown → `Combobox`
+- Native HTML select (no JS) → `native-select`
+- Boolean toggle → `Switch` (for settings) or `Checkbox` (for forms)
+- Single choice from few options → `RadioGroup`
+- Toggle between 2–5 options → `ToggleGroup` + `ToggleGroupItem`
+- OTP/verification code → `InputOTP`
+- Multi-line text → `Textarea`
+
+---
+
+## InputGroup requires InputGroupInput/InputGroupTextarea
+
+Never use raw `Input` or `Textarea` inside an `InputGroup`.
+
+**Incorrect:**
+
+```tsx
+
+
+
+```
+
+**Correct:**
+
+```tsx
+import { InputGroup, InputGroupInput } from "@/components/ui/input-group"
+
+
+
+
+```
+
+---
+
+## Buttons inside inputs use InputGroup + InputGroupAddon
+
+Never place a `Button` directly inside or adjacent to an `Input` with custom positioning.
+
+**Incorrect:**
+
+```tsx
+
+
+
+
+```
+
+**Correct:**
+
+```tsx
+import { InputGroup, InputGroupInput, InputGroupAddon } from "@/components/ui/input-group"
+
+
+
+
+
+
+
+```
+
+---
+
+## Option sets (2–7 choices) use ToggleGroup
+
+Don't manually loop `Button` components with active state.
+
+**Incorrect:**
+
+```tsx
+const [selected, setSelected] = useState("daily")
+
+
+ {["daily", "weekly", "monthly"].map((option) => (
+
+ ))}
+
+```
+
+**Correct:**
+
+```tsx
+import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
+
+
+ Daily
+ Weekly
+ Monthly
+
+```
+
+Combine with `Field` for labelled toggle groups:
+
+```tsx
+
+ Theme
+
+ Light
+ Dark
+ System
+
+
+```
+
+> **Note:** `defaultValue` and `type`/`multiple` props differ between base and radix. See [base-vs-radix.md](./base-vs-radix.md#togglegroup).
+
+---
+
+## FieldSet + FieldLegend for grouping related fields
+
+Use `FieldSet` + `FieldLegend` for related checkboxes, radios, or switches — not `div` with a heading:
+
+```tsx
+
+```
+
+---
+
+## Field validation and disabled states
+
+Both attributes are needed — `data-invalid`/`data-disabled` styles the field (label, description), while `aria-invalid`/`disabled` styles the control.
+
+```tsx
+// Invalid.
+
+ Email
+
+ Invalid email address.
+
+
+// Disabled.
+
+ Email
+
+
+```
+
+Works for all controls: `Input`, `Textarea`, `Select`, `Checkbox`, `RadioGroupItem`, `Switch`, `Slider`, `NativeSelect`, `InputOTP`.
diff --git a/distribution_fe/.agents/skills/shadcn/rules/icons.md b/distribution_fe/.agents/skills/shadcn/rules/icons.md
new file mode 100644
index 0000000..bba8102
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/rules/icons.md
@@ -0,0 +1,101 @@
+# Icons
+
+**Always use the project's configured `iconLibrary` for imports.** Check the `iconLibrary` field from project context: `lucide` → `lucide-react`, `tabler` → `@tabler/icons-react`, etc. Never assume `lucide-react`.
+
+---
+
+## Icons in Button use data-icon attribute
+
+Add `data-icon="inline-start"` (prefix) or `data-icon="inline-end"` (suffix) to the icon. No sizing classes on the icon.
+
+**Incorrect:**
+
+```tsx
+
+```
+
+**Correct:**
+
+```tsx
+
+
+
+```
+
+---
+
+## No sizing classes on icons inside components
+
+Components handle icon sizing via CSS. Don't add `size-4`, `w-4 h-4`, or other sizing classes to icons inside `Button`, `DropdownMenuItem`, `Alert`, `Sidebar*`, or other shadcn components. Unless the user explicitly asks for custom icon sizes.
+
+**Incorrect:**
+
+```tsx
+
+
+
+
+ Settings
+
+```
+
+**Correct:**
+
+```tsx
+
+
+
+
+ Settings
+
+```
+
+---
+
+## Pass icons as component objects, not string keys
+
+Use `icon={CheckIcon}`, not a string key to a lookup map.
+
+**Incorrect:**
+
+```tsx
+const iconMap = {
+ check: CheckIcon,
+ alert: AlertIcon,
+}
+
+function StatusBadge({ icon }: { icon: string }) {
+ const Icon = iconMap[icon]
+ return
+}
+
+
+```
+
+**Correct:**
+
+```tsx
+// Import from the project's configured iconLibrary (e.g. lucide-react, @tabler/icons-react).
+import { CheckIcon } from "lucide-react"
+
+function StatusBadge({ icon: Icon }: { icon: React.ComponentType }) {
+ return
+}
+
+
+```
diff --git a/distribution_fe/.agents/skills/shadcn/rules/styling.md b/distribution_fe/.agents/skills/shadcn/rules/styling.md
new file mode 100644
index 0000000..fe75197
--- /dev/null
+++ b/distribution_fe/.agents/skills/shadcn/rules/styling.md
@@ -0,0 +1,185 @@
+# Styling & Customization
+
+See [customization.md](../customization.md) for theming, CSS variables, and adding custom colors.
+
+## Contents
+
+- Semantic colors
+- Built-in variants first
+- className for layout only
+- No space-x-* / space-y-*
+- Prefer size-* over w-* h-* when equal
+- Prefer truncate shorthand
+- No manual dark: color overrides
+- Use cn() for conditional classes
+- No manual z-index on overlay components
+- Use shimmer / scroll-fade utilities, not custom animations
+
+---
+
+## Semantic colors
+
+**Incorrect:**
+
+```tsx
+
+ Secondary text
+
+```
+
+**Correct:**
+
+```tsx
+
+ Secondary text
+
+```
+
+---
+
+## No raw color values for status/state indicators
+
+For positive, negative, or status indicators, use Badge variants, semantic tokens like `text-destructive`, or define custom CSS variables — don't reach for raw Tailwind colors.
+
+**Incorrect:**
+
+```tsx
++20.1%
+Active
+-3.2%
+```
+
+**Correct:**
+
+```tsx
++20.1%
+Active
+-3.2%
+```
+
+If you need a success/positive color that doesn't exist as a semantic token, use a Badge variant or ask the user about adding a custom CSS variable to the theme (see [customization.md](../customization.md)).
+
+---
+
+## Built-in variants first
+
+**Incorrect:**
+
+```tsx
+
+```
+
+**Correct:**
+
+```tsx
+
+```
+
+---
+
+## className for layout only
+
+Use `className` for layout (e.g. `max-w-md`, `mx-auto`, `mt-4`), **not** for overriding component colors or typography. To change colors, use semantic tokens, built-in variants, or CSS variables.
+
+**Incorrect:**
+
+```tsx
+
+ Dashboard
+
+```
+
+**Correct:**
+
+```tsx
+
+ Dashboard
+
+```
+
+To customize a component's appearance, prefer these approaches in order:
+1. **Built-in variants** — `variant="outline"`, `variant="destructive"`, etc.
+2. **Semantic color tokens** — `bg-primary`, `text-muted-foreground`.
+3. **CSS variables** — define custom colors in the global CSS file (see [customization.md](../customization.md)).
+
+---
+
+## No space-x-* / space-y-*
+
+Use `gap-*` instead. `space-y-4` → `flex flex-col gap-4`. `space-x-2` → `flex gap-2`.
+
+```tsx
+
+
+
+
+
+```
+
+---
+
+## Prefer size-* over w-* h-* when equal
+
+`size-10` not `w-10 h-10`. Applies to icons, avatars, skeletons, etc.
+
+---
+
+## Prefer truncate shorthand
+
+`truncate` not `overflow-hidden text-ellipsis whitespace-nowrap`.
+
+---
+
+## No manual dark: color overrides
+
+Use semantic tokens — they handle light/dark via CSS variables. `bg-background text-foreground` not `bg-white dark:bg-gray-950`.
+
+---
+
+## Use cn() for conditional classes
+
+Use the `cn()` utility from the project for conditional or merged class names. Don't write manual ternaries in className strings.
+
+**Incorrect:**
+
+```tsx
+
+```
+
+**Correct:**
+
+```tsx
+import { cn } from "@/lib/utils"
+
+
+```
+
+---
+
+## No manual z-index on overlay components
+
+`Dialog`, `Sheet`, `Drawer`, `AlertDialog`, `DropdownMenu`, `Popover`, `Tooltip`, `HoverCard` handle their own stacking. Never add `z-50` or `z-[999]`.
+
+---
+
+## Use shimmer / scroll-fade utilities, not custom animations
+
+For a live "thinking…" or loading-text shimmer, apply the `shimmer` utility. Don't author a custom `@keyframes` or a `bg-clip-text` gradient sweep.
+
+For scroll-aware edge fading on a scroll container, use `scroll-fade` (and the axis variants `scroll-fade-x` / `scroll-fade-b`). Don't hand-roll mask gradients. The chat components already apply these internally: `Attachment` shimmers its title during upload, and `MessageScrollerViewport` fades its edges.
+
+**Incorrect:**
+
+```tsx
+
+ Thinking…
+
+```
+
+**Correct:**
+
+```tsx
+Thinking…
+```
diff --git a/distribution_fe/.claude/skills/shadcn/SKILL.md b/distribution_fe/.claude/skills/shadcn/SKILL.md
new file mode 100644
index 0000000..1b4c414
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/SKILL.md
@@ -0,0 +1,277 @@
+---
+name: shadcn
+description: Manages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI, including chat interfaces. Provides project context, component docs, and usage examples. Applies when working with shadcn/ui, component registries, presets, --preset codes, or any project with a components.json file. Also triggers for "shadcn init", "create an app with --preset", or "switch to --preset".
+user-invocable: false
+allowed-tools: Bash(npx shadcn@latest *), Bash(pnpm dlx shadcn@latest *), Bash(bunx --bun shadcn@latest *)
+---
+
+# shadcn/ui
+
+A framework for building ui, components and design systems. Components are added as source code to the user's project via the CLI.
+
+> **IMPORTANT:** Run all CLI commands using the project's package runner: `npx shadcn@latest`, `pnpm dlx shadcn@latest`, or `bunx --bun shadcn@latest` — based on the project's `packageManager`. Examples below use `npx shadcn@latest` but substitute the correct runner for the project.
+
+## Current Project Context
+
+```json
+!`npx shadcn@latest info --json`
+```
+
+The JSON above contains the project config and installed components. Use `npx shadcn@latest docs ` to get documentation and example URLs for any component.
+
+## Principles
+
+1. **Use existing components first.** Use `npx shadcn@latest search` to check registries before writing custom UI. Check community registries too.
+2. **Compose, don't reinvent.** Settings page = Tabs + Card + form controls. Dashboard = Sidebar + Card + Chart + Table.
+3. **Use built-in variants before custom styles.** `variant="outline"`, `size="sm"`, etc.
+4. **Use semantic colors.** `bg-primary`, `text-muted-foreground` — never raw values like `bg-blue-500`.
+
+## Critical Rules
+
+These rules are **always enforced**. Each links to a file with Incorrect/Correct code pairs.
+
+### Styling & Tailwind → [styling.md](./rules/styling.md)
+
+- **`className` for layout, not styling.** Never override component colors or typography.
+- **No `space-x-*` or `space-y-*`.** Use `flex` with `gap-*`. For vertical stacks, `flex flex-col gap-*`.
+- **Use `size-*` when width and height are equal.** `size-10` not `w-10 h-10`.
+- **Use `truncate` shorthand.** Not `overflow-hidden text-ellipsis whitespace-nowrap`.
+- **No manual `dark:` color overrides.** Use semantic tokens (`bg-background`, `text-muted-foreground`).
+- **Use `cn()` for conditional classes.** Don't write manual template literal ternaries.
+- **No manual `z-index` on overlay components.** Dialog, Sheet, Popover, etc. handle their own stacking.
+
+### Forms & Inputs → [forms.md](./rules/forms.md)
+
+- **Forms use `FieldGroup` + `Field`.** Never use raw `div` with `space-y-*` or `grid gap-*` for form layout.
+- **`InputGroup` uses `InputGroupInput`/`InputGroupTextarea`.** Never raw `Input`/`Textarea` inside `InputGroup`.
+- **Buttons inside inputs use `InputGroup` + `InputGroupAddon`.**
+- **Option sets (2–7 choices) use `ToggleGroup`.** Don't loop `Button` with manual active state.
+- **`FieldSet` + `FieldLegend` for grouping related checkboxes/radios.** Don't use a `div` with a heading.
+- **Field validation uses `data-invalid` + `aria-invalid`.** `data-invalid` on `Field`, `aria-invalid` on the control. For disabled: `data-disabled` on `Field`, `disabled` on the control.
+
+### Component Structure → [composition.md](./rules/composition.md)
+
+- **Items always inside their Group.** `SelectItem` → `SelectGroup`. `DropdownMenuItem` → `DropdownMenuGroup`. `CommandItem` → `CommandGroup`.
+- **Use `asChild` (radix) or `render` (base) for custom triggers.** Check `base` field from `npx shadcn@latest info`. → [base-vs-radix.md](./rules/base-vs-radix.md)
+- **Dialog, Sheet, and Drawer always need a Title.** `DialogTitle`, `SheetTitle`, `DrawerTitle` required for accessibility. Use `className="sr-only"` if visually hidden.
+- **Use full Card composition.** `CardHeader`/`CardTitle`/`CardDescription`/`CardContent`/`CardFooter`. Don't dump everything in `CardContent`.
+- **Button has no `isPending`/`isLoading`.** Compose with `Spinner` + `data-icon` + `disabled`.
+- **`TabsTrigger` must be inside `TabsList`.** Never render triggers directly in `Tabs`.
+- **`Avatar` always needs `AvatarFallback`.** For when the image fails to load.
+
+### Use Components, Not Custom Markup → [composition.md](./rules/composition.md)
+
+- **Use existing components before custom markup.** Check if a component exists before writing a styled `div`.
+- **Callouts use `Alert`.** Don't build custom styled divs.
+- **Empty states use `Empty`.** Don't build custom empty state markup.
+- **Toast follows the project base.** Use `toast` from the `toast` component for
+ Base UI projects. Use `toast()` from `sonner` for Radix and React Aria
+ projects.
+- **Use `Separator`** instead of `
` or ``.
+- **Use `Skeleton`** for loading placeholders. No custom `animate-pulse` divs.
+- **Use `Badge`** instead of custom styled spans.
+
+### Icons → [icons.md](./rules/icons.md)
+
+- **Icons in `Button` use `data-icon`.** `data-icon="inline-start"` or `data-icon="inline-end"` on the icon.
+- **No sizing classes on icons inside components.** Components handle icon sizing via CSS. No `size-4` or `w-4 h-4`.
+- **Pass icons as objects, not string keys.** `icon={CheckIcon}`, not a string lookup.
+
+### Chat & Messaging → [chat.md](./rules/chat.md)
+
+- **Chat UI composes the chat primitives.** Conversations use `MessageScroller`, rows use `Message`, surfaces use `Bubble`. Never hand-rolled bubble `div`s or a raw scroll container.
+- **`MessageScroller` owns scroll behavior.** Streaming follow, anchoring, and jump-to-latest (`MessageScrollerButton`) are built in. Don't write a `useStickToBottom`/`ResizeObserver` hook.
+- **Attachments use `Attachment`; system notes and dividers use `Marker`.** Not `Item` cards or `Separator` + a label.
+
+### CLI
+
+- **Never decode preset codes or build preset URLs manually.** Use `npx shadcn@latest preset decode `, `preset url `, or `preset open `. For project-aware preset detection, use `npx shadcn@latest preset resolve`.
+- **Apply preset codes directly with the CLI.** Use `npx shadcn@latest apply ` for existing projects, or `npx shadcn@latest init --preset ` when initializing.
+
+## Key Patterns
+
+These are the most common patterns that differentiate correct shadcn/ui code. For edge cases, see the linked rule files above.
+
+```tsx
+// Form layout: FieldGroup + Field, not div + Label.
+
+
+ Email
+
+
+
+
+// Validation: data-invalid on Field, aria-invalid on the control.
+
+ Email
+
+ Invalid email.
+
+
+// Icons in buttons: data-icon, no sizing classes.
+
+
+// Spacing: gap-*, not space-y-*.
+ // correct
+ // wrong
+
+// Equal dimensions: size-*, not w-* h-*.
+ // correct
+ // wrong
+
+// Status colors: Badge variants or semantic tokens, not raw colors.
++20.1% // correct
++20.1% // wrong
+```
+
+## Component Selection
+
+| Need | Use |
+| -------------------------- | --------------------------------------------------------------------------------------------------- |
+| Button/action | `Button` with appropriate variant |
+| Form inputs | `Input`, `Select`, `Combobox`, `Switch`, `Checkbox`, `RadioGroup`, `Textarea`, `InputOTP`, `Slider` |
+| Toggle between 2–5 options | `ToggleGroup` + `ToggleGroupItem` |
+| Data display | `Table`, `Card`, `Badge`, `Avatar` |
+| Navigation | `Sidebar`, `NavigationMenu`, `Breadcrumb`, `Tabs`, `Pagination` |
+| Overlays | `Dialog` (modal), `Sheet` (side panel), `Drawer` (bottom sheet), `AlertDialog` (confirmation) |
+| Feedback | `toast` (Base UI), `sonner` (Radix/Aria), `Alert`, `Progress`, `Skeleton`, `Spinner` |
+| Command palette | `Command` inside `Dialog` |
+| Charts | `Chart` (wraps Recharts) |
+| Layout | `Card`, `Separator`, `Resizable`, `ScrollArea`, `Accordion`, `Collapsible` |
+| Empty states | `Empty` |
+| Menus | `DropdownMenu`, `ContextMenu`, `Menubar` |
+| Tooltips/info | `Tooltip`, `HoverCard`, `Popover` |
+| Chat / conversation UI | `MessageScroller`, `Message`, `Bubble`, `Attachment`, `Marker` |
+
+## Key Fields
+
+The injected project context contains these key fields:
+
+- **`aliases`** → use the actual alias prefix for imports (e.g. `@/`, `~/`), never hardcode.
+- **`isRSC`** → when `true`, components using `useState`, `useEffect`, event handlers, or browser APIs need `"use client"` at the top of the file. Always reference this field when advising on the directive.
+- **`tailwindVersion`** → `"v4"` uses `@theme inline` blocks; `"v3"` uses `tailwind.config.js`.
+- **`tailwindCssFile`** → the global CSS file where custom CSS variables are defined. Always edit this file, never create a new one.
+- **`style`** → component visual treatment (e.g. `nova`, `vega`).
+- **`base`** → primitive library (`radix` or `base`). Affects component APIs and available props.
+- **`iconLibrary`** → determines icon imports. Use `lucide-react` for `lucide`, `@tabler/icons-react` for `tabler`, etc. Never assume `lucide-react`.
+- **`resolvedPaths`** → exact file-system destinations for components, utils, hooks, etc.
+- **`framework`** → routing and file conventions (e.g. Next.js App Router vs Vite SPA).
+- **`packageManager`** → use this for any non-shadcn dependency installs (e.g. `pnpm add date-fns` vs `npm install date-fns`).
+- **`preset`** → resolved preset code and values for the current project. Use `npx shadcn@latest preset resolve --json` when you only need preset information.
+
+See [cli.md — `info` command](./cli.md) for the full field reference.
+
+## Component Docs, Examples, and Usage
+
+Run `npx shadcn@latest docs ` to get the URLs for a component's documentation, examples, and API reference. Fetch these URLs to get the actual content.
+
+```bash
+npx shadcn@latest docs button dialog select
+```
+
+**When creating, fixing, debugging, or using a component, always run `npx shadcn@latest docs` and fetch the URLs first.** This ensures you're working with the correct API and usage patterns rather than guessing.
+
+## Workflow
+
+1. **Get project context** — already injected above. Run `npx shadcn@latest info` again if you need to refresh.
+2. **Check installed components first** — before running `add`, always check the `components` list from project context or list the `resolvedPaths.ui` directory. Don't import components that haven't been added, and don't re-add ones already installed.
+3. **Find components** — `npx shadcn@latest search`.
+4. **Get docs and examples** — run `npx shadcn@latest docs ` to get URLs, then fetch them. Use `npx shadcn@latest view` to browse registry items you haven't installed. To preview changes to installed components, use `npx shadcn@latest add --diff`.
+5. **Install or update** — `npx shadcn@latest add`. When updating existing components, use `--dry-run` and `--diff` to preview changes first (see [Updating Components](#updating-components) below).
+6. **Fix imports in third-party components** — After adding components from community registries (e.g. `@bundui`, `@magicui`), check the added non-UI files for hardcoded import paths like `@/components/ui/...`. These won't match the project's actual aliases. Use `npx shadcn@latest info` to get the correct `ui` alias (e.g. `@workspace/ui/components`) and rewrite the imports accordingly. The CLI rewrites imports for its own UI files, but third-party registry components may use default paths that don't match the project.
+7. **Review added components** — After adding a component or block from any registry, **always read the added files and verify they are correct**. Check for missing sub-components (e.g. `SelectItem` without `SelectGroup`), missing imports, incorrect composition, or violations of the [Critical Rules](#critical-rules). Also replace any icon imports with the project's `iconLibrary` from the project context (e.g. if the registry item uses `lucide-react` but the project uses `hugeicons`, swap the imports and icon names accordingly). Fix all issues before moving on.
+8. **Registry must be explicit** — When the user asks to add a block or component, **do not guess the registry**. If no registry is specified (e.g. user says "add a login block" without specifying `@shadcn`, `@tailark`, `owner/repo`, etc.), ask which registry to use. Never default to a registry on behalf of the user.
+9. **Switching presets** — Ask the user first: **overwrite**, **partial**, **merge**, or **skip**?
+ - **Inspect current preset**: `npx shadcn@latest preset resolve`. Use `--json` when you need structured values.
+ - **Inspect incoming preset**: `npx shadcn@latest preset decode `. Use `preset url ` or `preset open ` to share or open the preset builder.
+ - **Overwrite**: `npx shadcn@latest apply `. Overwrites detected components, fonts, and CSS variables.
+ - **Partial**: `npx shadcn@latest apply --only theme,font`. Updates only the selected preset parts without reinstalling UI components. Supported values are `theme` and `font`; comma-separated combinations are allowed. `icon` is intentionally not supported, because icon changes may require full component reinstall and transforms.
+ - **Merge**: `npx shadcn@latest init --preset --force --no-reinstall`, then run `npx shadcn@latest info` to list installed components, then for each installed component use `--dry-run` and `--diff` to [smart merge](#updating-components) it individually.
+ - **Skip**: `npx shadcn@latest init --preset --force --no-reinstall`. Only updates config and CSS, leaves components as-is.
+ - **Important**: Always run preset commands inside the user's project directory. `apply` only works in an existing project with a `components.json` file. The CLI automatically preserves the current base (`base` vs `radix`) from `components.json`. If you must use a scratch/temp directory (e.g. for `--dry-run` comparisons), pass `--base ` explicitly — preset codes do not encode the base.
+
+## Updating Components
+
+When the user asks to update a component from upstream while keeping their local changes, use `--dry-run` and `--diff` to intelligently merge. **NEVER fetch raw files from GitHub manually — always use the CLI.**
+
+1. Run `npx shadcn@latest add --dry-run` to see all files that would be affected.
+2. For each file, run `npx shadcn@latest add --diff ` to see what changed upstream vs local.
+3. Decide per file based on the diff:
+ - No local changes → safe to overwrite.
+ - Has local changes → read the local file, analyze the diff, and apply upstream updates while preserving local modifications.
+ - User says "just update everything" → use `--overwrite`, but confirm first.
+4. **Never use `--overwrite` without the user's explicit approval.**
+
+## Quick Reference
+
+```bash
+# Create a new project.
+npx shadcn@latest init --name my-app --preset base-nova
+npx shadcn@latest init --name my-app --preset a2r6bw --template vite
+
+# Create a monorepo project.
+npx shadcn@latest init --name my-app --preset base-nova --monorepo
+npx shadcn@latest init --name my-app --preset base-nova --template next --monorepo
+
+# Initialize existing project.
+npx shadcn@latest init --preset base-nova
+npx shadcn@latest init --defaults # shortcut: --template=next --preset=nova (base style implied)
+
+# Apply a preset to an existing project.
+npx shadcn@latest apply a2r6bw
+npx shadcn@latest apply a2r6bw --only theme
+npx shadcn@latest apply a2r6bw --only font
+npx shadcn@latest apply a2r6bw --only theme,font
+
+# Inspect preset codes and project preset state.
+npx shadcn@latest preset decode a2r6bw
+npx shadcn@latest preset url a2r6bw
+npx shadcn@latest preset open a2r6bw
+npx shadcn@latest preset resolve
+npx shadcn@latest preset resolve --json
+
+# Add components.
+npx shadcn@latest add button card dialog
+npx shadcn@latest add @magicui/shimmer-button
+npx shadcn@latest add owner/repo/item
+npx shadcn@latest add --all
+
+# Preview changes before adding/updating.
+npx shadcn@latest add button --dry-run
+npx shadcn@latest add button --diff button.tsx
+npx shadcn@latest add @acme/form --view button.tsx
+npx shadcn@latest add owner/repo/item --dry-run
+
+# Search registries.
+npx shadcn@latest search @shadcn -q "sidebar"
+npx shadcn@latest search @tailark -q "stats"
+npx shadcn@latest search owner/repo -q "login"
+npx shadcn@latest search # all configured registries
+npx shadcn@latest search @shadcn -q "menu" -t ui # filter by item type
+
+# Get component docs and example URLs.
+npx shadcn@latest docs button dialog select
+
+# View registry item details (for items not yet installed).
+npx shadcn@latest view @shadcn/button
+npx shadcn@latest view owner/repo/item
+```
+
+**Named presets:** `nova`, `vega`, `maia`, `lyra`, `mira`, `luma`
+**Templates:** `next`, `vite`, `start`, `react-router`, `astro` (all support `--monorepo`) and `laravel` (not supported for monorepo)
+**Preset codes:** Version-prefixed base62 strings (e.g. `a2r6bw` or `b0`), from [ui.shadcn.com](https://ui.shadcn.com).
+
+## Detailed References
+
+- [rules/forms.md](./rules/forms.md) — FieldGroup, Field, InputGroup, ToggleGroup, FieldSet, validation states
+- [rules/composition.md](./rules/composition.md) — Groups, overlays, Card, Tabs, Avatar, Alert, Empty, Toast, Separator, Skeleton, Badge, Button loading
+- [rules/chat.md](./rules/chat.md) — MessageScroller, Message, Bubble, Attachment, Marker; streaming, anchoring, jump-to-latest
+- [rules/icons.md](./rules/icons.md) — data-icon, icon sizing, passing icons as objects
+- [rules/styling.md](./rules/styling.md) — Semantic colors, variants, className, spacing, size, truncate, dark mode, cn(), z-index
+- [rules/base-vs-radix.md](./rules/base-vs-radix.md) — asChild vs render, Select, ToggleGroup, Slider, Accordion
+- [cli.md](./cli.md) — Commands, flags, presets, templates
+- [registry.md](./registry.md) — Authoring source registries, `include`, item definitions, dependencies, GitHub registry rules
+- [customization.md](./customization.md) — Theming, CSS variables, extending components
diff --git a/distribution_fe/.claude/skills/shadcn/agents/openai.yml b/distribution_fe/.claude/skills/shadcn/agents/openai.yml
new file mode 100644
index 0000000..ab636da
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/agents/openai.yml
@@ -0,0 +1,5 @@
+interface:
+ display_name: "shadcn/ui"
+ short_description: "Manages shadcn/ui components — adding, searching, fixing, debugging, styling, and composing UI."
+ icon_small: "./assets/shadcn-small.png"
+ icon_large: "./assets/shadcn.png"
diff --git a/distribution_fe/.claude/skills/shadcn/assets/shadcn-small.png b/distribution_fe/.claude/skills/shadcn/assets/shadcn-small.png
new file mode 100644
index 0000000..547154b
Binary files /dev/null and b/distribution_fe/.claude/skills/shadcn/assets/shadcn-small.png differ
diff --git a/distribution_fe/.claude/skills/shadcn/assets/shadcn.png b/distribution_fe/.claude/skills/shadcn/assets/shadcn.png
new file mode 100644
index 0000000..b7b6814
Binary files /dev/null and b/distribution_fe/.claude/skills/shadcn/assets/shadcn.png differ
diff --git a/distribution_fe/.claude/skills/shadcn/cli.md b/distribution_fe/.claude/skills/shadcn/cli.md
new file mode 100644
index 0000000..8a1d195
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/cli.md
@@ -0,0 +1,290 @@
+# shadcn CLI Reference
+
+Configuration is read from `components.json`.
+
+> **IMPORTANT:** Always run commands using the project's package runner: `npx shadcn@latest`, `pnpm dlx shadcn@latest`, or `bunx --bun shadcn@latest`. Check `packageManager` from project context to choose the right one. Examples below use `npx shadcn@latest` but substitute the correct runner for the project.
+
+> **IMPORTANT:** Only use the flags documented below. Do not invent or guess flags — if a flag isn't listed here, it doesn't exist. The CLI auto-detects the package manager from the project's lockfile; there is no `--package-manager` flag.
+
+## Contents
+
+- Commands: init, apply, add (dry-run, smart merge), search, view, docs, info, build
+- Templates: next, vite, start, react-router, astro
+- Presets: named, code, URL formats and fields
+- Switching presets
+
+---
+
+## Commands
+
+### `init` — Initialize or create a project
+
+```bash
+npx shadcn@latest init [components...] [options]
+```
+
+Initializes shadcn/ui in an existing project or creates a new project (when `--name` is provided). Optionally installs components in the same step.
+
+| Flag | Short | Description | Default |
+| ----------------------- | ----- | --------------------------------------------------------- | ------- |
+| `--template ` | `-t` | Template (next, start, vite, next-monorepo, react-router) | — |
+| `--preset [name]` | `-p` | Preset configuration (named, code, or URL) | — |
+| `--yes` | `-y` | Skip confirmation prompt | `true` |
+| `--defaults` | `-d` | Use defaults (`--template=next --preset=base-nova`) | `false` |
+| `--force` | `-f` | Force overwrite existing configuration | `false` |
+| `--cwd ` | `-c` | Working directory | current |
+| `--name ` | `-n` | Name for new project | — |
+| `--silent` | `-s` | Mute output | `false` |
+| `--rtl` | | Enable RTL support | — |
+| `--reinstall` | | Re-install existing UI components | `false` |
+| `--monorepo` | | Scaffold a monorepo project | — |
+| `--no-monorepo` | | Skip the monorepo prompt | — |
+
+`npx shadcn@latest create` is an alias for `npx shadcn@latest init`.
+
+### `apply` — Apply a preset to an existing project
+
+```bash
+npx shadcn@latest apply [preset] [options]
+```
+
+Applies a preset to an existing project, overwriting preset-driven config, fonts, CSS variables, and detected UI components.
+
+| Flag | Short | Description | Default |
+| ------------------- | ----- | ------------------------------------------ | ------- |
+| `--preset ` | — | Preset configuration (named, code, or URL) | — |
+| `--yes` | `-y` | Skip confirmation prompt | `false` |
+| `--cwd ` | `-c` | Working directory | current |
+| `--silent` | `-s` | Mute output | `false` |
+
+`[preset]` is a shorthand for `--preset `. If both are provided, they must match.
+If no preset is provided, the CLI offers to open the custom preset builder on `ui.shadcn.com/create`.
+
+### `add` — Add components
+
+> **IMPORTANT:** To compare local components against upstream or to preview changes, ALWAYS use `npx shadcn@latest add --dry-run`, `--diff`, or `--view`. NEVER fetch raw files from GitHub or other sources manually. The CLI handles registry resolution, file paths, and CSS diffing automatically.
+
+```bash
+npx shadcn@latest add [components...] [options]
+```
+
+Accepts component names, registry-prefixed names (`@magicui/shimmer-button`),
+GitHub item addresses (`owner/repo/item`), URLs, or local paths.
+
+| Flag | Short | Description | Default |
+| --------------- | ----- | -------------------------------------------------------------------------------------------------------------------- | ------- |
+| `--yes` | `-y` | Skip confirmation prompt | `false` |
+| `--overwrite` | `-o` | Overwrite existing files | `false` |
+| `--cwd ` | `-c` | Working directory | current |
+| `--all` | `-a` | Add all available components | `false` |
+| `--path ` | `-p` | Target path for the component | — |
+| `--silent` | `-s` | Mute output | `false` |
+| `--dry-run` | | Preview all changes without writing files | `false` |
+| `--diff [path]` | | Show diffs. Without a path, shows the first 5 files. With a path, shows that file only (implies `--dry-run`) | — |
+| `--view [path]` | | Show file contents. Without a path, shows the first 5 files. With a path, shows that file only (implies `--dry-run`) | — |
+
+#### Dry-Run Mode
+
+Use `--dry-run` to preview what `add` would do without writing any files. `--diff` and `--view` both imply `--dry-run`.
+
+```bash
+# Preview all changes.
+npx shadcn@latest add button --dry-run
+
+# Show diffs for all files (top 5).
+npx shadcn@latest add button --diff
+
+# Show the diff for a specific file.
+npx shadcn@latest add button --diff button.tsx
+
+# Show contents for all files (top 5).
+npx shadcn@latest add button --view
+
+# Show the full content of a specific file.
+npx shadcn@latest add button --view button.tsx
+
+# Works with URLs too.
+npx shadcn@latest add https://api.npoint.io/abc123 --dry-run
+
+# Works with public GitHub registries too.
+npx shadcn@latest add owner/repo/item --dry-run
+
+# CSS diffs.
+npx shadcn@latest add button --diff globals.css
+```
+
+**When to use dry-run:**
+
+- When the user asks "what files will this add?" or "what will this change?" — use `--dry-run`.
+- Before overwriting existing components — use `--diff` to preview the changes first.
+- When the user wants to inspect component source code without installing — use `--view`.
+- When checking what CSS changes would be made to `globals.css` — use `--diff globals.css`.
+- When the user asks to review or audit third-party registry code before installing — use `--view` to inspect the source.
+
+> **`npx shadcn@latest add --dry-run` vs `npx shadcn@latest view`:** Prefer `npx shadcn@latest add --dry-run/--diff/--view` over `npx shadcn@latest view` when the user wants to preview changes to their project. `npx shadcn@latest view` only shows raw registry metadata. `npx shadcn@latest add --dry-run` shows exactly what would happen in the user's project: resolved file paths, diffs against existing files, and CSS updates. Use `npx shadcn@latest view` only when the user wants to browse registry info without a project context.
+
+#### Smart Merge from Upstream
+
+See [Updating Components in SKILL.md](./SKILL.md#updating-components) for the full workflow.
+
+### `search` — Search registries
+
+```bash
+npx shadcn@latest search [registries...] [options]
+```
+
+Fuzzy search across registries. Also aliased as `npx shadcn@latest list`.
+Supports namespaces (`@acme`), public GitHub registry sources (`owner/repo`),
+and registry catalog URLs. Without `-q`, lists all items. When no registries are
+passed, searches every registry configured in `components.json`.
+
+| Flag | Short | Description | Default |
+| ------------------- | ----- | ------------------------------------------------- | ------- |
+| `--query ` | `-q` | Search query | — |
+| `--type ` | `-t` | Filter by item type (e.g. `ui`, `block`, `hook`); comma-separated | — |
+| `--limit ` | `-l` | Max items to display | `100` |
+| `--offset ` | `-o` | Items to skip | `0` |
+| `--json` | | Output as JSON | `false` |
+| `--cwd ` | `-c` | Working directory | current |
+
+### `view` — View item details
+
+```bash
+npx shadcn@latest view [options]
+```
+
+Displays item info including file contents. Examples:
+`npx shadcn@latest view @shadcn/button`,
+`npx shadcn@latest view owner/repo/item`.
+
+### `docs` — Get component documentation URLs
+
+```bash
+npx shadcn@latest docs [options]
+```
+
+Outputs resolved URLs for component documentation, examples, and API references. Accepts one or more component names. Fetch the URLs to get the actual content.
+
+Example output for `npx shadcn@latest docs input button`:
+
+```
+base radix
+
+input
+ docs https://ui.shadcn.com/docs/components/radix/input
+ examples https://raw.githubusercontent.com/.../examples/input-example.tsx
+
+button
+ docs https://ui.shadcn.com/docs/components/radix/button
+ examples https://raw.githubusercontent.com/.../examples/button-example.tsx
+```
+
+Some components include an `api` link to the underlying library (e.g. `cmdk` for the command component).
+
+### `diff` — Check for updates
+
+Do not use this command. Use `npx shadcn@latest add --diff` instead.
+
+### `info` — Project information
+
+```bash
+npx shadcn@latest info [options]
+```
+
+Displays project info and `components.json` configuration. Run this first to discover the project's framework, aliases, Tailwind version, and resolved paths.
+
+| Flag | Short | Description | Default |
+| ------------- | ----- | ----------------- | ------- |
+| `--cwd ` | `-c` | Working directory | current |
+
+**Project Info fields:**
+
+| Field | Type | Meaning |
+| -------------------- | --------- | ------------------------------------------------------------------ |
+| `framework` | `string` | Detected framework (`next`, `vite`, `react-router`, `start`, etc.) |
+| `frameworkVersion` | `string` | Framework version (e.g. `15.2.4`) |
+| `isSrcDir` | `boolean` | Whether the project uses a `src/` directory |
+| `isRSC` | `boolean` | Whether React Server Components are enabled |
+| `isTsx` | `boolean` | Whether the project uses TypeScript |
+| `tailwindVersion` | `string` | `"v3"` or `"v4"` |
+| `tailwindConfigFile` | `string` | Path to the Tailwind config file |
+| `tailwindCssFile` | `string` | Path to the global CSS file |
+| `aliasPrefix` | `string` | Import alias prefix (e.g. `@`, `~`, `@/`) |
+| `packageManager` | `string` | Detected package manager (`npm`, `pnpm`, `yarn`, `bun`) |
+
+**Components.json fields:**
+
+| Field | Type | Meaning |
+| -------------------- | --------- | ------------------------------------------------------------------------------------------ |
+| `base` | `string` | Primitive library (`radix` or `base`) — determines component APIs and available props |
+| `style` | `string` | Visual style (e.g. `nova`, `vega`) |
+| `rsc` | `boolean` | RSC flag from config |
+| `tsx` | `boolean` | TypeScript flag |
+| `tailwind.config` | `string` | Tailwind config path |
+| `tailwind.css` | `string` | Global CSS path — this is where custom CSS variables go |
+| `iconLibrary` | `string` | Icon library — determines icon import package (e.g. `lucide-react`, `@tabler/icons-react`) |
+| `aliases.components` | `string` | Component import alias (e.g. `@/components`) |
+| `aliases.utils` | `string` | Utils import alias (e.g. `@/lib/utils`) |
+| `aliases.ui` | `string` | UI component alias (e.g. `@/components/ui`) |
+| `aliases.lib` | `string` | Lib alias (e.g. `@/lib`) |
+| `aliases.hooks` | `string` | Hooks alias (e.g. `@/hooks`) |
+| `resolvedPaths` | `object` | Absolute file-system paths for each alias |
+| `registries` | `object` | Configured custom registries |
+
+**Links fields:**
+
+The `info` output includes a **Links** section with templated URLs for component docs, source, and examples. For resolved URLs, use `npx shadcn@latest docs ` instead.
+
+### `build` — Build a custom registry
+
+```bash
+npx shadcn@latest build [registry] [options]
+```
+
+Builds `registry.json` into individual JSON files for distribution. Default input: `./registry.json`, default output: `./public/r`.
+
+For authoring rules, `include`, item definitions, `registryDependencies`, and
+GitHub registry behavior, see [registry.md](./registry.md).
+
+| Flag | Short | Description | Default |
+| ----------------- | ----- | ----------------- | ------------ |
+| `--output ` | `-o` | Output directory | `./public/r` |
+| `--cwd ` | `-c` | Working directory | current |
+
+---
+
+## Templates
+
+| Value | Framework | Monorepo support |
+| -------------- | -------------- | ---------------- |
+| `next` | Next.js | Yes |
+| `vite` | Vite | Yes |
+| `start` | TanStack Start | Yes |
+| `react-router` | React Router | Yes |
+| `astro` | Astro | Yes |
+| `laravel` | Laravel | No |
+
+All templates support monorepo scaffolding via the `--monorepo` flag. When passed, the CLI uses a monorepo-specific template directory (e.g. `next-monorepo`, `vite-monorepo`). When neither `--monorepo` nor `--no-monorepo` is passed, the CLI prompts interactively. Laravel does not support monorepo scaffolding.
+
+---
+
+## Presets
+
+Three ways to specify a preset via `--preset`:
+
+1. **Named:** `--preset nova` or `--preset lyra`
+2. **Code:** `--preset a2r6bw` (version-prefixed base62 string, e.g. `a2r6bw` or `b0`)
+3. **URL:** `--preset "https://ui.shadcn.com/init?base=radix&style=nova&..."`
+
+> **IMPORTANT:** Never try to decode, fetch, or resolve preset codes manually. Preset codes are opaque — pass them directly to `npx shadcn@latest init --preset ` and let the CLI handle resolution.
+> Use `npx shadcn@latest apply --preset ` when overwriting an existing project's preset.
+
+## Switching Presets
+
+Ask the user first: **overwrite**, **merge**, or **skip** existing components?
+
+- **Overwrite / Re-install** → `npx shadcn@latest apply --preset `. Overwrites all detected component files with the new preset styles. Use when the user hasn't customized components.
+- **Merge** → `npx shadcn@latest init --preset --force --no-reinstall`, then run `npx shadcn@latest info` to get the list of installed components and use the [smart merge workflow](./SKILL.md#updating-components) to update them one by one, preserving local changes. Use when the user has customized components.
+- **Skip** → `npx shadcn@latest init --preset --force --no-reinstall`. Only updates config and CSS variables, leaves existing components as-is.
+
+Always run preset commands inside the user's project directory. `apply` only works in an existing project with a `components.json` file. The CLI automatically preserves the current base (`base` vs `radix`) from `components.json`. If you must use a scratch/temp directory (e.g. for `--dry-run` comparisons), pass `--base ` explicitly — preset codes do not encode the base.
diff --git a/distribution_fe/.claude/skills/shadcn/customization.md b/distribution_fe/.claude/skills/shadcn/customization.md
new file mode 100644
index 0000000..16954f5
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/customization.md
@@ -0,0 +1,209 @@
+# Customization & Theming
+
+Components reference semantic CSS variable tokens. Change the variables to change every component.
+
+## Contents
+
+- How it works (CSS variables → Tailwind utilities → components)
+- Color variables and OKLCH format
+- Dark mode setup
+- Changing the theme (presets, CSS variables)
+- Adding custom colors (Tailwind v3 and v4)
+- Border radius
+- Customizing components (variants, className, wrappers)
+- Checking for updates
+
+---
+
+## How It Works
+
+1. CSS variables defined in `:root` (light) and `.dark` (dark mode).
+2. Tailwind maps them to utilities: `bg-primary`, `text-muted-foreground`, etc.
+3. Components use these utilities — changing a variable changes all components that reference it.
+
+---
+
+## Color Variables
+
+Every color follows the `name` / `name-foreground` convention. The base variable is for backgrounds, `-foreground` is for text/icons on that background.
+
+| Variable | Purpose |
+| -------------------------------------------- | -------------------------------- |
+| `--background` / `--foreground` | Page background and default text |
+| `--card` / `--card-foreground` | Card surfaces |
+| `--primary` / `--primary-foreground` | Primary buttons and actions |
+| `--secondary` / `--secondary-foreground` | Secondary actions |
+| `--muted` / `--muted-foreground` | Muted/disabled states |
+| `--accent` / `--accent-foreground` | Hover and accent states |
+| `--destructive` / `--destructive-foreground` | Error and destructive actions |
+| `--border` | Default border color |
+| `--input` | Form input borders |
+| `--ring` | Focus ring color |
+| `--chart-1` through `--chart-5` | Chart/data visualization |
+| `--sidebar-*` | Sidebar-specific colors |
+| `--surface` / `--surface-foreground` | Secondary surface |
+
+Colors use OKLCH: `--primary: oklch(0.205 0 0)` where values are lightness (0–1), chroma (0 = gray), and hue (0–360).
+
+---
+
+## Dark Mode
+
+Class-based toggle via `.dark` on the root element. In Next.js, use `next-themes`:
+
+```tsx
+import { ThemeProvider } from "next-themes"
+
+
+ {children}
+
+```
+
+---
+
+## Changing the Theme
+
+```bash
+# Apply a preset code from ui.shadcn.com.
+npx shadcn@latest apply --preset a2r6bw
+
+# Positional shorthand also works.
+npx shadcn@latest apply a2r6bw
+
+# Switch to a named preset and overwrite existing components.
+npx shadcn@latest apply --preset nova
+
+# Preserve existing components instead.
+npx shadcn@latest init --preset nova --force --no-reinstall
+
+# Use a custom theme URL.
+npx shadcn@latest apply --preset "https://ui.shadcn.com/init?base=radix&style=nova&theme=blue&..."
+```
+
+Or edit CSS variables directly in `globals.css`.
+
+---
+
+## Adding Custom Colors
+
+Add variables to the file at `tailwindCssFile` from `npx shadcn@latest info` (typically `globals.css`). Never create a new CSS file for this.
+
+```css
+/* 1. Define in the global CSS file. */
+:root {
+ --warning: oklch(0.84 0.16 84);
+ --warning-foreground: oklch(0.28 0.07 46);
+}
+.dark {
+ --warning: oklch(0.41 0.11 46);
+ --warning-foreground: oklch(0.99 0.02 95);
+}
+```
+
+```css
+/* 2a. Register with Tailwind v4 (@theme inline). */
+@theme inline {
+ --color-warning: var(--warning);
+ --color-warning-foreground: var(--warning-foreground);
+}
+```
+
+When `tailwindVersion` is `"v3"` (check via `npx shadcn@latest info`), register in `tailwind.config.js` instead:
+
+```js
+// 2b. Register with Tailwind v3 (tailwind.config.js).
+module.exports = {
+ theme: {
+ extend: {
+ colors: {
+ warning: "oklch(var(--warning) / )",
+ "warning-foreground":
+ "oklch(var(--warning-foreground) / )",
+ },
+ },
+ },
+}
+```
+
+```tsx
+// 3. Use in components.
+Warning
+```
+
+---
+
+## Border Radius
+
+`--radius` controls border radius globally. Components derive values from it (`rounded-lg` = `var(--radius)`, `rounded-md` = `calc(var(--radius) - 2px)`).
+
+---
+
+## Customizing Components
+
+See also: [rules/styling.md](./rules/styling.md) for Incorrect/Correct examples.
+
+Prefer these approaches in order:
+
+### 1. Built-in variants
+
+```tsx
+
+```
+
+### 2. Tailwind classes via `className`
+
+```tsx
+...
+```
+
+### 3. Add a new variant
+
+Edit the component source to add a variant via `cva`:
+
+```tsx
+// components/ui/button.tsx
+warning: "bg-warning text-warning-foreground hover:bg-warning/90",
+```
+
+### 4. Wrapper components
+
+Compose shadcn/ui primitives into higher-level components:
+
+```tsx
+export function ConfirmDialog({ title, description, onConfirm, children }) {
+ return (
+
+ {children}
+
+
+ {title}
+ {description}
+
+
+ Cancel
+ Confirm
+
+
+
+ )
+}
+```
+
+---
+
+## Checking for Updates
+
+```bash
+npx shadcn@latest add button --diff
+```
+
+To preview exactly what would change before updating, use `--dry-run` and `--diff`:
+
+```bash
+npx shadcn@latest add button --dry-run # see all affected files
+npx shadcn@latest add button --diff button.tsx # see the diff for a specific file
+```
+
+See [Updating Components in SKILL.md](./SKILL.md#updating-components) for the full smart merge workflow.
diff --git a/distribution_fe/.claude/skills/shadcn/evals/evals.json b/distribution_fe/.claude/skills/shadcn/evals/evals.json
new file mode 100644
index 0000000..c1b7bdd
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/evals/evals.json
@@ -0,0 +1,77 @@
+{
+ "skill_name": "shadcn",
+ "evals": [
+ {
+ "id": 1,
+ "prompt": "I'm building a Next.js app with shadcn/ui (base-nova preset, lucide icons). Create a settings form component with fields for: full name, email address, and notification preferences (email, SMS, push notifications as toggle options). Add validation states for required fields.",
+ "expected_output": "A React component using FieldGroup, Field, ToggleGroup, data-invalid/aria-invalid validation, gap-* spacing, and semantic colors.",
+ "files": [],
+ "expectations": [
+ "Uses FieldGroup and Field components for form layout instead of raw div with space-y",
+ "Uses Switch for independent on/off notification toggles (not looping Button with manual active state)",
+ "Uses data-invalid on Field and aria-invalid on the input control for validation states",
+ "Uses gap-* (e.g. gap-4, gap-6) instead of space-y-* or space-x-* for spacing",
+ "Uses semantic color tokens (e.g. bg-background, text-muted-foreground, text-destructive) instead of raw colors like bg-red-500",
+ "No manual dark: color overrides"
+ ]
+ },
+ {
+ "id": 2,
+ "prompt": "Create a dialog component for editing a user profile. It should have the user's avatar at the top, input fields for name and bio, and Save/Cancel buttons with appropriate icons. Using shadcn/ui with radix-nova preset and tabler icons.",
+ "expected_output": "A React component with DialogTitle, Avatar+AvatarFallback, data-icon on icon buttons, no icon sizing classes, tabler icon imports.",
+ "files": [],
+ "expectations": [
+ "Includes DialogTitle for accessibility (visible or with sr-only class)",
+ "Avatar component includes AvatarFallback",
+ "Icons on buttons use the data-icon attribute (data-icon=\"inline-start\" or data-icon=\"inline-end\")",
+ "No sizing classes on icons inside components (no size-4, w-4, h-4, etc.)",
+ "Uses tabler icons (@tabler/icons-react) instead of lucide-react",
+ "Uses asChild for custom triggers (radix preset)"
+ ]
+ },
+ {
+ "id": 3,
+ "prompt": "Create a dashboard component that shows 4 stat cards in a grid. Each card has a title, large number, percentage change badge, and a loading skeleton state. Using shadcn/ui with base-nova preset and lucide icons.",
+ "expected_output": "A React component with full Card composition, Skeleton for loading, Badge for changes, semantic colors, gap-* spacing.",
+ "files": [],
+ "expectations": [
+ "Uses full Card composition with CardHeader, CardTitle, CardContent (not dumping everything into CardContent)",
+ "Uses Skeleton component for loading placeholders instead of custom animate-pulse divs",
+ "Uses Badge component for percentage change instead of custom styled spans",
+ "Uses semantic color tokens instead of raw color values like bg-green-500 or text-red-600",
+ "Uses gap-* instead of space-y-* or space-x-* for spacing",
+ "Uses size-* when width and height are equal instead of separate w-* h-*"
+ ]
+ },
+ {
+ "id": 4,
+ "prompt": "I'm building a Next.js app with shadcn/ui (base-nova preset, lucide icons). Build a chat conversation view: a scrollable thread of messages from two different people, each with an avatar, sender name, timestamp, and message bubble. A couple of messages include an image attachment and a PDF file attachment, and there's a 'Today' divider separating the days.",
+ "expected_output": "A React component composing MessageScroller, Message, Bubble, Attachment, and Marker from the registry instead of hand-rolled bubble/divider/attachment markup.",
+ "files": [],
+ "expectations": [
+ "Uses MessageScroller (MessageScrollerProvider, MessageScrollerViewport, MessageScrollerContent, MessageScrollerItem) for the scrollable thread instead of a raw overflow-y-auto div or ScrollArea",
+ "Wraps each row in MessageScrollerItem inside MessageScrollerContent",
+ "Uses Message with MessageAvatar/MessageContent/MessageHeader for row layout instead of custom flex divs",
+ "Uses Bubble + BubbleContent for the message surface instead of a styled div with bg-muted/bg-primary",
+ "Uses Attachment (AttachmentMedia, AttachmentContent, AttachmentTitle, AttachmentDescription) for the file and image attachments instead of Item or a custom card",
+ "Uses Marker (variant=\"separator\") for the 'Today' divider instead of Separator plus a centered label",
+ "Uses semantic color tokens and gap-* spacing; no raw colors like bg-emerald-500 and no space-y-*",
+ "Includes \"use client\" when the component uses state or event handlers (isRSC)"
+ ]
+ },
+ {
+ "id": 5,
+ "prompt": "Using shadcn/ui (base-nova preset, lucide icons), build a streaming AI chat UI. The assistant's reply streams in while it generates, the view auto-scrolls to follow the latest content but stops following if the user scrolls up to read earlier messages, a 'jump to latest' button appears when the user has scrolled away from the bottom, and a subtle 'thinking…' shimmer shows while the model is generating.",
+ "expected_output": "A React component that delegates scroll/anchor behavior to MessageScroller and uses MessageScrollerButton for jump-to-latest and the shimmer utility for the thinking indicator — no hand-rolled scroll logic or custom shimmer keyframes.",
+ "files": [],
+ "expectations": [
+ "Uses MessageScroller with MessageScrollerProvider (autoScroll) and scrollAnchor on message items for the stick-to-bottom/follow behavior instead of a custom useStickToBottom hook or ResizeObserver/scrollTop wiring",
+ "Uses MessageScrollerButton for the jump-to-latest control instead of a hand-built conditional button driven by manual scroll-position state",
+ "Uses the shimmer utility class for the 'thinking…' indicator instead of a custom @keyframes or bg-clip-text gradient animation",
+ "Wraps each message row in MessageScrollerItem inside MessageScrollerContent",
+ "Uses Message + Bubble + BubbleContent for the conversation rows instead of hand-rolled bubble divs",
+ "Uses semantic color tokens and gap-* spacing; includes \"use client\" (isRSC)"
+ ]
+ }
+ ]
+}
diff --git a/distribution_fe/.claude/skills/shadcn/mcp.md b/distribution_fe/.claude/skills/shadcn/mcp.md
new file mode 100644
index 0000000..6539dda
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/mcp.md
@@ -0,0 +1,105 @@
+# shadcn MCP Server
+
+The CLI includes an MCP server that lets AI assistants search, browse, view, and install items from registries.
+
+---
+
+## Setup
+
+```bash
+shadcn mcp # start the MCP server (stdio)
+shadcn mcp init # write config for your editor
+```
+
+Editor config files:
+
+| Editor | Config file |
+| ----------- | ------------------------------- |
+| Claude Code | `.mcp.json` |
+| Cursor | `.cursor/mcp.json` |
+| VS Code | `.vscode/mcp.json` |
+| OpenCode | `opencode.json` |
+| Codex | `~/.codex/config.toml` (manual) |
+
+---
+
+## Tools
+
+> **Tip:** MCP tools handle registry operations (search, view, install). For project configuration (aliases, framework, Tailwind version), use `npx shadcn@latest info` — there is no MCP equivalent.
+
+### `shadcn:get_project_registries`
+
+Returns registry names from `components.json`. Errors if no `components.json` exists.
+
+**Input:** none
+
+### `shadcn:list_items_in_registries`
+
+Lists all items from one or more registries. Registries can be configured
+namespaces such as `@acme`, public GitHub sources such as `owner/repo`, or
+registry catalog URLs. Omit `registries` to list from every registry configured
+in `components.json`.
+
+**Input:** `registries` (string[], optional — omit for all configured), `types` (string[], optional — e.g. `["ui", "block"]`), `limit` (number, optional, defaults to 100), `offset` (number, optional)
+
+### `shadcn:search_items_in_registries`
+
+Fuzzy search across registries. Registries can be configured namespaces, public
+GitHub sources, or registry catalog URLs. Omit `registries` to search every
+registry configured in `components.json` — e.g. "find me a hero" across all
+configured registries.
+
+**Input:** `registries` (string[], optional — omit for all configured), `query` (string), `types` (string[], optional — e.g. `["ui", "block"]`), `limit` (number, optional, defaults to 100), `offset` (number, optional)
+
+### `shadcn:view_items_in_registries`
+
+View item details including full file contents.
+
+**Input:** `items` (string[]) — e.g.
+`["@shadcn/button", "@shadcn/card", "owner/repo/item"]`
+
+### `shadcn:get_item_examples_from_registries`
+
+Find usage examples and demos with source code. Omit `registries` to search
+every registry configured in `components.json`.
+
+**Input:** `registries` (string[], optional — omit for all configured), `query` (string) — e.g. `"accordion-demo"`, `"button example"`
+
+### `shadcn:get_add_command_for_items`
+
+Returns the CLI install command.
+
+**Input:** `items` (string[]) — e.g. `["@shadcn/button"]`
+
+### `shadcn:get_audit_checklist`
+
+Returns a checklist for verifying components (imports, deps, lint, TypeScript).
+
+**Input:** none
+
+---
+
+## Configuring Registries
+
+Namespaced and authenticated registries are set in `components.json`. The
+`@shadcn` registry is always built-in. Public GitHub registries can also be used
+directly as `owner/repo` registry sources when the repository has a root
+`registry.json`; they do not need `components.json` configuration.
+
+```json
+{
+ "registries": {
+ "@acme": "https://acme.com/r/{name}.json",
+ "@private": {
+ "url": "https://private.com/r/{name}.json",
+ "headers": { "Authorization": "Bearer ${MY_TOKEN}" }
+ }
+ }
+}
+```
+
+- Names must start with `@`.
+- URLs must contain `{name}`.
+- `${VAR}` references are resolved from environment variables.
+
+Community registry index: `https://ui.shadcn.com/r/registries.json`
diff --git a/distribution_fe/.claude/skills/shadcn/registry.md b/distribution_fe/.claude/skills/shadcn/registry.md
new file mode 100644
index 0000000..5369468
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/registry.md
@@ -0,0 +1,277 @@
+# Registry Authoring and Addresses
+
+Use this reference when the user wants to create, fix, publish, or reason about
+a shadcn registry.
+
+## Mental Model
+
+A registry has two forms:
+
+- **Source registry**: an authored `registry.json` in a project or repository.
+ It may use `include` and file paths that point at source files.
+- **Built registry**: generated JSON files served to CLI consumers, usually
+ from `public/r`. Use `npx shadcn@latest build` to create this form.
+
+The CLI installer consumes registry item payloads. A source registry is a way to
+author those payloads from real files.
+
+Registry items are not limited to React components. They can distribute
+components, hooks, utilities, design tokens, pages, config files, docs, rules,
+workflows, templates, MCP files, and other project files.
+
+## Root `registry.json`
+
+The root registry file should define registry metadata and either `items` or
+`include`.
+
+```json
+{
+ "$schema": "https://ui.shadcn.com/schema/registry.json",
+ "name": "acme",
+ "homepage": "https://acme.com",
+ "items": [
+ {
+ "name": "absolute-url",
+ "type": "registry:lib",
+ "title": "Absolute URL",
+ "description": "A utility to turn any path into an absolute URL.",
+ "files": [
+ {
+ "path": "lib/absolute-url.ts",
+ "type": "registry:lib"
+ }
+ ]
+ }
+ ]
+}
+```
+
+Root registry rules:
+
+- Root `registry.json` must include `name` and `homepage`.
+- `items` is an array of registry item definitions.
+- `include` may be used to split the source registry into multiple files.
+- Included registry files may omit `name` and `homepage`.
+
+## Include
+
+Use `include` to keep large registries modular.
+
+```json
+{
+ "$schema": "https://ui.shadcn.com/schema/registry.json",
+ "name": "acme",
+ "homepage": "https://acme.com",
+ "include": ["registry/ui/registry.json", "registry/blocks/registry.json"]
+}
+```
+
+Include rules:
+
+- Include paths are relative to the `registry.json` that declares them.
+- Include paths must explicitly point to a `registry.json` file.
+- Do not use remote URLs, absolute paths, or parent traversal (`..`).
+- Item file paths are relative to the registry file that declares the item.
+- Duplicate item names fail across the resolved registry.
+
+Example included file:
+
+```json
+{
+ "items": [
+ {
+ "name": "button",
+ "type": "registry:ui",
+ "files": [
+ {
+ "path": "button.tsx",
+ "type": "registry:ui"
+ }
+ ]
+ }
+ ]
+}
+```
+
+If this file is at `registry/ui/registry.json`, then `button.tsx` is read from
+`registry/ui/button.tsx`, and the built item path is emitted relative to the
+root registry.
+
+## Item Definitions
+
+Common item fields:
+
+```json
+{
+ "name": "login-form",
+ "type": "registry:block",
+ "title": "Login Form",
+ "description": "A login form with email and password fields.",
+ "dependencies": ["zod"],
+ "registryDependencies": ["button", "input", "label"],
+ "files": [
+ {
+ "path": "blocks/login-form.tsx",
+ "type": "registry:block"
+ }
+ ],
+ "cssVars": {
+ "light": {
+ "brand": "oklch(0.62 0.18 250)"
+ },
+ "dark": {
+ "brand": "oklch(0.72 0.16 250)"
+ }
+ }
+}
+```
+
+Important fields:
+
+- `name`: the installable item name. It is not necessarily a file path.
+- `type`: one of the registry item types, such as `registry:ui`,
+ `registry:block`, `registry:lib`, `registry:hook`, `registry:file`,
+ `registry:page`, `registry:theme`, `registry:style`, `registry:font`, or
+ `registry:item`.
+- `files`: source files copied or generated by the item.
+- `dependencies`: npm runtime dependencies.
+- `devDependencies`: npm development dependencies.
+- `registryDependencies`: other registry items required by this item.
+- `cssVars`, `css`, `tailwind`, `envVars`, and `docs`: optional install-time
+ additions.
+
+File rules:
+
+- File paths are relative to the declaring `registry.json`.
+- `registry:file` and `registry:page` files require a `target`.
+- Do not use remote file URLs in source registry file paths.
+- Keep source files copy-pasteable: no hidden app-only imports.
+
+## Registry Dependencies
+
+`registryDependencies` entries are item addresses, not file paths.
+
+```json
+{
+ "name": "login-form",
+ "type": "registry:block",
+ "registryDependencies": ["button", "@acme/input", "acme/ui/card#v1.2.0"],
+ "files": [
+ {
+ "path": "blocks/login-form.tsx",
+ "type": "registry:block"
+ }
+ ]
+}
+```
+
+Dependency rules:
+
+- Bare names such as `"button"` mean official shadcn items.
+- Bare names never mean same-registry or same-repository items.
+- Namespaced dependencies use `@namespace/item-name`.
+- GitHub dependencies use `owner/repo/item-name`.
+- Pin GitHub dependencies with `owner/repo/item-name#ref` when needed.
+- Refs are not inherited. If `owner/repo/foo#v2` depends on `bar` from the same
+ repo at `v2`, write `owner/repo/bar#v2`.
+- Do not use relative dependencies such as `"./bar"`.
+
+## Address Schemes
+
+When reasoning about a registry item string, classify it first.
+
+| Address | Scheme | Meaning |
+| ----------------------------------- | --------- | ------------------------------------------------------------ |
+| `button` | shadcn | Official shadcn item named `button`. |
+| `@acme/button` | namespace | Item `button` from configured registry `@acme`. |
+| `@acme/ui/button` | namespace | Item `ui/button` from configured registry `@acme`. |
+| `https://example.com/r/button.json` | url | Built registry item JSON at that URL. |
+| `./button.json` | file | Built registry item JSON on disk. |
+| `acme/ui/button` | github | Item `button` from GitHub repo `acme/ui`. |
+| `acme/ui/forms/login#main` | github | Item `forms/login` from GitHub repo `acme/ui` at ref `main`. |
+
+For namespace and GitHub addresses, slashful item names are allowed and are item
+names, not file paths. Addresses ending in `.json` keep file-address
+precedence, so `acme/ui/data/schema.json` is treated as a file path, not a
+GitHub item address.
+
+## GitHub Registries
+
+A public GitHub repository can act as a source registry when it has a root
+`registry.json`.
+
+```txt
+owner/repo/item-name[#ref]
+```
+
+Rules:
+
+- The first two path segments are GitHub owner and repo.
+- All remaining path segments are the registry item name.
+- The source entrypoint is always root `registry.json`.
+- GitHub registries are source registries consumed directly by the CLI. They do
+ not require `shadcn build` or generated item JSON files.
+- `include` follows the same source-registry rules as local registries.
+- Currently, GitHub addresses support public `github.com` repositories only.
+- Private repos and GitHub Enterprise require explicit product decisions.
+
+When implementing GitHub registry fetching, resolve refs to a commit SHA before
+reading source files. Do not read moving refs directly from
+`raw.githubusercontent.com`, because branch-like refs can be cached for several
+minutes.
+
+Preferred flow:
+
+```txt
+owner/repo[#ref]
+ -> resolve ref with git ls-remote
+ -> commit SHA
+ -> read https://raw.githubusercontent.com/{owner}/{repo}/{sha}/registry.json
+ -> read includes and item files from the same SHA
+```
+
+This keeps a command on one consistent repository snapshot.
+
+Full 40-character commit SHAs are already stable and can be used directly.
+Branches, tags, and short refs require Git so the CLI can resolve them to a
+commit SHA first.
+
+## Build and Verify
+
+Use the CLI to build source registries:
+
+```bash
+npx shadcn@latest build
+npx shadcn@latest build registry.json --output public/r
+```
+
+Use CLI commands to inspect the result:
+
+```bash
+npx shadcn@latest list @acme
+npx shadcn@latest search @acme -q "login"
+npx shadcn@latest view @acme/login-form
+npx shadcn@latest add @acme/login-form --dry-run
+npx shadcn@latest registry validate ./registry.json
+```
+
+Use GitHub addresses directly for public GitHub registries:
+
+```bash
+npx shadcn@latest list owner/repo
+npx shadcn@latest search owner/repo -q "login"
+npx shadcn@latest view owner/repo/item
+npx shadcn@latest add owner/repo/item --dry-run
+npx shadcn@latest registry validate owner/repo
+```
+
+When working on registry implementation in the shadcn/ui codebase:
+
+- Keep address parsing pure and testable.
+- Do not add side effects to validators.
+- Preserve existing behavior for official shadcn, namespace, URL, and file
+ schemes.
+- Add tests for address parsing, source loading, dependency resolution, list,
+ search, view, and add paths.
+- Prefer small source-reader abstractions over a plugin system until there are
+ multiple real providers.
diff --git a/distribution_fe/.claude/skills/shadcn/rules/base-vs-radix.md b/distribution_fe/.claude/skills/shadcn/rules/base-vs-radix.md
new file mode 100644
index 0000000..c1ed7d1
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/rules/base-vs-radix.md
@@ -0,0 +1,306 @@
+# Base vs Radix
+
+API differences between `base` and `radix`. Check the `base` field from `npx shadcn@latest info`.
+
+## Contents
+
+- Composition: asChild vs render
+- Button / trigger as non-button element
+- Select (items prop, placeholder, positioning, multiple, object values)
+- ToggleGroup (type vs multiple)
+- Slider (scalar vs array)
+- Accordion (type and defaultValue)
+
+---
+
+## Composition: asChild (radix) vs render (base)
+
+Radix uses `asChild` to replace the default element. Base uses `render`. Don't wrap triggers in extra elements.
+
+**Incorrect:**
+
+```tsx
+
+
+
+
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+
+
+```
+
+**Correct (base):**
+
+```tsx
+ }>Open
+```
+
+This applies to all trigger and close components: `DialogTrigger`, `SheetTrigger`, `AlertDialogTrigger`, `DropdownMenuTrigger`, `PopoverTrigger`, `TooltipTrigger`, `CollapsibleTrigger`, `DialogClose`, `SheetClose`, `NavigationMenuLink`, `BreadcrumbLink`, `SidebarMenuButton`, `Badge`, `Item`.
+
+---
+
+## Button / trigger as non-button element (base only)
+
+When `render` changes an element to a non-button (``, ``), add `nativeButton={false}`.
+
+**Incorrect (base):** missing `nativeButton={false}`.
+
+```tsx
+}>Read the docs
+```
+
+**Correct (base):**
+
+```tsx
+} nativeButton={false}>
+ Read the docs
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+```
+
+Same for triggers whose `render` is not a `Button`:
+
+```tsx
+// base.
+ } nativeButton={false}>
+ Pick date
+
+```
+
+---
+
+## Select
+
+**items prop (base only).** Base requires an `items` prop on the root. Radix uses inline JSX only.
+
+**Incorrect (base):**
+
+```tsx
+
+```
+
+**Correct (base):**
+
+```tsx
+const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+]
+
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+```
+
+**Placeholder.** Base uses a `{ value: null }` item in the items array. Radix uses ``.
+
+**Content positioning.** Base uses `alignItemWithTrigger`. Radix uses `position`.
+
+```tsx
+// base.
+
+
+// radix.
+
+```
+
+---
+
+## Select — multiple selection and object values (base only)
+
+Base supports `multiple`, render-function children on `SelectValue`, and object values with `itemToStringValue`. Radix is single-select with string values only.
+
+**Correct (base — multiple selection):**
+
+```tsx
+
+```
+
+**Correct (base — object values):**
+
+```tsx
+
+```
+
+---
+
+## ToggleGroup
+
+Base uses a `multiple` boolean prop. Radix uses `type="single"` or `type="multiple"`.
+
+**Incorrect (base):**
+
+```tsx
+
+ Daily
+
+```
+
+**Correct (base):**
+
+```tsx
+// Single (no prop needed), defaultValue is always an array.
+
+ Daily
+ Weekly
+
+
+// Multi-selection.
+
+ Bold
+ Italic
+
+```
+
+**Correct (radix):**
+
+```tsx
+// Single, defaultValue is a string.
+
+ Daily
+ Weekly
+
+
+// Multi-selection.
+
+ Bold
+ Italic
+
+```
+
+**Controlled single value:**
+
+```tsx
+// base — wrap/unwrap arrays.
+const [value, setValue] = React.useState("normal")
+ setValue(v[0])}>
+
+// radix — plain string.
+const [value, setValue] = React.useState("normal")
+
+```
+
+---
+
+## Slider
+
+Base accepts a plain number for a single thumb. Radix always requires an array.
+
+**Incorrect (base):**
+
+```tsx
+
+```
+
+**Correct (base):**
+
+```tsx
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+```
+
+Both use arrays for range sliders. Controlled `onValueChange` in base may need a cast:
+
+```tsx
+// base.
+const [value, setValue] = React.useState([0.3, 0.7])
+ setValue(v as number[])} />
+
+// radix.
+const [value, setValue] = React.useState([0.3, 0.7])
+
+```
+
+---
+
+## Accordion
+
+Radix requires `type="single"` or `type="multiple"` and supports `collapsible`. `defaultValue` is a string. Base uses no `type` prop, uses `multiple` boolean, and `defaultValue` is always an array.
+
+**Incorrect (base):**
+
+```tsx
+
+ ...
+
+```
+
+**Correct (base):**
+
+```tsx
+
+ ...
+
+
+// Multi-select.
+
+ ...
+ ...
+
+```
+
+**Correct (radix):**
+
+```tsx
+
+ ...
+
+```
diff --git a/distribution_fe/.claude/skills/shadcn/rules/chat.md b/distribution_fe/.claude/skills/shadcn/rules/chat.md
new file mode 100644
index 0000000..8ce62fe
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/rules/chat.md
@@ -0,0 +1,224 @@
+# Chat & Messaging
+
+Components for conversation and chat UI. Compose these instead of hand-rolling
+bubbles, scroll containers, dividers, or attachment cards.
+
+Install: `npx shadcn@latest add message-scroller message bubble attachment marker`
+
+The same component names and props ship for both `base` and `radix`; only
+composition differs (`render` vs `asChild`). See [base-vs-radix.md](./base-vs-radix.md).
+
+## Contents
+
+- Scrollable threads use MessageScroller
+- Message rows use Message
+- Message surfaces use Bubble
+- Attachments use Attachment
+- System notes and dividers use Marker
+- Streaming, anchoring, and jump-to-latest are built in
+- Escape hatch: the scroller hooks
+
+---
+
+## Scrollable threads use MessageScroller
+
+A conversation that scrolls, follows new messages, restores position, or jumps
+to a message uses `MessageScroller`. Don't build a raw overflow container with
+manual scroll wiring, and don't reach for `ScrollArea`.
+
+The parts nest in a fixed order. Every direct child of the content is wrapped in
+a `MessageScrollerItem` so the scroller can measure, anchor, preserve position,
+track visibility, and jump to it. `MessageScrollerButton` sits inside
+`MessageScroller`, after the viewport.
+
+**Incorrect:**
+
+```tsx
+// Hand-rolled scroll container with manual stick-to-bottom logic.
+
+
+ {messages.map((m) => (
+
+ ))}
+
+
+```
+
+**Correct:**
+
+```tsx
+
+
+
+
+ {messages.map((message) => (
+
+
+ {/* ...message content... */}
+
+
+ ))}
+
+
+
+
+
+```
+
+---
+
+## Message rows use Message
+
+`Message` lays out a single row: avatar, header, content, footer, with
+alignment. Group consecutive rows from one sender with `MessageGroup`. Don't
+rebuild the row from flex divs.
+
+`align="end"` is the current user's side; `align="start"` is everyone else.
+
+```tsx
+
+
+
+
+ {initials}
+
+
+
+ {sender.name}
+
+ {text}
+
+ {time}
+
+
+```
+
+---
+
+## Message surfaces use Bubble
+
+The colored message surface is `Bubble` + `BubbleContent`, never a styled `div`
+with `bg-muted` / `bg-primary` and hand-managed corners.
+
+- `variant`: `default`, `secondary`, `muted`, `tinted`, `outline`, `ghost`, `destructive`.
+- `align`: `start` or `end` (matches the `Message` side).
+
+`BubbleReactions` renders the reaction cluster. `side` (`top` | `bottom`) and
+`align` (`start` | `end`) position it against the bubble. Don't lay reactions out
+with absolutely-positioned `Badge`s.
+
+**Incorrect:**
+
+```tsx
+
+ {text}
+
+```
+
+**Correct:**
+
+```tsx
+
+ {text}
+
+ 👍 2
+
+
+```
+
+---
+
+## Attachments use Attachment
+
+File and image attachments use `Attachment`, not `Item` or a custom card. It
+carries upload state, so wire `state` to the real status rather than rendering a
+separate spinner.
+
+- `state`: `idle`, `uploading`, `processing`, `error`, `done`. `uploading` and
+ `processing` apply the `shimmer` animation to the title automatically.
+- `size`: `default`, `sm`, `xs`. `orientation`: `horizontal`, `vertical`.
+- Use `AttachmentGroup` to lay out several attachments in a scrolling row.
+
+```tsx
+
+
+
+
+
+ homepage-feedback.pdf
+ PDF · 2.4 MB
+
+
+
+
+
+
+
+```
+
+For an image, use `` with an `img` child.
+
+---
+
+## System notes and dividers use Marker
+
+Status lines ("Sarah joined the conversation"), date dividers ("Today"), and
+labeled separators are `Marker`, not a `Separator` plus a centered span.
+
+- `variant`: `default` (plain row), `separator` (centered label with rules on
+ each side), `border` (bottom-bordered row).
+- `MarkerIcon` holds a leading icon; `MarkerContent` holds the label.
+
+**Incorrect:**
+
+```tsx
+
+
+ Today
+
+
+```
+
+**Correct:**
+
+```tsx
+
+ Today
+
+```
+
+---
+
+## Streaming, anchoring, and jump-to-latest are built in
+
+`MessageScroller` handles the behavior that chat UIs usually reinvent. Don't
+write a `useStickToBottom` hook, a `ResizeObserver`, or manual `scrollTop` math.
+
+- **Follow the live edge while streaming.** `MessageScrollerProvider` with
+ `autoScroll` keeps the view pinned to new content and yields the moment the
+ user scrolls up. Streaming token updates that grow the last message are
+ followed automatically.
+- **Anchor a turn.** `scrollAnchor` on a `MessageScrollerItem` marks the row to
+ hold in view (typically the user's message that started the turn).
+- **Jump to latest.** `MessageScrollerButton` appears when the user scrolls away
+ and scrolls back on click. `direction="end"` (default) or `direction="start"`.
+ It is a self-managing control, so don't gate it behind your own scroll-position
+ state.
+
+For a "thinking…" indicator while the model generates, apply the `shimmer`
+utility to text. Don't author a custom keyframe animation. See
+[styling.md](./styling.md).
+
+---
+
+## Escape hatch: the scroller hooks
+
+For behavior the parts don't expose, read state from the hooks rather than
+re-implementing the scroller: `useMessageScroller`,
+`useMessageScrollerVisibility`, and `useMessageScrollerScrollable`. They come
+from the auto-installed `@shadcn/react` dependency, so there's nothing extra to
+install. Reach for them only when composition can't express what you need.
diff --git a/distribution_fe/.claude/skills/shadcn/rules/composition.md b/distribution_fe/.claude/skills/shadcn/rules/composition.md
new file mode 100644
index 0000000..a8aa427
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/rules/composition.md
@@ -0,0 +1,213 @@
+# Component Composition
+
+## Contents
+
+- Items always inside their Group component
+- Callouts use Alert
+- Empty states use Empty component
+- Toast notifications follow the project base
+- Choosing between overlay components
+- Dialog, Sheet, and Drawer always need a Title
+- Card structure
+- Button has no isPending or isLoading prop
+- TabsTrigger must be inside TabsList
+- Avatar always needs AvatarFallback
+- Use Separator instead of raw hr or border divs
+- Use Skeleton for loading placeholders
+- Use Badge instead of custom styled spans
+
+---
+
+## Items always inside their Group component
+
+Never render items directly inside the content container.
+
+**Incorrect:**
+
+```tsx
+
+ Apple
+ Banana
+
+```
+
+**Correct:**
+
+```tsx
+
+
+ Apple
+ Banana
+
+
+```
+
+This applies to all group-based components:
+
+| Item | Group |
+|------|-------|
+| `SelectItem`, `SelectLabel` | `SelectGroup` |
+| `DropdownMenuItem`, `DropdownMenuLabel`, `DropdownMenuSub` | `DropdownMenuGroup` |
+| `MenubarItem` | `MenubarGroup` |
+| `ContextMenuItem` | `ContextMenuGroup` |
+| `CommandItem` | `CommandGroup` |
+| `MessageScrollerItem` | `MessageScrollerContent` |
+| `Message` (consecutive, same sender) | `MessageGroup` |
+| `Bubble` (stacked) | `BubbleGroup` |
+| `Attachment` (in a row) | `AttachmentGroup` |
+
+Chat components nest in a fixed order (`MessageScrollerProvider` → `MessageScroller` → `MessageScrollerViewport` → `MessageScrollerContent` → `MessageScrollerItem`). See [chat.md](./chat.md).
+
+---
+
+## Callouts use Alert
+
+```tsx
+
+ Warning
+ Something needs attention.
+
+```
+
+---
+
+## Empty states use Empty component
+
+```tsx
+
+
+
+ No projects yet
+ Get started by creating a new project.
+
+
+
+
+
+```
+
+---
+
+## Toast notifications follow the project base
+
+For Base UI projects, use the `toast` component:
+
+```tsx
+import { toast } from "@/components/ui/toast"
+
+toast.add({
+ title: "Changes saved.",
+})
+```
+
+For Radix and React Aria projects, use Sonner:
+
+```tsx
+import { toast } from "sonner"
+
+toast.success("Changes saved.")
+toast.error("Something went wrong.")
+toast("File deleted.", {
+ action: { label: "Undo", onClick: () => undoDelete() },
+})
+```
+
+---
+
+## Choosing between overlay components
+
+| Use case | Component |
+|----------|-----------|
+| Focused task that requires input | `Dialog` |
+| Destructive action confirmation | `AlertDialog` |
+| Side panel with details or filters | `Sheet` |
+| Mobile-first bottom panel | `Drawer` |
+| Quick info on hover | `HoverCard` |
+| Small contextual content on click | `Popover` |
+
+---
+
+## Dialog, Sheet, and Drawer always need a Title
+
+`DialogTitle`, `SheetTitle`, `DrawerTitle` are required for accessibility. Use `className="sr-only"` if visually hidden.
+
+```tsx
+
+
+ Edit Profile
+ Update your profile.
+
+ ...
+
+```
+
+---
+
+## Card structure
+
+Use full composition — don't dump everything into `CardContent`:
+
+```tsx
+
+
+ Team Members
+ Manage your team.
+
+ ...
+
+
+
+
+```
+
+---
+
+## Button has no isPending or isLoading prop
+
+Compose with `Spinner` + `data-icon` + `disabled`:
+
+```tsx
+
+```
+
+---
+
+## TabsTrigger must be inside TabsList
+
+Never render `TabsTrigger` directly inside `Tabs` — always wrap in `TabsList`:
+
+```tsx
+
+
+ Account
+ Password
+
+ ...
+
+```
+
+---
+
+## Avatar always needs AvatarFallback
+
+Always include `AvatarFallback` for when the image fails to load:
+
+```tsx
+
+
+ JD
+
+```
+
+---
+
+## Use existing components instead of custom markup
+
+| Instead of | Use |
+|---|---|
+| `
` or `` | ` ` |
+| `` with styled divs | ` ` |
+| `` | `` |
diff --git a/distribution_fe/.claude/skills/shadcn/rules/forms.md b/distribution_fe/.claude/skills/shadcn/rules/forms.md
new file mode 100644
index 0000000..f451e2f
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/rules/forms.md
@@ -0,0 +1,192 @@
+# Forms & Inputs
+
+## Contents
+
+- Forms use FieldGroup + Field
+- InputGroup requires InputGroupInput/InputGroupTextarea
+- Buttons inside inputs use InputGroup + InputGroupAddon
+- Option sets (2–7 choices) use ToggleGroup
+- FieldSet + FieldLegend for grouping related fields
+- Field validation and disabled states
+
+---
+
+## Forms use FieldGroup + Field
+
+Always use `FieldGroup` + `Field` — never raw `div` with `space-y-*`:
+
+```tsx
+
+
+ Email
+
+
+
+ Password
+
+
+
+```
+
+Use `Field orientation="horizontal"` for settings pages. Use `FieldLabel className="sr-only"` for visually hidden labels.
+
+**Choosing form controls:**
+
+- Simple text input → `Input`
+- Dropdown with predefined options → `Select`
+- Searchable dropdown → `Combobox`
+- Native HTML select (no JS) → `native-select`
+- Boolean toggle → `Switch` (for settings) or `Checkbox` (for forms)
+- Single choice from few options → `RadioGroup`
+- Toggle between 2–5 options → `ToggleGroup` + `ToggleGroupItem`
+- OTP/verification code → `InputOTP`
+- Multi-line text → `Textarea`
+
+---
+
+## InputGroup requires InputGroupInput/InputGroupTextarea
+
+Never use raw `Input` or `Textarea` inside an `InputGroup`.
+
+**Incorrect:**
+
+```tsx
+
+
+
+```
+
+**Correct:**
+
+```tsx
+import { InputGroup, InputGroupInput } from "@/components/ui/input-group"
+
+
+
+
+```
+
+---
+
+## Buttons inside inputs use InputGroup + InputGroupAddon
+
+Never place a `Button` directly inside or adjacent to an `Input` with custom positioning.
+
+**Incorrect:**
+
+```tsx
+
+
+
+
+```
+
+**Correct:**
+
+```tsx
+import { InputGroup, InputGroupInput, InputGroupAddon } from "@/components/ui/input-group"
+
+
+
+
+
+
+
+```
+
+---
+
+## Option sets (2–7 choices) use ToggleGroup
+
+Don't manually loop `Button` components with active state.
+
+**Incorrect:**
+
+```tsx
+const [selected, setSelected] = useState("daily")
+
+
+ {["daily", "weekly", "monthly"].map((option) => (
+
+ ))}
+
+```
+
+**Correct:**
+
+```tsx
+import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
+
+
+ Daily
+ Weekly
+ Monthly
+
+```
+
+Combine with `Field` for labelled toggle groups:
+
+```tsx
+
+ Theme
+
+ Light
+ Dark
+ System
+
+
+```
+
+> **Note:** `defaultValue` and `type`/`multiple` props differ between base and radix. See [base-vs-radix.md](./base-vs-radix.md#togglegroup).
+
+---
+
+## FieldSet + FieldLegend for grouping related fields
+
+Use `FieldSet` + `FieldLegend` for related checkboxes, radios, or switches — not `div` with a heading:
+
+```tsx
+
+```
+
+---
+
+## Field validation and disabled states
+
+Both attributes are needed — `data-invalid`/`data-disabled` styles the field (label, description), while `aria-invalid`/`disabled` styles the control.
+
+```tsx
+// Invalid.
+
+ Email
+
+ Invalid email address.
+
+
+// Disabled.
+
+ Email
+
+
+```
+
+Works for all controls: `Input`, `Textarea`, `Select`, `Checkbox`, `RadioGroupItem`, `Switch`, `Slider`, `NativeSelect`, `InputOTP`.
diff --git a/distribution_fe/.claude/skills/shadcn/rules/icons.md b/distribution_fe/.claude/skills/shadcn/rules/icons.md
new file mode 100644
index 0000000..bba8102
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/rules/icons.md
@@ -0,0 +1,101 @@
+# Icons
+
+**Always use the project's configured `iconLibrary` for imports.** Check the `iconLibrary` field from project context: `lucide` → `lucide-react`, `tabler` → `@tabler/icons-react`, etc. Never assume `lucide-react`.
+
+---
+
+## Icons in Button use data-icon attribute
+
+Add `data-icon="inline-start"` (prefix) or `data-icon="inline-end"` (suffix) to the icon. No sizing classes on the icon.
+
+**Incorrect:**
+
+```tsx
+
+```
+
+**Correct:**
+
+```tsx
+
+
+
+```
+
+---
+
+## No sizing classes on icons inside components
+
+Components handle icon sizing via CSS. Don't add `size-4`, `w-4 h-4`, or other sizing classes to icons inside `Button`, `DropdownMenuItem`, `Alert`, `Sidebar*`, or other shadcn components. Unless the user explicitly asks for custom icon sizes.
+
+**Incorrect:**
+
+```tsx
+
+
+
+
+ Settings
+
+```
+
+**Correct:**
+
+```tsx
+
+
+
+
+ Settings
+
+```
+
+---
+
+## Pass icons as component objects, not string keys
+
+Use `icon={CheckIcon}`, not a string key to a lookup map.
+
+**Incorrect:**
+
+```tsx
+const iconMap = {
+ check: CheckIcon,
+ alert: AlertIcon,
+}
+
+function StatusBadge({ icon }: { icon: string }) {
+ const Icon = iconMap[icon]
+ return
+}
+
+
+```
+
+**Correct:**
+
+```tsx
+// Import from the project's configured iconLibrary (e.g. lucide-react, @tabler/icons-react).
+import { CheckIcon } from "lucide-react"
+
+function StatusBadge({ icon: Icon }: { icon: React.ComponentType }) {
+ return
+}
+
+
+```
diff --git a/distribution_fe/.claude/skills/shadcn/rules/styling.md b/distribution_fe/.claude/skills/shadcn/rules/styling.md
new file mode 100644
index 0000000..fe75197
--- /dev/null
+++ b/distribution_fe/.claude/skills/shadcn/rules/styling.md
@@ -0,0 +1,185 @@
+# Styling & Customization
+
+See [customization.md](../customization.md) for theming, CSS variables, and adding custom colors.
+
+## Contents
+
+- Semantic colors
+- Built-in variants first
+- className for layout only
+- No space-x-* / space-y-*
+- Prefer size-* over w-* h-* when equal
+- Prefer truncate shorthand
+- No manual dark: color overrides
+- Use cn() for conditional classes
+- No manual z-index on overlay components
+- Use shimmer / scroll-fade utilities, not custom animations
+
+---
+
+## Semantic colors
+
+**Incorrect:**
+
+```tsx
+
+ Secondary text
+
+```
+
+**Correct:**
+
+```tsx
+
+ Secondary text
+
+```
+
+---
+
+## No raw color values for status/state indicators
+
+For positive, negative, or status indicators, use Badge variants, semantic tokens like `text-destructive`, or define custom CSS variables — don't reach for raw Tailwind colors.
+
+**Incorrect:**
+
+```tsx
++20.1%
+Active
+-3.2%
+```
+
+**Correct:**
+
+```tsx
++20.1%
+Active
+-3.2%
+```
+
+If you need a success/positive color that doesn't exist as a semantic token, use a Badge variant or ask the user about adding a custom CSS variable to the theme (see [customization.md](../customization.md)).
+
+---
+
+## Built-in variants first
+
+**Incorrect:**
+
+```tsx
+
+```
+
+**Correct:**
+
+```tsx
+
+```
+
+---
+
+## className for layout only
+
+Use `className` for layout (e.g. `max-w-md`, `mx-auto`, `mt-4`), **not** for overriding component colors or typography. To change colors, use semantic tokens, built-in variants, or CSS variables.
+
+**Incorrect:**
+
+```tsx
+
+ Dashboard
+
+```
+
+**Correct:**
+
+```tsx
+
+ Dashboard
+
+```
+
+To customize a component's appearance, prefer these approaches in order:
+1. **Built-in variants** — `variant="outline"`, `variant="destructive"`, etc.
+2. **Semantic color tokens** — `bg-primary`, `text-muted-foreground`.
+3. **CSS variables** — define custom colors in the global CSS file (see [customization.md](../customization.md)).
+
+---
+
+## No space-x-* / space-y-*
+
+Use `gap-*` instead. `space-y-4` → `flex flex-col gap-4`. `space-x-2` → `flex gap-2`.
+
+```tsx
+
+
+
+
+
+```
+
+---
+
+## Prefer size-* over w-* h-* when equal
+
+`size-10` not `w-10 h-10`. Applies to icons, avatars, skeletons, etc.
+
+---
+
+## Prefer truncate shorthand
+
+`truncate` not `overflow-hidden text-ellipsis whitespace-nowrap`.
+
+---
+
+## No manual dark: color overrides
+
+Use semantic tokens — they handle light/dark via CSS variables. `bg-background text-foreground` not `bg-white dark:bg-gray-950`.
+
+---
+
+## Use cn() for conditional classes
+
+Use the `cn()` utility from the project for conditional or merged class names. Don't write manual ternaries in className strings.
+
+**Incorrect:**
+
+```tsx
+
+```
+
+**Correct:**
+
+```tsx
+import { cn } from "@/lib/utils"
+
+
+```
+
+---
+
+## No manual z-index on overlay components
+
+`Dialog`, `Sheet`, `Drawer`, `AlertDialog`, `DropdownMenu`, `Popover`, `Tooltip`, `HoverCard` handle their own stacking. Never add `z-50` or `z-[999]`.
+
+---
+
+## Use shimmer / scroll-fade utilities, not custom animations
+
+For a live "thinking…" or loading-text shimmer, apply the `shimmer` utility. Don't author a custom `@keyframes` or a `bg-clip-text` gradient sweep.
+
+For scroll-aware edge fading on a scroll container, use `scroll-fade` (and the axis variants `scroll-fade-x` / `scroll-fade-b`). Don't hand-roll mask gradients. The chat components already apply these internally: `Attachment` shimmers its title during upload, and `MessageScrollerViewport` fades its edges.
+
+**Incorrect:**
+
+```tsx
+
+ Thinking…
+
+```
+
+**Correct:**
+
+```tsx
+Thinking…
+```
diff --git a/distribution_fe/.git_backup_distribution_fe/COMMIT_EDITMSG b/distribution_fe/.git_backup_distribution_fe/COMMIT_EDITMSG
new file mode 100644
index 0000000..9e7d5c7
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/COMMIT_EDITMSG
@@ -0,0 +1 @@
+feat: initial commit
diff --git a/distribution_fe/.git_backup_distribution_fe/FETCH_HEAD b/distribution_fe/.git_backup_distribution_fe/FETCH_HEAD
new file mode 100644
index 0000000..e69de29
diff --git a/distribution_fe/.git_backup_distribution_fe/HEAD b/distribution_fe/.git_backup_distribution_fe/HEAD
new file mode 100644
index 0000000..cb089cd
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/distribution_fe/.git_backup_distribution_fe/config b/distribution_fe/.git_backup_distribution_fe/config
new file mode 100644
index 0000000..d545cda
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/config
@@ -0,0 +1,7 @@
+[core]
+ repositoryformatversion = 0
+ filemode = false
+ bare = false
+ logallrefupdates = true
+ symlinks = false
+ ignorecase = true
diff --git a/distribution_fe/.git_backup_distribution_fe/description b/distribution_fe/.git_backup_distribution_fe/description
new file mode 100644
index 0000000..498b267
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/applypatch-msg.sample b/distribution_fe/.git_backup_distribution_fe/hooks/applypatch-msg.sample
new file mode 100644
index 0000000..a5d7b84
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/applypatch-msg.sample
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit. The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
+test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
+:
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/commit-msg.sample b/distribution_fe/.git_backup_distribution_fe/hooks/commit-msg.sample
new file mode 100644
index 0000000..b58d118
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/commit-msg.sample
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message. The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit. The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
+ echo >&2 Duplicate Signed-off-by lines.
+ exit 1
+}
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/fsmonitor-watchman.sample b/distribution_fe/.git_backup_distribution_fe/hooks/fsmonitor-watchman.sample
new file mode 100644
index 0000000..23e856f
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/fsmonitor-watchman.sample
@@ -0,0 +1,174 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use IPC::Open2;
+
+# An example hook script to integrate Watchman
+# (https://facebook.github.io/watchman/) with git to speed up detecting
+# new and modified files.
+#
+# The hook is passed a version (currently 2) and last update token
+# formatted as a string and outputs to stdout a new update token and
+# all files that have been modified since the update token. Paths must
+# be relative to the root of the working tree and separated by a single NUL.
+#
+# To enable this hook, rename this file to "query-watchman" and set
+# 'git config core.fsmonitor .git/hooks/query-watchman'
+#
+my ($version, $last_update_token) = @ARGV;
+
+# Uncomment for debugging
+# print STDERR "$0 $version $last_update_token\n";
+
+# Check the hook interface version
+if ($version ne 2) {
+ die "Unsupported query-fsmonitor hook version '$version'.\n" .
+ "Falling back to scanning...\n";
+}
+
+my $git_work_tree = get_working_dir();
+
+my $retry = 1;
+
+my $json_pkg;
+eval {
+ require JSON::XS;
+ $json_pkg = "JSON::XS";
+ 1;
+} or do {
+ require JSON::PP;
+ $json_pkg = "JSON::PP";
+};
+
+launch_watchman();
+
+sub launch_watchman {
+ my $o = watchman_query();
+ if (is_work_tree_watched($o)) {
+ output_result($o->{clock}, @{$o->{files}});
+ }
+}
+
+sub output_result {
+ my ($clockid, @files) = @_;
+
+ # Uncomment for debugging watchman output
+ # open (my $fh, ">", ".git/watchman-output.out");
+ # binmode $fh, ":utf8";
+ # print $fh "$clockid\n@files\n";
+ # close $fh;
+
+ binmode STDOUT, ":utf8";
+ print $clockid;
+ print "\0";
+ local $, = "\0";
+ print @files;
+}
+
+sub watchman_clock {
+ my $response = qx/watchman clock "$git_work_tree"/;
+ die "Failed to get clock id on '$git_work_tree'.\n" .
+ "Falling back to scanning...\n" if $? != 0;
+
+ return $json_pkg->new->utf8->decode($response);
+}
+
+sub watchman_query {
+ my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
+ or die "open2() failed: $!\n" .
+ "Falling back to scanning...\n";
+
+ # In the query expression below we're asking for names of files that
+ # changed since $last_update_token but not from the .git folder.
+ #
+ # To accomplish this, we're using the "since" generator to use the
+ # recency index to select candidate nodes and "fields" to limit the
+ # output to file names only. Then we're using the "expression" term to
+ # further constrain the results.
+ my $last_update_line = "";
+ if (substr($last_update_token, 0, 1) eq "c") {
+ $last_update_token = "\"$last_update_token\"";
+ $last_update_line = qq[\n"since": $last_update_token,];
+ }
+ my $query = <<" END";
+ ["query", "$git_work_tree", {$last_update_line
+ "fields": ["name"],
+ "expression": ["not", ["dirname", ".git"]]
+ }]
+ END
+
+ # Uncomment for debugging the watchman query
+ # open (my $fh, ">", ".git/watchman-query.json");
+ # print $fh $query;
+ # close $fh;
+
+ print CHLD_IN $query;
+ close CHLD_IN;
+ my $response = do {local $/; };
+
+ # Uncomment for debugging the watch response
+ # open ($fh, ">", ".git/watchman-response.json");
+ # print $fh $response;
+ # close $fh;
+
+ die "Watchman: command returned no output.\n" .
+ "Falling back to scanning...\n" if $response eq "";
+ die "Watchman: command returned invalid output: $response\n" .
+ "Falling back to scanning...\n" unless $response =~ /^\{/;
+
+ return $json_pkg->new->utf8->decode($response);
+}
+
+sub is_work_tree_watched {
+ my ($output) = @_;
+ my $error = $output->{error};
+ if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
+ $retry--;
+ my $response = qx/watchman watch "$git_work_tree"/;
+ die "Failed to make watchman watch '$git_work_tree'.\n" .
+ "Falling back to scanning...\n" if $? != 0;
+ $output = $json_pkg->new->utf8->decode($response);
+ $error = $output->{error};
+ die "Watchman: $error.\n" .
+ "Falling back to scanning...\n" if $error;
+
+ # Uncomment for debugging watchman output
+ # open (my $fh, ">", ".git/watchman-output.out");
+ # close $fh;
+
+ # Watchman will always return all files on the first query so
+ # return the fast "everything is dirty" flag to git and do the
+ # Watchman query just to get it over with now so we won't pay
+ # the cost in git to look up each individual file.
+ my $o = watchman_clock();
+ $error = $output->{error};
+
+ die "Watchman: $error.\n" .
+ "Falling back to scanning...\n" if $error;
+
+ output_result($o->{clock}, ("/"));
+ $last_update_token = $o->{clock};
+
+ eval { launch_watchman() };
+ return 0;
+ }
+
+ die "Watchman: $error.\n" .
+ "Falling back to scanning...\n" if $error;
+
+ return 1;
+}
+
+sub get_working_dir {
+ my $working_dir;
+ if ($^O =~ 'msys' || $^O =~ 'cygwin') {
+ $working_dir = Win32::GetCwd();
+ $working_dir =~ tr/\\/\//;
+ } else {
+ require Cwd;
+ $working_dir = Cwd::cwd();
+ }
+
+ return $working_dir;
+}
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/post-update.sample b/distribution_fe/.git_backup_distribution_fe/hooks/post-update.sample
new file mode 100644
index 0000000..ec17ec1
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/post-update.sample
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/pre-applypatch.sample b/distribution_fe/.git_backup_distribution_fe/hooks/pre-applypatch.sample
new file mode 100644
index 0000000..4142082
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/pre-applypatch.sample
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+precommit="$(git rev-parse --git-path hooks/pre-commit)"
+test -x "$precommit" && exec "$precommit" ${1+"$@"}
+:
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/pre-commit.sample b/distribution_fe/.git_backup_distribution_fe/hooks/pre-commit.sample
new file mode 100644
index 0000000..29ed5ee
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/pre-commit.sample
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments. The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+ against=HEAD
+else
+ # Initial commit: diff against an empty tree object
+ against=$(git hash-object -t tree /dev/null)
+fi
+
+# If you want to allow non-ASCII filenames set this variable to true.
+allownonascii=$(git config --type=bool hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ASCII filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+ # Note that the use of brackets around a tr range is ok here, (it's
+ # even required, for portability to Solaris 10's /usr/bin/tr), since
+ # the square bracket bytes happen to fall in the designated range.
+ test $(git diff-index --cached --name-only --diff-filter=A -z $against |
+ LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+ cat <<\EOF
+Error: Attempt to add a non-ASCII file name.
+
+This can cause problems if you want to work with people on other platforms.
+
+To be portable it is advisable to rename the file.
+
+If you know what you are doing you can disable this check using:
+
+ git config hooks.allownonascii true
+EOF
+ exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/pre-merge-commit.sample b/distribution_fe/.git_backup_distribution_fe/hooks/pre-merge-commit.sample
new file mode 100644
index 0000000..399eab1
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/pre-merge-commit.sample
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git merge" with no arguments. The hook should
+# exit with non-zero status after issuing an appropriate message to
+# stderr if it wants to stop the merge commit.
+#
+# To enable this hook, rename this file to "pre-merge-commit".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+ exec "$GIT_DIR/hooks/pre-commit"
+:
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/pre-push.sample b/distribution_fe/.git_backup_distribution_fe/hooks/pre-push.sample
new file mode 100644
index 0000000..4ce688d
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/pre-push.sample
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# An example hook script to verify what is about to be pushed. Called by "git
+# push" after it has checked the remote status, but before anything has been
+# pushed. If this script exits with a non-zero status nothing will be pushed.
+#
+# This hook is called with the following parameters:
+#
+# $1 -- Name of the remote to which the push is being done
+# $2 -- URL to which the push is being done
+#
+# If pushing without using a named remote those arguments will be equal.
+#
+# Information about the commits which are being pushed is supplied as lines to
+# the standard input in the form:
+#
+#
+#
+# This sample shows how to prevent push of commits where the log message starts
+# with "WIP" (work in progress).
+
+remote="$1"
+url="$2"
+
+zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing"
+ exit 1
+ fi
+ fi
+done
+
+exit 0
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/pre-rebase.sample b/distribution_fe/.git_backup_distribution_fe/hooks/pre-rebase.sample
new file mode 100644
index 0000000..6cbef5c
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/pre-rebase.sample
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+ topic="refs/heads/$2"
+else
+ topic=`git symbolic-ref HEAD` ||
+ exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+ ;;
+*)
+ exit 0 ;# we do not interrupt others.
+ ;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master. Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+ echo >&2 "No such branch $topic"
+ exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+ echo >&2 "$topic is fully merged to master; better remove it."
+ exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next? If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+ not_in_topic=`git rev-list "^$topic" master`
+ if test -z "$not_in_topic"
+ then
+ echo >&2 "$topic is already up to date with master"
+ exit 1 ;# we could allow it, but there is no point.
+ else
+ exit 0
+ fi
+else
+ not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+ /usr/bin/perl -e '
+ my $topic = $ARGV[0];
+ my $msg = "* $topic has commits already merged to public branch:\n";
+ my (%not_in_next) = map {
+ /^([0-9a-f]+) /;
+ ($1 => 1);
+ } split(/\n/, $ARGV[1]);
+ for my $elem (map {
+ /^([0-9a-f]+) (.*)$/;
+ [$1 => $2];
+ } split(/\n/, $ARGV[2])) {
+ if (!exists $not_in_next{$elem->[0]}) {
+ if ($msg) {
+ print STDERR $msg;
+ undef $msg;
+ }
+ print STDERR " $elem->[1]\n";
+ }
+ }
+ ' "$topic" "$not_in_next" "$not_in_master"
+ exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+ merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+ it is deleted. If you need to build on top of it to correct
+ earlier mistakes, a new topic branch is created by forking at
+ the tip of the "master". This is not strictly necessary, but
+ it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+ branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next". Young
+ topic branches can have stupid mistakes you would rather
+ clean up before publishing, and things that have not been
+ merged into other branches can be easily rebased without
+ affecting other people. But once it is published, you would
+ not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+ Then you can delete it. More importantly, you should not
+ build on top of it -- other people may already want to
+ change things related to the topic as patches against your
+ "master", so if you need further changes, it is better to
+ fork the topic (perhaps with the same name) afresh from the
+ tip of "master".
+
+Let's look at this example:
+
+ o---o---o---o---o---o---o---o---o---o "next"
+ / / / /
+ / a---a---b A / /
+ / / / /
+ / / c---c---c---c B /
+ / / / \ /
+ / / / b---b C \ /
+ / / / / \ /
+ ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished. It has been fully merged up to "master" and "next",
+ and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+ git rev-list ^master ^topic next
+ git rev-list ^master next
+
+ if these match, topic has not merged in next at all.
+
+To compute (2):
+
+ git rev-list master..topic
+
+ if this is empty, it is fully merged to "master".
+
+DOC_END
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/pre-receive.sample b/distribution_fe/.git_backup_distribution_fe/hooks/pre-receive.sample
new file mode 100644
index 0000000..a1fd29e
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/pre-receive.sample
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to make use of push options.
+# The example simply echoes all push options that start with 'echoback='
+# and rejects all pushes when the "reject" push option is used.
+#
+# To enable this hook, rename this file to "pre-receive".
+
+if test -n "$GIT_PUSH_OPTION_COUNT"
+then
+ i=0
+ while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
+ do
+ eval "value=\$GIT_PUSH_OPTION_$i"
+ case "$value" in
+ echoback=*)
+ echo "echo from the pre-receive-hook: ${value#*=}" >&2
+ ;;
+ reject)
+ exit 1
+ esac
+ i=$((i + 1))
+ done
+fi
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/prepare-commit-msg.sample b/distribution_fe/.git_backup_distribution_fe/hooks/prepare-commit-msg.sample
new file mode 100644
index 0000000..10fa14c
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/prepare-commit-msg.sample
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source. The hook's purpose is to edit the commit
+# message file. If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples. The first one removes the
+# "# Please enter the commit message..." help message.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output. It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited. This is rarely a good idea.
+
+COMMIT_MSG_FILE=$1
+COMMIT_SOURCE=$2
+SHA1=$3
+
+/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
+
+# case "$COMMIT_SOURCE,$SHA1" in
+# ,|template,)
+# /usr/bin/perl -i.bak -pe '
+# print "\n" . `git diff --cached --name-status -r`
+# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
+# *) ;;
+# esac
+
+# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
+# if test -z "$COMMIT_SOURCE"
+# then
+# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
+# fi
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/push-to-checkout.sample b/distribution_fe/.git_backup_distribution_fe/hooks/push-to-checkout.sample
new file mode 100644
index 0000000..af5a0c0
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/push-to-checkout.sample
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+# An example hook script to update a checked-out tree on a git push.
+#
+# This hook is invoked by git-receive-pack(1) when it reacts to git
+# push and updates reference(s) in its repository, and when the push
+# tries to update the branch that is currently checked out and the
+# receive.denyCurrentBranch configuration variable is set to
+# updateInstead.
+#
+# By default, such a push is refused if the working tree and the index
+# of the remote repository has any difference from the currently
+# checked out commit; when both the working tree and the index match
+# the current commit, they are updated to match the newly pushed tip
+# of the branch. This hook is to be used to override the default
+# behaviour; however the code below reimplements the default behaviour
+# as a starting point for convenient modification.
+#
+# The hook receives the commit with which the tip of the current
+# branch is going to be updated:
+commit=$1
+
+# It can exit with a non-zero status to refuse the push (when it does
+# so, it must not modify the index or the working tree).
+die () {
+ echo >&2 "$*"
+ exit 1
+}
+
+# Or it can make any necessary changes to the working tree and to the
+# index to bring them to the desired state when the tip of the current
+# branch is updated to the new commit, and exit with a zero status.
+#
+# For example, the hook can simply run git read-tree -u -m HEAD "$1"
+# in order to emulate git fetch that is run in the reverse direction
+# with git push, as the two-tree form of git read-tree -u -m is
+# essentially the same as git switch or git checkout that switches
+# branches while keeping the local changes in the working tree that do
+# not interfere with the difference between the branches.
+
+# The below is a more-or-less exact translation to shell of the C code
+# for the default behaviour for git's push-to-checkout hook defined in
+# the push_to_deploy() function in builtin/receive-pack.c.
+#
+# Note that the hook will be executed from the repository directory,
+# not from the working tree, so if you want to perform operations on
+# the working tree, you will have to adapt your code accordingly, e.g.
+# by adding "cd .." or using relative paths.
+
+if ! git update-index -q --ignore-submodules --refresh
+then
+ die "Up-to-date check failed"
+fi
+
+if ! git diff-files --quiet --ignore-submodules --
+then
+ die "Working directory has unstaged changes"
+fi
+
+# This is a rough translation of:
+#
+# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
+if git cat-file -e HEAD 2>/dev/null
+then
+ head=HEAD
+else
+ head=$(git hash-object -t tree --stdin &2
+ exit 1
+}
+
+unset GIT_DIR GIT_WORK_TREE
+cd "$worktree" &&
+
+if grep -q "^diff --git " "$1"
+then
+ validate_patch "$1"
+else
+ validate_cover_letter "$1"
+fi &&
+
+if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL"
+then
+ git config --unset-all sendemail.validateWorktree &&
+ trap 'git worktree remove -ff "$worktree"' EXIT &&
+ validate_series
+fi
diff --git a/distribution_fe/.git_backup_distribution_fe/hooks/update.sample b/distribution_fe/.git_backup_distribution_fe/hooks/update.sample
new file mode 100644
index 0000000..c4d426b
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/hooks/update.sample
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to block unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+# This boolean sets whether unannotated tags will be allowed into the
+# repository. By default they won't be.
+# hooks.allowdeletetag
+# This boolean sets whether deleting tags will be allowed in the
+# repository. By default they won't be.
+# hooks.allowmodifytag
+# This boolean sets whether a tag may be modified after creation. By default
+# it won't be.
+# hooks.allowdeletebranch
+# This boolean sets whether deleting branches will be allowed in the
+# repository. By default they won't be.
+# hooks.denycreatebranch
+# This boolean sets whether remotely creating branches will be denied
+# in the repository. By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+ echo "Don't run this script from the command line." >&2
+ echo " (if you want, you could supply GIT_DIR then run" >&2
+ echo " $0 )" >&2
+ exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+ echo "usage: $0 " >&2
+ exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --type=bool hooks.allowunannotated)
+allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
+allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
+allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+ echo "*** Project description file hasn't been set" >&2
+ exit 1
+ ;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero=$(git hash-object --stdin &2
+ echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+ exit 1
+ fi
+ ;;
+ refs/tags/*,delete)
+ # delete tag
+ if [ "$allowdeletetag" != "true" ]; then
+ echo "*** Deleting a tag is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/tags/*,tag)
+ # annotated tag
+ if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+ then
+ echo "*** Tag '$refname' already exists." >&2
+ echo "*** Modifying a tag is not allowed in this repository." >&2
+ exit 1
+ fi
+ ;;
+ refs/heads/*,commit)
+ # branch
+ if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+ echo "*** Creating a branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/heads/*,delete)
+ # delete branch
+ if [ "$allowdeletebranch" != "true" ]; then
+ echo "*** Deleting a branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/remotes/*,commit)
+ # tracking branch
+ ;;
+ refs/remotes/*,delete)
+ # delete tracking branch
+ if [ "$allowdeletebranch" != "true" ]; then
+ echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ *)
+ # Anything else (is there anything else?)
+ echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+ exit 1
+ ;;
+esac
+
+# --- Finished
+exit 0
diff --git a/distribution_fe/.git_backup_distribution_fe/index b/distribution_fe/.git_backup_distribution_fe/index
new file mode 100644
index 0000000..35d848a
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/index differ
diff --git a/distribution_fe/.git_backup_distribution_fe/info/exclude b/distribution_fe/.git_backup_distribution_fe/info/exclude
new file mode 100644
index 0000000..a5196d1
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/distribution_fe/.git_backup_distribution_fe/logs/HEAD b/distribution_fe/.git_backup_distribution_fe/logs/HEAD
new file mode 100644
index 0000000..7f96bf3
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/logs/HEAD
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 088d90049e99bcf4d4c7d4018d36368f0ceb81a8 Kalana B. Thilakarathna 1787642417 +0530 commit (initial): feat: initial commit
diff --git a/distribution_fe/.git_backup_distribution_fe/logs/refs/heads/master b/distribution_fe/.git_backup_distribution_fe/logs/refs/heads/master
new file mode 100644
index 0000000..7f96bf3
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/logs/refs/heads/master
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 088d90049e99bcf4d4c7d4018d36368f0ceb81a8 Kalana B. Thilakarathna 1787642417 +0530 commit (initial): feat: initial commit
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/03/b693a7f93d0da640b45d5961a6a30c718b3177 b/distribution_fe/.git_backup_distribution_fe/objects/03/b693a7f93d0da640b45d5961a6a30c718b3177
new file mode 100644
index 0000000..2736e0d
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/03/b693a7f93d0da640b45d5961a6a30c718b3177 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/05/e726d1b4201bc8c7716d2b058279676582e8c0 b/distribution_fe/.git_backup_distribution_fe/objects/05/e726d1b4201bc8c7716d2b058279676582e8c0
new file mode 100644
index 0000000..5a91548
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/05/e726d1b4201bc8c7716d2b058279676582e8c0 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/08/8d90049e99bcf4d4c7d4018d36368f0ceb81a8 b/distribution_fe/.git_backup_distribution_fe/objects/08/8d90049e99bcf4d4c7d4018d36368f0ceb81a8
new file mode 100644
index 0000000..fa2b84a
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/08/8d90049e99bcf4d4c7d4018d36368f0ceb81a8 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/0d/4ba497cebf1e2e01992220edbb40a88abc5212 b/distribution_fe/.git_backup_distribution_fe/objects/0d/4ba497cebf1e2e01992220edbb40a88abc5212
new file mode 100644
index 0000000..a788ea1
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/0d/4ba497cebf1e2e01992220edbb40a88abc5212 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/1e/66186dfe120684092c6e3eef77e24022918ac8 b/distribution_fe/.git_backup_distribution_fe/objects/1e/66186dfe120684092c6e3eef77e24022918ac8
new file mode 100644
index 0000000..261224b
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/objects/1e/66186dfe120684092c6e3eef77e24022918ac8
@@ -0,0 +1,2 @@
+xm�1NÄ0E©}НM‹64@³ì¨ �{‰‘㉿�àŒ[
\ No newline at end of file
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/27/0dd7415ba36c38c4e4ea76c8907dd3d3aa2e44 b/distribution_fe/.git_backup_distribution_fe/objects/27/0dd7415ba36c38c4e4ea76c8907dd3d3aa2e44
new file mode 100644
index 0000000..d10dbd4
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/27/0dd7415ba36c38c4e4ea76c8907dd3d3aa2e44 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/2f/8795a936c6fbca951780dd7da3eec156b43084 b/distribution_fe/.git_backup_distribution_fe/objects/2f/8795a936c6fbca951780dd7da3eec156b43084
new file mode 100644
index 0000000..c85e484
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/2f/8795a936c6fbca951780dd7da3eec156b43084 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/3d/44f4815118cefa955f645c7cf24796c77c4927 b/distribution_fe/.git_backup_distribution_fe/objects/3d/44f4815118cefa955f645c7cf24796c77c4927
new file mode 100644
index 0000000..32d5972
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/3d/44f4815118cefa955f645c7cf24796c77c4927 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/45/343f1b48bd33af0bf3478283ff4a49b8894a9f b/distribution_fe/.git_backup_distribution_fe/objects/45/343f1b48bd33af0bf3478283ff4a49b8894a9f
new file mode 100644
index 0000000..ba6715b
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/45/343f1b48bd33af0bf3478283ff4a49b8894a9f differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/46/1b0084104385d8cb1d4d6b5f6114033be973fe b/distribution_fe/.git_backup_distribution_fe/objects/46/1b0084104385d8cb1d4d6b5f6114033be973fe
new file mode 100644
index 0000000..9fdab19
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/objects/46/1b0084104385d8cb1d4d6b5f6114033be973fe
@@ -0,0 +1,2 @@
+xÈK
+€0@×9…07Gú "¦}¥¢·W\Îxƒ—yˆ{ëBQׄxš6!ÎzÉý¬B—V·©PÉ%M†pðã’ÿnUåA!y
\ No newline at end of file
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/70/ca41f00bdd2dabe4fc05bf7232ff04924c374f b/distribution_fe/.git_backup_distribution_fe/objects/70/ca41f00bdd2dabe4fc05bf7232ff04924c374f
new file mode 100644
index 0000000..17018c1
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/70/ca41f00bdd2dabe4fc05bf7232ff04924c374f differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/71/8d6fea4835ec2d246af9800eddb7ffb276240c b/distribution_fe/.git_backup_distribution_fe/objects/71/8d6fea4835ec2d246af9800eddb7ffb276240c
new file mode 100644
index 0000000..d1a82db
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/71/8d6fea4835ec2d246af9800eddb7ffb276240c differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/73/15a79b7d0a246fa8afcb64e85d6426a1958b0c b/distribution_fe/.git_backup_distribution_fe/objects/73/15a79b7d0a246fa8afcb64e85d6426a1958b0c
new file mode 100644
index 0000000..dd4ca4e
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/objects/73/15a79b7d0a246fa8afcb64e85d6426a1958b0c
@@ -0,0 +1,2 @@
+xUQ±NÅ0dîWT#4b€áM Vfv'M[CšTq"xBýw즭`‹ï컳c|4íãÃÓÍOӶê–ìäfP—VM9/tѺ`Gô6t6κòÝŠîd‚òÕ;é7@î>M*žÈ2šSq[[¦ï% ÿÂÐ3&¾¬ccp¡m^")aYôÈ!ÁS'�È1+v¯ÑÇ$=3R>îy‡„`¼“ù#�,É
(1”b�u˅ìû†&Aº
+1•Ñ TmTʞсëà‘mEöL=/1¸�·¨ϚOtÔ{ΒÑï¤G£kyp(ž§øÚÇÜ]YyìSŒŸ»X}ž{Ì.”ó½ øz%̋µœQ䨘ÌÿµížÜÈwKXZ›µù “–�
\ No newline at end of file
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/7b/b15a3e59978f48d191e43804e150f32d9aec44 b/distribution_fe/.git_backup_distribution_fe/objects/7b/b15a3e59978f48d191e43804e150f32d9aec44
new file mode 100644
index 0000000..aca5660
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/objects/7b/b15a3e59978f48d191e43804e150f32d9aec44
@@ -0,0 +1,5 @@
+xmSÁŽ›0í9_�8FkIšíö”Cû+*ÇL‚U°‘=�¬Vù÷Ž
vi•~Ïóæ½sîÌ9«Êòøås“e¹=ä߳¼Q:�¨Œþu�üœXGgϗ¼äՌâÇJzӌÝrs°jèa´#„b'Ðä‘Z“WÒpÇÌû[ŸGÕ5‰˜OåPXLÔ|Z¨NéÀ€_z1¶, *°c7«²÷|»-¶üݺûã=�ý}قüí¡“T¡ÍÏ^aNþ^˜œ ÐRÁ*Ïé,°Q„M늿ò2
+ŸÚñ
+Jí
+i,°‹`áì;Õ¾zwVñ*ÉÉN8Ç&a•И±5”ì#ˆ•Ôx^ٕ�»tÇI Úñs÷huä;~\£[èC²¼.ùá/™¬ToTsˆ5f�éƒÜ?”kE#á|T•ܣPÝMé†õ`¯áùÔ{~\ñ7&´¢å“Î9§aˆ_-aúñ|Q›
+‹Á8ŒÉðÉïØÚ4sç]²µ0)h]½Ŕk*†]ÑËÃóFSɌ1ZùE]Ùó�LJ"îù7¾�
#Æn¼*ÍV±Âå’.'ãÿ“)kˆ~½Pô5póØü7FÅ
\ No newline at end of file
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/8b/d0e39085d5260e7f8faffcad2fdc45e10aef33 b/distribution_fe/.git_backup_distribution_fe/objects/8b/d0e39085d5260e7f8faffcad2fdc45e10aef33
new file mode 100644
index 0000000..f2e61d2
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/objects/8b/d0e39085d5260e7f8faffcad2fdc45e10aef33
@@ -0,0 +1,3 @@
+xuPËJÄ0uݯ8âֶ ADPt6UdöÎmrÛf&½‘$í؝áú%&Ý—çÕZ×âúêæìî¼,ñ¸yÞ6·Â_ñJêYbé'Ëey_\`7˜€tÍëq`4‰X7á(îT+cfŒÐz¦£‘j é“Òï÷áÊɜ3=$�±Œý¤âä#- k¡MױGçݘ�<¢'#YSS¤
+ïLz�ãÙòLÑOF3Œ`/NóÇèt.Qç^µ6!�S¡ޣåÎ%£“71ˑ,)”æ
+/Ìš?=+Ê!.š*֙6ÍÓ#ýÓ`tÕ
\ No newline at end of file
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/98/ff035b0228a6045943ce431155f3961fd1fe73 b/distribution_fe/.git_backup_distribution_fe/objects/98/ff035b0228a6045943ce431155f3961fd1fe73
new file mode 100644
index 0000000..a35b13a
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/98/ff035b0228a6045943ce431155f3961fd1fe73 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/a8/a2054a152e7f764ca02887b8ec7c9c91a091b3 b/distribution_fe/.git_backup_distribution_fe/objects/a8/a2054a152e7f764ca02887b8ec7c9c91a091b3
new file mode 100644
index 0000000..4bef783
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/a8/a2054a152e7f764ca02887b8ec7c9c91a091b3 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/bc/a0e21ac88217b481c589802feb66db29a1b648 b/distribution_fe/.git_backup_distribution_fe/objects/bc/a0e21ac88217b481c589802feb66db29a1b648
new file mode 100644
index 0000000..36322da
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/objects/bc/a0e21ac88217b481c589802feb66db29a1b648
@@ -0,0 +1,3 @@
+xeQËNÃ0äܯˆ|ŒÚ8@Õê�
+„ǨBN¼´¦~ÉvBê¿㵓>ÂÉڙݙ�u-t�ÝÍçW¿“,#�–†°¯ÆsYdÂS»j²|¿½¾¹'ӄ^°"LK2Íð)¸KkXƒS°÷dÝwS!ô÷
+e½m¡ݎ›g^?n¡ٍoyƒ¦gÝJ/%aà^4k<©`Í倌TÀ†ezۄ¿�ӢŰØQ·Š…ôC8‹d+§U2¸T恥XâF©¾Ü-ÐÆϰèm¹j,HPžŠK5#Ú
�'¯âi³þôñüŠJ@¹x͞>Äw8¡~{ú¯ðce&*R„w[qà€k�°„h*&¯¨;Õ¬ðnX͊F«O¾9Có¼Ìÿ—Ç|‘–'‘UJÿcÀ•£ÑD1èFtØ0¦"°?®I”fð‘þ̅<‡ÉŸ3½à
\ No newline at end of file
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/bd/0c391ddd1088e9067844c48835bf4abcd61783 b/distribution_fe/.git_backup_distribution_fe/objects/bd/0c391ddd1088e9067844c48835bf4abcd61783
new file mode 100644
index 0000000..91dfec7
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/objects/bd/0c391ddd1088e9067844c48835bf4abcd61783
@@ -0,0 +1,2 @@
+xM�½
+Â0E�ó—L hÀ¥ƒ«³«‹8¤1•@~Jò…VJß]¢¢®÷Îí}ê±ﺍcʄƗyzŒG¯K9k_-V9ðF9ûÊ4�l¾ÿ0iç'o»ÐfΘ�_١FC.E˜(”R.Ž•Êáïàr•X�-ÕñéŠv'”leOÑM<†
\ No newline at end of file
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/c5/9e98a0ba69902ee359a9beca04d7661ae5480f b/distribution_fe/.git_backup_distribution_fe/objects/c5/9e98a0ba69902ee359a9beca04d7661ae5480f
new file mode 100644
index 0000000..8ee5a80
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/objects/c5/9e98a0ba69902ee359a9beca04d7661ae5480f
@@ -0,0 +1 @@
+xe�An!E»ö)¨²i‘Ôô9@4ž©+°0QrûšDmUuƒüÿ·á™%Éb^Þ^&bAŽȁ°�g‰xÊ÷4”+\`»Ε½…Ç{Qæ>´ç[¦}#þ‘Îí7>cm$šÃÁtl�xDíyÃa2^ºûOŽʃ—]O
JU˜Ðuü²SŠÃÌÔ¸÷ãéإ"XW0?â²oÀ%O·Ê%Ù,îk•zÏu½?ýzò٬¤_`žÂÌFJŸˆÍ*Õəúà7´*5FŒÏàtÀ€~-ØB¥Òª·0ñ*0¶š´ËEµá«4~
\ No newline at end of file
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/d5/64d0bc3dd917926892c55e3706cc116d5b165e b/distribution_fe/.git_backup_distribution_fe/objects/d5/64d0bc3dd917926892c55e3706cc116d5b165e
new file mode 100644
index 0000000..24279dc
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/d5/64d0bc3dd917926892c55e3706cc116d5b165e differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/de/dd1d16aabc9d9605aa428ab16b7bc81da17b80 b/distribution_fe/.git_backup_distribution_fe/objects/de/dd1d16aabc9d9605aa428ab16b7bc81da17b80
new file mode 100644
index 0000000..eb77c9f
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/de/dd1d16aabc9d9605aa428ab16b7bc81da17b80 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/distribution_fe/.git_backup_distribution_fe/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
new file mode 100644
index 0000000..7112238
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/e8/597e11c99aabf1ed29db3012ff2772f0fa8c27 b/distribution_fe/.git_backup_distribution_fe/objects/e8/597e11c99aabf1ed29db3012ff2772f0fa8c27
new file mode 100644
index 0000000..9a954ac
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/e8/597e11c99aabf1ed29db3012ff2772f0fa8c27 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/e8/7e24da14e72c8e4b61379587a2c98a8e146b02 b/distribution_fe/.git_backup_distribution_fe/objects/e8/7e24da14e72c8e4b61379587a2c98a8e146b02
new file mode 100644
index 0000000..137921a
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/e8/7e24da14e72c8e4b61379587a2c98a8e146b02 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/ec/d831f8a0b5d801cfe9cd6cf7601ffb710381cd b/distribution_fe/.git_backup_distribution_fe/objects/ec/d831f8a0b5d801cfe9cd6cf7601ffb710381cd
new file mode 100644
index 0000000..d0165eb
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/ec/d831f8a0b5d801cfe9cd6cf7601ffb710381cd differ
diff --git a/distribution_fe/.git_backup_distribution_fe/objects/f6/2ca4272ccf54d4064f7780d852400c0ac32df1 b/distribution_fe/.git_backup_distribution_fe/objects/f6/2ca4272ccf54d4064f7780d852400c0ac32df1
new file mode 100644
index 0000000..c06dded
Binary files /dev/null and b/distribution_fe/.git_backup_distribution_fe/objects/f6/2ca4272ccf54d4064f7780d852400c0ac32df1 differ
diff --git a/distribution_fe/.git_backup_distribution_fe/refs/heads/master b/distribution_fe/.git_backup_distribution_fe/refs/heads/master
new file mode 100644
index 0000000..561b131
--- /dev/null
+++ b/distribution_fe/.git_backup_distribution_fe/refs/heads/master
@@ -0,0 +1 @@
+088d90049e99bcf4d4c7d4018d36368f0ceb81a8
diff --git a/distribution_fe/.gitignore b/distribution_fe/.gitignore
new file mode 100644
index 0000000..c59e98a
--- /dev/null
+++ b/distribution_fe/.gitignore
@@ -0,0 +1,36 @@
+# dependencies
+/node_modules
+/.pnp
+.pnp.*
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/versions
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# env files (can opt-in for committing if needed)
+.env*
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/distribution_fe/.prettierignore b/distribution_fe/.prettierignore
new file mode 100644
index 0000000..461b008
--- /dev/null
+++ b/distribution_fe/.prettierignore
@@ -0,0 +1,7 @@
+dist/
+node_modules/
+.next/
+.turbo/
+coverage/
+pnpm-lock.yaml
+.pnpm-store/
\ No newline at end of file
diff --git a/distribution_fe/.prettierrc b/distribution_fe/.prettierrc
new file mode 100644
index 0000000..a8a2054
--- /dev/null
+++ b/distribution_fe/.prettierrc
@@ -0,0 +1,11 @@
+{
+ "endOfLine": "lf",
+ "semi": false,
+ "singleQuote": false,
+ "tabWidth": 2,
+ "trailingComma": "es5",
+ "printWidth": 80,
+ "plugins": ["prettier-plugin-tailwindcss"],
+ "tailwindStylesheet": "app/globals.css",
+ "tailwindFunctions": ["cn", "cva"]
+}
diff --git a/distribution_fe/AGENTS.md b/distribution_fe/AGENTS.md
new file mode 100644
index 0000000..8bd0e39
--- /dev/null
+++ b/distribution_fe/AGENTS.md
@@ -0,0 +1,5 @@
+
+# This is NOT the Next.js you know
+
+This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
+
diff --git a/distribution_fe/README.md b/distribution_fe/README.md
new file mode 100644
index 0000000..1e66186
--- /dev/null
+++ b/distribution_fe/README.md
@@ -0,0 +1,21 @@
+# Next.js template
+
+This is a Next.js template with shadcn/ui.
+
+## Adding components
+
+To add components to your app, run the following command:
+
+```bash
+npx shadcn@latest add button
+```
+
+This will place the ui components in the `components` directory.
+
+## Using components
+
+To use the components in your app, import them as follows:
+
+```tsx
+import { Button } from "@/components/ui/button";
+```
diff --git a/distribution_fe/app/(auth)/login/page.tsx b/distribution_fe/app/(auth)/login/page.tsx
new file mode 100644
index 0000000..db32810
--- /dev/null
+++ b/distribution_fe/app/(auth)/login/page.tsx
@@ -0,0 +1,14 @@
+export default function LoginPage() {
+ return (
+
+
+
+ Sign in
+
+ Authentication will be wired up once the backend is ready.
+
+
+
+
+ )
+}
diff --git a/distribution_fe/app/(dashboard)/layout.tsx b/distribution_fe/app/(dashboard)/layout.tsx
new file mode 100644
index 0000000..308eafc
--- /dev/null
+++ b/distribution_fe/app/(dashboard)/layout.tsx
@@ -0,0 +1,24 @@
+import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar'
+import { AppSidebar } from '@/components/layout/app-sidebar'
+import { BottomNav } from '@/components/layout/bottom-nav'
+
+export default function DashboardLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+ )
+}
diff --git a/distribution_fe/app/(dashboard)/page.tsx b/distribution_fe/app/(dashboard)/page.tsx
new file mode 100644
index 0000000..342568f
--- /dev/null
+++ b/distribution_fe/app/(dashboard)/page.tsx
@@ -0,0 +1,8 @@
+export default function DashboardPage() {
+ return (
+
+ Dashboard
+ Welcome to the Distribution ERP.
+
+ )
+}
diff --git a/distribution_fe/app/favicon.ico b/distribution_fe/app/favicon.ico
new file mode 100644
index 0000000..718d6fe
Binary files /dev/null and b/distribution_fe/app/favicon.ico differ
diff --git a/distribution_fe/app/globals.css b/distribution_fe/app/globals.css
new file mode 100644
index 0000000..e8597e1
--- /dev/null
+++ b/distribution_fe/app/globals.css
@@ -0,0 +1,129 @@
+@import "tailwindcss";
+@import "tw-animate-css";
+@import "shadcn/tailwind.css";
+
+@custom-variant dark (&:is(.dark *));
+
+:root {
+ --background: oklch(1 0 0);
+ --foreground: oklch(0.148 0.004 228.8);
+ --card: oklch(1 0 0);
+ --card-foreground: oklch(0.148 0.004 228.8);
+ --popover: oklch(1 0 0);
+ --popover-foreground: oklch(0.148 0.004 228.8);
+ --primary: oklch(0.218 0.008 223.9);
+ --primary-foreground: oklch(0.987 0.002 197.1);
+ --secondary: oklch(0.963 0.002 197.1);
+ --secondary-foreground: oklch(0.218 0.008 223.9);
+ --muted: oklch(0.963 0.002 197.1);
+ --muted-foreground: oklch(0.56 0.021 213.5);
+ --accent: oklch(0.963 0.002 197.1);
+ --accent-foreground: oklch(0.218 0.008 223.9);
+ --destructive: oklch(0.577 0.245 27.325);
+ --border: oklch(0.925 0.005 214.3);
+ --input: oklch(0.925 0.005 214.3);
+ --ring: oklch(0.723 0.014 214.4);
+ --chart-1: oklch(0.872 0.007 219.6);
+ --chart-2: oklch(0.56 0.021 213.5);
+ --chart-3: oklch(0.45 0.017 213.2);
+ --chart-4: oklch(0.378 0.015 216);
+ --chart-5: oklch(0.275 0.011 216.9);
+ --radius: 0.625rem;
+ --sidebar: oklch(0.987 0.002 197.1);
+ --sidebar-foreground: oklch(0.148 0.004 228.8);
+ --sidebar-primary: oklch(0.218 0.008 223.9);
+ --sidebar-primary-foreground: oklch(0.987 0.002 197.1);
+ --sidebar-accent: oklch(0.963 0.002 197.1);
+ --sidebar-accent-foreground: oklch(0.218 0.008 223.9);
+ --sidebar-border: oklch(0.925 0.005 214.3);
+ --sidebar-ring: oklch(0.723 0.014 214.4);
+}
+
+.dark {
+ --background: oklch(0.148 0.004 228.8);
+ --foreground: oklch(0.987 0.002 197.1);
+ --card: oklch(0.218 0.008 223.9);
+ --card-foreground: oklch(0.987 0.002 197.1);
+ --popover: oklch(0.218 0.008 223.9);
+ --popover-foreground: oklch(0.987 0.002 197.1);
+ --primary: oklch(0.925 0.005 214.3);
+ --primary-foreground: oklch(0.218 0.008 223.9);
+ --secondary: oklch(0.275 0.011 216.9);
+ --secondary-foreground: oklch(0.987 0.002 197.1);
+ --muted: oklch(0.275 0.011 216.9);
+ --muted-foreground: oklch(0.723 0.014 214.4);
+ --accent: oklch(0.275 0.011 216.9);
+ --accent-foreground: oklch(0.987 0.002 197.1);
+ --destructive: oklch(0.704 0.191 22.216);
+ --border: oklch(1 0 0 / 10%);
+ --input: oklch(1 0 0 / 15%);
+ --ring: oklch(0.56 0.021 213.5);
+ --chart-1: oklch(0.872 0.007 219.6);
+ --chart-2: oklch(0.56 0.021 213.5);
+ --chart-3: oklch(0.45 0.017 213.2);
+ --chart-4: oklch(0.378 0.015 216);
+ --chart-5: oklch(0.275 0.011 216.9);
+ --sidebar: oklch(0.218 0.008 223.9);
+ --sidebar-foreground: oklch(0.987 0.002 197.1);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.987 0.002 197.1);
+ --sidebar-accent: oklch(0.275 0.011 216.9);
+ --sidebar-accent-foreground: oklch(0.987 0.002 197.1);
+ --sidebar-border: oklch(1 0 0 / 10%);
+ --sidebar-ring: oklch(0.56 0.021 213.5);
+}
+
+@theme inline {
+ --font-sans: var(--font-sans);
+ --font-heading: var(--font-heading);
+ --color-sidebar-ring: var(--sidebar-ring);
+ --color-sidebar-border: var(--sidebar-border);
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+ --color-sidebar-accent: var(--sidebar-accent);
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+ --color-sidebar-primary: var(--sidebar-primary);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --color-sidebar: var(--sidebar);
+ --color-chart-5: var(--chart-5);
+ --color-chart-4: var(--chart-4);
+ --color-chart-3: var(--chart-3);
+ --color-chart-2: var(--chart-2);
+ --color-chart-1: var(--chart-1);
+ --color-ring: var(--ring);
+ --color-input: var(--input);
+ --color-border: var(--border);
+ --color-destructive: var(--destructive);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-accent: var(--accent);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-muted: var(--muted);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-secondary: var(--secondary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-primary: var(--primary);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-popover: var(--popover);
+ --color-card-foreground: var(--card-foreground);
+ --color-card: var(--card);
+ --color-foreground: var(--foreground);
+ --color-background: var(--background);
+ --radius-sm: calc(var(--radius) * 0.6);
+ --radius-md: calc(var(--radius) * 0.8);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) * 1.4);
+ --radius-2xl: calc(var(--radius) * 1.8);
+ --radius-3xl: calc(var(--radius) * 2.2);
+ --radius-4xl: calc(var(--radius) * 2.6);
+}
+
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+ html {
+ @apply font-sans;
+ }
+}
\ No newline at end of file
diff --git a/distribution_fe/app/layout.tsx b/distribution_fe/app/layout.tsx
new file mode 100644
index 0000000..d19ccf2
--- /dev/null
+++ b/distribution_fe/app/layout.tsx
@@ -0,0 +1,35 @@
+import { Geist_Mono, Outfit, Nunito_Sans } from "next/font/google"
+
+import "./globals.css"
+import { ThemeProvider } from "@/components/theme-provider"
+import { AuthProvider } from "@/contexts/auth-context"
+import { TooltipProvider } from "@/components/ui/tooltip"
+import { cn } from "@/lib/utils"
+
+const nunitoSansHeading = Nunito_Sans({ subsets: ['latin'], variable: '--font-heading' })
+const outfit = Outfit({ subsets: ['latin'], variable: '--font-sans' })
+const fontMono = Geist_Mono({ subsets: ['latin'], variable: '--font-mono' })
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode
+}>) {
+ return (
+
+
+
+
+
+ {children}
+
+
+
+
+
+ )
+}
diff --git a/distribution_fe/components.json b/distribution_fe/components.json
new file mode 100644
index 0000000..7315a79
--- /dev/null
+++ b/distribution_fe/components.json
@@ -0,0 +1,25 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "base-rhea",
+ "rsc": true,
+ "tsx": true,
+ "tailwind": {
+ "config": "",
+ "css": "app/globals.css",
+ "baseColor": "mist",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "iconLibrary": "hugeicons",
+ "rtl": false,
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "menuColor": "default",
+ "menuAccent": "subtle",
+ "registries": {}
+}
diff --git a/distribution_fe/components/.gitkeep b/distribution_fe/components/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/distribution_fe/components/layout/app-sidebar.tsx b/distribution_fe/components/layout/app-sidebar.tsx
new file mode 100644
index 0000000..40c1c75
--- /dev/null
+++ b/distribution_fe/components/layout/app-sidebar.tsx
@@ -0,0 +1,175 @@
+'use client'
+
+import Link from 'next/link'
+import { usePathname } from 'next/navigation'
+import { HugeiconsIcon } from '@hugeicons/react'
+import { ChevronRightIcon, UserIcon } from '@hugeicons/core-free-icons'
+
+import {
+ Sidebar,
+ SidebarContent,
+ SidebarFooter,
+ SidebarGroup,
+ SidebarHeader,
+ SidebarMenu,
+ SidebarMenuButton,
+ SidebarMenuItem,
+ SidebarMenuSub,
+ SidebarMenuSubButton,
+ SidebarMenuSubItem,
+ SidebarRail,
+} from '@/components/ui/sidebar'
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from '@/components/ui/collapsible'
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from '@/components/ui/select'
+import { useAuth, type Role } from '@/contexts/auth-context'
+import { DASHBOARD_ITEM, NAV_GROUPS, type NavGroup, type NavItem } from '@/config/nav'
+
+function canSee(item: NavItem, permissions: string[]): boolean {
+ if (!item.permission) return true
+ return permissions.includes('*') || permissions.includes(item.permission)
+}
+
+function isGroupVisible(group: NavGroup, permissions: string[]): boolean {
+ return group.items.some((item) => canSee(item, permissions))
+}
+
+export function AppSidebar() {
+ const { user, setRole, permissions } = useAuth()
+ const pathname = usePathname()
+
+ const dashboardActive = pathname === DASHBOARD_ITEM.href
+
+ return (
+
+
+
+
+ D
+
+
+ Distribution
+
+
+
+
+
+ {/* Dashboard — standalone, not inside a collapsible group */}
+
+
+
+ }
+ isActive={dashboardActive}
+ tooltip={DASHBOARD_ITEM.title}
+ >
+
+ {DASHBOARD_ITEM.title}
+
+
+
+
+
+ {/* Collapsible groups */}
+ {NAV_GROUPS.map((group) => {
+ if (!isGroupVisible(group, permissions)) return null
+
+ const visibleItems = group.items.filter((item) =>
+ canSee(item, permissions),
+ )
+ const groupActive = visibleItems.some(
+ (item) =>
+ pathname === item.href ||
+ (item.href !== '/' && pathname.startsWith(item.href)),
+ )
+
+ return (
+
+
+
+ {/* Group trigger — looks like a regular nav button */}
+
+ }
+ isActive={groupActive}
+ tooltip={group.title}
+ >
+
+ {group.title}
+
+
+
+
+ {/* Sub-items with indent line */}
+
+
+ {visibleItems.map((item) => {
+ const isActive =
+ pathname === item.href ||
+ (item.href !== '/' &&
+ pathname.startsWith(item.href))
+ return (
+
+ }
+ isActive={isActive}
+ >
+
+ {item.title}
+
+
+ )
+ })}
+
+
+
+
+
+ )
+ })}
+
+
+
+
+
+
+
+
+
+ {user.fullName}
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/distribution_fe/components/layout/bottom-nav.tsx b/distribution_fe/components/layout/bottom-nav.tsx
new file mode 100644
index 0000000..8e50df5
--- /dev/null
+++ b/distribution_fe/components/layout/bottom-nav.tsx
@@ -0,0 +1,52 @@
+'use client'
+
+import Link from 'next/link'
+import { usePathname } from 'next/navigation'
+import { HugeiconsIcon } from '@hugeicons/react'
+
+import { cn } from '@/lib/utils'
+import { useAuth } from '@/contexts/auth-context'
+import { BOTTOM_NAV_CANDIDATES, type NavItem } from '@/config/nav'
+
+const MAX_TABS = 5
+
+export function BottomNav() {
+ const pathname = usePathname()
+ const { permissions } = useAuth()
+
+ const visibleItems: NavItem[] = BOTTOM_NAV_CANDIDATES.filter((item) => {
+ if (!item.permission) return true
+ return permissions.includes('*') || permissions.includes(item.permission)
+ }).slice(0, MAX_TABS)
+
+ return (
+
+ )
+}
diff --git a/distribution_fe/components/shared/data-table/data-table.tsx b/distribution_fe/components/shared/data-table/data-table.tsx
new file mode 100644
index 0000000..55bab03
--- /dev/null
+++ b/distribution_fe/components/shared/data-table/data-table.tsx
@@ -0,0 +1,686 @@
+'use client';
+
+import React, { useState, useMemo, useRef, useCallback } from 'react';
+import Link from 'next/link';
+import { HugeiconsIcon } from '@hugeicons/react';
+import {
+ ArrowDataTransferVerticalIcon,
+ ArrowUp01Icon,
+ ArrowDown01Icon,
+ ChevronRightIcon,
+} from '@hugeicons/core-free-icons';
+
+import {
+ Table, TableBody, TableCell, TableHead, TableHeader, TableRow,
+} from '@/components/ui/table';
+import { Checkbox } from '@/components/ui/checkbox';
+import { Button } from '@/components/ui/button';
+import { Badge } from '@/components/ui/badge';
+import { Skeleton } from '@/components/ui/skeleton';
+import { cn } from '@/lib/utils';
+
+import { TableToolbar } from './table-toolbar';
+import { TablePagination } from './table-pagination';
+import { filterData } from './hooks/use-table-filter';
+import { sortData } from './hooks/use-table-sort';
+import { exportTable } from './hooks/use-table-export';
+import { getNestedValue, resolveUrlTemplate } from './utils/nested-value';
+import type {
+ TableConfig, ColumnDef, FieldConfig, SortState, FilterState, PageState,
+ ServerSideParams, ExportFormat,
+} from './types';
+
+interface DataTableProps {
+ config: TableConfig;
+ data: T[];
+ loading?: boolean;
+ totalCount?: number;
+ onSortChange?: (s: SortState) => void;
+ onFilterChange?: (f: FilterState) => void;
+ onPageChange?: (p: PageState) => void;
+ onSelectionChange?: (rows: T[]) => void;
+ onRowClick?: (row: T) => void;
+ onRowExpand?: (row: T) => void;
+ onServerSideChange?: (p: ServerSideParams) => void;
+}
+
+function normalizeField(f: FieldConfig | string): FieldConfig {
+ return typeof f === 'string' ? { key: f } : f;
+}
+
+function SortIcon({ colKey, sortState }: { colKey: string; sortState: SortState }) {
+ if (sortState.column !== colKey) {
+ return (
+
+ );
+ }
+ return sortState.direction === 'asc'
+ ?
+ : ;
+}
+
+function MobileCard({
+ row,
+ columns,
+ mobileCardCfg,
+ onClick,
+}: {
+ row: T;
+ columns: ColumnDef[];
+ mobileCardCfg?: TableConfig['mobileCard'];
+ onClick?: (row: T) => void;
+}) {
+ const actionCol = columns.find(c => !c.title && c.cellRender);
+ const dataColumns = columns.filter(c => !!c.title);
+
+ const primaryCol = dataColumns[0];
+ // Always 2 columns, max 4 fields (2 rows) to prevent cramping
+ const previewCols = (mobileCardCfg?.previewColumns
+ ? dataColumns.filter(c => mobileCardCfg.previewColumns!.includes(c.key))
+ : dataColumns.slice(1, 3)
+ ).slice(0, 4);
+
+ const href = mobileCardCfg?.detailHref?.(row);
+ const isNavigable = !!href || !!onClick;
+
+ const inner = (
+
+ {/* Header: primary field + chevron */}
+
+
+ {primaryCol && }
+
+ {isNavigable && (
+
+ )}
+
+
+ {/* Preview fields — fixed 2-column grid */}
+ {previewCols.length > 0 && (
+
+ {previewCols.map(col => (
+
+
+ {col.title}
+
+
+
+
+
+ ))}
+
+ )}
+
+ {/* Actions — only when not navigating away */}
+ {!href && actionCol && (
+ e.stopPropagation()}
+ >
+ {actionCol.cellRender!(row, actionCol)}
+
+ )}
+
+ );
+
+ if (href) {
+ return {inner};
+ }
+
+ return (
+ onClick?.(row)}>
+ {inner}
+
+ );
+}
+
+function CellContent({
+ row, col,
+}: { row: T; col: ColumnDef }) {
+ if (col.cellRender) return <>{col.cellRender(row, col)}>;
+
+ const fields = col.fields.map(normalizeField);
+ const layout = col.layout ?? 'vertical';
+
+ const rendered = fields.map((field, i) => {
+ const raw = getNestedValue(row, field.key);
+ const text = field.transform
+ ? field.transform(raw, row)
+ : `${field.prefix ?? ''}${raw ?? ''}${field.suffix ?? ''}`;
+
+ const renderer = field.renderer ?? 'text';
+
+ if (renderer === 'badge') {
+ const colorClass = field.badgeConfig?.colorMap?.[String(raw)] ?? field.badgeConfig?.defaultColor ?? '';
+ return (
+
+ {text}
+
+ );
+ }
+
+ if (renderer === 'link') {
+ const href = field.linkConfig?.urlKey
+ ? String(getNestedValue(row, field.linkConfig.urlKey) ?? '#')
+ : field.linkConfig?.urlTemplate
+ ? resolveUrlTemplate(field.linkConfig.urlTemplate, row)
+ : '#';
+ return (
+ e.stopPropagation()}
+ >
+ {text}
+
+ );
+ }
+
+ return (
+
+ {text}
+
+ );
+ });
+
+ const crossAlign =
+ col.align === 'right' ? 'items-end' : col.align === 'center' ? 'items-center' : '';
+
+ if (layout === 'horizontal') {
+ return (
+
+ {rendered}
+
+ );
+ }
+ return {rendered};
+}
+
+export function DataTable({
+ config,
+ data,
+ loading,
+ totalCount,
+ onSortChange,
+ onFilterChange,
+ onPageChange,
+ onSelectionChange,
+ onRowClick,
+ onServerSideChange,
+}: DataTableProps) {
+ const [sortState, setSortState] = useState({ column: null, direction: null });
+ const [filterState, setFilterState] = useState({ global: '', columns: {} });
+ const [pageState, setPageState] = useState({
+ page: 1,
+ pageSize: config.pagination?.pageSize ?? 10,
+ });
+ const [selectedKeys, setSelectedKeys] = useState>(new Set());
+ const [expandedKeys, setExpandedKeys] = useState>(new Set());
+ const [hiddenColumns, setHiddenColumns] = useState>(
+ () => new Set(config.columns.filter(c => c.visible === false).map(c => c.key))
+ );
+ const [columnWidths, setColumnWidths] = useState>({});
+ const [columnOrder, setColumnOrder] = useState(() => config.columns.map(c => c.key));
+ const [draggedKey, setDraggedKey] = useState(null);
+ const [dropTargetKey, setDropTargetKey] = useState(null);
+ const scrollContainerRef = useRef(null);
+ const [scrollTop, setScrollTop] = useState(0);
+ const [containerH, setContainerH] = useState(500);
+
+ function rowKey(row: T): string {
+ if (!config.rowKey) return JSON.stringify(row);
+ if (typeof config.rowKey === 'function') return String(config.rowKey(row));
+ return String(row[config.rowKey as keyof T]);
+ }
+
+ const normalizedColumns = useMemo(() =>
+ config.columns.map(col => ({
+ ...col,
+ fields: col.fields.map(normalizeField) as FieldConfig[],
+ })), [config.columns]);
+
+ const orderedColumns = useMemo(() =>
+ columnOrder
+ .map(key => normalizedColumns.find(c => c.key === key))
+ .filter(Boolean) as typeof normalizedColumns,
+ [normalizedColumns, columnOrder]
+ );
+
+ const visibleColumns = useMemo(() =>
+ orderedColumns.filter(c => !hiddenColumns.has(c.key)),
+ [orderedColumns, hiddenColumns]
+ );
+
+ const filteredData = useMemo(() =>
+ config.serverSide ? data : filterData(data, filterState, normalizedColumns as ColumnDef[]),
+ [data, filterState, normalizedColumns, config.serverSide]
+ );
+
+ const sortedData = useMemo(() =>
+ config.serverSide ? data : sortData(filteredData, sortState, normalizedColumns as ColumnDef[]),
+ [filteredData, sortState, normalizedColumns, config.serverSide]
+ );
+
+ const totalRecords = useMemo(() =>
+ config.serverSide ? (totalCount ?? data.length) : filteredData.length,
+ [config.serverSide, totalCount, data.length, filteredData.length]
+ );
+
+ const rowHeightPx = useMemo(() => {
+ const map: Record = { compact: 36, normal: 48, comfortable: 60 };
+ return map[config.density ?? 'normal'] ?? 48;
+ }, [config.density]);
+
+ const virtualRange = useMemo(() => {
+ if (!config.virtualScroll) return null;
+ const buf = 6;
+ const start = Math.max(0, Math.floor(scrollTop / rowHeightPx) - buf);
+ const end = Math.min(sortedData.length, Math.ceil((scrollTop + containerH) / rowHeightPx) + buf);
+ return { start, end };
+ }, [config.virtualScroll, scrollTop, containerH, rowHeightPx, sortedData.length]);
+
+ const paginatedData = useMemo(() => {
+ if (config.serverSide || !config.pagination?.enabled) return sortedData;
+ const { page, pageSize } = pageState;
+ return sortedData.slice((page - 1) * pageSize, page * pageSize);
+ }, [sortedData, pageState, config.serverSide, config.pagination?.enabled]);
+
+ const displayData = useMemo(() =>
+ virtualRange ? sortedData.slice(virtualRange.start, virtualRange.end) : paginatedData,
+ [virtualRange, sortedData, paginatedData]
+ );
+
+ const spacerTop = (virtualRange?.start ?? 0) * rowHeightPx;
+ const spacerBottom = virtualRange ? (sortedData.length - virtualRange.end) * rowHeightPx : 0;
+
+ const selectablePageData = useMemo(() =>
+ config.isRowSelectable ? paginatedData.filter(r => config.isRowSelectable!(r)) : paginatedData,
+ [paginatedData, config.isRowSelectable]
+ );
+ const allSelected = selectablePageData.length > 0 && selectablePageData.every(r => selectedKeys.has(rowKey(r)));
+ const someSelected = selectablePageData.some(r => selectedKeys.has(rowKey(r))) && !allSelected;
+
+ // --- Handlers ---
+
+ function handleSort(col: ColumnDef) {
+ if (!col.sortable) return;
+ setSortState(prev => {
+ const next: SortState =
+ prev.column !== col.key ? { column: col.key, direction: 'asc' }
+ : prev.direction === 'asc' ? { column: col.key, direction: 'desc' }
+ : { column: null, direction: null };
+ onSortChange?.(next);
+ if (config.serverSide) onServerSideChange?.({ sort: next, filter: filterState, page: pageState });
+ return next;
+ });
+ }
+
+ function handleGlobalFilter(value: string) {
+ const next: FilterState = { ...filterState, global: value };
+ setFilterState(next);
+ setPageState(p => ({ ...p, page: 1 }));
+ onFilterChange?.(next);
+ if (config.serverSide) onServerSideChange?.({ sort: sortState, filter: next, page: { ...pageState, page: 1 } });
+ }
+
+ function toggleRow(row: T) {
+ if (config.isRowSelectable && !config.isRowSelectable(row)) return;
+ const key = rowKey(row);
+ const next = new Set(selectedKeys);
+ next.has(key) ? next.delete(key) : next.add(key);
+ setSelectedKeys(next);
+ onSelectionChange?.(data.filter(r => next.has(rowKey(r))));
+ }
+
+ function toggleAll() {
+ const next = new Set(selectedKeys);
+ if (allSelected) {
+ selectablePageData.map(rowKey).forEach(k => next.delete(k));
+ } else {
+ selectablePageData.forEach(r => next.add(rowKey(r)));
+ }
+ setSelectedKeys(next);
+ onSelectionChange?.(data.filter(r => next.has(rowKey(r))));
+ }
+
+ function clearSelection() {
+ setSelectedKeys(new Set());
+ onSelectionChange?.([]);
+ }
+
+ function toggleExpand(row: T) {
+ const key = rowKey(row);
+ setExpandedKeys(prev => {
+ const next = new Set(prev);
+ next.has(key) ? next.delete(key) : next.add(key);
+ return next;
+ });
+ }
+
+ function toggleColumnVisibility(key: string) {
+ setHiddenColumns(prev => {
+ const next = new Set(prev);
+ next.has(key) ? next.delete(key) : next.add(key);
+ return next;
+ });
+ }
+
+ function handlePageChange(page: number) {
+ const next = { ...pageState, page };
+ setPageState(next);
+ onPageChange?.(next);
+ if (config.serverSide) onServerSideChange?.({ sort: sortState, filter: filterState, page: next });
+ }
+
+ function handlePageSizeChange(pageSize: number) {
+ const next = { page: 1, pageSize };
+ setPageState(next);
+ onPageChange?.(next);
+ if (config.serverSide) onServerSideChange?.({ sort: sortState, filter: filterState, page: next });
+ }
+
+ function handleScroll(e: React.UIEvent) {
+ setScrollTop(e.currentTarget.scrollTop);
+ setContainerH(e.currentTarget.clientHeight);
+ }
+
+ const handleResizeStart = useCallback((e: React.PointerEvent, colKey: string) => {
+ e.preventDefault();
+ e.stopPropagation();
+ const th = (e.currentTarget as HTMLElement).closest('th') as HTMLElement;
+ if (!th) return;
+ const startX = e.clientX;
+ const startWidth = th.offsetWidth;
+ th.setPointerCapture(e.pointerId);
+
+ const onMove = (ev: PointerEvent) => {
+ const newWidth = Math.max(80, startWidth + ev.clientX - startX);
+ setColumnWidths(w => ({ ...w, [colKey]: newWidth }));
+ };
+ const onUp = () => {
+ th.removeEventListener('pointermove', onMove);
+ th.removeEventListener('pointerup', onUp);
+ };
+ th.addEventListener('pointermove', onMove);
+ th.addEventListener('pointerup', onUp);
+ }, []);
+
+ function handleDragStart(e: React.DragEvent, colKey: string) {
+ setDraggedKey(colKey);
+ e.dataTransfer.effectAllowed = 'move';
+ }
+
+ function handleDragOver(e: React.DragEvent, colKey: string) {
+ e.preventDefault();
+ setDropTargetKey(colKey);
+ }
+
+ function handleDrop(e: React.DragEvent, colKey: string) {
+ e.preventDefault();
+ if (!draggedKey || draggedKey === colKey) return;
+ setColumnOrder(prev => {
+ const next = [...prev];
+ const from = next.indexOf(draggedKey);
+ const to = next.indexOf(colKey);
+ if (from < 0 || to < 0) return prev;
+ next.splice(from, 1);
+ next.splice(to, 0, draggedKey);
+ return next;
+ });
+ setDraggedKey(null);
+ setDropTargetKey(null);
+ }
+
+ function handleDragEnd() {
+ setDraggedKey(null);
+ setDropTargetKey(null);
+ }
+
+ const exportConfig = typeof config.exportable === 'object' ? config.exportable : undefined;
+ const showExport = !!config.exportable;
+
+ function handleExport(format: ExportFormat) {
+ exportTable(format, sortedData, visibleColumns as ColumnDef[], exportConfig?.filename ?? 'export');
+ }
+
+ const skeletonCount = config.pagination?.pageSize ?? 10;
+ const alignClass = (col: ColumnDef) =>
+ col.align === 'right' ? 'justify-end' : col.align === 'center' ? 'justify-center' : 'justify-start';
+
+ return (
+
+ []}
+ hiddenColumns={hiddenColumns}
+ globalFilter={filterState.global}
+ showExport={showExport}
+ exportFormats={exportConfig?.formats}
+ selectedCount={selectedKeys.size}
+ onGlobalFilterChange={handleGlobalFilter}
+ onColumnVisibilityChange={toggleColumnVisibility}
+ onExport={handleExport}
+ onClearSelection={clearSelection}
+ />
+
+ {/* Mobile card view */}
+
+ {loading && Array.from({ length: skeletonCount }).map((_, i) => (
+
+
+
+ {Array.from({ length: 4 }).map((__, j) => )}
+
+
+ ))}
+ {!loading && displayData.length === 0 && (
+
+ {config.emptyMessage ?? 'No records found.'}
+
+ )}
+ {!loading && displayData.map(row => (
+ []}
+ mobileCardCfg={config.mobileCard}
+ onClick={onRowClick}
+ />
+ ))}
+
+
+ {/* Desktop table view */}
+
+
+
+
+ {config.selectable && (
+
+
+
+ )}
+ {config.expandable && }
+ {visibleColumns.map(col => {
+ const width = columnWidths[col.key] ?? col.width ?? 160;
+ return (
+ handleDragStart(e, col.key)}
+ onDragOver={e => handleDragOver(e, col.key)}
+ onDrop={e => handleDrop(e, col.key)}
+ onDragEnd={handleDragEnd}
+ onClick={() => handleSort(col as ColumnDef)}
+ >
+ ))}>
+ {col.headerRender ? col.headerRender(col as ColumnDef) : col.title}
+ {col.sortable && }
+
+ {col.resizable !== false && (
+ handleResizeStart(e, col.key)}
+ onClick={e => e.stopPropagation()}
+ />
+ )}
+
+ );
+ })}
+
+
+
+
+ {loading && Array.from({ length: skeletonCount }).map((_, i) => (
+
+ {config.selectable && }
+ {config.expandable && }
+ {visibleColumns.map(col => (
+
+
+
+ ))}
+
+ ))}
+
+ {!loading && displayData.length === 0 && (
+
+
+ {config.emptyMessage ?? 'No records found.'}
+
+
+ )}
+
+ {!loading && virtualRange && spacerTop > 0 && (
+
+ )}
+
+ {!loading && displayData.map(row => {
+ const key = rowKey(row);
+ const isSelected = selectedKeys.has(key);
+ const isExpanded = expandedKeys.has(key);
+ return (
+
+ onRowClick?.(row)}
+ >
+ {config.selectable && (
+ e.stopPropagation()}>
+ toggleRow(row)}
+ />
+
+ )}
+ {config.expandable && (
+ e.stopPropagation()}>
+
+
+ )}
+ {visibleColumns.map(col => (
+
+ } />
+
+ ))}
+
+ {config.expandable && isExpanded && (
+
+
+ {config.expandRender?.(row)}
+
+
+ )}
+
+ );
+ })}
+
+ {!loading && virtualRange && spacerBottom > 0 && (
+
+ )}
+
+
+
+
+ {config.pagination?.enabled && (
+
+ )}
+
+ );
+}
diff --git a/distribution_fe/components/shared/data-table/hooks/use-table-export.ts b/distribution_fe/components/shared/data-table/hooks/use-table-export.ts
new file mode 100644
index 0000000..02beed1
--- /dev/null
+++ b/distribution_fe/components/shared/data-table/hooks/use-table-export.ts
@@ -0,0 +1,73 @@
+import { type ColumnDef, type ExportFormat, type FieldConfig } from '../types';
+import { getNestedValue } from '../utils/nested-value';
+
+export function exportTable(
+ format: ExportFormat, data: T[], columns: ColumnDef[], filename = 'export'
+): void {
+ const exportable = columns.filter(c => c.exportable !== false);
+ if (format === 'csv') exportCsv(data, exportable, filename);
+ if (format === 'excel') exportExcel(data, exportable, filename);
+ if (format === 'pdf') exportPdf(data, exportable, filename);
+}
+
+function resolveCellText(row: T, col: ColumnDef): string {
+ return col.fields.map(f => {
+ const field: FieldConfig = typeof f === 'string' ? { key: f } : f;
+ const raw = getNestedValue(row, field.key);
+ if (field.transform) return field.transform(raw, row);
+ return `${field.prefix ?? ''}${raw ?? ''}${field.suffix ?? ''}`;
+ }).join(' ');
+}
+
+function download(blob: Blob, name: string) {
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url; a.download = name; a.click();
+ URL.revokeObjectURL(url);
+}
+
+function escHtml(s: string) {
+ return s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
+}
+
+function exportCsv(data: T[], columns: ColumnDef[], filename: string) {
+ const headers = columns.map(c => `"${c.title}"`).join(',');
+ const rows = data.map(row =>
+ columns.map(col => `"${resolveCellText(row, col).replace(/"/g, '""')}"`).join(',')
+ );
+ download(new Blob([[headers, ...rows].join('\r\n')], { type: 'text/csv;charset=utf-8;' }), `${filename}.csv`);
+}
+
+function exportExcel(data: T[], columns: ColumnDef[], filename: string) {
+ const thead = columns.map(c => `${escHtml(c.title)} `).join('');
+ const tbody = data.map(row =>
+ `${columns.map(col => `${escHtml(resolveCellText(row, col))} `).join('')} `
+ ).join('');
+ const html = `
+
+ ${thead}${tbody}
`;
+ download(new Blob([html], { type: 'application/vnd.ms-excel;charset=utf-8;' }), `${filename}.xls`);
+}
+
+function exportPdf(data: T[], columns: ColumnDef[], filename: string) {
+ const thead = columns.map(c =>
+ `${escHtml(c.title)} `
+ ).join('');
+ const tbody = data.map(row =>
+ `${columns.map(col =>
+ `${escHtml(resolveCellText(row, col))} `
+ ).join('')} `
+ ).join('');
+ const win = window.open('', '_blank');
+ if (!win) return;
+ win.document.write(`
+ ${escHtml(filename)}
+
+ ${escHtml(filename)}
+ ${thead} ${tbody}
+
+ `);
+ win.document.close();
+}
diff --git a/distribution_fe/components/shared/data-table/hooks/use-table-filter.ts b/distribution_fe/components/shared/data-table/hooks/use-table-filter.ts
new file mode 100644
index 0000000..6d68daa
--- /dev/null
+++ b/distribution_fe/components/shared/data-table/hooks/use-table-filter.ts
@@ -0,0 +1,33 @@
+import { type ColumnDef, type FieldConfig, type FilterState } from '../types';
+import { getNestedValue } from '../utils/nested-value';
+
+export function filterData(data: T[], state: FilterState, columns: ColumnDef[]): T[] {
+ let result = data;
+
+ if (state.global.trim()) {
+ const term = state.global.toLowerCase();
+ result = result.filter(row =>
+ columns.some(col =>
+ col.fields.some(f => {
+ const key = typeof f === 'string' ? f : (f as FieldConfig).key;
+ return String(getNestedValue(row, key) ?? '').toLowerCase().includes(term);
+ })
+ )
+ );
+ }
+
+ const colFilters = Object.entries(state.columns).filter(([, v]) => v.trim());
+ for (const [colKey, term] of colFilters) {
+ const col = columns.find(c => c.key === colKey);
+ if (!col) continue;
+ const lower = term.toLowerCase();
+ result = result.filter(row =>
+ col.fields.some(f => {
+ const key = typeof f === 'string' ? f : (f as FieldConfig).key;
+ return String(getNestedValue(row, key) ?? '').toLowerCase().includes(lower);
+ })
+ );
+ }
+
+ return result;
+}
diff --git a/distribution_fe/components/shared/data-table/hooks/use-table-sort.ts b/distribution_fe/components/shared/data-table/hooks/use-table-sort.ts
new file mode 100644
index 0000000..ecceb08
--- /dev/null
+++ b/distribution_fe/components/shared/data-table/hooks/use-table-sort.ts
@@ -0,0 +1,31 @@
+import { type ColumnDef, type SortState } from '../types';
+import { getNestedValue } from '../utils/nested-value';
+
+export function sortData(data: T[], state: SortState, columns: ColumnDef[]): T[] {
+ if (!state.column || !state.direction) return data;
+ const col = columns.find(c => c.key === state.column);
+ if (!col) return data;
+
+ if (col.sortFn) {
+ const sorted = [...data].sort(col.sortFn);
+ return state.direction === 'desc' ? sorted.reverse() : sorted;
+ }
+
+ const primaryField = col.fields[0];
+ const fieldKey = typeof primaryField === 'string' ? primaryField : primaryField.key;
+
+ return [...data].sort((a, b) => {
+ const av = getNestedValue(a, fieldKey);
+ const bv = getNestedValue(b, fieldKey);
+ const result = compareValues(av, bv);
+ return state.direction === 'asc' ? result : -result;
+ });
+}
+
+function compareValues(a: unknown, b: unknown): number {
+ if (a == null) return -1;
+ if (b == null) return 1;
+ if (typeof a === 'number' && typeof b === 'number') return a - b;
+ if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
+ return String(a).localeCompare(String(b), undefined, { numeric: true, sensitivity: 'base' });
+}
diff --git a/distribution_fe/components/shared/data-table/index.ts b/distribution_fe/components/shared/data-table/index.ts
new file mode 100644
index 0000000..171a929
--- /dev/null
+++ b/distribution_fe/components/shared/data-table/index.ts
@@ -0,0 +1,17 @@
+export { DataTable } from './data-table';
+export type {
+ TableConfig,
+ ColumnDef,
+ FieldConfig,
+ MobileCardConfig,
+ SortState,
+ FilterState,
+ PageState,
+ ServerSideParams,
+ ExportFormat,
+ BadgeConfig,
+ IconConfig,
+ LinkConfig,
+ PaginationConfig,
+ ExportConfig,
+} from './types';
diff --git a/distribution_fe/components/shared/data-table/table-pagination.tsx b/distribution_fe/components/shared/data-table/table-pagination.tsx
new file mode 100644
index 0000000..61a3562
--- /dev/null
+++ b/distribution_fe/components/shared/data-table/table-pagination.tsx
@@ -0,0 +1,106 @@
+'use client';
+
+import { HugeiconsIcon } from '@hugeicons/react';
+import { ChevronLeftIcon, ChevronRightIcon } from '@hugeicons/core-free-icons';
+import { Button } from '@/components/ui/button';
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from '@/components/ui/select';
+
+interface TablePaginationProps {
+ page: number;
+ pageSize: number;
+ totalRecords: number;
+ pageSizeOptions?: number[];
+ onPageChange: (page: number) => void;
+ onPageSizeChange: (size: number) => void;
+}
+
+function buildPageNumbers(page: number, totalPages: number): (number | '...')[] {
+ if (totalPages <= 7) return Array.from({ length: totalPages }, (_, i) => i + 1);
+ const pages: (number | '...')[] = [1];
+ if (page > 3) pages.push('...');
+ for (let i = Math.max(2, page - 1); i <= Math.min(totalPages - 1, page + 1); i++) {
+ pages.push(i);
+ }
+ if (page < totalPages - 2) pages.push('...');
+ pages.push(totalPages);
+ return pages;
+}
+
+export function TablePagination({
+ page,
+ pageSize,
+ totalRecords,
+ pageSizeOptions = [10, 25, 50, 100],
+ onPageChange,
+ onPageSizeChange,
+}: TablePaginationProps) {
+ const totalPages = Math.max(1, Math.ceil(totalRecords / pageSize));
+ const from = Math.min((page - 1) * pageSize + 1, totalRecords);
+ const to = Math.min(page * pageSize, totalRecords);
+ const pages = buildPageNumbers(page, totalPages);
+
+ return (
+
+
+ Rows per page:
+
+
+ {totalRecords === 0 ? '0 records' : `${from}–${to} of ${totalRecords} records`}
+
+
+
+
+
+
+ {pages.map((p, i) =>
+ p === '...' ? (
+ …
+ ) : (
+
+ )
+ )}
+
+
+
+
+ );
+}
diff --git a/distribution_fe/components/shared/data-table/table-toolbar.tsx b/distribution_fe/components/shared/data-table/table-toolbar.tsx
new file mode 100644
index 0000000..6fa2574
--- /dev/null
+++ b/distribution_fe/components/shared/data-table/table-toolbar.tsx
@@ -0,0 +1,124 @@
+'use client';
+
+import { useRef } from 'react';
+import { HugeiconsIcon } from '@hugeicons/react';
+import {
+ Search01Icon,
+ Cancel01Icon,
+ ColumnsThreeCogIcon,
+ Download01Icon,
+} from '@hugeicons/core-free-icons';
+import { Input } from '@/components/ui/input';
+import { Button } from '@/components/ui/button';
+import { Badge } from '@/components/ui/badge';
+import {
+ DropdownMenu,
+ DropdownMenuCheckboxItem,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from '@/components/ui/dropdown-menu';
+import { type ColumnDef, type ExportFormat } from './types';
+
+interface TableToolbarProps {
+ columns: ColumnDef[];
+ hiddenColumns: Set;
+ globalFilter: string;
+ showExport?: boolean;
+ exportFormats?: ExportFormat[];
+ selectedCount?: number;
+ onGlobalFilterChange: (value: string) => void;
+ onColumnVisibilityChange: (key: string) => void;
+ onExport?: (format: ExportFormat) => void;
+ onClearSelection?: () => void;
+}
+
+export function TableToolbar({
+ columns,
+ hiddenColumns,
+ globalFilter,
+ showExport,
+ exportFormats = ['csv', 'excel', 'pdf'],
+ selectedCount = 0,
+ onGlobalFilterChange,
+ onColumnVisibilityChange,
+ onExport,
+ onClearSelection,
+}: TableToolbarProps) {
+ const inputRef = useRef(null);
+
+ return (
+
+ {/* Global search */}
+
+
+ onGlobalFilterChange(e.target.value)}
+ placeholder="Search…"
+ className="pl-8 pr-8 h-8 text-sm"
+ />
+ {globalFilter && (
+
+ )}
+
+
+ {/* Selection badge */}
+ {selectedCount > 0 && (
+
+
+ {selectedCount} selected
+
+
+
+ )}
+
+ {/* Column visibility */}
+
+ }>
+
+ Columns
+
+
+ {columns.map(col => (
+ onColumnVisibilityChange(col.key)}
+ >
+ {col.title}
+
+ ))}
+
+
+
+ {/* Export */}
+ {showExport && onExport && (
+
+ }>
+
+ Export
+
+
+ {exportFormats.map(fmt => (
+ onExport(fmt)}>
+ {fmt.toUpperCase()}
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/distribution_fe/components/shared/data-table/types.ts b/distribution_fe/components/shared/data-table/types.ts
new file mode 100644
index 0000000..5ac114d
--- /dev/null
+++ b/distribution_fe/components/shared/data-table/types.ts
@@ -0,0 +1,117 @@
+export type CellRenderer = 'text' | 'badge' | 'icon' | 'link' | 'custom';
+export type ColumnLayout = 'vertical' | 'horizontal';
+export type SortDirection = 'asc' | 'desc' | null;
+export type ExportFormat = 'csv' | 'excel' | 'pdf';
+export type ColumnAlign = 'left' | 'center' | 'right';
+
+export interface BadgeConfig {
+ colorMap?: Record;
+ defaultColor?: string;
+}
+
+export interface IconConfig {
+ iconMap?: Record;
+ defaultIcon?: string;
+ colorMap?: Record;
+ defaultColorClass?: string;
+}
+
+export interface LinkConfig {
+ urlKey?: string;
+ urlTemplate?: string;
+ target?: '_blank' | '_self';
+}
+
+export interface FieldConfig {
+ key: string;
+ label?: string;
+ renderer?: CellRenderer;
+ primary?: boolean;
+ class?: string;
+ badgeConfig?: BadgeConfig;
+ iconConfig?: IconConfig;
+ linkConfig?: LinkConfig;
+ truncate?: boolean;
+ prefix?: string;
+ suffix?: string;
+ transform?: (value: unknown, row: unknown) => string;
+}
+
+export interface ColumnDef {
+ key: string;
+ title: string;
+ fields: (FieldConfig | string)[];
+ layout?: ColumnLayout;
+ sortable?: boolean;
+ filterable?: boolean;
+ sticky?: 'left' | 'right' | false;
+ width?: number;
+ minWidth?: number;
+ resizable?: boolean;
+ visible?: boolean;
+ align?: ColumnAlign;
+ group?: string;
+ exportable?: boolean;
+ sortFn?: (a: T, b: T) => number;
+ cellRender?: (row: T, col: ColumnDef) => React.ReactNode;
+ headerRender?: (col: ColumnDef) => React.ReactNode;
+}
+
+export interface PaginationConfig {
+ enabled: boolean;
+ pageSize?: number;
+ pageSizeOptions?: number[];
+}
+
+export interface ExportConfig {
+ formats?: ExportFormat[];
+ filename?: string;
+}
+
+export interface MobileCardConfig {
+ /** Column keys to show in the compact summary (after the primary column). Defaults to first 2. */
+ previewColumns?: string[];
+ /** Return a URL to navigate to on card tap. Takes precedence over onRowClick. */
+ detailHref?: (row: T) => string;
+}
+
+export interface TableConfig {
+ columns: ColumnDef[];
+ rowKey?: keyof T | ((row: T) => string);
+ selectable?: boolean;
+ multiSelect?: boolean;
+ expandable?: boolean;
+ stickyHeader?: boolean;
+ pagination?: PaginationConfig;
+ virtualScroll?: boolean;
+ virtualScrollHeight?: string;
+ serverSide?: boolean;
+ exportable?: boolean | ExportConfig;
+ density?: 'compact' | 'normal' | 'comfortable';
+ emptyMessage?: string;
+ rowClass?: (row: T) => string;
+ isRowSelectable?: (row: T) => boolean;
+ expandRender?: (row: T) => React.ReactNode;
+ mobileCard?: MobileCardConfig;
+}
+
+export interface SortState {
+ column: string | null;
+ direction: SortDirection;
+}
+
+export interface FilterState {
+ global: string;
+ columns: Record;
+}
+
+export interface PageState {
+ page: number;
+ pageSize: number;
+}
+
+export interface ServerSideParams {
+ sort: SortState;
+ filter: FilterState;
+ page: PageState;
+}
diff --git a/distribution_fe/components/shared/data-table/utils/nested-value.ts b/distribution_fe/components/shared/data-table/utils/nested-value.ts
new file mode 100644
index 0000000..5bf79eb
--- /dev/null
+++ b/distribution_fe/components/shared/data-table/utils/nested-value.ts
@@ -0,0 +1,11 @@
+export function getNestedValue(obj: unknown, path: string): unknown {
+ return path.split('.').reduce(
+ (acc, key) => (acc as Record)?.[key], obj
+ );
+}
+
+export function resolveUrlTemplate(template: string, row: unknown): string {
+ return template.replace(/\{(\w+(?:\.\w+)*)\}/g, (_, path) =>
+ String(getNestedValue(row, path) ?? '')
+ );
+}
diff --git a/distribution_fe/components/theme-provider.tsx b/distribution_fe/components/theme-provider.tsx
new file mode 100644
index 0000000..3d44f48
--- /dev/null
+++ b/distribution_fe/components/theme-provider.tsx
@@ -0,0 +1,71 @@
+"use client"
+
+import * as React from "react"
+import { ThemeProvider as NextThemesProvider, useTheme } from "next-themes"
+
+function ThemeProvider({
+ children,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+ {children}
+
+ )
+}
+
+function isTypingTarget(target: EventTarget | null) {
+ if (!(target instanceof HTMLElement)) {
+ return false
+ }
+
+ return (
+ target.isContentEditable ||
+ target.tagName === "INPUT" ||
+ target.tagName === "TEXTAREA" ||
+ target.tagName === "SELECT"
+ )
+}
+
+function ThemeHotkey() {
+ const { resolvedTheme, setTheme } = useTheme()
+
+ React.useEffect(() => {
+ function onKeyDown(event: KeyboardEvent) {
+ if (event.defaultPrevented || event.repeat) {
+ return
+ }
+
+ if (event.metaKey || event.ctrlKey || event.altKey) {
+ return
+ }
+
+ if (event.key.toLowerCase() !== "d") {
+ return
+ }
+
+ if (isTypingTarget(event.target)) {
+ return
+ }
+
+ setTheme(resolvedTheme === "dark" ? "light" : "dark")
+ }
+
+ window.addEventListener("keydown", onKeyDown)
+
+ return () => {
+ window.removeEventListener("keydown", onKeyDown)
+ }
+ }, [resolvedTheme, setTheme])
+
+ return null
+}
+
+export { ThemeProvider }
diff --git a/distribution_fe/components/ui/badge.tsx b/distribution_fe/components/ui/badge.tsx
new file mode 100644
index 0000000..6d49b91
--- /dev/null
+++ b/distribution_fe/components/ui/badge.tsx
@@ -0,0 +1,52 @@
+import { mergeProps } from "@base-ui/react/merge-props"
+import { useRender } from "@base-ui/react/use-render"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const badgeVariants = cva(
+ "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-2xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
+ secondary:
+ "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
+ destructive:
+ "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
+ outline:
+ "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
+ ghost:
+ "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+)
+
+function Badge({
+ className,
+ variant = "default",
+ render,
+ ...props
+}: useRender.ComponentProps<"span"> & VariantProps) {
+ return useRender({
+ defaultTagName: "span",
+ props: mergeProps<"span">(
+ {
+ className: cn(badgeVariants({ variant }), className),
+ },
+ props
+ ),
+ render,
+ state: {
+ slot: "badge",
+ variant,
+ },
+ })
+}
+
+export { Badge, badgeVariants }
diff --git a/distribution_fe/components/ui/button.tsx b/distribution_fe/components/ui/button.tsx
new file mode 100644
index 0000000..e87e24d
--- /dev/null
+++ b/distribution_fe/components/ui/button.tsx
@@ -0,0 +1,56 @@
+import { Button as ButtonPrimitive } from "@base-ui/react/button"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const buttonVariants = cva(
+ "group/button inline-flex shrink-0 items-center justify-center rounded-2xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
+ outline:
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-transparent dark:hover:bg-input/30",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
+ ghost:
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
+ destructive:
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default:
+ "h-8 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
+ xs: "h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3",
+ sm: "h-7 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
+ lg: "h-9 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
+ icon: "size-8",
+ "icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
+ "icon-sm": "size-7",
+ "icon-lg": "size-9",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+function Button({
+ className,
+ variant = "default",
+ size = "default",
+ ...props
+}: ButtonPrimitive.Props & VariantProps) {
+ return (
+
+ )
+}
+
+export { Button, buttonVariants }
diff --git a/distribution_fe/components/ui/checkbox.tsx b/distribution_fe/components/ui/checkbox.tsx
new file mode 100644
index 0000000..b361461
--- /dev/null
+++ b/distribution_fe/components/ui/checkbox.tsx
@@ -0,0 +1,29 @@
+"use client"
+
+import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
+
+import { cn } from "@/lib/utils"
+import { HugeiconsIcon } from "@hugeicons/react"
+import { Tick02Icon } from "@hugeicons/core-free-icons"
+
+function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
+ return (
+
+
+
+
+
+ )
+}
+
+export { Checkbox }
diff --git a/distribution_fe/components/ui/collapsible.tsx b/distribution_fe/components/ui/collapsible.tsx
new file mode 100644
index 0000000..488fb33
--- /dev/null
+++ b/distribution_fe/components/ui/collapsible.tsx
@@ -0,0 +1,21 @@
+"use client"
+
+import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"
+
+function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {
+ return
+}
+
+function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {
+ return (
+
+ )
+}
+
+function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {
+ return (
+
+ )
+}
+
+export { Collapsible, CollapsibleTrigger, CollapsibleContent }
diff --git a/distribution_fe/components/ui/dropdown-menu.tsx b/distribution_fe/components/ui/dropdown-menu.tsx
new file mode 100644
index 0000000..8a0c5b9
--- /dev/null
+++ b/distribution_fe/components/ui/dropdown-menu.tsx
@@ -0,0 +1,267 @@
+"use client"
+
+import * as React from "react"
+import { Menu as MenuPrimitive } from "@base-ui/react/menu"
+
+import { cn } from "@/lib/utils"
+import { HugeiconsIcon } from "@hugeicons/react"
+import { ArrowRight01Icon, Tick02Icon } from "@hugeicons/core-free-icons"
+
+function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
+ return
+}
+
+function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
+ return
+}
+
+function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
+ return
+}
+
+function DropdownMenuContent({
+ align = "start",
+ alignOffset = 0,
+ side = "bottom",
+ sideOffset = 4,
+ className,
+ ...props
+}: MenuPrimitive.Popup.Props &
+ Pick<
+ MenuPrimitive.Positioner.Props,
+ "align" | "alignOffset" | "side" | "sideOffset"
+ >) {
+ return (
+
+
+
+
+
+ )
+}
+
+function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
+ return
+}
+
+function DropdownMenuLabel({
+ className,
+ inset,
+ ...props
+}: MenuPrimitive.GroupLabel.Props & {
+ inset?: boolean
+}) {
+ return (
+
+ )
+}
+
+function DropdownMenuItem({
+ className,
+ inset,
+ variant = "default",
+ ...props
+}: MenuPrimitive.Item.Props & {
+ inset?: boolean
+ variant?: "default" | "destructive"
+}) {
+ return (
+
+ )
+}
+
+function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
+ return
+}
+
+function DropdownMenuSubTrigger({
+ className,
+ inset,
+ children,
+ ...props
+}: MenuPrimitive.SubmenuTrigger.Props & {
+ inset?: boolean
+}) {
+ return (
+
+ {children}
+
+
+ )
+}
+
+function DropdownMenuSubContent({
+ align = "start",
+ alignOffset = -3,
+ side = "right",
+ sideOffset = 0,
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuCheckboxItem({
+ className,
+ children,
+ checked,
+ inset,
+ ...props
+}: MenuPrimitive.CheckboxItem.Props & {
+ inset?: boolean
+}) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
+ return (
+
+ )
+}
+
+function DropdownMenuRadioItem({
+ className,
+ children,
+ inset,
+ ...props
+}: MenuPrimitive.RadioItem.Props & {
+ inset?: boolean
+}) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function DropdownMenuSeparator({
+ className,
+ ...props
+}: MenuPrimitive.Separator.Props) {
+ return (
+
+ )
+}
+
+function DropdownMenuShortcut({
+ className,
+ ...props
+}: React.ComponentProps<"span">) {
+ return (
+
+ )
+}
+
+export {
+ DropdownMenu,
+ DropdownMenuPortal,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuGroup,
+ DropdownMenuLabel,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioGroup,
+ DropdownMenuRadioItem,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuSub,
+ DropdownMenuSubTrigger,
+ DropdownMenuSubContent,
+}
diff --git a/distribution_fe/components/ui/input.tsx b/distribution_fe/components/ui/input.tsx
new file mode 100644
index 0000000..f40013f
--- /dev/null
+++ b/distribution_fe/components/ui/input.tsx
@@ -0,0 +1,20 @@
+import * as React from "react"
+import { Input as InputPrimitive } from "@base-ui/react/input"
+
+import { cn } from "@/lib/utils"
+
+function Input({ className, type, ...props }: React.ComponentProps<"input">) {
+ return (
+
+ )
+}
+
+export { Input }
diff --git a/distribution_fe/components/ui/select.tsx b/distribution_fe/components/ui/select.tsx
new file mode 100644
index 0000000..338b3b4
--- /dev/null
+++ b/distribution_fe/components/ui/select.tsx
@@ -0,0 +1,200 @@
+"use client"
+
+import * as React from "react"
+import { Select as SelectPrimitive } from "@base-ui/react/select"
+
+import { cn } from "@/lib/utils"
+import { HugeiconsIcon } from "@hugeicons/react"
+import { UnfoldMoreIcon, Tick02Icon, ArrowUp01Icon, ArrowDown01Icon } from "@hugeicons/core-free-icons"
+
+const Select = SelectPrimitive.Root
+
+function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {
+ return (
+
+ )
+}
+
+function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
+ return (
+
+ )
+}
+
+function SelectTrigger({
+ className,
+ size = "default",
+ children,
+ ...props
+}: SelectPrimitive.Trigger.Props & {
+ size?: "sm" | "default"
+}) {
+ return (
+
+ {children}
+
+ }
+ />
+
+ )
+}
+
+function SelectContent({
+ className,
+ children,
+ side = "bottom",
+ sideOffset = 4,
+ align = "center",
+ alignOffset = 0,
+ alignItemWithTrigger = true,
+ ...props
+}: SelectPrimitive.Popup.Props &
+ Pick<
+ SelectPrimitive.Positioner.Props,
+ "align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger"
+ >) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ )
+}
+
+function SelectLabel({
+ className,
+ ...props
+}: SelectPrimitive.GroupLabel.Props) {
+ return (
+
+ )
+}
+
+function SelectItem({
+ className,
+ children,
+ ...props
+}: SelectPrimitive.Item.Props) {
+ return (
+
+
+ {children}
+
+
+ }
+ >
+
+
+
+ )
+}
+
+function SelectSeparator({
+ className,
+ ...props
+}: SelectPrimitive.Separator.Props) {
+ return (
+
+ )
+}
+
+function SelectScrollUpButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+function SelectScrollDownButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+export {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectScrollDownButton,
+ SelectScrollUpButton,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+}
diff --git a/distribution_fe/components/ui/separator.tsx b/distribution_fe/components/ui/separator.tsx
new file mode 100644
index 0000000..6e1369e
--- /dev/null
+++ b/distribution_fe/components/ui/separator.tsx
@@ -0,0 +1,25 @@
+"use client"
+
+import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
+
+import { cn } from "@/lib/utils"
+
+function Separator({
+ className,
+ orientation = "horizontal",
+ ...props
+}: SeparatorPrimitive.Props) {
+ return (
+
+ )
+}
+
+export { Separator }
diff --git a/distribution_fe/components/ui/sheet.tsx b/distribution_fe/components/ui/sheet.tsx
new file mode 100644
index 0000000..281964b
--- /dev/null
+++ b/distribution_fe/components/ui/sheet.tsx
@@ -0,0 +1,138 @@
+"use client"
+
+import * as React from "react"
+import { Dialog as SheetPrimitive } from "@base-ui/react/dialog"
+
+import { cn } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
+import { HugeiconsIcon } from "@hugeicons/react"
+import { Cancel01Icon } from "@hugeicons/core-free-icons"
+
+function Sheet({ ...props }: SheetPrimitive.Root.Props) {
+ return
+}
+
+function SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {
+ return
+}
+
+function SheetClose({ ...props }: SheetPrimitive.Close.Props) {
+ return
+}
+
+function SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {
+ return
+}
+
+function SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {
+ return (
+
+ )
+}
+
+function SheetContent({
+ className,
+ children,
+ side = "right",
+ showCloseButton = true,
+ ...props
+}: SheetPrimitive.Popup.Props & {
+ side?: "top" | "right" | "bottom" | "left"
+ showCloseButton?: boolean
+}) {
+ return (
+
+
+
+ {children}
+ {showCloseButton && (
+
+ }
+ >
+
+ Close
+
+ )}
+
+
+ )
+}
+
+function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
+ return (
+
+ )
+}
+
+function SheetDescription({
+ className,
+ ...props
+}: SheetPrimitive.Description.Props) {
+ return (
+
+ )
+}
+
+export {
+ Sheet,
+ SheetTrigger,
+ SheetClose,
+ SheetContent,
+ SheetHeader,
+ SheetFooter,
+ SheetTitle,
+ SheetDescription,
+}
diff --git a/distribution_fe/components/ui/sidebar.tsx b/distribution_fe/components/ui/sidebar.tsx
new file mode 100644
index 0000000..13323df
--- /dev/null
+++ b/distribution_fe/components/ui/sidebar.tsx
@@ -0,0 +1,727 @@
+"use client"
+
+import * as React from "react"
+import { mergeProps } from "@base-ui/react/merge-props"
+import { useRender } from "@base-ui/react/use-render"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { useIsMobile } from "@/hooks/use-mobile"
+import { cn } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Separator } from "@/components/ui/separator"
+import {
+ Sheet,
+ SheetContent,
+ SheetDescription,
+ SheetHeader,
+ SheetTitle,
+} from "@/components/ui/sheet"
+import { Skeleton } from "@/components/ui/skeleton"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/components/ui/tooltip"
+import { HugeiconsIcon } from "@hugeicons/react"
+import { SidebarLeftIcon } from "@hugeicons/core-free-icons"
+
+const SIDEBAR_COOKIE_NAME = "sidebar_state"
+const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
+const SIDEBAR_WIDTH = "16rem"
+const SIDEBAR_WIDTH_MOBILE = "18rem"
+const SIDEBAR_WIDTH_ICON = "3rem"
+const SIDEBAR_KEYBOARD_SHORTCUT = "b"
+
+type SidebarContextProps = {
+ state: "expanded" | "collapsed"
+ open: boolean
+ setOpen: (open: boolean) => void
+ openMobile: boolean
+ setOpenMobile: (open: boolean) => void
+ isMobile: boolean
+ toggleSidebar: () => void
+}
+
+const SidebarContext = React.createContext(null)
+
+function useSidebar() {
+ const context = React.useContext(SidebarContext)
+ if (!context) {
+ throw new Error("useSidebar must be used within a SidebarProvider.")
+ }
+
+ return context
+}
+
+function SidebarProvider({
+ defaultOpen = true,
+ open: openProp,
+ onOpenChange: setOpenProp,
+ className,
+ style,
+ children,
+ ...props
+}: React.ComponentProps<"div"> & {
+ defaultOpen?: boolean
+ open?: boolean
+ onOpenChange?: (open: boolean) => void
+}) {
+ const isMobile = useIsMobile()
+ const [openMobile, setOpenMobile] = React.useState(false)
+
+ // This is the internal state of the sidebar.
+ // We use openProp and setOpenProp for control from outside the component.
+ const [_open, _setOpen] = React.useState(defaultOpen)
+ const open = openProp ?? _open
+ const setOpen = React.useCallback(
+ (value: boolean | ((value: boolean) => boolean)) => {
+ const openState = typeof value === "function" ? value(open) : value
+ if (setOpenProp) {
+ setOpenProp(openState)
+ } else {
+ _setOpen(openState)
+ }
+
+ // This sets the cookie to keep the sidebar state.
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
+ },
+ [setOpenProp, open]
+ )
+
+ // Helper to toggle the sidebar.
+ const toggleSidebar = React.useCallback(() => {
+ return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)
+ }, [isMobile, setOpen, setOpenMobile])
+
+ // Adds a keyboard shortcut to toggle the sidebar.
+ React.useEffect(() => {
+ const handleKeyDown = (event: KeyboardEvent) => {
+ if (
+ event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
+ (event.metaKey || event.ctrlKey)
+ ) {
+ event.preventDefault()
+ toggleSidebar()
+ }
+ }
+
+ window.addEventListener("keydown", handleKeyDown)
+ return () => window.removeEventListener("keydown", handleKeyDown)
+ }, [toggleSidebar])
+
+ // We add a state so that we can do data-state="expanded" or "collapsed".
+ // This makes it easier to style the sidebar with Tailwind classes.
+ const state = open ? "expanded" : "collapsed"
+
+ const contextValue = React.useMemo(
+ () => ({
+ state,
+ open,
+ setOpen,
+ isMobile,
+ openMobile,
+ setOpenMobile,
+ toggleSidebar,
+ }),
+ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
+ )
+
+ return (
+
+
+ {children}
+
+
+ )
+}
+
+function Sidebar({
+ side = "left",
+ variant = "sidebar",
+ collapsible = "offcanvas",
+ className,
+ children,
+ dir,
+ ...props
+}: React.ComponentProps<"div"> & {
+ side?: "left" | "right"
+ variant?: "sidebar" | "floating" | "inset"
+ collapsible?: "offcanvas" | "icon" | "none"
+}) {
+ const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
+
+ if (collapsible === "none") {
+ return (
+
+ {children}
+
+ )
+ }
+
+ if (isMobile) {
+ return (
+
+
+
+ Sidebar
+ Displays the mobile sidebar.
+
+ {children}
+
+
+ )
+ }
+
+ return (
+
+ {/* This is what handles the sidebar gap on desktop */}
+
+
+
+ {children}
+
+
+
+ )
+}
+
+function SidebarTrigger({
+ className,
+ onClick,
+ ...props
+}: React.ComponentProps) {
+ const { toggleSidebar } = useSidebar()
+
+ return (
+
+ )
+}
+
+function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
+ const { toggleSidebar } = useSidebar()
+
+ return (
+
+ )
+}
+
+function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
+ return (
+
+ )
+}
+
+function SidebarInput({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SidebarHeader({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function SidebarFooter({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function SidebarSeparator({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SidebarContent({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function SidebarGroupLabel({
+ className,
+ render,
+ ...props
+}: useRender.ComponentProps<"div"> & React.ComponentProps<"div">) {
+ return useRender({
+ defaultTagName: "div",
+ props: mergeProps<"div">(
+ {
+ className: cn(
+ "flex h-8 shrink-0 items-center rounded-xl px-3 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-3 [&>svg]:size-4 [&>svg]:shrink-0",
+ className
+ ),
+ },
+ props
+ ),
+ render,
+ state: {
+ slot: "sidebar-group-label",
+ sidebar: "group-label",
+ },
+ })
+}
+
+function SidebarGroupAction({
+ className,
+ render,
+ ...props
+}: useRender.ComponentProps<"button"> & React.ComponentProps<"button">) {
+ return useRender({
+ defaultTagName: "button",
+ props: mergeProps<"button">(
+ {
+ className: cn(
+ "absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-xl p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-3 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
+ className
+ ),
+ },
+ props
+ ),
+ render,
+ state: {
+ slot: "sidebar-group-action",
+ sidebar: "group-action",
+ },
+ })
+}
+
+function SidebarGroupContent({
+ className,
+ ...props
+}: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">) {
+ return (
+
+ )
+}
+
+function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) {
+ return (
+
+ )
+}
+
+const sidebarMenuButtonVariants = cva(
+ "peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-xl px-3 py-2 text-left text-sm whitespace-nowrap ring-sidebar-ring outline-hidden transition-[width,height,padding] duration-200 group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-3 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 has-[>svg:first-child]:pl-2.5 has-[>svg:last-child]:pr-2.5 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate",
+ {
+ variants: {
+ variant: {
+ default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
+ outline:
+ "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
+ },
+ size: {
+ default: "h-8 text-sm",
+ sm: "h-7 text-xs",
+ lg: "h-12 px-3 text-sm group-data-[collapsible=icon]:p-0!",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+function SidebarMenuButton({
+ render,
+ isActive = false,
+ variant = "default",
+ size = "default",
+ tooltip,
+ className,
+ ...props
+}: useRender.ComponentProps<"button"> &
+ React.ComponentProps<"button"> & {
+ isActive?: boolean
+ tooltip?: string | React.ComponentProps
+ } & VariantProps) {
+ const { isMobile, state } = useSidebar()
+ const comp = useRender({
+ defaultTagName: "button",
+ props: mergeProps<"button">(
+ {
+ className: cn(sidebarMenuButtonVariants({ variant, size }), className),
+ },
+ props
+ ),
+ render: !tooltip ? render : ,
+ state: {
+ slot: "sidebar-menu-button",
+ sidebar: "menu-button",
+ size,
+ active: isActive,
+ },
+ })
+
+ if (!tooltip) {
+ return comp
+ }
+
+ if (typeof tooltip === "string") {
+ tooltip = {
+ children: tooltip,
+ }
+ }
+
+ return (
+
+ {comp}
+
+
+ )
+}
+
+function SidebarMenuAction({
+ className,
+ render,
+ showOnHover = false,
+ ...props
+}: useRender.ComponentProps<"button"> &
+ React.ComponentProps<"button"> & {
+ showOnHover?: boolean
+ }) {
+ return useRender({
+ defaultTagName: "button",
+ props: mergeProps<"button">(
+ {
+ className: cn(
+ "absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-xl p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-3 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
+ showOnHover &&
+ "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-active/menu-button:text-sidebar-accent-foreground aria-expanded:opacity-100 md:opacity-0",
+ className
+ ),
+ },
+ props
+ ),
+ render,
+ state: {
+ slot: "sidebar-menu-action",
+ sidebar: "menu-action",
+ },
+ })
+}
+
+function SidebarMenuBadge({
+ className,
+ ...props
+}: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function SidebarMenuSkeleton({
+ className,
+ showIcon = false,
+ ...props
+}: React.ComponentProps<"div"> & {
+ showIcon?: boolean
+}) {
+ // Random width between 50 to 90%.
+ const [width] = React.useState(() => {
+ return `${Math.floor(Math.random() * 40) + 50}%`
+ })
+
+ return (
+
+ {showIcon && (
+
+ )}
+
+
+ )
+}
+
+function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) {
+ return (
+
+ )
+}
+
+function SidebarMenuSubItem({
+ className,
+ ...props
+}: React.ComponentProps<"li">) {
+ return (
+
+ )
+}
+
+function SidebarMenuSubButton({
+ render,
+ size = "md",
+ isActive = false,
+ className,
+ ...props
+}: useRender.ComponentProps<"a"> &
+ React.ComponentProps<"a"> & {
+ size?: "sm" | "md"
+ isActive?: boolean
+ }) {
+ return useRender({
+ defaultTagName: "a",
+ props: mergeProps<"a">(
+ {
+ className: cn(
+ "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-xl px-3 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-3 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-sm data-[size=sm]:text-xs data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
+ className
+ ),
+ },
+ props
+ ),
+ render,
+ state: {
+ slot: "sidebar-menu-sub-button",
+ sidebar: "menu-sub-button",
+ size,
+ active: isActive,
+ },
+ })
+}
+
+export {
+ Sidebar,
+ SidebarContent,
+ SidebarFooter,
+ SidebarGroup,
+ SidebarGroupAction,
+ SidebarGroupContent,
+ SidebarGroupLabel,
+ SidebarHeader,
+ SidebarInput,
+ SidebarInset,
+ SidebarMenu,
+ SidebarMenuAction,
+ SidebarMenuBadge,
+ SidebarMenuButton,
+ SidebarMenuItem,
+ SidebarMenuSkeleton,
+ SidebarMenuSub,
+ SidebarMenuSubButton,
+ SidebarMenuSubItem,
+ SidebarProvider,
+ SidebarRail,
+ SidebarSeparator,
+ SidebarTrigger,
+ useSidebar,
+}
diff --git a/distribution_fe/components/ui/skeleton.tsx b/distribution_fe/components/ui/skeleton.tsx
new file mode 100644
index 0000000..d598583
--- /dev/null
+++ b/distribution_fe/components/ui/skeleton.tsx
@@ -0,0 +1,13 @@
+import { cn } from "@/lib/utils"
+
+function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+export { Skeleton }
diff --git a/distribution_fe/components/ui/table.tsx b/distribution_fe/components/ui/table.tsx
new file mode 100644
index 0000000..abeaced
--- /dev/null
+++ b/distribution_fe/components/ui/table.tsx
@@ -0,0 +1,116 @@
+"use client"
+
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+function Table({ className, ...props }: React.ComponentProps<"table">) {
+ return (
+
+
+
+ )
+}
+
+function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
+ return (
+
+ )
+}
+
+function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
+ return (
+
+ )
+}
+
+function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
+ return (
+ tr]:last:border-b-0",
+ className
+ )}
+ {...props}
+ />
+ )
+}
+
+function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
+ return (
+
+ )
+}
+
+function TableHead({ className, ...props }: React.ComponentProps<"th">) {
+ return (
+
+ )
+}
+
+function TableCell({ className, ...props }: React.ComponentProps<"td">) {
+ return (
+
+ )
+}
+
+function TableCaption({
+ className,
+ ...props
+}: React.ComponentProps<"caption">) {
+ return (
+
+ )
+}
+
+export {
+ Table,
+ TableHeader,
+ TableBody,
+ TableFooter,
+ TableHead,
+ TableRow,
+ TableCell,
+ TableCaption,
+}
diff --git a/distribution_fe/components/ui/tooltip.tsx b/distribution_fe/components/ui/tooltip.tsx
new file mode 100644
index 0000000..bc2c8d0
--- /dev/null
+++ b/distribution_fe/components/ui/tooltip.tsx
@@ -0,0 +1,66 @@
+"use client"
+
+import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip"
+
+import { cn } from "@/lib/utils"
+
+function TooltipProvider({
+ delay = 0,
+ ...props
+}: TooltipPrimitive.Provider.Props) {
+ return (
+
+ )
+}
+
+function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
+ return
+}
+
+function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
+ return
+}
+
+function TooltipContent({
+ className,
+ side = "top",
+ sideOffset = 4,
+ align = "center",
+ alignOffset = 0,
+ children,
+ ...props
+}: TooltipPrimitive.Popup.Props &
+ Pick<
+ TooltipPrimitive.Positioner.Props,
+ "align" | "alignOffset" | "side" | "sideOffset"
+ >) {
+ return (
+
+
+
+ {children}
+
+
+
+
+ )
+}
+
+export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
diff --git a/distribution_fe/config/nav.ts b/distribution_fe/config/nav.ts
new file mode 100644
index 0000000..41ba81a
--- /dev/null
+++ b/distribution_fe/config/nav.ts
@@ -0,0 +1,154 @@
+import type { IconSvgElement } from '@hugeicons/react'
+import {
+ DashboardSquare01Icon,
+ Location01Icon,
+ Route01Icon,
+ Car01Icon,
+ Building02Icon,
+ Package01Icon,
+ CatalogueIcon,
+ BarCode01Icon,
+ Layers01Icon,
+ Discount01Icon,
+ DiscountTag01Icon,
+ UserGroupIcon,
+ Store01Icon,
+ UserShield01Icon,
+ ShieldUserIcon,
+ LicenseDraftIcon,
+ LicenseIcon,
+ ShoppingCart01Icon,
+ PackageReceiveIcon,
+ TruckIcon,
+ DeliveryBox01Icon,
+ DeliveryTruck01Icon,
+ DollarSquareIcon,
+ ClipboardListIcon,
+ BankIcon,
+ PackageMoving01Icon,
+} from '@hugeicons/core-free-icons'
+
+export interface NavItem {
+ title: string
+ href: string
+ icon: IconSvgElement
+ permission?: string
+}
+
+export interface NavGroup {
+ title: string
+ icon: IconSvgElement
+ items: NavItem[]
+}
+
+// Standalone item rendered at top — not inside any collapsible group
+export const DASHBOARD_ITEM: NavItem = {
+ title: 'Dashboard',
+ href: '/',
+ icon: DashboardSquare01Icon,
+}
+
+export const NAV_GROUPS: NavGroup[] = [
+ {
+ title: 'Master Data',
+ icon: Building02Icon,
+ items: [
+ { title: 'Regions', href: '/master/regions', icon: Location01Icon, permission: 'regions.view' },
+ { title: 'Routes', href: '/master/routes', icon: Route01Icon, permission: 'routes.view' },
+ { title: 'Vehicles', href: '/master/vehicles', icon: Car01Icon, permission: 'vehicles.view' },
+ { title: 'Warehouses', href: '/master/warehouses', icon: Building02Icon, permission: 'warehouses.view' },
+ ],
+ },
+ {
+ title: 'Catalogue',
+ icon: CatalogueIcon,
+ items: [
+ { title: 'Items', href: '/catalogue/items', icon: Package01Icon, permission: 'items.view' },
+ { title: 'Categories', href: '/catalogue/categories', icon: CatalogueIcon, permission: 'categories.view' },
+ { title: 'Brands', href: '/catalogue/brands', icon: BarCode01Icon, permission: 'categories.view' },
+ { title: 'UOMs', href: '/catalogue/uoms', icon: Layers01Icon, permission: 'categories.view' },
+ ],
+ },
+ {
+ title: 'Pricing',
+ icon: Discount01Icon,
+ items: [
+ { title: 'Price Lists', href: '/pricing/price-lists', icon: Discount01Icon, permission: 'pricelists.view' },
+ { title: 'Schemes', href: '/pricing/schemes', icon: DiscountTag01Icon, permission: 'schemes.view' },
+ ],
+ },
+ {
+ title: 'Suppliers',
+ icon: UserGroupIcon,
+ items: [
+ { title: 'Suppliers', href: '/suppliers', icon: UserGroupIcon, permission: 'suppliers.view' },
+ ],
+ },
+ {
+ title: 'Stores',
+ icon: Store01Icon,
+ items: [
+ { title: 'Stores', href: '/stores', icon: Store01Icon, permission: 'stores.view' },
+ ],
+ },
+ {
+ title: 'Users & Access',
+ icon: UserShield01Icon,
+ items: [
+ { title: 'Users', href: '/users', icon: UserShield01Icon, permission: 'users.view' },
+ { title: 'Roles', href: '/users/roles', icon: ShieldUserIcon, permission: 'roles.view' },
+ ],
+ },
+ {
+ title: 'Drivers',
+ icon: LicenseDraftIcon,
+ items: [
+ { title: 'Driver Profiles', href: '/drivers', icon: LicenseDraftIcon, permission: 'driver_profiles.view' },
+ { title: 'Compliance', href: '/drivers/compliance', icon: LicenseIcon, permission: 'compliance.manage' },
+ ],
+ },
+ {
+ title: 'Procurement',
+ icon: ShoppingCart01Icon,
+ items: [
+ { title: 'Purchase Orders', href: '/procurement/orders', icon: ShoppingCart01Icon, permission: 'purchase_orders.view' },
+ { title: 'Goods Receipt', href: '/procurement/grn', icon: PackageReceiveIcon, permission: 'purchase_orders.view' },
+ ],
+ },
+ {
+ title: 'Operations',
+ icon: TruckIcon,
+ items: [
+ { title: 'Rides', href: '/operations/rides', icon: TruckIcon, permission: 'rides.view' },
+ { title: 'Loading Sheets', href: '/operations/loading', icon: DeliveryBox01Icon, permission: 'loading.view' },
+ { title: 'Delivery Tasks', href: '/operations/deliveries', icon: DeliveryTruck01Icon, permission: 'rides.view' },
+ ],
+ },
+ {
+ title: 'Sales & Orders',
+ icon: DollarSquareIcon,
+ items: [
+ { title: 'Sales', href: '/sales', icon: DollarSquareIcon, permission: 'orders.view' },
+ { title: 'Orders', href: '/sales/orders', icon: ClipboardListIcon, permission: 'orders.view' },
+ { title: 'Payments', href: '/sales/payments', icon: BankIcon, permission: 'orders.view' },
+ ],
+ },
+ {
+ title: 'Stock',
+ icon: PackageMoving01Icon,
+ items: [
+ { title: 'Stock Balances', href: '/stock', icon: Package01Icon, permission: 'warehouses.view' },
+ { title: 'Stock Movements', href: '/stock/movements', icon: PackageMoving01Icon, permission: 'warehouses.view' },
+ ],
+ },
+]
+
+// Ordered candidates for mobile bottom nav — first 5 visible are shown
+export const BOTTOM_NAV_CANDIDATES: NavItem[] = [
+ { title: 'Home', href: '/', icon: DashboardSquare01Icon },
+ { title: 'Stores', href: '/stores', icon: Store01Icon, permission: 'stores.view' },
+ { title: 'Rides', href: '/operations/rides', icon: TruckIcon, permission: 'rides.view' },
+ { title: 'Loading', href: '/operations/loading', icon: DeliveryBox01Icon, permission: 'loading.view' },
+ { title: 'Sales', href: '/sales', icon: DollarSquareIcon, permission: 'orders.view' },
+ { title: 'Items', href: '/catalogue/items', icon: Package01Icon, permission: 'items.view' },
+]
diff --git a/distribution_fe/contexts/auth-context.tsx b/distribution_fe/contexts/auth-context.tsx
new file mode 100644
index 0000000..f17fdf6
--- /dev/null
+++ b/distribution_fe/contexts/auth-context.tsx
@@ -0,0 +1,107 @@
+'use client'
+
+import { createContext, useContext, useState, type ReactNode } from 'react'
+
+export type Role = 'admin' | 'warehouse' | 'sales'
+
+export interface MockUser {
+ id: string
+ fullName: string
+ username: string
+ roleId: string
+ role: Role
+}
+
+interface AuthContextValue {
+ user: MockUser
+ permissions: string[]
+ setRole: (role: Role) => void
+}
+
+// Mock permissions per role — replace with real API call once auth is implemented
+const MOCK_PERMISSIONS: Record = {
+ admin: ['*'],
+ warehouse: [
+ 'items.view',
+ 'categories.view',
+ 'regions.view',
+ 'routes.view',
+ 'vehicles.view',
+ 'warehouses.view',
+ 'loading.view',
+ 'loading.dispatch',
+ 'loading.receive',
+ 'loading.resolve',
+ 'rides.view',
+ 'rides.manage',
+ 'rides.cancel.request',
+ 'driver_profiles.view',
+ 'compliance.manage',
+ ],
+ sales: [
+ 'stores.view',
+ 'stores.create',
+ 'stores.update',
+ 'orders.view',
+ 'orders.create',
+ 'orders.update',
+ 'items.view',
+ 'categories.view',
+ 'regions.view',
+ 'routes.view',
+ 'rides.view',
+ 'driver_profiles.view',
+ ],
+}
+
+const MOCK_USERS: Record = {
+ admin: {
+ id: '00000000-0000-0000-0000-000000000001',
+ fullName: 'Admin User',
+ username: 'admin',
+ roleId: '00000000-0000-0000-0000-000000000010',
+ role: 'admin',
+ },
+ warehouse: {
+ id: '00000000-0000-0000-0000-000000000002',
+ fullName: 'Warehouse Staff',
+ username: 'warehouse',
+ roleId: '00000000-0000-0000-0000-000000000011',
+ role: 'warehouse',
+ },
+ sales: {
+ id: '00000000-0000-0000-0000-000000000003',
+ fullName: 'Sales Rep',
+ username: 'sales',
+ roleId: '00000000-0000-0000-0000-000000000012',
+ role: 'sales',
+ },
+}
+
+const AuthContext = createContext(null)
+
+export function AuthProvider({ children }: { children: ReactNode }) {
+ const [role, setRoleState] = useState('admin')
+
+ function setRole(newRole: Role) {
+ setRoleState(newRole)
+ }
+
+ return (
+
+ {children}
+
+ )
+}
+
+export function useAuth(): AuthContextValue {
+ const ctx = useContext(AuthContext)
+ if (!ctx) throw new Error('useAuth must be used inside AuthProvider')
+ return ctx
+}
diff --git a/distribution_fe/eslint.config.mjs b/distribution_fe/eslint.config.mjs
new file mode 100644
index 0000000..05e726d
--- /dev/null
+++ b/distribution_fe/eslint.config.mjs
@@ -0,0 +1,18 @@
+import { defineConfig, globalIgnores } from "eslint/config";
+import nextVitals from "eslint-config-next/core-web-vitals";
+import nextTs from "eslint-config-next/typescript";
+
+const eslintConfig = defineConfig([
+ ...nextVitals,
+ ...nextTs,
+ // Override default ignores of eslint-config-next.
+ globalIgnores([
+ // Default ignores of eslint-config-next:
+ ".next/**",
+ "out/**",
+ "build/**",
+ "next-env.d.ts",
+ ]),
+]);
+
+export default eslintConfig;
diff --git a/distribution_fe/hooks/.gitkeep b/distribution_fe/hooks/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/distribution_fe/hooks/use-mobile.ts b/distribution_fe/hooks/use-mobile.ts
new file mode 100644
index 0000000..2b0fe1d
--- /dev/null
+++ b/distribution_fe/hooks/use-mobile.ts
@@ -0,0 +1,19 @@
+import * as React from "react"
+
+const MOBILE_BREAKPOINT = 768
+
+export function useIsMobile() {
+ const [isMobile, setIsMobile] = React.useState(undefined)
+
+ React.useEffect(() => {
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
+ const onChange = () => {
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
+ }
+ mql.addEventListener("change", onChange)
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
+ return () => mql.removeEventListener("change", onChange)
+ }, [])
+
+ return !!isMobile
+}
diff --git a/distribution_fe/hooks/use-permission.ts b/distribution_fe/hooks/use-permission.ts
new file mode 100644
index 0000000..071a437
--- /dev/null
+++ b/distribution_fe/hooks/use-permission.ts
@@ -0,0 +1,20 @@
+'use client'
+
+import { useAuth } from '@/contexts/auth-context'
+
+export function usePermission(permission: string): boolean {
+ const { permissions } = useAuth()
+ return permissions.includes('*') || permissions.includes(permission)
+}
+
+export function usePermissions(codes: string[]): boolean[] {
+ const { permissions } = useAuth()
+ const isAdmin = permissions.includes('*')
+ return codes.map((code) => isAdmin || permissions.includes(code))
+}
+
+export function useHasAnyPermission(codes: string[]): boolean {
+ const { permissions } = useAuth()
+ if (permissions.includes('*')) return true
+ return codes.some((code) => permissions.includes(code))
+}
diff --git a/distribution_fe/lib/.gitkeep b/distribution_fe/lib/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/distribution_fe/lib/api.ts b/distribution_fe/lib/api.ts
new file mode 100644
index 0000000..5746263
--- /dev/null
+++ b/distribution_fe/lib/api.ts
@@ -0,0 +1,37 @@
+import axios, { type AxiosError } from 'axios'
+
+export const api = axios.create({
+ baseURL: process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:5000',
+ headers: { 'Content-Type': 'application/json' },
+})
+
+// Inject auth token on every request
+api.interceptors.request.use((config) => {
+ // TODO: replace with real token from cookie once auth is implemented
+ const token = typeof window !== 'undefined'
+ ? document.cookie.split('; ').find(r => r.startsWith('access-token='))?.split('=')[1]
+ : null
+ if (token) config.headers.Authorization = `Bearer ${token}`
+ return config
+})
+
+// Normalize error responses
+api.interceptors.response.use(
+ (res) => res,
+ (error: AxiosError<{ error: string }>) => {
+ const status = error.response?.status
+ if (status === 401) {
+ // Redirect to login when auth is implemented
+ if (typeof window !== 'undefined') window.location.href = '/login'
+ }
+ return Promise.reject(error)
+ }
+)
+
+// Helper to extract error message from API response
+export function getApiError(error: unknown): string {
+ if (axios.isAxiosError(error)) {
+ return error.response?.data?.error ?? error.message
+ }
+ return 'An unexpected error occurred'
+}
diff --git a/distribution_fe/lib/utils.ts b/distribution_fe/lib/utils.ts
new file mode 100644
index 0000000..bd0c391
--- /dev/null
+++ b/distribution_fe/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
diff --git a/distribution_fe/next.config.ts b/distribution_fe/next.config.ts
new file mode 100644
index 0000000..f62ca42
--- /dev/null
+++ b/distribution_fe/next.config.ts
@@ -0,0 +1,5 @@
+import type { NextConfig } from "next"
+
+const nextConfig: NextConfig = {}
+
+export default nextConfig
diff --git a/distribution_fe/package-lock.json b/distribution_fe/package-lock.json
new file mode 100644
index 0000000..62bca10
--- /dev/null
+++ b/distribution_fe/package-lock.json
@@ -0,0 +1,9906 @@
+{
+ "name": "distribution_fe",
+ "version": "0.0.1",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "distribution_fe",
+ "version": "0.0.1",
+ "dependencies": {
+ "@base-ui/react": "^1.7.0",
+ "@hugeicons/core-free-icons": "^4.3.0",
+ "@hugeicons/react": "^1.1.10",
+ "axios": "^1.19.0",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "next": "16.2.6",
+ "next-themes": "^0.4.6",
+ "react": "19.2.4",
+ "react-dom": "19.2.4",
+ "shadcn": "^4.19.0",
+ "tailwind-merge": "^3.6.0",
+ "tw-animate-css": "^1.4.0"
+ },
+ "devDependencies": {
+ "@tailwindcss/postcss": "^4",
+ "@types/node": "^20",
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "eslint": "^9",
+ "eslint-config-next": "16.2.6",
+ "prettier": "^3.8.3",
+ "prettier-plugin-tailwindcss": "^0.8.0",
+ "tailwindcss": "^4",
+ "typescript": "^5"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
+ "license": "MIT",
+ "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/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.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
+ "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.8",
+ "@babel/types": "^7.29.8",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz",
+ "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz",
+ "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.29.7",
+ "@babel/helper-member-expression-to-functions": "^7.29.7",
+ "@babel/helper-optimise-call-expression": "^7.29.7",
+ "@babel/helper-replace-supers": "^7.29.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz",
+ "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz",
+ "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
+ "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz",
+ "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-member-expression-to-functions": "^7.29.7",
+ "@babel/helper-optimise-call-expression": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz",
+ "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
+ "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
+ "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.8"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz",
+ "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz",
+ "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz",
+ "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typescript": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz",
+ "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.29.7",
+ "@babel/helper-create-class-features-plugin": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7",
+ "@babel/plugin-syntax-typescript": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-typescript": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.29.7.tgz",
+ "integrity": "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
+ "@babel/plugin-syntax-jsx": "^7.29.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.29.7",
+ "@babel/plugin-transform-typescript": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
+ "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz",
+ "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.8",
+ "@babel/helper-globals": "^7.29.7",
+ "@babel/parser": "^7.29.8",
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.8",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
+ "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@base-ui/react": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.7.0.tgz",
+ "integrity": "sha512-j+8QjX44C32jrXD/qyEAGpFr70FRpGL2CY61mQd9nBPWN737CK0xxD1ceJ055rW4RtdvFDT1e7otzdlfxvsYug==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.29.2",
+ "@base-ui/utils": "0.3.2",
+ "@floating-ui/react-dom": "^2.1.9",
+ "@floating-ui/utils": "^0.2.12",
+ "use-sync-external-store": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@date-fns/tz": "^1.2.0",
+ "@types/react": "^17 || ^18 || ^19",
+ "date-fns": "^4.0.0",
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ },
+ "peerDependenciesMeta": {
+ "@date-fns/tz": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ },
+ "date-fns": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@base-ui/utils": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.3.2.tgz",
+ "integrity": "sha512-oWy1aq/I2GmYjpl4PhEAhzflF8VPGKgZeq0xAWTbfD5KBWyxcN0ZP2+WHSUm/5Z6lVMBDLReLcoXwSYoRc/zNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.29.2",
+ "@floating-ui/utils": "^0.2.12",
+ "reselect": "^5.2.0",
+ "use-sync-external-store": "^1.6.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^17 || ^18 || ^19",
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@dotenvx/dotenvx": {
+ "version": "1.75.1",
+ "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.75.1.tgz",
+ "integrity": "sha512-/BITOC9dmS/edY2zQwZNicQ059O6RKabtQfyEafV0nGtfYRNHYy1DIPiYVcov40+tob9hfmBnbR963dS+EQ1DQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@dotenvx/primitives": "^0.8.0",
+ "commander": "^11.1.0",
+ "conf": "^10.2.0",
+ "dotenv": "^17.2.1",
+ "enquirer": "^2.4.1",
+ "env-paths": "^2.2.1",
+ "execa": "^5.1.1",
+ "fdir": "^6.2.0",
+ "ignore": "^5.3.0",
+ "object-treeify": "1.1.33",
+ "open": "^8.4.2",
+ "picomatch": "^4.0.4",
+ "systeminformation": "^5.22.11",
+ "undici": "^7.11.0",
+ "which": "^4.0.0",
+ "yocto-spinner": "^1.1.0"
+ },
+ "bin": {
+ "dotenvx": "src/cli/dotenvx.js"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/isexe": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz",
+ "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/open": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "license": "MIT",
+ "dependencies": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/picomatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "license": "ISC"
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@dotenvx/dotenvx/node_modules/which": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
+ "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^3.1.1"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@dotenvx/primitives": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@dotenvx/primitives/-/primitives-0.8.0.tgz",
+ "integrity": "sha512-VYJy0uhFm9zTJ1TxBaW/pA8bjbOM/OttaNMwZ1RHG4JKyRG7DhSdiqD1ipQoAyoD22olUtxbP78W9xY3Wd11bg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
+ "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.1",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
+ "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz",
+ "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
+ "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.5"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz",
+ "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.14.0",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.3.0",
+ "minimatch": "^3.1.5",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.5",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz",
+ "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz",
+ "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.12"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz",
+ "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.8.0",
+ "@floating-ui/utils": "^0.2.12"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.9",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz",
+ "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.8.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.12",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz",
+ "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==",
+ "license": "MIT"
+ },
+ "node_modules/@hono/node-server": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.1.tgz",
+ "integrity": "sha512-ELuehkj5VCBdgEw9zs+ivkKwyzzUCSQuE96YmiPvn1ECBoZCczbFXJLeEGMTYjphP6gydh4pHMqEYPVMYUVgQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ },
+ "peerDependencies": {
+ "hono": "^4"
+ }
+ },
+ "node_modules/@hugeicons/core-free-icons": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@hugeicons/core-free-icons/-/core-free-icons-4.3.0.tgz",
+ "integrity": "sha512-5DC5gq2psNDKBQThOjpuFCtMco8nl2FkrBzZgG15cFGM0kSwUoych/pw0DmjBygF9qRDITdBPtmzJqLsOeImMg==",
+ "license": "MIT"
+ },
+ "node_modules/@hugeicons/react": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@hugeicons/react/-/react-1.1.10.tgz",
+ "integrity": "sha512-9tAsd92yMVVGP+E+d8cM+wc0VnXuYZHNbWQi7TOe8k2neawmhiaFmVFbzyruejhOMa197/LbgvSED32ayUo3ZA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=16.0.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
+ "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/types": "^0.15.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz",
+ "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.2",
+ "@humanfs/types": "^0.15.0",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/types": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz",
+ "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@img/colour": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
+ "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
+ "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
+ "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
+ "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
+ "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
+ "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
+ "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
+ "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
+ "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.7.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
+ "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@modelcontextprotocol/sdk": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz",
+ "integrity": "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==",
+ "license": "MIT",
+ "dependencies": {
+ "@hono/node-server": "^1.19.9 || ^2.0.5",
+ "ajv": "^8.17.1",
+ "ajv-formats": "^3.0.1",
+ "content-type": "^1.0.5",
+ "cors": "^2.8.5",
+ "cross-spawn": "^7.0.5",
+ "eventsource": "^3.0.2",
+ "eventsource-parser": "^3.0.0",
+ "express": "^5.2.1",
+ "express-rate-limit": "^8.2.1",
+ "hono": "^4.11.4",
+ "jose": "^6.1.3",
+ "json-schema-typed": "^8.0.2",
+ "pkce-challenge": "^5.0.0",
+ "raw-body": "^3.0.0",
+ "zod": "^3.25 || ^4.0",
+ "zod-to-json-schema": "^3.25.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@cfworker/json-schema": "^4.1.1",
+ "zod": "^3.25 || ^4.0"
+ },
+ "peerDependenciesMeta": {
+ "@cfworker/json-schema": {
+ "optional": true
+ },
+ "zod": {
+ "optional": false
+ }
+ }
+ },
+ "node_modules/@modelcontextprotocol/sdk/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@modelcontextprotocol/sdk/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "license": "MIT"
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz",
+ "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tybys/wasm-util": "^0.10.3"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
+ },
+ "peerDependencies": {
+ "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4",
+ "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.6.tgz",
+ "integrity": "sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw==",
+ "license": "MIT"
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.2.6.tgz",
+ "integrity": "sha512-Z8l6o4JWKUl755x4R+wogD86KPeU+Ckw4K+SYG4kHeOJtRenDeK+OSbGcqZpDtbwn9DsJVdir2UxmwXuinUbUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-glob": "3.3.1"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.6.tgz",
+ "integrity": "sha512-ZJGkkcNfYgrrMkqOdZ7zoLa1TOy0qpcMfk/z4Mh/FKUz40gVO+HNQWqmLxf67Z5WB64DRp0dhEbyHfel+6sJUg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.6.tgz",
+ "integrity": "sha512-v/YLBHIY132Ced3puBJ7YJKw1lqsCrgcNo2aRJlCEyQrrCeRJlvGlnmxhPxNQI3KE3N1DN5r9TPNPvka3nq5RQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.6.tgz",
+ "integrity": "sha512-RPOvqlYBbcQjkz9VQQDZ2T2bARIjXZV1KFlt+V2Mr6SW/e4I9fcKsaA0hdyf2FHoTlsV2xnBd5Y912rP/1Ce6w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.6.tgz",
+ "integrity": "sha512-URUTu1+dMkxJsPFgm+OeEvq9wf5sujw0EvgYy80TDGHTSLTnIHeqb0Eu8A3sC95IRgjejQL+kC4mw+4yPxiAXA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.6.tgz",
+ "integrity": "sha512-DOj182mPV8G3UkrayLoREM5YEYI+Dk5wv7Ox9xl1fFibAELEsFD0lDPfHIeILlutMMfdyhlzYPELG3peuKaurw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.6.tgz",
+ "integrity": "sha512-HKQ5SP/V/ub73UvF7n/zeJlxk2kLmtL7Wzrg4WfmkjmNos5onJ2tKu7yZOPdL18A6Svfn3max29ym+ry7NkK4g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.6.tgz",
+ "integrity": "sha512-LZXpTlPyS5v7HhSmnvsLGP3iIYgYOBnc8r8ArlT55sGHV89bR2HlDdBjWQ+PY6SJMmk8TuVGFuxalnP3k/0Dwg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.6.tgz",
+ "integrity": "sha512-F0+4i0h9J6C4eE3EAPWsoCk7UW/dbzOjyzxY0qnDUOYFu6FFmdZ6l97/XdV3/Nz3VYyO7UWjyEJUXkGqcoXfMA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nolyfill/is-core-module": {
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
+ "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.4.0"
+ }
+ },
+ "node_modules/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sec-ant/readable-stream": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
+ "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==",
+ "license": "MIT"
+ },
+ "node_modules/@sindresorhus/merge-streams": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz",
+ "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@tailwindcss/node": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz",
+ "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.5",
+ "enhanced-resolve": "^5.24.1",
+ "jiti": "^2.7.0",
+ "lightningcss": "1.32.0",
+ "magic-string": "^0.30.21",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.3.3"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz",
+ "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.3.3",
+ "@tailwindcss/oxide-darwin-arm64": "4.3.3",
+ "@tailwindcss/oxide-darwin-x64": "4.3.3",
+ "@tailwindcss/oxide-freebsd-x64": "4.3.3",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.3.3",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.3.3",
+ "@tailwindcss/oxide-linux-x64-musl": "4.3.3",
+ "@tailwindcss/oxide-wasm32-wasi": "4.3.3",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.3.3"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz",
+ "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz",
+ "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz",
+ "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz",
+ "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz",
+ "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz",
+ "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz",
+ "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz",
+ "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz",
+ "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz",
+ "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.11.1",
+ "@emnapi/runtime": "^1.11.1",
+ "@emnapi/wasi-threads": "^1.2.2",
+ "@napi-rs/wasm-runtime": "^1.1.4",
+ "@tybys/wasm-util": "^0.10.2",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz",
+ "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz",
+ "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/postcss": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz",
+ "integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "@tailwindcss/node": "4.3.3",
+ "@tailwindcss/oxide": "4.3.3",
+ "postcss": "^8.5.16",
+ "tailwindcss": "4.3.3"
+ }
+ },
+ "node_modules/@ts-morph/common": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.27.0.tgz",
+ "integrity": "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-glob": "^3.3.3",
+ "minimatch": "^10.0.1",
+ "path-browserify": "^1.0.1"
+ }
+ },
+ "node_modules/@ts-morph/common/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@ts-morph/common/node_modules/brace-expansion": {
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@ts-morph/common/node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/@ts-morph/common/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@ts-morph/common/node_modules/minimatch": {
+ "version": "10.2.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz",
+ "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.8"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz",
+ "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "20.19.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
+ "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.18",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz",
+ "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.5",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz",
+ "integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
+ "node_modules/@types/validate-npm-package-name": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/validate-npm-package-name/-/validate-npm-package-name-4.0.2.tgz",
+ "integrity": "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==",
+ "license": "MIT"
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.68.0.tgz",
+ "integrity": "sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.12.2",
+ "@typescript-eslint/scope-manager": "8.68.0",
+ "@typescript-eslint/type-utils": "8.68.0",
+ "@typescript-eslint/utils": "8.68.0",
+ "@typescript-eslint/visitor-keys": "8.68.0",
+ "ignore": "^7.0.5",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.68.0",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz",
+ "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.68.0.tgz",
+ "integrity": "sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.68.0",
+ "@typescript-eslint/types": "8.68.0",
+ "@typescript-eslint/typescript-estree": "8.68.0",
+ "@typescript-eslint/visitor-keys": "8.68.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.68.0.tgz",
+ "integrity": "sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.68.0",
+ "@typescript-eslint/types": "^8.68.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.68.0.tgz",
+ "integrity": "sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.68.0",
+ "@typescript-eslint/visitor-keys": "8.68.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.68.0.tgz",
+ "integrity": "sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.68.0.tgz",
+ "integrity": "sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.68.0",
+ "@typescript-eslint/typescript-estree": "8.68.0",
+ "@typescript-eslint/utils": "8.68.0",
+ "debug": "^4.4.3",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz",
+ "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.68.0.tgz",
+ "integrity": "sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.68.0",
+ "@typescript-eslint/tsconfig-utils": "8.68.0",
+ "@typescript-eslint/types": "8.68.0",
+ "@typescript-eslint/visitor-keys": "8.68.0",
+ "debug": "^4.4.3",
+ "minimatch": "^10.2.2",
+ "semver": "^7.7.3",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "10.2.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz",
+ "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.8"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.68.0.tgz",
+ "integrity": "sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.9.1",
+ "@typescript-eslint/scope-manager": "8.68.0",
+ "@typescript-eslint/types": "8.68.0",
+ "@typescript-eslint/typescript-estree": "8.68.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.68.0.tgz",
+ "integrity": "sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.68.0",
+ "eslint-visitor-keys": "^5.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-android-arm-eabi": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz",
+ "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-android-arm64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz",
+ "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-arm64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz",
+ "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-x64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz",
+ "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-freebsd-x64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz",
+ "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz",
+ "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz",
+ "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz",
+ "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz",
+ "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-loong64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz",
+ "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-loong64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz",
+ "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz",
+ "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz",
+ "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz",
+ "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz",
+ "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz",
+ "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz",
+ "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-openharmony-arm64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz",
+ "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz",
+ "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "1.10.0",
+ "@emnapi/runtime": "1.10.0",
+ "@napi-rs/wasm-runtime": "^1.1.4"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
+ "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz",
+ "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz",
+ "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz",
+ "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/accepts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "^3.0.0",
+ "negotiator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
+ "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
+ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
+ "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ajv-formats/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "license": "MIT"
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
+ "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "get-intrinsic": "^1.3.0",
+ "is-string": "^1.1.1",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
+ "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-shim-unscopables": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ast-types": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
+ "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ast-types-flow": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
+ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/atomically": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz",
+ "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axe-core": {
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz",
+ "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz",
+ "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.16.0",
+ "form-data": "^4.0.6",
+ "https-proxy-agent": "^5.0.1",
+ "proxy-from-env": "^2.1.0"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.11.19",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz",
+ "integrity": "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==",
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz",
+ "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "^3.1.2",
+ "content-type": "^2.0.0",
+ "debug": "^4.4.3",
+ "http-errors": "^2.0.1",
+ "iconv-lite": "^0.7.2",
+ "on-finished": "^2.4.1",
+ "qs": "^6.15.2",
+ "raw-body": "^3.0.2",
+ "type-is": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/body-parser/node_modules/content-type": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz",
+ "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.18",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
+ "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.8",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz",
+ "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.11.12",
+ "caniuse-lite": "^1.0.30001809",
+ "electron-to-chromium": "^1.5.402",
+ "node-releases": "^2.0.53",
+ "update-browserslist-db": "^1.3.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bundle-name": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
+ "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
+ "license": "MIT",
+ "dependencies": {
+ "run-applescript": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz",
+ "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "get-intrinsic": "^1.3.0",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001810",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz",
+ "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/class-variance-authority": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://polar.sh/cva"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
+ "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/code-block-writer": {
+ "version": "13.0.3",
+ "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz",
+ "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==",
+ "license": "MIT"
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "14.0.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
+ "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/conf": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/conf/-/conf-10.2.0.tgz",
+ "integrity": "sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.6.3",
+ "ajv-formats": "^2.1.1",
+ "atomically": "^1.7.0",
+ "debounce-fn": "^4.0.0",
+ "dot-prop": "^6.0.1",
+ "env-paths": "^2.2.1",
+ "json-schema-typed": "^7.0.3",
+ "onetime": "^5.1.2",
+ "pkg-up": "^3.1.0",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/conf/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/conf/node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/conf/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "license": "MIT"
+ },
+ "node_modules/conf/node_modules/json-schema-typed": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz",
+ "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/conf/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
+ "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.6.0"
+ }
+ },
+ "node_modules/cors": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/cosmiconfig": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz",
+ "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==",
+ "license": "MIT",
+ "dependencies": {
+ "env-paths": "^2.2.1",
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/debounce-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz",
+ "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz",
+ "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/default-browser": {
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.1.tgz",
+ "integrity": "sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==",
+ "license": "MIT",
+ "dependencies": {
+ "bundle-name": "^4.1.0",
+ "default-browser-id": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser-id": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz",
+ "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz",
+ "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dot-prop": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
+ "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
+ "license": "MIT",
+ "dependencies": {
+ "is-obj": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "17.4.2",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
+ "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.414",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.414.tgz",
+ "integrity": "sha512-aYlviXiaXBbzvKgyALpcMmqa3Np3sDr0XnZbEG62n2UpZFbEcjQ4EEMOLGzVPhwVnwTz0lvKY+GcARbunuHekw==",
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.24.5",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz",
+ "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/enquirer": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
+ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-colors": "^4.1.1",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.24.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz",
+ "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.2",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.2.1",
+ "is-set": "^2.0.3",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.1",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.4",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.4",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "stop-iteration-iterator": "^1.1.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.19"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-abstract-get": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz",
+ "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.2",
+ "is-callable": "^1.2.7",
+ "object-inspect": "^1.13.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz",
+ "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.2",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.1.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.3.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "iterator.prototype": "^1.1.5",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz",
+ "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-abstract-get": "^1.0.0",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.1.0",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.5",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz",
+ "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==",
+ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.2",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.6",
+ "@eslint/js": "9.39.5",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.5",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-config-next": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.2.6.tgz",
+ "integrity": "sha512-z2ELYSkyrrJ6cuunTU8vhsT/RpouPkjaSah06nVW6Rg2Hpg0Vs8s497/e5s8G8qtdp4ccsiovz5P1rv+5VSW2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@next/eslint-plugin-next": "16.2.6",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.32.0",
+ "eslint-plugin-jsx-a11y": "^6.10.0",
+ "eslint-plugin-react": "^7.37.0",
+ "eslint-plugin-react-hooks": "^7.0.0",
+ "globals": "16.4.0",
+ "typescript-eslint": "^8.46.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=9.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-config-next/node_modules/globals": {
+ "version": "16.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
+ "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.10",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz",
+ "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.16.1",
+ "resolve": "^2.0.0-next.6"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz",
+ "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@nolyfill/is-core-module": "1.0.39",
+ "debug": "^4.4.0",
+ "get-tsconfig": "^4.10.0",
+ "is-bun-module": "^2.0.0",
+ "stable-hash": "^0.0.5",
+ "tinyglobby": "^0.2.13",
+ "unrs-resolver": "^1.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-import-resolver-typescript"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*",
+ "eslint-plugin-import-x": "*"
+ },
+ "peerDependenciesMeta": {
+ "eslint-plugin-import": {
+ "optional": true
+ },
+ "eslint-plugin-import-x": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz",
+ "integrity": "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.32.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
+ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rtsao/scc": "^1.1.0",
+ "array-includes": "^3.1.9",
+ "array.prototype.findlastindex": "^1.2.6",
+ "array.prototype.flat": "^1.3.3",
+ "array.prototype.flatmap": "^1.3.3",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.12.1",
+ "hasown": "^2.0.2",
+ "is-core-module": "^2.16.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "object.groupby": "^1.0.3",
+ "object.values": "^1.2.1",
+ "semver": "^6.3.1",
+ "string.prototype.trimend": "^1.0.9",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
+ "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "aria-query": "^5.3.2",
+ "array-includes": "^3.1.8",
+ "array.prototype.flatmap": "^1.3.2",
+ "ast-types-flow": "^0.0.8",
+ "axe-core": "^4.10.0",
+ "axobject-query": "^4.1.0",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^3.3.5",
+ "language-tags": "^1.0.9",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.includes": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.37.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
+ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.3",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.2.1",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.9",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.12",
+ "string.prototype.repeat": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz",
+ "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/parser": "^7.24.4",
+ "hermes-parser": "^0.25.1",
+ "zod": "^3.25.0 || ^4.0.0",
+ "zod-validation-error": "^3.5.0 || ^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/eventsource": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
+ "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
+ "license": "MIT",
+ "dependencies": {
+ "eventsource-parser": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/eventsource-parser": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.1.tgz",
+ "integrity": "sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/execa": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz",
+ "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==",
+ "license": "MIT",
+ "dependencies": {
+ "@sindresorhus/merge-streams": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "figures": "^6.1.0",
+ "get-stream": "^9.0.0",
+ "human-signals": "^8.0.1",
+ "is-plain-obj": "^4.1.0",
+ "is-stream": "^4.0.1",
+ "npm-run-path": "^6.0.0",
+ "pretty-ms": "^9.2.0",
+ "signal-exit": "^4.1.0",
+ "strip-final-newline": "^4.0.0",
+ "yoctocolors": "^2.1.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.5.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/express": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.1",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "finalhandler": "^2.1.0",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "merge-descriptors": "^2.0.0",
+ "mime-types": "^3.0.0",
+ "on-finished": "^2.4.1",
+ "once": "^1.4.0",
+ "parseurl": "^1.3.3",
+ "proxy-addr": "^2.0.7",
+ "qs": "^6.14.0",
+ "range-parser": "^1.2.1",
+ "router": "^2.2.0",
+ "send": "^1.1.0",
+ "serve-static": "^2.2.0",
+ "statuses": "^2.0.1",
+ "type-is": "^2.0.1",
+ "vary": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/express-rate-limit": {
+ "version": "8.6.2",
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.6.2.tgz",
+ "integrity": "sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "ip-address": "^10.2.0"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/express-rate-limit"
+ },
+ "peerDependencies": {
+ "express": ">= 4.11"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "license": "MIT"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.6.tgz",
+ "integrity": "sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fastq": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/figures": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz",
+ "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-unicode-supported": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "on-finished": "^2.4.1",
+ "parseurl": "^1.3.3",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz",
+ "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "11.4.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz",
+ "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==",
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz",
+ "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2",
+ "hasown": "^2.0.4",
+ "is-callable": "^1.2.7",
+ "is-document.all": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/fuzzysort": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-3.1.0.tgz",
+ "integrity": "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==",
+ "license": "MIT"
+ },
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
+ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-east-asian-width": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz",
+ "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-own-enumerable-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-own-enumerable-keys/-/get-own-enumerable-keys-1.0.0.tgz",
+ "integrity": "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
+ "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
+ "license": "MIT",
+ "dependencies": {
+ "@sec-ant/readable-stream": "^0.4.1",
+ "is-stream": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.14.3",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz",
+ "integrity": "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "license": "ISC"
+ },
+ "node_modules/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
+ "node_modules/hono": {
+ "version": "4.13.4",
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.4.tgz",
+ "integrity": "sha512-AGEwKIyRMHRv1t8Wjwa3LHxQ61X5CqrdFT+4BRNTpqS5aJNnpl5WLjADb7vFlJzI/8uK7T5QLVApCMQKNa3LgQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.9.0"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz",
+ "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz",
+ "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ip-address": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz",
+ "integrity": "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "license": "MIT"
+ },
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bun-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
+ "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.7.1"
+ }
+ },
+ "node_modules/is-bun-module/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-document.all": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz",
+ "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
+ "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-in-ssh": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz",
+ "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-interactive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz",
+ "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "license": "MIT"
+ },
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-regexp": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-3.1.0.tgz",
+ "integrity": "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
+ "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz",
+ "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz",
+ "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-inside-container": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
+ "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/jose": {
+ "version": "6.2.10",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.10.tgz",
+ "integrity": "sha512-iiW7J9qRFlGxvCOIBDBDxFePQSn7ZMAnrYGhrrOo6siO/MIqwfyilLR27pkfDgUk+raLuzADS8A3S/KLBisc0g==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
+ "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodeca"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-typed": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz",
+ "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz",
+ "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
+ "license": "MIT",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.23",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
+ "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "language-subtag-registry": "^0.3.20"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
+ "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.32.0",
+ "lightningcss-darwin-arm64": "1.32.0",
+ "lightningcss-darwin-x64": "1.32.0",
+ "lightningcss-freebsd-x64": "1.32.0",
+ "lightningcss-linux-arm-gnueabihf": "1.32.0",
+ "lightningcss-linux-arm64-gnu": "1.32.0",
+ "lightningcss-linux-arm64-musl": "1.32.0",
+ "lightningcss-linux-x64-gnu": "1.32.0",
+ "lightningcss-linux-x64-musl": "1.32.0",
+ "lightningcss-win32-arm64-msvc": "1.32.0",
+ "lightningcss-win32-x64-msvc": "1.32.0"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
+ "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
+ "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
+ "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
+ "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
+ "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
+ "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
+ "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
+ "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
+ "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
+ "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
+ "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/log-symbols": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz",
+ "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^5.3.0",
+ "is-unicode-supported": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/is-unicode-supported": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
+ "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.1.tgz",
+ "integrity": "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "license": "MIT"
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz",
+ "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mimic-function": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
+ "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/napi-postinstall": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
+ "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "napi-postinstall": "lib/cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/napi-postinstall"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/negotiator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz",
+ "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==",
+ "license": "MIT",
+ "dependencies": {
+ "content-type": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/negotiator/node_modules/content-type": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz",
+ "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/next": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.2.6.tgz",
+ "integrity": "sha512-qOVgKJg1+At15NpeUP+eJgCHvTCgXsogweq87Ri/Ix7PkqQHg4sdaXmSFqKlgaIXE4kW0g25LE68W87UANlHtw==",
+ "license": "MIT",
+ "dependencies": {
+ "@next/env": "16.2.6",
+ "@swc/helpers": "0.5.15",
+ "baseline-browser-mapping": "^2.9.19",
+ "caniuse-lite": "^1.0.30001579",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.6"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "16.2.6",
+ "@next/swc-darwin-x64": "16.2.6",
+ "@next/swc-linux-arm64-gnu": "16.2.6",
+ "@next/swc-linux-arm64-musl": "16.2.6",
+ "@next/swc-linux-x64-gnu": "16.2.6",
+ "@next/swc-linux-x64-musl": "16.2.6",
+ "@next/swc-win32-arm64-msvc": "16.2.6",
+ "@next/swc-win32-x64-msvc": "16.2.6",
+ "sharp": "^0.34.5"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "@playwright/test": "^1.51.1",
+ "babel-plugin-react-compiler": "*",
+ "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
+ "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@playwright/test": {
+ "optional": true
+ },
+ "babel-plugin-react-compiler": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/next-themes": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz",
+ "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/next/node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/node-exports-info": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz",
+ "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array.prototype.flatmap": "^1.3.3",
+ "es-errors": "^1.3.0",
+ "object.entries": "^1.1.9",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.53",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz",
+ "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz",
+ "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^4.0.0",
+ "unicorn-magic": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-run-path/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object-treeify": {
+ "version": "1.1.33",
+ "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz",
+ "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
+ "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
+ "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/onetime/node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/open": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/open/-/open-11.0.1.tgz",
+ "integrity": "sha512-NzwMUB6C1D0+Kd+9iMS/H4k+Ck3cTX6Ckyfr/gAGlmvSE1LUQZnEZvWBi4PYmMwH/S5SMeTXnE+9uAz8uF+pWw==",
+ "license": "MIT",
+ "dependencies": {
+ "default-browser": "^5.4.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-in-ssh": "^1.0.0",
+ "is-inside-container": "^1.0.0",
+ "powershell-utils": "^0.2.0",
+ "wsl-utils": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ora": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz",
+ "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^5.3.0",
+ "cli-cursor": "^5.0.0",
+ "cli-spinners": "^2.9.2",
+ "is-interactive": "^2.0.0",
+ "is-unicode-supported": "^2.0.0",
+ "log-symbols": "^6.0.0",
+ "stdin-discarder": "^0.2.2",
+ "string-width": "^7.2.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ora/node_modules/ansi-regex": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz",
+ "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ora/node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/ora/node_modules/strip-ansi": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.2.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/own-keys": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz",
+ "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4",
+ "get-intrinsic": "^1.3.0",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse-ms": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
+ "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-browserify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
+ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+ "license": "MIT"
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
+ "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pkce-challenge": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz",
+ "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/pkg-up": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
+ "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-up/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-up/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-up/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-up/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-up/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.26",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
+ "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.17",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz",
+ "integrity": "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==",
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/powershell-utils": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.2.0.tgz",
+ "integrity": "sha512-ZlsFlG7MtSFCoc5xreOvBAozCJ6Pf06opgJjh9ONEv418xpZSAzNjstD36C6+JwOnfSqOW/9uDkqKjezTdxZhw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.9.6",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz",
+ "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-plugin-tailwindcss": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.8.1.tgz",
+ "integrity": "sha512-iaFMYqDsE4ffdDkn5qup0j5f2aCEBFZrdrZnvu9QKTlWx/iGPeQ4HHu7b7fCPMxeo9nwQBiOAh2nSypdFYWJkw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.19"
+ },
+ "peerDependencies": {
+ "@ianvs/prettier-plugin-sort-imports": "*",
+ "@prettier/plugin-hermes": "*",
+ "@prettier/plugin-oxc": "*",
+ "@prettier/plugin-pug": "*",
+ "@shopify/prettier-plugin-liquid": "*",
+ "@trivago/prettier-plugin-sort-imports": "*",
+ "@zackad/prettier-plugin-twig": "*",
+ "prettier": "^3.0",
+ "prettier-plugin-astro": "*",
+ "prettier-plugin-css-order": "*",
+ "prettier-plugin-jsdoc": "*",
+ "prettier-plugin-marko": "*",
+ "prettier-plugin-multiline-arrays": "*",
+ "prettier-plugin-organize-attributes": "*",
+ "prettier-plugin-organize-imports": "*",
+ "prettier-plugin-sort-imports": "*",
+ "prettier-plugin-svelte": "*"
+ },
+ "peerDependenciesMeta": {
+ "@ianvs/prettier-plugin-sort-imports": {
+ "optional": true
+ },
+ "@prettier/plugin-hermes": {
+ "optional": true
+ },
+ "@prettier/plugin-oxc": {
+ "optional": true
+ },
+ "@prettier/plugin-pug": {
+ "optional": true
+ },
+ "@shopify/prettier-plugin-liquid": {
+ "optional": true
+ },
+ "@trivago/prettier-plugin-sort-imports": {
+ "optional": true
+ },
+ "@zackad/prettier-plugin-twig": {
+ "optional": true
+ },
+ "prettier-plugin-astro": {
+ "optional": true
+ },
+ "prettier-plugin-css-order": {
+ "optional": true
+ },
+ "prettier-plugin-jsdoc": {
+ "optional": true
+ },
+ "prettier-plugin-marko": {
+ "optional": true
+ },
+ "prettier-plugin-multiline-arrays": {
+ "optional": true
+ },
+ "prettier-plugin-organize-attributes": {
+ "optional": true
+ },
+ "prettier-plugin-organize-imports": {
+ "optional": true
+ },
+ "prettier-plugin-sort-imports": {
+ "optional": true
+ },
+ "prettier-plugin-svelte": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pretty-ms": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz",
+ "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==",
+ "license": "MIT",
+ "dependencies": {
+ "parse-ms": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/prompts/node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.15.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
+ "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "es-define-property": "^1.0.1",
+ "side-channel": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/range-parser": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz",
+ "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.7.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
+ "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
+ "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.4"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/recast": {
+ "version": "0.23.21",
+ "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.21.tgz",
+ "integrity": "sha512-mFAyJq9vUbSTARLZUvAEf1z3YxlvAwswbmxMx2mPA/MSm4KmpwvwvhsH/NIrZhyOuwD60Lzyw2qh83uCbgTPYw==",
+ "license": "MIT",
+ "dependencies": {
+ "ast-types": "^0.16.1",
+ "esprima": "~4.0.0",
+ "source-map": "~0.6.1",
+ "tiny-invariant": "^1.3.3",
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
+ "which-builtin-type": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/reselect": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.3.0.tgz",
+ "integrity": "sha512-XGoLeRAVzUTcJ1qkxPQhDJyIZ5d6zzZD9nT7AEZOaaU9UbWclhycElmhO+VD5bFeLuzhPBaOV2oXC8uG35ZSpg==",
+ "license": "MIT"
+ },
+ "node_modules/resolve": {
+ "version": "2.0.0-next.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
+ "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.2",
+ "node-exports-info": "^1.6.0",
+ "object-keys": "^1.1.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
+ "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^7.0.0",
+ "signal-exit": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/onetime": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
+ "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-function": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/router": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "is-promise": "^4.0.0",
+ "parseurl": "^1.3.3",
+ "path-to-regexp": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz",
+ "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz",
+ "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "get-intrinsic": "^1.3.0",
+ "has-symbols": "^1.1.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-push-apply": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.1",
+ "mime-types": "^3.0.2",
+ "ms": "^2.1.3",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "statuses": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
+ "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "parseurl": "^1.3.3",
+ "send": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-proto": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+ "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/shadcn": {
+ "version": "4.19.0",
+ "resolved": "https://registry.npmjs.org/shadcn/-/shadcn-4.19.0.tgz",
+ "integrity": "sha512-EQF6R+CUXTsEP2BpyhxrUEAFesrtFD1POvVOf5jM+wkgtA4kG1EW1+1Wlmi9LqiprSL681JJXBcS0u8WkVVVyQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.28.0",
+ "@babel/parser": "^7.28.0",
+ "@babel/plugin-transform-typescript": "^7.28.0",
+ "@babel/preset-typescript": "^7.27.1",
+ "@dotenvx/dotenvx": "^1.48.4",
+ "@modelcontextprotocol/sdk": "^1.26.0",
+ "@types/validate-npm-package-name": "^4.0.2",
+ "browserslist": "^4.26.2",
+ "commander": "^14.0.0",
+ "cosmiconfig": "^9.0.0",
+ "dedent": "^1.6.0",
+ "deepmerge": "^4.3.1",
+ "diff": "^8.0.2",
+ "execa": "^9.6.0",
+ "fast-glob": "^3.3.3",
+ "fs-extra": "^11.3.1",
+ "fuzzysort": "^3.1.0",
+ "kleur": "^4.1.5",
+ "open": "^11.0.0",
+ "ora": "^8.2.0",
+ "postcss": "^8.5.6",
+ "postcss-selector-parser": "^7.1.0",
+ "prompts": "^2.4.2",
+ "recast": "^0.23.11",
+ "socks": "^2.8.8",
+ "stringify-object": "^5.0.0",
+ "tailwind-merge": "^3.0.1",
+ "ts-morph": "^26.0.0",
+ "tsconfig-paths": "^4.2.0",
+ "undici": "^7.27.2",
+ "validate-npm-package-name": "^7.0.1",
+ "zod": "^3.24.1",
+ "zod-to-json-schema": "^3.24.6"
+ },
+ "bin": {
+ "shadcn": "dist/index.js"
+ },
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "node_modules/shadcn/node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/shadcn/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/shadcn/node_modules/tsconfig-paths": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
+ "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==",
+ "license": "MIT",
+ "dependencies": {
+ "json5": "^2.2.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/shadcn/node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/sharp": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
+ "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@img/colour": "^1.0.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.34.5",
+ "@img/sharp-darwin-x64": "0.34.5",
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
+ "@img/sharp-libvips-linux-arm": "1.2.4",
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
+ "@img/sharp-libvips-linux-x64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
+ "@img/sharp-linux-arm": "0.34.5",
+ "@img/sharp-linux-arm64": "0.34.5",
+ "@img/sharp-linux-ppc64": "0.34.5",
+ "@img/sharp-linux-riscv64": "0.34.5",
+ "@img/sharp-linux-s390x": "0.34.5",
+ "@img/sharp-linux-x64": "0.34.5",
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
+ "@img/sharp-linuxmusl-x64": "0.34.5",
+ "@img/sharp-wasm32": "0.34.5",
+ "@img/sharp-win32-arm64": "0.34.5",
+ "@img/sharp-win32-ia32": "0.34.5",
+ "@img/sharp-win32-x64": "0.34.5"
+ }
+ },
+ "node_modules/sharp/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "license": "ISC",
+ "optional": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
+ "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4",
+ "side-channel-list": "^1.0.1",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "license": "MIT"
+ },
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz",
+ "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==",
+ "license": "MIT",
+ "dependencies": {
+ "ip-address": "^10.1.1",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stable-hash": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
+ "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/stdin-discarder": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz",
+ "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/stop-iteration-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
+ "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "internal-slot": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz",
+ "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/emoji-regex": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
+ "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
+ "license": "MIT"
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.2.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/string.prototype.includes": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
+ "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
+ "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "regexp.prototype.flags": "^1.5.3",
+ "set-function-name": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.repeat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
+ "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz",
+ "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "define-data-property": "^1.1.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.2",
+ "es-object-atoms": "^1.1.2",
+ "has-property-descriptors": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz",
+ "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/stringify-object": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-5.0.0.tgz",
+ "integrity": "sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "get-own-enumerable-keys": "^1.0.0",
+ "is-obj": "^3.0.0",
+ "is-regexp": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/yeoman/stringify-object?sponsor=1"
+ }
+ },
+ "node_modules/stringify-object/node_modules/is-obj": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-3.0.0.tgz",
+ "integrity": "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz",
+ "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/styled-jsx": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
+ "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
+ "license": "MIT",
+ "dependencies": {
+ "client-only": "0.0.1"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/systeminformation": {
+ "version": "5.33.2",
+ "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.33.2.tgz",
+ "integrity": "sha512-T0w9cJPXe0AVMOukHTBNMrqU9mf3LdRR6dxLdnNbM9LdKEcH5yWT5FEN7ljvgh4cjliLy7pICtViQtVeYqaZxg==",
+ "license": "MIT",
+ "os": [
+ "darwin",
+ "linux",
+ "win32",
+ "freebsd",
+ "openbsd",
+ "netbsd",
+ "sunos",
+ "android"
+ ],
+ "bin": {
+ "systeminformation": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "funding": {
+ "type": "Buy me a coffee",
+ "url": "https://www.buymeacoffee.com/systeminfo"
+ }
+ },
+ "node_modules/tailwind-merge": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz",
+ "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz",
+ "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tapable": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+ "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
+ "license": "MIT"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/ts-api-utils": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+ "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
+ "node_modules/ts-morph": {
+ "version": "26.0.0",
+ "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-26.0.0.tgz",
+ "integrity": "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug==",
+ "license": "MIT",
+ "dependencies": {
+ "@ts-morph/common": "~0.27.0",
+ "code-block-writer": "^13.0.3"
+ }
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/tw-animate-css": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz",
+ "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Wombosvideo"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz",
+ "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==",
+ "license": "MIT",
+ "dependencies": {
+ "content-type": "^2.0.0",
+ "media-typer": "^1.1.0",
+ "mime-types": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/type-is/node_modules/content-type": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz",
+ "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+ "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+ "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "reflect.getprototypeof": "^1.0.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz",
+ "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.9",
+ "for-each": "^0.3.5",
+ "gopd": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "possible-typed-array-names": "^1.1.0",
+ "reflect.getprototypeof": "^1.0.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-eslint": {
+ "version": "8.68.0",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.68.0.tgz",
+ "integrity": "sha512-MHy0Y0ynqeEbx/S45+i/bBssdy3X6KNBfmJAP35GrgtNxu2TQ5K5xsFDhAnmsq1jvpdoZOPG1LGtJo0HWqYCrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.68.0",
+ "@typescript-eslint/parser": "8.68.0",
+ "@typescript-eslint/typescript-estree": "8.68.0",
+ "@typescript-eslint/utils": "8.68.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+ "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "which-boxed-primitive": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz",
+ "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/unicorn-magic": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
+ "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/unrs-resolver": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz",
+ "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "napi-postinstall": "^0.3.4"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unrs-resolver"
+ },
+ "optionalDependencies": {
+ "@unrs/resolver-binding-android-arm-eabi": "1.12.2",
+ "@unrs/resolver-binding-android-arm64": "1.12.2",
+ "@unrs/resolver-binding-darwin-arm64": "1.12.2",
+ "@unrs/resolver-binding-darwin-x64": "1.12.2",
+ "@unrs/resolver-binding-freebsd-x64": "1.12.2",
+ "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2",
+ "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2",
+ "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-arm64-musl": "1.12.2",
+ "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-loong64-musl": "1.12.2",
+ "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2",
+ "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-x64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-x64-musl": "1.12.2",
+ "@unrs/resolver-binding-openharmony-arm64": "1.12.2",
+ "@unrs/resolver-binding-wasm32-wasi": "1.12.2",
+ "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2",
+ "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2",
+ "@unrs/resolver-binding-win32-x64-msvc": "1.12.2"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz",
+ "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
+ "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/validate-npm-package-name": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz",
+ "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==",
+ "license": "ISC",
+ "engines": {
+ "node": "^20.17.0 || >=22.9.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+ "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-bigint": "^1.1.0",
+ "is-boolean-object": "^1.2.1",
+ "is-number-object": "^1.1.1",
+ "is-string": "^1.1.1",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+ "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "function.prototype.name": "^1.1.6",
+ "has-tostringtag": "^1.0.2",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.1.0",
+ "is-finalizationregistry": "^1.1.0",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.2.1",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.1.0",
+ "which-collection": "^1.0.2",
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.22",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz",
+ "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/wsl-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-1.0.0.tgz",
+ "integrity": "sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==",
+ "license": "MIT",
+ "dependencies": {
+ "is-wsl": "^3.1.0",
+ "powershell-utils": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/wsl-utils/node_modules/powershell-utils": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz",
+ "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "license": "ISC"
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yocto-spinner": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-1.2.2.tgz",
+ "integrity": "sha512-DODGl1wJjA/s5pnJFKau9lIYHT81lnhob1i3e1TjxZRxEhWRKl74nTbWE6H5KlkViQQTo/Z29YFdxzTZAMY3ng==",
+ "license": "MIT",
+ "dependencies": {
+ "yoctocolors": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=18.19"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yoctocolors": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.2.0.tgz",
+ "integrity": "sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
+ "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-to-json-schema": {
+ "version": "3.25.2",
+ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz",
+ "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==",
+ "license": "ISC",
+ "peerDependencies": {
+ "zod": "^3.25.28 || ^4"
+ }
+ },
+ "node_modules/zod-validation-error": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
+ "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "zod": "^3.25.0 || ^4.0.0"
+ }
+ }
+ }
+}
diff --git a/distribution_fe/package.json b/distribution_fe/package.json
new file mode 100644
index 0000000..981c91f
--- /dev/null
+++ b/distribution_fe/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "distribution_fe",
+ "version": "0.0.1",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "eslint",
+ "format": "prettier --write \"**/*.{ts,tsx}\"",
+ "typecheck": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@base-ui/react": "^1.7.0",
+ "@hugeicons/core-free-icons": "^4.3.0",
+ "@hugeicons/react": "^1.1.10",
+ "axios": "^1.19.0",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "next": "16.2.6",
+ "next-themes": "^0.4.6",
+ "react": "19.2.4",
+ "react-dom": "19.2.4",
+ "shadcn": "^4.19.0",
+ "tailwind-merge": "^3.6.0",
+ "tw-animate-css": "^1.4.0"
+ },
+ "devDependencies": {
+ "@tailwindcss/postcss": "^4",
+ "@types/node": "^20",
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "eslint": "^9",
+ "eslint-config-next": "16.2.6",
+ "prettier": "^3.8.3",
+ "prettier-plugin-tailwindcss": "^0.8.0",
+ "tailwindcss": "^4",
+ "typescript": "^5"
+ }
+}
diff --git a/distribution_fe/postcss.config.mjs b/distribution_fe/postcss.config.mjs
new file mode 100644
index 0000000..2f8795a
--- /dev/null
+++ b/distribution_fe/postcss.config.mjs
@@ -0,0 +1,7 @@
+const config = {
+ plugins: {
+ "@tailwindcss/postcss": {},
+ },
+}
+
+export default config
diff --git a/distribution_fe/public/.gitkeep b/distribution_fe/public/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/distribution_fe/skills-lock.json b/distribution_fe/skills-lock.json
new file mode 100644
index 0000000..9f36136
--- /dev/null
+++ b/distribution_fe/skills-lock.json
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "skills": {
+ "shadcn": {
+ "source": "shadcn/ui",
+ "sourceType": "github",
+ "skillPath": "skills/shadcn/SKILL.md",
+ "computedHash": "f99ef49d9909d380ca683ceb8dc8c25775c20ee38140112c394e037d8c11ee18"
+ }
+ }
+}
diff --git a/distribution_fe/tsconfig.json b/distribution_fe/tsconfig.json
new file mode 100644
index 0000000..bca0e21
--- /dev/null
+++ b/distribution_fe/tsconfig.json
@@ -0,0 +1,35 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "react-jsx",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./*"]
+ }
+ },
+ "include": [
+ "next-env.d.ts",
+ "next.config.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ "**/*.mts",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts"
+ ],
+ "exclude": ["node_modules"]
+}
diff --git a/distribution_fe/types/api.ts b/distribution_fe/types/api.ts
new file mode 100644
index 0000000..31f2162
--- /dev/null
+++ b/distribution_fe/types/api.ts
@@ -0,0 +1,521 @@
+// ─── Enums ────────────────────────────────────────────────────────────────────
+
+export type KycStatus = 'Pending' | 'Verified' | 'Rejected'
+export type LocationType = 'Warehouse' | 'Vehicle'
+export type MovementType =
+ | 'Sale' | 'CustomerReturn' | 'Transfer' | 'Damage'
+ | 'Adjustment' | 'Load' | 'PurchaseReceipt' | 'PurchaseReturn'
+export type LoadingSheetStatus =
+ | 'Pending' | 'DispatchConfirmed' | 'ReceiptConfirmed'
+ | 'DiscrepancyFlagged' | 'Resolved'
+export type RideType = 'Delivery' | 'Sale'
+export type RideStatus =
+ | 'Draft' | 'Open' | 'Active' | 'CancelRequested' | 'Cancelled' | 'Closed'
+export type CancelRequestType =
+ | 'VehicleBreakdown' | 'DriverUnavailable' | 'RouteIssue' | 'Other'
+export type CancelRequestStatus = 'Pending' | 'Approved' | 'Rejected'
+export type PurchaseOrderStatus =
+ | 'Issued' | 'PartiallyReceived' | 'Received' | 'Closed' | 'Cancelled'
+export type SaleStatus = 'Pending' | 'Completed' | 'Cancelled'
+export type OrderStatus = 'Pending' | 'PartiallyFulfilled' | 'Fulfilled' | 'Cancelled'
+export type PaymentStatus = 'Pending' | 'PartiallyPaid' | 'Paid'
+export type PaymentMethod = 'Cash' | 'Credit'
+export type DeliveryTaskStatus = 'Pending' | 'Delivered' | 'PartiallyDelivered' | 'Failed'
+export type VehicleType = 'Car' | 'Truck' | 'Van' | 'Motorcycle' | 'Bicycle'
+export type WarehouseType =
+ | 'DistributionCenter' | 'FulfillmentCenter' | 'CrossDocking'
+ | 'ColdStorage' | 'BondedWarehouse' | 'AutomatedWarehouse'
+export type SchemeRuleType = 'BuyXGetY' | 'SlabDiscount' | 'FlatPercent' | 'FreeBundle'
+export type SyncSource = 'Manual' | 'Erp'
+
+// ─── Pagination ───────────────────────────────────────────────────────────────
+
+export interface PaginatedResponse {
+ page: number
+ pageSize: number
+ total: number
+ items: T[]
+}
+
+// ─── Auth / Users ─────────────────────────────────────────────────────────────
+
+export interface UserResponse {
+ id: string
+ username: string
+ fullName: string
+ roleId: string
+ roleName: string
+ reportsToUserId: string | null
+ isActive: boolean
+ createdAt: string
+ updatedAt: string | null
+}
+
+export interface RoleResponse {
+ id: string
+ name: string
+ level: number
+ isActive: boolean
+ createdAt: string
+}
+
+export interface PermissionResponse {
+ permissionId: string
+ code: string
+ description: string
+}
+
+// ─── Regions / Routes ────────────────────────────────────────────────────────
+
+export interface RegionResponse {
+ id: string
+ name: string
+ isActive: boolean
+ createdAt: string
+}
+
+export interface RouteResponse {
+ id: string
+ regionId: string
+ routeName: string
+ startPoint: string
+ endPoint: string
+ length: number
+ isActive: boolean
+ createdAt: string
+}
+
+// ─── Vehicles / Warehouses ───────────────────────────────────────────────────
+
+export interface VehicleResponse {
+ id: string
+ regNumber: string
+ numberPlate: string
+ type: VehicleType
+ isActive: boolean
+ createdAt: string
+}
+
+export interface WarehouseResponse {
+ id: string
+ name: string
+ location: string
+ type: WarehouseType
+ vehicleId: string | null
+ isActive: boolean
+ createdAt: string
+}
+
+// ─── Stores ───────────────────────────────────────────────────────────────────
+
+export interface StoreResponse {
+ id: string
+ routeId: string
+ ownerName: string
+ storeName: string
+ storeAddress: string
+ latitude: number
+ longitude: number
+ oneTimeAmount: number
+ creditAmount: number
+ creditLimit: number
+ outstandingBalance: number
+ segment: string | null
+ kycStatus: KycStatus
+ isActive: boolean
+ createdAt: string
+}
+
+export interface KycDocumentResponse {
+ id: string
+ storeId: string
+ documentType: string
+ fileReference: string
+ uploadedAt: string
+}
+
+export interface OutstandingBalanceResponse {
+ storeId: string
+ creditLimit: number
+ outstandingBalance: number
+ availableCredit: number
+}
+
+export interface StoreDashboardResponse {
+ storeId: string
+ period: string
+ orderCount: number
+ totalOrderValue: number
+ lastOrderDate: string | null
+}
+
+// ─── Catalogue ────────────────────────────────────────────────────────────────
+
+export interface CategoryResponse {
+ id: string
+ name: string
+ isActive: boolean
+ createdAt: string
+ subCategories: SubCategoryResponse[]
+}
+
+export interface SubCategoryResponse {
+ id: string
+ name: string
+ isActive: boolean
+ createdAt: string
+}
+
+export interface BrandResponse {
+ id: string
+ name: string
+ isActive: boolean
+ createdAt: string
+}
+
+export interface UomResponse {
+ id: string
+ name: string
+ isActive: boolean
+ createdAt: string
+}
+
+export interface UomConversion {
+ id: string
+ fromUomId: string
+ fromUomName: string
+ toUomId: string
+ toUomName: string
+ factor: number
+}
+
+export interface ItemSummaryResponse {
+ id: string
+ sku: string
+ name: string
+ categoryId: string
+ categoryName: string
+ subCategoryId: string | null
+ subCategoryName: string | null
+ brandId: string | null
+ brandName: string | null
+ baseUomId: string
+ baseUomName: string
+ salePrice: number
+ syncSource: SyncSource
+ isActive: boolean
+ createdAt: string
+}
+
+export interface ItemDetailResponse extends ItemSummaryResponse {
+ description: string | null
+ conversions: UomConversion[]
+}
+
+// ─── Price Lists ──────────────────────────────────────────────────────────────
+
+export interface PriceListItemResponse {
+ id: string
+ itemId: string
+ sku: string
+ itemName: string
+ price: number
+ minPrice: number | null
+}
+
+export interface PriceListResponse {
+ id: string
+ name: string
+ regionId: string | null
+ regionName: string | null
+ effectiveFrom: string
+ effectiveTo: string
+ isActive: boolean
+ createdAt: string
+ items: PriceListItemResponse[]
+}
+
+// ─── Schemes ──────────────────────────────────────────────────────────────────
+
+export interface BundleComponent {
+ itemId: string
+ sku: string
+ itemName: string
+ qty: number
+}
+
+export interface SchemeResponse {
+ id: string
+ name: string
+ ruleType: SchemeRuleType
+ ruleConfig: string | null
+ triggerItemId: string | null
+ triggerItemName: string | null
+ triggerQty: number
+ freeItemId: string | null
+ freeItemName: string | null
+ freeQty: number
+ bundleComponents: BundleComponent[]
+ regionId: string | null
+ regionName: string | null
+ eligibleSegment: string | null
+ dateRangeFrom: string
+ dateRangeTo: string
+ agentLimitExempt: boolean
+ baselineExpectedSales: number
+ isActive: boolean
+ createdAt: string
+}
+
+// ─── Suppliers ────────────────────────────────────────────────────────────────
+
+export interface SupplierResponse {
+ id: string
+ name: string
+ contactInfo: string | null
+ performanceScore: number | null
+ isActive: boolean
+ createdAt: string
+}
+
+// ─── Purchase Orders ──────────────────────────────────────────────────────────
+
+export interface PurchaseOrderItemResponse {
+ id: string
+ itemId: string
+ sku: string
+ itemName: string
+ quantity: number
+ unitCost: number
+ receivedQuantity: number
+ cancelledQuantity: number
+ isCancelled: boolean
+}
+
+export interface PurchaseOrderResponse {
+ id: string
+ supplierId: string
+ supplierName: string
+ createdByUserId: string
+ status: PurchaseOrderStatus
+ cancelReason: string | null
+ isActive: boolean
+ createdAt: string
+ items: PurchaseOrderItemResponse[]
+}
+
+export interface GrnItemResponse {
+ id: string
+ purchaseOrderItemId: string
+ itemId: string
+ sku: string
+ itemName: string
+ acceptedQuantity: number
+ rejectedQuantity: number
+}
+
+export interface GrnResponse {
+ id: string
+ purchaseOrderId: string
+ receivedByUserId: string
+ warehouseId: string
+ warehouseName: string
+ receivedAt: string
+ createdAt: string
+ items: GrnItemResponse[]
+}
+
+// ─── Stock ────────────────────────────────────────────────────────────────────
+
+export interface StockBalanceResponse {
+ itemId: string
+ itemName: string
+ locationId: string
+ locationType: LocationType
+ quantity: number
+ updatedAt: string
+}
+
+export interface StockMovementResponse {
+ id: string
+ itemId: string
+ itemName: string
+ fromLocationId: string | null
+ fromLocationType: LocationType | null
+ toLocationId: string | null
+ toLocationType: LocationType | null
+ quantity: number
+ type: MovementType
+ reasonCode: string | null
+ referenceId: string | null
+ createdAt: string
+ createdBy: string
+}
+
+// ─── Driver / Rides ───────────────────────────────────────────────────────────
+
+export interface DriverProfileResponse {
+ id: string
+ userId: string
+ userFullName: string
+ licenseNumber: string
+ licenseExpiry: string
+ medicalClearanceExpiry: string
+ isActive: boolean
+ createdAt: string
+}
+
+export interface DriverComplianceConfigResponse {
+ id: string
+ enforceLicenseExpiry: boolean
+ enforceMedicalClearance: boolean
+ updatedAt: string
+ updatedBy: string
+}
+
+export interface RideResponse {
+ id: string
+ rideType: RideType
+ status: RideStatus
+ vehicleId: string
+ vehicleNumberPlate: string
+ driverProfileId: string
+ driverFullName: string
+ routeId: string
+ routeName: string
+ sourceWarehouseId: string
+ sourceWarehouseName: string
+ meterstart: number
+ meterend: number
+ startedAt: string | null
+ activatedAt: string | null
+ closedAt: string | null
+ createdAt: string
+}
+
+export interface CancelRequestResponse {
+ id: string
+ rideId: string
+ typeCode: CancelRequestType
+ reason: string
+ requestedBy: string
+ requestedAt: string
+ status: CancelRequestStatus
+ approvedBy: string | null
+ approvedAt: string | null
+}
+
+// ─── Loading Sheets ───────────────────────────────────────────────────────────
+
+export interface LoadingSheetItemResponse {
+ id: string
+ fK_ItemId: string
+ itemName: string
+ quantityDispatched: number
+ quantityReceived: number
+ quantityResolved: number
+}
+
+export interface LoadingSheetResponse {
+ id: string
+ fK_RideId: string
+ fK_SourceWarehouseId: string
+ warehouseName: string
+ status: LoadingSheetStatus
+ dispatchConfirmedAt: string | null
+ dispatchConfirmedBy: string | null
+ receiptConfirmedAt: string | null
+ receiptConfirmedBy: string | null
+ createdAt: string
+ items: LoadingSheetItemResponse[]
+}
+
+// ─── Delivery Tasks ───────────────────────────────────────────────────────────
+
+export interface DeliveryTaskItemResponse {
+ itemId: string
+ itemName: string
+ quantity: number
+ quantityFulfilled: number
+ unitPrice: number
+}
+
+export interface DeliveryTaskResponse {
+ id: string
+ fK_RideId: string
+ fK_OrderId: string
+ storeId: string
+ storeName: string
+ sequence: number
+ status: DeliveryTaskStatus
+ customerConfirmed: boolean
+ confirmedAt: string | null
+ note: string | null
+ items: DeliveryTaskItemResponse[]
+ createdAt: string
+}
+
+// ─── Sales / Orders / Payments ────────────────────────────────────────────────
+
+export interface SaleItemResponse {
+ itemId: string
+ quantity: number
+ quantityFulfilled: number
+ unitPrice: number
+}
+
+export interface SaleResponse {
+ id: string
+ saleDate: string
+ storeId: string
+ createdByUserId: string
+ rideId: string | null
+ totalAmount: number
+ status: SaleStatus
+ paymentStatus: PaymentStatus
+ fulfillImmediately: boolean
+ completedAt: string | null
+ orderId: string
+ orderStatus: OrderStatus
+ orderFulfilledAt: string | null
+ items: SaleItemResponse[]
+ isActive: boolean
+ createdAt: string
+}
+
+export interface OrderItemResponse {
+ itemId: string
+ quantity: number
+ quantityFulfilled: number
+ unitPrice: number
+}
+
+export interface OrderResponse {
+ id: string
+ saleId: string
+ orderDate: string
+ storeId: string
+ totalAmount: number
+ status: OrderStatus
+ fulfilledAt: string | null
+ items: OrderItemResponse[]
+ isActive: boolean
+ createdAt: string
+}
+
+export interface PaymentResponse {
+ id: string
+ saleId: string
+ storeId: string
+ amount: number
+ method: PaymentMethod
+ collectedAt: string
+ collectedBy: string
+ createdAt: string
+}
+
+// ─── API Error ────────────────────────────────────────────────────────────────
+
+export interface ApiError {
+ error: string
+}
diff --git a/sharedDocs/BACKEND_API_REFERENCE.md b/sharedDocs/BACKEND_API_REFERENCE.md
new file mode 100644
index 0000000..31a58a4
--- /dev/null
+++ b/sharedDocs/BACKEND_API_REFERENCE.md
@@ -0,0 +1,2601 @@
+# Distribution ERP — Backend API Reference
+
+> **Stack:** ASP.NET Core (.NET 9) · MySQL (Entity Framework Core)
+> **Base URL:** `https://` (configure per environment)
+> **Swagger UI:** available at `/swagger` in Development mode
+> **Content-Type:** `application/json` for all requests unless noted (`multipart/form-data` for KYC uploads)
+
+---
+
+## Table of Contents
+
+1. [Authentication & JWT](#1-authentication--jwt)
+2. [Authorization Model](#2-authorization-model)
+3. [Global Response Conventions](#3-global-response-conventions)
+4. [Enumerations Reference](#4-enumerations-reference)
+5. [Pagination](#5-pagination)
+6. [Modules](#6-modules)
+ - [Auth](#61-auth)
+ - [Users](#62-users)
+ - [Roles](#63-roles)
+ - [Authorization Checks](#64-authorization-checks)
+ - [Regions](#65-regions)
+ - [Routes](#66-routes)
+ - [Vehicles](#67-vehicles)
+ - [Warehouses](#68-warehouses)
+ - [Stores](#69-stores)
+ - [Store KYC Documents](#610-store-kyc-documents)
+ - [Categories & Subcategories](#611-categories--subcategories)
+ - [Brands](#612-brands)
+ - [Units of Measure (UOMs)](#613-units-of-measure-uoms)
+ - [Items](#614-items)
+ - [Price Lists](#615-price-lists)
+ - [Schemes (Promotions)](#616-schemes-promotions)
+ - [Suppliers](#617-suppliers)
+ - [Purchase Orders (PO)](#618-purchase-orders-po)
+ - [Goods Receipt Notes (GRN)](#619-goods-receipt-notes-grn)
+ - [Purchase Returns](#620-purchase-returns)
+ - [Stock](#621-stock)
+ - [Driver Profiles](#622-driver-profiles)
+ - [Driver Compliance Config](#623-driver-compliance-config)
+ - [Rides](#624-rides)
+ - [Loading Sheets](#625-loading-sheets)
+ - [Delivery Tasks](#626-delivery-tasks)
+ - [Sales](#627-sales)
+ - [Orders](#628-orders)
+ - [Payments](#629-payments)
+ - [Sync (ERP Import)](#630-sync-erp-import)
+7. [Business Flows](#7-business-flows)
+ - [Region → Route → Store Setup](#71-region--route--store-setup)
+ - [Sale Flow](#72-sale-flow-sales-run)
+ - [Delivery Flow](#73-delivery-flow-end-to-end-ride-lifecycle)
+ - [Ride Cancellation Flow](#74-ride-cancellation-flow)
+ - [Payment Flow](#75-payment-flow)
+ - [Purchase Order Flow](#76-purchase-order-flow-procurement)
+ - [Loading Sheet Flow](#77-loading-sheet-flow-detail)
+ - [Stock Flow](#78-stock-flow-how-stock-moves)
+ - [Scheme / Promotion Flow](#79-scheme--promotion-flow)
+
+---
+
+## 1. Authentication
+
+> ⚠️ **YET TO IMPLEMENT**
+>
+> Authentication is handled by a **dedicated external Auth Service** (separate microservice). This backend acts as a **connector/proxy** — the Next.js frontend never calls the Auth Service directly; all auth traffic flows through this backend's `/api/auth/*` endpoints.
+>
+> The exact contract (token format, claims, endpoints, session strategy) is not yet finalized. The `/api/auth` routes are scaffolded in the backend as pass-through stubs pending Auth Service integration.
+>
+> What is decided:
+> - The frontend calls **this backend** for all auth operations, not the Auth Service directly.
+> - This backend forwards the request to the Auth Service and relays the response.
+> - All other endpoints on this backend will validate whatever credential the Auth Service issues (token format TBD).
+>
+> **Do not implement auth in the frontend until this section is updated.**
+
+---
+
+## 2. Authorization Model
+
+The system uses two orthogonal authorization concepts:
+
+### 2.1 Permission-Based Access Control
+
+Every protected endpoint is guarded by a **policy string** (e.g. `"orders.view"`). The JWT's `role_id` claim is used to look up the role's granted permissions in the database. The frontend should gracefully hide/disable UI elements the user lacks permission for (use the `/api/authorization/permissions/{code}` endpoint to check at runtime).
+
+#### Full Permission Code List
+
+| Permission Code | What it Controls |
+|---|---|
+| `items.view` | Read items, brands, UOMs |
+| `items.create` | Create items, brands, UOMs; also gate for Sync endpoints |
+| `items.update` | Update items, brands, UOMs |
+| `items.delete` | Delete items, brands, UOMs |
+| `categories.view` | Read categories/subcategories |
+| `categories.create` | Create categories/subcategories |
+| `categories.update` | Update categories/subcategories |
+| `categories.delete` | Delete categories/subcategories |
+| `regions.view` | Read regions |
+| `regions.create` | Create regions |
+| `regions.update` | Update regions |
+| `regions.delete` | Delete regions |
+| `routes.view` | Read routes |
+| `routes.create` | Create routes |
+| `routes.update` | Update routes |
+| `routes.delete` | Delete routes |
+| `vehicles.view` | Read vehicles |
+| `vehicles.create` | Create vehicles |
+| `vehicles.update` | Update vehicles |
+| `vehicles.delete` | Delete vehicles |
+| `warehouses.view` | Read warehouses |
+| `warehouses.create` | Create warehouses |
+| `warehouses.update` | Update warehouses |
+| `warehouses.delete` | Delete warehouses |
+| `stores.view` | Read stores, visit history, dashboard |
+| `stores.create` | Create stores |
+| `stores.update` | Update stores, upload KYC docs |
+| `stores.delete` | Delete stores |
+| `stores.credit.update` | Update credit limit / outstanding balance |
+| `stores.kyc.verify` | Change a store's KYC status |
+| `orders.view` | Read orders, sales |
+| `orders.create` | Create orders, sales |
+| `orders.update` | Update orders |
+| `orders.delete` | Delete orders |
+| `users.view` | Read users |
+| `users.create` | Create users |
+| `users.update` | Update users |
+| `users.assign_role` | Change a user's role |
+| `users.assign_scope` | Set a user's region/route/store scope |
+| `users.deactivate` | Deactivate users |
+| `driver_profiles.view` | Read driver profiles |
+| `driver_profiles.create` | Create driver profiles |
+| `driver_profiles.update` | Update driver profiles |
+| `driver_profiles.deactivate` | Deactivate driver profiles |
+| `compliance.manage` | Read/update driver compliance config |
+| `rides.view` | Read rides, cancel requests |
+| `rides.create` | Create rides |
+| `rides.manage` | Assign driver, open, activate, close rides |
+| `rides.cancel.request` | Raise a cancel request on a ride |
+| `rides.cancel.approve` | Approve or reject a cancel request |
+| `loading.view` | Read loading sheets |
+| `loading.dispatch` | Create loading sheets, set items, confirm dispatch |
+| `loading.receive` | Set receipt items, confirm receipt |
+| `loading.resolve` | Resolve discrepancy on a loading sheet |
+
+### 2.2 Scope-Based Data Filtering
+
+Users can be restricted to specific **regions**, **routes**, or **stores**. Certain read operations (orders/sales by store, etc.) enforce this scope. Use the scope-check endpoints to determine what data a user can access:
+
+- `GET /api/authorization/scopes/stores/{storeId}` — can the current user access this store?
+- `GET /api/authorization/scopes/routes/{routeId}` — can the current user access this route?
+- `GET /api/authorization/scopes/regions/{regionId}` — can the current user access this region?
+- `GET /api/authorization/scopes/stores` — list all store IDs the current user can access
+
+---
+
+## 3. Global Response Conventions
+
+| HTTP Status | Meaning |
+|---|---|
+| `200 OK` | Success (read / update / action) |
+| `201 Created` | Resource created; `Location` header + body returned |
+| `204 No Content` | Delete successful |
+| `400 Bad Request` | Validation error or invalid state; body: `{ "error": "message" }` |
+| `401 Unauthorized` | Missing or invalid JWT |
+| `403 Forbidden` | Authenticated but access denied (scope) |
+| `404 Not Found` | Resource not found |
+| `409 Conflict` | Business rule violation (duplicate, already exists, etc.) |
+
+All timestamps are **ISO 8601 UTC** strings (e.g. `"2024-01-15T09:30:00Z"`).
+All IDs are **GUIDs** in the format `"3fa85f64-5717-4562-b3fc-2c963f66afa6"`.
+
+---
+
+## 4. Enumerations Reference
+
+### `KycStatus`
+| Value | Description |
+|---|---|
+| `0` / `"Pending"` | Awaiting review |
+| `1` / `"Verified"` | KYC approved |
+| `2` / `"Rejected"` | KYC rejected |
+
+### `LocationType`
+| Value | Description |
+|---|---|
+| `0` / `"Warehouse"` | Stock held in a warehouse |
+| `1` / `"Vehicle"` | Stock loaded on a vehicle |
+
+### `MovementType`
+| Value | Description |
+|---|---|
+| `0` / `"Sale"` | Stock reduced by a sale |
+| `1` / `"CustomerReturn"` | Stock returned by customer |
+| `2` / `"Transfer"` | Moved between locations |
+| `3` / `"Damage"` | Written off as damaged |
+| `4` / `"Adjustment"` | Manual stock correction |
+| `5` / `"Load"` | Vehicle loading event |
+| `6` / `"PurchaseReceipt"` | GRN stock addition |
+| `7` / `"PurchaseReturn"` | Returned to supplier |
+
+### `LoadingSheetStatus`
+| Value | Description |
+|---|---|
+| `0` / `"Pending"` | Created, not yet dispatched |
+| `1` / `"DispatchConfirmed"` | Warehouse confirmed dispatch |
+| `2` / `"ReceiptConfirmed"` | Driver confirmed receipt |
+| `3` / `"DiscrepancyFlagged"` | Quantities differ; needs resolution |
+| `4` / `"Resolved"` | Discrepancy settled |
+
+### `RideType`
+| Value | Description |
+|---|---|
+| `0` / `"Delivery"` | Delivery-only run |
+| `1` / `"Sale"` | Sales run (driver can take orders) |
+
+### `RideStatus`
+| Value | Description |
+|---|---|
+| `0` / `"Draft"` | Created, not yet started |
+| `1` / `"Open"` | Route opened, ready to activate |
+| `2` / `"Active"` | Currently in progress |
+| `3` / `"CancelRequested"` | Cancel requested, pending approval |
+| `4` / `"Cancelled"` | Cancelled |
+| `5` / `"Closed"` | Completed |
+
+### `CancelRequestType`
+| Value | Description |
+|---|---|
+| `0` / `"VehicleBreakdown"` | Vehicle broke down |
+| `1` / `"DriverUnavailable"` | Driver unavailable |
+| `2` / `"RouteIssue"` | Route-related issue |
+| `3` / `"Other"` | Other reason |
+
+### `CancelRequestStatus`
+| Value | Description |
+|---|---|
+| `0` / `"Pending"` | Awaiting approval decision |
+| `1` / `"Approved"` | Cancel request approved |
+| `2` / `"Rejected"` | Cancel request rejected |
+
+### `PurchaseOrderStatus`
+| Value | Description |
+|---|---|
+| `0` / `"Issued"` | PO created, not yet received |
+| `1` / `"PartiallyReceived"` | Some items received via GRN |
+| `2` / `"Received"` | All items received |
+| `3` / `"Closed"` | Manually closed |
+| `4` / `"Cancelled"` | PO cancelled |
+
+### `SaleStatus`
+| Value | Description |
+|---|---|
+| `0` / `"Pending"` | Sale not yet completed |
+| `1` / `"Completed"` | Sale fulfilled |
+| `2` / `"Cancelled"` | Sale cancelled |
+
+### `OrderStatus`
+| Value | Description |
+|---|---|
+| `0` / `"Pending"` | Order awaiting fulfilment |
+| `1` / `"PartiallyFulfilled"` | Some items fulfilled |
+| `2` / `"Fulfilled"` | Fully fulfilled |
+| `3` / `"Cancelled"` | Order cancelled |
+
+### `PaymentStatus`
+| Value | Description |
+|---|---|
+| `0` / `"Pending"` | No payment received |
+| `1` / `"PartiallyPaid"` | Partial payment received |
+| `2` / `"Paid"` | Fully paid |
+
+### `PaymentMethod`
+| Value | Description |
+|---|---|
+| `0` / `"Cash"` | Cash payment |
+| `1` / `"Credit"` | Credit payment |
+
+### `DeliveryTaskStatus`
+| Value | Description |
+|---|---|
+| `0` / `"Pending"` | Not yet actioned |
+| `1` / `"Delivered"` | Fully delivered |
+| `2` / `"PartiallyDelivered"` | Partially delivered |
+| `3` / `"Failed"` | Delivery failed |
+
+### `VehicleType`
+| Value | Description |
+|---|---|
+| `0` / `"Car"` | Car |
+| `1` / `"Truck"` | Truck |
+| `2` / `"Van"` | Van |
+| `3` / `"Motorcycle"` | Motorcycle |
+| `4` / `"Bicycle"` | Bicycle |
+
+### `WareHouseType`
+| Value | Description |
+|---|---|
+| `0` / `"DistributionCenter"` | Distribution center |
+| `1` / `"FulfillmentCenter"` | Fulfilment center |
+| `2` / `"CrossDocking"` | Cross-docking facility |
+| `3` / `"ColdStorage"` | Cold storage |
+| `4` / `"BondedWarehouse"` | Bonded warehouse |
+| `5` / `"AutomatedWarehouse"` | Automated warehouse |
+
+### `SchemeRuleType`
+| Value | Description |
+|---|---|
+| `0` / `"BuyXGetY"` | Buy X quantity of trigger item, get Y free |
+| `1` / `"SlabDiscount"` | Tiered order-value discount |
+| `2` / `"FlatPercent"` | Flat percentage discount |
+| `3` / `"FreeBundle"` | Buy a bundle of required items, get free item |
+
+### `SyncSource` (on Items)
+| Value | Description |
+|---|---|
+| `0` / `"Manual"` | Created directly in this system |
+| `1` / `"Erp"` | Imported via the Sync API |
+
+---
+
+## 5. Pagination
+
+Endpoints that support pagination accept these query parameters:
+
+| Parameter | Type | Default | Description |
+|---|---|---|---|
+| `page` | `int` | `1` | 1-based page number |
+| `pageSize` | `int` | `20` | Records per page |
+
+Paginated responses use this wrapper:
+```json
+{
+ "page": 1,
+ "pageSize": 20,
+ "total": 150,
+ "items": [ ... ]
+}
+```
+
+**Endpoints with pagination:** Driver Profiles, Rides, Loading Sheets, Stock Balances, Stock Movements, Ride Cancel Requests.
+
+All other list endpoints return a plain array — **implement client-side pagination or virtual scrolling for large datasets**.
+
+---
+
+## 6. Modules
+
+---
+
+### 6.1 Auth
+
+> ⚠️ **YET TO IMPLEMENT** — See [Section 1](#1-authentication) for context.
+>
+> The `/api/auth` routes are stubs. Shape of requests and responses will be defined once the Auth Service contract is agreed.
+
+**Base path:** `/api/auth`
+
+---
+
+### 6.2 Users
+
+**Base path:** `/api/users`
+**Required:** JWT token
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/users` | `users.view` | List all users |
+| `GET` | `/api/users/{id}` | `users.view` | Get user by ID |
+| `POST` | `/api/users` | `users.create` | Create user |
+| `PUT` | `/api/users/{id}` | `users.update` | Update user full name |
+| `PUT` | `/api/users/{id}/role` | `users.assign_role` | Assign role to user |
+| `PUT` | `/api/users/{id}/scope` | `users.assign_scope` | Set user's data scope |
+| `DELETE` | `/api/users/{id}` | `users.deactivate` | Deactivate user |
+
+#### Create User — `POST /api/users`
+```json
+{
+ "username": "string", // required, unique login name
+ "password": "string", // required, plaintext (hashed server-side)
+ "fullName": "string", // required
+ "roleId": "guid", // required
+ "reportsToUserId": "guid" // optional, parent user in hierarchy
+}
+```
+
+#### Update User — `PUT /api/users/{id}`
+```json
+{ "fullName": "string" }
+```
+
+#### Assign Role — `PUT /api/users/{id}/role`
+```json
+{ "roleId": "guid" }
+```
+
+#### Assign Scope — `PUT /api/users/{id}/scope`
+```json
+{
+ "regionIds": ["guid", ...], // list (can be empty)
+ "routeIds": ["guid", ...],
+ "storeIds": ["guid", ...]
+}
+```
+
+#### User Response Object
+```json
+{
+ "id": "guid",
+ "username": "string",
+ "fullName": "string",
+ "roleId": "guid",
+ "roleName": "string",
+ "reportsToUserId": "guid | null",
+ "isActive": true,
+ "createdAt": "datetime",
+ "updatedAt": "datetime | null"
+}
+```
+
+---
+
+### 6.3 Roles
+
+**Base path:** `/api/roles`
+**Required:** JWT token (no specific permission — any authenticated user)
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/roles` | List all roles |
+| `GET` | `/api/roles/{id}` | Get role by ID |
+| `GET` | `/api/roles/{id}/permissions` | Get permissions assigned to role |
+
+#### Role Response
+```json
+{
+ "id": "guid",
+ "name": "string",
+ "level": 1, // integer hierarchy level; lower = more authority
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+#### Role Permissions Response
+Array of:
+```json
+{
+ "permissionId": "guid",
+ "code": "orders.view", // use this code for Policy checks
+ "description": "string"
+}
+```
+
+---
+
+### 6.4 Authorization Checks
+
+**Base path:** `/api/authorization`
+**Required:** JWT token
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/authorization/permissions/{permissionCode}` | Check if current user's role has a permission |
+| `GET` | `/api/authorization/scopes/stores/{storeId}` | Check if current user can access a store |
+| `GET` | `/api/authorization/scopes/routes/{routeId}` | Check if current user can access a route |
+| `GET` | `/api/authorization/scopes/regions/{regionId}` | Check if current user can access a region |
+| `GET` | `/api/authorization/scopes/stores` | Get all store IDs accessible to current user |
+
+**Permission check response:**
+```json
+{ "hasPermission": true }
+```
+
+**Scope check responses:**
+```json
+{ "hasScope": true } // stores/routes/regions
+{ "storeIds": ["guid", "guid", ...] } // accessible stores list
+```
+
+---
+
+### 6.5 Regions
+
+**Base path:** `/api/regions`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/regions` | `regions.view` | List all regions |
+| `GET` | `/api/regions/{id}` | `regions.view` | Get region by ID |
+| `POST` | `/api/regions` | `regions.create` | Create region |
+| `PUT` | `/api/regions/{id}` | `regions.update` | Update region |
+| `DELETE` | `/api/regions/{id}` | `regions.delete` | Delete region |
+
+**Create/Update request:**
+```json
+{ "name": "string" }
+```
+
+**Response:**
+```json
+{
+ "id": "guid",
+ "name": "string",
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.6 Routes
+
+**Base path:** `/api/routes`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/routes` | `routes.view` | List all routes |
+| `GET` | `/api/routes/{id}` | `routes.view` | Get route by ID |
+| `POST` | `/api/routes` | `routes.create` | Create route |
+| `PUT` | `/api/routes/{id}` | `routes.update` | Update route |
+| `DELETE` | `/api/routes/{id}` | `routes.delete` | Delete route |
+
+**Create/Update request:**
+```json
+{
+ "regionId": "guid", // required
+ "routeName": "string", // required
+ "startPoint": "string", // required
+ "endPoint": "string", // required
+ "length": 12.5 // decimal (kilometers)
+}
+```
+
+**Response:**
+```json
+{
+ "id": "guid",
+ "regionId": "guid",
+ "routeName": "string",
+ "startPoint": "string",
+ "endPoint": "string",
+ "length": 12.5,
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.7 Vehicles
+
+**Base path:** `/api/vehicles`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/vehicles` | `vehicles.view` | List all vehicles |
+| `GET` | `/api/vehicles/{id}` | `vehicles.view` | Get vehicle by ID |
+| `POST` | `/api/vehicles` | `vehicles.create` | Create vehicle |
+| `PUT` | `/api/vehicles/{id}` | `vehicles.update` | Update vehicle |
+| `DELETE` | `/api/vehicles/{id}` | `vehicles.delete` | Delete vehicle |
+
+**Create/Update request:**
+```json
+{
+ "regNumber": "string", // registration number
+ "numberPlate": "string", // display plate
+ "type": "Van" // VehicleType enum
+}
+```
+
+**Response:**
+```json
+{
+ "id": "guid",
+ "regNumber": "string",
+ "numberPlate": "string",
+ "type": "Van",
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.8 Warehouses
+
+**Base path:** `/api/warehouses`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/warehouses` | `warehouses.view` | List all warehouses |
+| `GET` | `/api/warehouses/{id}` | `warehouses.view` | Get warehouse by ID |
+| `POST` | `/api/warehouses` | `warehouses.create` | Create warehouse |
+| `PUT` | `/api/warehouses/{id}` | `warehouses.update` | Update warehouse |
+| `DELETE` | `/api/warehouses/{id}` | `warehouses.delete` | Delete warehouse |
+
+**Create/Update request:**
+```json
+{
+ "name": "string",
+ "location": "string",
+ "type": "DistributionCenter", // WareHouseType enum
+ "vehicleId": "guid | null" // optional, link to a vehicle
+}
+```
+
+**Response:**
+```json
+{
+ "id": "guid",
+ "name": "string",
+ "location": "string",
+ "type": "DistributionCenter",
+ "vehicleId": "guid | null",
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.9 Stores
+
+**Base path:** `/api/stores`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/stores` | `stores.view` | List all stores |
+| `GET` | `/api/stores/{id}` | `stores.view` | Get store by ID |
+| `POST` | `/api/stores` | `stores.create` | Create store |
+| `PUT` | `/api/stores/{id}` | `stores.update` | Update store |
+| `DELETE` | `/api/stores/{id}` | `stores.delete` | Delete store |
+| `PUT` | `/api/stores/{id}/credit-limit` | `stores.credit.update` | Update credit limit |
+| `PUT` | `/api/stores/{id}/outstanding-balance` | `stores.credit.update` | Update outstanding balance |
+| `GET` | `/api/stores/{id}/outstanding-balance` | `stores.view` | Get outstanding balance details |
+| `PUT` | `/api/stores/{id}/kyc/verify` | `stores.kyc.verify` | Verify or reject KYC |
+| `PUT` | `/api/stores/{id}/segment` | `stores.update` | Classify store segment |
+| `GET` | `/api/stores/{id}/visit-history` | `stores.view` | Get store visit history |
+| `GET` | `/api/stores/{id}/schemes/{schemeId}/eligibility` | `stores.view` | Check scheme eligibility |
+| `GET` | `/api/stores/{id}/dashboard` | `stores.view` | Get store dashboard metrics |
+
+#### Create/Update Store
+```json
+{
+ "routeId": "guid",
+ "ownerName": "string",
+ "storeName": "string",
+ "storeAddress": "string",
+ "latitude": 6.927079,
+ "longitude": 79.861244,
+ "oneTimeAmount": 0.00, // one-time registration/setup fee
+ "creditAmount": 0.00 // assigned credit amount
+}
+```
+
+#### Store Response
+```json
+{
+ "id": "guid",
+ "routeId": "guid",
+ "ownerName": "string",
+ "storeName": "string",
+ "storeAddress": "string",
+ "latitude": 6.927079,
+ "longitude": 79.861244,
+ "oneTimeAmount": 0.00,
+ "creditAmount": 0.00,
+ "creditLimit": 50000.00,
+ "outstandingBalance": 12500.00,
+ "segment": "Gold | null", // Gold, Silver, Key Account, High Risk, etc.
+ "kycStatus": "Pending",
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+#### Update Credit Limit — `PUT /api/stores/{id}/credit-limit`
+```json
+{
+ "newLimit": 75000.00,
+ "approverId": "guid" // user ID of the approver
+}
+```
+
+#### Update Outstanding Balance — `PUT /api/stores/{id}/outstanding-balance`
+```json
+{ "newBalance": 10000.00 }
+```
+
+#### Outstanding Balance Response — `GET /api/stores/{id}/outstanding-balance`
+```json
+{
+ "storeId": "guid",
+ "creditLimit": 50000.00,
+ "outstandingBalance": 12500.00,
+ "availableCredit": 37500.00
+}
+```
+
+#### Verify KYC — `PUT /api/stores/{id}/kyc/verify`
+```json
+{
+ "status": "Verified", // KycStatus: Verified or Rejected
+ "notes": "string | null"
+}
+```
+
+#### Classify Segment — `PUT /api/stores/{id}/segment`
+```json
+{ "segment": "Gold" }
+```
+
+#### Visit History Response — `GET /api/stores/{id}/visit-history`
+Array of:
+```json
+{
+ "visitId": "guid",
+ "visitDate": "datetime",
+ "repUserId": "guid",
+ "outcome": "string"
+}
+```
+
+#### Scheme Eligibility — `GET /api/stores/{id}/schemes/{schemeId}/eligibility`
+```json
+{
+ "eligible": true,
+ "reason": "string | null"
+}
+```
+
+#### Store Dashboard — `GET /api/stores/{id}/dashboard?period=monthly`
+`period` query param is a string (e.g. `"daily"`, `"weekly"`, `"monthly"`).
+
+```json
+{
+ "storeId": "guid",
+ "period": "monthly",
+ "orderCount": 12,
+ "totalOrderValue": 145000.00,
+ "lastOrderDate": "datetime | null"
+}
+```
+
+---
+
+### 6.10 Store KYC Documents
+
+**Base path:** `/api/stores/{storeId}/kyc-documents`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/stores/{storeId}/kyc-documents` | `stores.view` | Get all KYC documents for a store |
+| `POST` | `/api/stores/{storeId}/kyc-documents` | `stores.update` | Upload a KYC document |
+
+#### Upload KYC Document — `POST /api/stores/{storeId}/kyc-documents`
+
+> **Content-Type:** `multipart/form-data`
+
+| Form field | Type | Required | Description |
+|---|---|---|---|
+| `documentType` | `string` | Yes | Document type label (e.g. `"NIC"`, `"Business Registration"`) |
+| `file` | `File` | Yes | The document file |
+
+**Response:**
+```json
+{
+ "id": "guid",
+ "storeId": "guid",
+ "documentType": "NIC",
+ "fileReference": "string", // server-side file reference/path
+ "uploadedAt": "datetime"
+}
+```
+
+---
+
+### 6.11 Categories & Subcategories
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/categories` | `categories.view` | List all categories (with subcategories) |
+| `GET` | `/api/categories/{id}` | `categories.view` | Get category by ID |
+| `POST` | `/api/categories` | `categories.create` | Create category |
+| `PUT` | `/api/categories/{id}` | `categories.update` | Update category |
+| `DELETE` | `/api/categories/{id}` | `categories.delete` | Delete category |
+| `POST` | `/api/categories/{categoryId}/subcategories` | `categories.create` | Create subcategory |
+| `PUT` | `/api/subcategories/{id}` | `categories.update` | Update subcategory |
+| `DELETE` | `/api/subcategories/{id}` | `categories.delete` | Delete subcategory |
+
+**Create/Update category or subcategory:**
+```json
+{ "name": "string" }
+```
+
+**Category detail response (GET by ID):**
+```json
+{
+ "id": "guid",
+ "name": "string",
+ "isActive": true,
+ "createdAt": "datetime",
+ "subCategories": [
+ { "id": "guid", "name": "string", "isActive": true, "createdAt": "datetime" }
+ ]
+}
+```
+
+**Category list response (GET all):** Array of above objects.
+
+---
+
+### 6.12 Brands
+
+**Base path:** `/api/brands`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/brands` | `items.view` | List all brands |
+| `GET` | `/api/brands/{id}` | `items.view` | Get brand by ID |
+| `POST` | `/api/brands` | `items.create` | Create brand |
+| `PUT` | `/api/brands/{id}` | `items.update` | Update brand |
+| `DELETE` | `/api/brands/{id}` | `items.delete` | Delete brand |
+
+**Create/Update:** `{ "name": "string" }`
+
+**Response:** `{ "id": "guid", "name": "string", "isActive": true, "createdAt": "datetime" }`
+
+---
+
+### 6.13 Units of Measure (UOMs)
+
+**Base path:** `/api/uoms`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/uoms` | `items.view` | List all UOMs |
+| `GET` | `/api/uoms/{id}` | `items.view` | Get UOM by ID |
+| `POST` | `/api/uoms` | `items.create` | Create UOM |
+| `PUT` | `/api/uoms/{id}` | `items.update` | Update UOM |
+| `DELETE` | `/api/uoms/{id}` | `items.delete` | Delete UOM |
+
+**Create/Update:** `{ "name": "string" }`
+
+**Response:** `{ "id": "guid", "name": "string", "isActive": true, "createdAt": "datetime" }`
+
+---
+
+### 6.14 Items
+
+**Base path:** `/api/items`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/items` | `items.view` | List items (filterable) |
+| `GET` | `/api/items/{id}` | `items.view` | Get item detail |
+| `POST` | `/api/items` | `items.create` | Create item |
+| `PUT` | `/api/items/{id}` | `items.update` | Update item |
+| `DELETE` | `/api/items/{id}` | `items.delete` | Delete item |
+| `PUT` | `/api/items/{id}/uom-conversions` | `items.update` | Replace all UOM conversions |
+
+#### List Items — `GET /api/items`
+
+Optional query filters:
+| Param | Type | Description |
+|---|---|---|
+| `categoryId` | `guid` | Filter by category |
+| `subCategoryId` | `guid` | Filter by subcategory |
+| `brandId` | `guid` | Filter by brand |
+
+#### Create Item — `POST /api/items`
+```json
+{
+ "sku": "string", // required, unique SKU
+ "name": "string", // required
+ "description": "string", // optional
+ "categoryId": "guid", // required
+ "subCategoryId": "guid", // optional
+ "brandId": "guid", // optional
+ "baseUomId": "guid", // required, base unit of measure
+ "salePrice": 150.00, // optional default sale price
+ "conversions": [ // optional UOM conversion rules
+ {
+ "fromUomId": "guid",
+ "toUomId": "guid",
+ "factor": 12.0 // 1 fromUom = factor toUom
+ }
+ ]
+}
+```
+Returns `409 Conflict` if SKU already exists.
+
+#### Update Item — `PUT /api/items/{id}`
+```json
+{
+ "name": "string",
+ "description": "string | null",
+ "categoryId": "guid",
+ "subCategoryId": "guid | null",
+ "brandId": "guid | null",
+ "baseUomId": "guid",
+ "salePrice": 150.00
+}
+```
+
+#### Replace UOM Conversions — `PUT /api/items/{id}/uom-conversions`
+Replaces **all** existing conversions for the item.
+```json
+{
+ "conversions": [
+ { "fromUomId": "guid", "toUomId": "guid", "factor": 12.0 }
+ ]
+}
+```
+
+#### Item Summary Response (list)
+```json
+{
+ "id": "guid",
+ "sku": "string",
+ "name": "string",
+ "categoryId": "guid",
+ "categoryName": "string",
+ "subCategoryId": "guid | null",
+ "subCategoryName": "string | null",
+ "brandId": "guid | null",
+ "brandName": "string | null",
+ "baseUomId": "guid",
+ "baseUomName": "string",
+ "salePrice": 150.00,
+ "syncSource": "Manual | Erp",
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+#### Item Detail Response (single)
+Same as summary plus:
+```json
+{
+ "description": "string | null",
+ "conversions": [
+ {
+ "id": "guid",
+ "fromUomId": "guid",
+ "fromUomName": "string",
+ "toUomId": "guid",
+ "toUomName": "string",
+ "factor": 12.0
+ }
+ ]
+}
+```
+
+---
+
+### 6.15 Price Lists
+
+**Base path:** `/api/price-lists`
+**Required:** JWT token (no specific permission policy — any authenticated user)
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/price-lists` | List price lists (filterable by region) |
+| `GET` | `/api/price-lists/{id}` | Get price list with all items |
+| `POST` | `/api/price-lists` | Create price list |
+| `PUT` | `/api/price-lists/{id}` | Update price list metadata |
+| `DELETE` | `/api/price-lists/{id}` | Delete price list |
+| `PUT` | `/api/price-lists/{id}/items/{sku}` | Upsert an item's price in this list |
+| `DELETE` | `/api/price-lists/{id}/items/{sku}` | Remove an item from this list |
+
+#### List Price Lists — `GET /api/price-lists`
+Optional query: `?regionId={guid}`
+
+#### Create/Update Price List
+```json
+{
+ "name": "string",
+ "regionId": "guid | null", // null = applies to all regions
+ "effectiveFrom": "datetime",
+ "effectiveTo": "datetime"
+}
+```
+Returns `409 Conflict` if overlapping active price list for the same region exists.
+
+#### Upsert Item Price — `PUT /api/price-lists/{id}/items/{sku}`
+`sku` is the item's SKU string in the URL path.
+```json
+{
+ "price": 150.00,
+ "minPrice": 130.00 // optional, null = price is non-negotiable
+}
+```
+
+#### Price List Response
+```json
+{
+ "id": "guid",
+ "name": "string",
+ "regionId": "guid | null",
+ "regionName": "string | null",
+ "effectiveFrom": "datetime",
+ "effectiveTo": "datetime",
+ "isActive": true,
+ "createdAt": "datetime",
+ "items": [
+ {
+ "id": "guid",
+ "itemId": "guid",
+ "sku": "string",
+ "itemName": "string",
+ "price": 150.00,
+ "minPrice": 130.00
+ }
+ ]
+}
+```
+
+---
+
+### 6.16 Schemes (Promotions)
+
+**Base path:** `/api/schemes`
+**Required:** JWT token (no specific permission policy)
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/schemes` | List schemes (optional `?regionId={guid}`) |
+| `GET` | `/api/schemes/{id}` | Get scheme detail |
+| `POST` | `/api/schemes` | Create scheme |
+| `PUT` | `/api/schemes/{id}` | Update scheme metadata |
+| `DELETE` | `/api/schemes/{id}` | Delete scheme |
+| `PUT` | `/api/schemes/{id}/free-goods-rule` | Set free-goods rule |
+| `DELETE` | `/api/schemes/{id}/free-goods-rule` | Clear free-goods rule |
+| `PUT` | `/api/schemes/{id}/bundle-components/{itemId}` | Upsert bundle component |
+| `DELETE` | `/api/schemes/{id}/bundle-components/{itemId}` | Remove bundle component |
+| `GET` | `/api/schemes/eligible?storeId={guid}&orderId={guid}` | Get eligible schemes for a store+order |
+| `GET` | `/api/schemes/{id}/spend` | Get scheme spend analytics |
+| `GET` | `/api/schemes/{id}/roi` | Get scheme ROI analytics |
+| `POST` | `/api/orders/{id}/apply-scheme` | Apply a scheme to an order |
+
+#### Scheme Rule Types
+
+- **`BuyXGetY`**: Store buys `triggerQty` of `triggerItemId`, gets `freeQty` of `freeItemId` for free.
+- **`SlabDiscount`**: Tiered discount based on order value. `ruleConfig` JSON: `{ "tiers": [ { "minOrderAmount": 10000, "discountPercent": 5.0 }, ... ] }` (ordered ascending).
+- **`FlatPercent`**: Flat percentage off. `ruleConfig` JSON: `{ "discountPercent": 10.0 }`.
+- **`FreeBundle`**: Store buys all required bundle components, gets `freeQty` of `freeItemId` free.
+
+#### Create Scheme — `POST /api/schemes`
+```json
+{
+ "name": "string",
+ "ruleType": "SlabDiscount", // SchemeRuleType enum
+ "ruleConfig": "{...}", // JSON string; required for SlabDiscount/FlatPercent, null for BuyXGetY/FreeBundle
+ "regionId": "guid | null", // null = all regions
+ "eligibleSegment": "Gold | null", // null = all segments
+ "dateRangeFrom": "datetime",
+ "dateRangeTo": "datetime",
+ "agentLimitExempt": false, // if true, exempt from agent discount ceiling
+ "baselineExpectedSales": 500000.00, // optional, used for ROI calc
+ // Optional one-shot fields (can also use separate endpoints later):
+ "triggerItemId": "guid | null", // BuyXGetY: item store must buy
+ "triggerQty": 10, // BuyXGetY: quantity trigger
+ "freeItemId": "guid | null", // BuyXGetY/FreeBundle: item given free
+ "freeQty": 2.0, // quantity of free item
+ "bundleComponents": [ // FreeBundle: required purchase items
+ { "itemId": "guid", "qty": 5 }
+ ]
+}
+```
+
+#### Update Scheme — `PUT /api/schemes/{id}`
+```json
+{
+ "name": "string",
+ "ruleConfig": "{...} | null",
+ "regionId": "guid | null",
+ "eligibleSegment": "string | null",
+ "dateRangeFrom": "datetime",
+ "dateRangeTo": "datetime",
+ "agentLimitExempt": false,
+ "baselineExpectedSales": 500000.00
+}
+```
+
+#### Set Free Goods Rule — `PUT /api/schemes/{id}/free-goods-rule`
+```json
+{
+ "triggerItemId": "guid | null", // required for BuyXGetY; ignored for FreeBundle
+ "triggerQty": 10, // required for BuyXGetY; ignored for FreeBundle
+ "freeItemId": "guid", // required
+ "freeQty": 2.0 // required
+}
+```
+
+#### Upsert Bundle Component — `PUT /api/schemes/{id}/bundle-components/{itemId}`
+```json
+{ "qty": 5 }
+```
+
+#### Apply Scheme to Order — `POST /api/orders/{id}/apply-scheme`
+```json
+{ "schemeId": "guid" }
+```
+
+#### Scheme Response
+```json
+{
+ "id": "guid",
+ "name": "string",
+ "ruleType": "BuyXGetY",
+ "ruleConfig": "string | null",
+ "triggerItemId": "guid | null",
+ "triggerItemName": "string | null",
+ "triggerQty": 10,
+ "freeItemId": "guid | null",
+ "freeItemName": "string | null",
+ "freeQty": 2.0,
+ "bundleComponents": [
+ { "itemId": "guid", "sku": "string", "itemName": "string", "qty": 5 }
+ ],
+ "regionId": "guid | null",
+ "regionName": "string | null",
+ "eligibleSegment": "Gold | null",
+ "dateRangeFrom": "datetime",
+ "dateRangeTo": "datetime",
+ "agentLimitExempt": false,
+ "baselineExpectedSales": 500000.00,
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+#### Eligible Schemes Response — `GET /api/schemes/eligible?storeId=...&orderId=...`
+Array of:
+```json
+{
+ "schemeId": "guid",
+ "schemeName": "string",
+ "ruleType": "SlabDiscount",
+ "eligible": true,
+ "reason": "string | null",
+ "discountAmount": 1500.00,
+ "freeItemId": "guid | null",
+ "freeQty": 2.0
+}
+```
+
+#### Scheme Spend — `GET /api/schemes/{id}/spend`
+```json
+{
+ "schemeId": "guid",
+ "totalDiscountSpend": 15000.00,
+ "totalFreeGoodsCostSpend": 3000.00,
+ "totalSpend": 18000.00,
+ "redemptionCount": 45
+}
+```
+
+#### Scheme ROI — `GET /api/schemes/{id}/roi`
+```json
+{
+ "schemeId": "guid",
+ "baselineExpectedSales": 500000.00,
+ "actualSales": 650000.00,
+ "incrementalSales": 150000.00,
+ "totalSpend": 18000.00,
+ "roi": 7.33 // (incrementalSales - totalSpend) / totalSpend; null if baseline not set
+}
+```
+
+---
+
+### 6.17 Suppliers
+
+**Base path:** `/api/suppliers`
+**Required:** JWT token (no specific permission policy)
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/suppliers` | List all suppliers |
+| `GET` | `/api/suppliers/{id}` | Get supplier by ID |
+| `POST` | `/api/suppliers` | Create supplier |
+| `PUT` | `/api/suppliers/{id}` | Update supplier |
+| `DELETE` | `/api/suppliers/{id}` | Delete supplier (returns `409` if has active POs) |
+| `POST` | `/api/suppliers/{id}/evaluate` | Trigger supplier performance evaluation |
+
+**Create/Update:**
+```json
+{
+ "name": "string",
+ "contactInfo": "string | null"
+}
+```
+
+**Response:**
+```json
+{
+ "id": "guid",
+ "name": "string",
+ "contactInfo": "string | null",
+ "performanceScore": 4.5, // decimal | null; computed by evaluate
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.18 Purchase Orders (PO)
+
+**Base path:** `/api/purchase-orders`
+**Required:** JWT token (no specific permission policy)
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/purchase-orders` | List POs (optional filters) |
+| `GET` | `/api/purchase-orders/{id}` | Get PO detail |
+| `POST` | `/api/purchase-orders` | Create PO |
+| `PUT` | `/api/purchase-orders/{id}` | Update PO lines (while Issued) |
+| `POST` | `/api/purchase-orders/{id}/close` | Manually close PO |
+| `POST` | `/api/purchase-orders/{id}/cancel` | Cancel entire PO |
+| `POST` | `/api/purchase-orders/{id}/items/{itemId}/cancel` | Cancel a single PO line |
+| `POST` | `/api/purchase-orders/{id}/match-invoice` | Match PO to GRN/Invoice |
+| `POST` | `/api/purchase-orders/{id}/resolve-variance` | Resolve invoice variance |
+
+#### List POs — `GET /api/purchase-orders`
+Optional query filters:
+| Param | Type | Description |
+|---|---|---|
+| `supplierId` | `guid` | Filter by supplier |
+| `status` | `PurchaseOrderStatus` | Filter by status |
+
+#### Create PO — `POST /api/purchase-orders`
+```json
+{
+ "supplierId": "guid",
+ "items": [
+ {
+ "itemId": "guid",
+ "quantity": 100,
+ "unitCost": 85.00
+ }
+ ]
+}
+```
+
+#### Update PO — `PUT /api/purchase-orders/{id}`
+Only valid while status is `Issued`.
+```json
+{
+ "items": [
+ {
+ "purchaseOrderItemId": "guid | null", // null = new line, guid = update existing
+ "itemId": "guid",
+ "quantity": 120,
+ "unitCost": 83.00
+ }
+ ]
+}
+```
+
+#### Cancel PO — `POST /api/purchase-orders/{id}/cancel`
+```json
+{ "reason": "string" }
+```
+
+#### Cancel PO Line — `POST /api/purchase-orders/{id}/items/{itemId}/cancel`
+`itemId` here is the `PurchaseOrderItem.Id` (not the item's SKU ID).
+```json
+{ "reason": "string | null" }
+```
+
+#### Match Invoice — `POST /api/purchase-orders/{id}/match-invoice`
+Query params: `?invoiceId={guid}&grnId={guid}` (both optional)
+
+**Response:**
+```json
+{
+ "purchaseOrderId": "guid",
+ "goodsReceiptId": "guid | null",
+ "invoiceId": "guid | null",
+ "isMatched": true,
+ "lines": [
+ {
+ "purchaseOrderItemId": "guid",
+ "itemId": "guid",
+ "orderedQuantity": 100,
+ "acceptedQuantity": 98,
+ "unitCost": 85.00,
+ "quantityMatches": false
+ }
+ ],
+ "note": "string"
+}
+```
+
+#### Resolve Variance — `POST /api/purchase-orders/{id}/resolve-variance`
+```json
+{
+ "variance": "string", // description of the variance
+ "resolution": "string", // resolution action taken
+ "adjustedUnitCost": 84.00, // optional adjusted cost
+ "purchaseOrderItemId": "guid" // optional, which line was adjusted
+}
+```
+
+**Response:**
+```json
+{
+ "purchaseOrderId": "guid",
+ "variance": "string",
+ "resolution": "string",
+ "resolvedAt": "datetime"
+}
+```
+
+#### PO Response
+```json
+{
+ "id": "guid",
+ "supplierId": "guid",
+ "supplierName": "string",
+ "createdByUserId": "guid",
+ "status": "Issued",
+ "cancelReason": "string | null",
+ "isActive": true,
+ "createdAt": "datetime",
+ "items": [
+ {
+ "id": "guid",
+ "itemId": "guid",
+ "sku": "string",
+ "itemName": "string",
+ "quantity": 100,
+ "unitCost": 85.00,
+ "receivedQuantity": 50,
+ "cancelledQuantity": 0,
+ "isCancelled": false
+ }
+ ]
+}
+```
+
+---
+
+### 6.19 Goods Receipt Notes (GRN)
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/goods-receipts/{id}` | Get GRN by ID |
+| `GET` | `/api/purchase-orders/{id}/goods-receipts` | List GRNs for a PO |
+| `POST` | `/api/purchase-orders/{id}/goods-receipts` | Create GRN for PO |
+
+#### Create GRN — `POST /api/purchase-orders/{id}/goods-receipts`
+Returns `409 Conflict` if the PO is not in a receivable status.
+```json
+{
+ "warehouseId": "guid",
+ "items": [
+ {
+ "purchaseOrderItemId": "guid", // PO line being received
+ "acceptedQuantity": 98,
+ "rejectedQuantity": 2
+ }
+ ]
+}
+```
+
+#### GRN Response
+```json
+{
+ "id": "guid",
+ "purchaseOrderId": "guid",
+ "receivedByUserId": "guid",
+ "warehouseId": "guid",
+ "warehouseName": "string",
+ "receivedAt": "datetime",
+ "createdAt": "datetime",
+ "items": [
+ {
+ "id": "guid",
+ "purchaseOrderItemId": "guid",
+ "itemId": "guid",
+ "sku": "string",
+ "itemName": "string",
+ "acceptedQuantity": 98,
+ "rejectedQuantity": 2
+ }
+ ]
+}
+```
+
+---
+
+### 6.20 Purchase Returns
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/purchase-returns/{id}` | Get purchase return by ID |
+| `GET` | `/api/purchase-orders/{id}/returns` | List returns for a PO |
+| `POST` | `/api/purchase-orders/{id}/returns` | Create purchase return for PO |
+
+#### Create Purchase Return — `POST /api/purchase-orders/{id}/returns`
+Returns `409 Conflict` on business rule violations.
+```json
+{
+ "reason": "string",
+ "items": [
+ {
+ "itemId": "guid",
+ "quantity": 5
+ }
+ ]
+}
+```
+
+#### Purchase Return Response
+```json
+{
+ "id": "guid",
+ "purchaseOrderId": "guid",
+ "reason": "string",
+ "isActive": true,
+ "createdAt": "datetime",
+ "items": [
+ {
+ "id": "guid",
+ "itemId": "guid",
+ "sku": "string",
+ "itemName": "string",
+ "quantity": 5
+ }
+ ]
+}
+```
+
+---
+
+### 6.21 Stock
+
+**Base path:** `/api/stock`
+**Required:** JWT token (no specific permission policy)
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/stock/balances` | Get stock balances (paginated, filterable) |
+| `GET` | `/api/stock/balances/{itemId}/total` | Get total stock across all locations for item |
+| `GET` | `/api/stock/movements` | Get stock movement history (paginated, filterable) |
+| `POST` | `/api/stock/transfer` | Transfer stock between locations |
+| `POST` | `/api/stock/damage` | Record damaged stock write-off |
+| `POST` | `/api/stock/customer-return` | Record customer return to vehicle |
+| `POST` | `/api/stock/adjustment` | Record stock adjustment |
+
+#### Get Stock Balances — `GET /api/stock/balances`
+Query params (all optional):
+| Param | Type | Description |
+|---|---|---|
+| `locationId` | `guid` | Filter by specific location (warehouse or vehicle ID) |
+| `locationType` | `LocationType` | Filter by location type (`Warehouse` or `Vehicle`) |
+| `itemId` | `guid` | Filter by item |
+| `page` | `int` | Default: 1 |
+| `pageSize` | `int` | Default: 20 |
+
+**Response:** Paginated list of `StockBalanceResponse`:
+```json
+{
+ "page": 1, "pageSize": 20, "total": 100,
+ "items": [
+ {
+ "itemId": "guid",
+ "itemName": "string",
+ "locationId": "guid",
+ "locationType": "Warehouse",
+ "quantity": 250.0,
+ "updatedAt": "datetime"
+ }
+ ]
+}
+```
+
+#### Get Item Total — `GET /api/stock/balances/{itemId}/total`
+```json
+{
+ "itemId": "guid",
+ "itemName": "string",
+ "totalQuantity": 500.0,
+ "breakdown": [
+ {
+ "itemId": "guid",
+ "itemName": "string",
+ "locationId": "guid",
+ "locationType": "Vehicle",
+ "quantity": 250.0,
+ "updatedAt": "datetime"
+ }
+ ]
+}
+```
+
+#### Get Stock Movements — `GET /api/stock/movements`
+Query params (all optional):
+| Param | Type | Description |
+|---|---|---|
+| `locationId` | `guid` | Filter by location |
+| `itemId` | `guid` | Filter by item |
+| `type` | `MovementType` | Filter by movement type |
+| `from` | `datetime` | Start date filter |
+| `to` | `datetime` | End date filter |
+| `page` | `int` | Default: 1 |
+| `pageSize` | `int` | Default: 20 |
+
+**Response:** Paginated list of `StockMovementResponse`:
+```json
+{
+ "items": [
+ {
+ "id": "guid",
+ "itemId": "guid",
+ "itemName": "string",
+ "fromLocationId": "guid | null",
+ "fromLocationType": "Warehouse | null",
+ "toLocationId": "guid | null",
+ "toLocationType": "Vehicle | null",
+ "quantity": 100.0,
+ "type": "Transfer",
+ "reasonCode": "string | null",
+ "referenceId": "guid | null", // e.g. SaleId, RideId, etc.
+ "createdAt": "datetime",
+ "createdBy": "guid"
+ }
+ ]
+}
+```
+
+#### Transfer Stock — `POST /api/stock/transfer`
+```json
+{
+ "itemId": "guid",
+ "fromLocationId": "guid",
+ "fromLocationType": "Warehouse",
+ "toLocationId": "guid",
+ "toLocationType": "Vehicle",
+ "quantity": 50.0,
+ "referenceId": "guid | null" // e.g. loading sheet ID
+}
+```
+
+#### Record Damage — `POST /api/stock/damage`
+```json
+{
+ "itemId": "guid",
+ "locationId": "guid",
+ "locationType": "Warehouse",
+ "quantity": 3.0,
+ "reasonCode": "string" // e.g. "WaterDamage", "ExpiredGoods"
+}
+```
+
+#### Record Customer Return — `POST /api/stock/customer-return`
+```json
+{
+ "itemId": "guid",
+ "vehicleId": "guid", // returns go to vehicle stock
+ "quantity": 2.0,
+ "referenceId": "guid | null"
+}
+```
+
+#### Record Adjustment — `POST /api/stock/adjustment`
+```json
+{
+ "itemId": "guid",
+ "locationId": "guid",
+ "locationType": "Warehouse",
+ "quantity": -5.0, // negative = reduce stock, positive = add stock
+ "reasonCode": "string"
+}
+```
+
+---
+
+### 6.22 Driver Profiles
+
+**Base path:** `/api/driver-profiles`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/driver-profiles` | `driver_profiles.view` | List driver profiles (paginated) |
+| `GET` | `/api/driver-profiles/{id}` | `driver_profiles.view` | Get driver profile by ID |
+| `POST` | `/api/driver-profiles` | `driver_profiles.create` | Create driver profile |
+| `PUT` | `/api/driver-profiles/{id}` | `driver_profiles.update` | Update driver profile |
+| `DELETE` | `/api/driver-profiles/{id}` | `driver_profiles.deactivate` | Deactivate driver profile |
+
+#### List — `GET /api/driver-profiles?page=1&pageSize=20`
+
+#### Create Driver Profile — `POST /api/driver-profiles`
+```json
+{
+ "fK_UserId": "guid", // user to link this profile to
+ "licenseNumber": "string",
+ "licenseExpiry": "datetime",
+ "medicalClearanceExpiry": "datetime"
+}
+```
+
+#### Update Driver Profile — `PUT /api/driver-profiles/{id}`
+```json
+{
+ "licenseNumber": "string",
+ "licenseExpiry": "datetime",
+ "medicalClearanceExpiry": "datetime"
+}
+```
+
+#### Driver Profile Response
+```json
+{
+ "id": "guid",
+ "userId": "guid",
+ "userFullName": "string",
+ "licenseNumber": "string",
+ "licenseExpiry": "datetime",
+ "medicalClearanceExpiry": "datetime",
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.23 Driver Compliance Config
+
+**Base path:** `/api/driver-compliance-config`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/driver-compliance-config` | `compliance.manage` | Get current config |
+| `PUT` | `/api/driver-compliance-config` | `compliance.manage` | Create or update config |
+
+This is a singleton resource — only one config record exists system-wide.
+
+**GET response** (returns `204 No Content` if not yet configured):
+```json
+{
+ "id": "guid",
+ "enforceLicenseExpiry": true,
+ "enforceMedicalClearance": true,
+ "updatedAt": "datetime",
+ "updatedBy": "guid"
+}
+```
+
+**PUT request:**
+```json
+{
+ "enforceLicenseExpiry": true,
+ "enforceMedicalClearance": false
+}
+```
+
+---
+
+### 6.24 Rides
+
+**Base path:** `/api/rides`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/rides` | `rides.view` | List rides (paginated, filterable) |
+| `GET` | `/api/rides/{id}` | `rides.view` | Get ride detail |
+| `POST` | `/api/rides` | `rides.create` | Create ride |
+| `PUT` | `/api/rides/{id}/driver` | `rides.manage` | Assign/change driver |
+| `POST` | `/api/rides/{id}/open` | `rides.manage` | Transition to Open status |
+| `POST` | `/api/rides/{id}/activate` | `rides.manage` | Activate ride (record meter start) |
+| `POST` | `/api/rides/{id}/close` | `rides.manage` | Close ride (record meter end) |
+| `POST` | `/api/rides/{id}/cancel-request` | `rides.cancel.request` | Raise a cancel request |
+| `GET` | `/api/rides/cancel-requests` | `rides.view` | List all cancel requests |
+| `POST` | `/api/rides/cancel-requests/{id}/approve` | `rides.cancel.approve` | Approve cancel request |
+| `POST` | `/api/rides/cancel-requests/{id}/reject` | `rides.cancel.approve` | Reject cancel request |
+| `GET` | `/api/rides/{id}/cancel-request` | `rides.view` | Get cancel request for a ride |
+| `GET` | `/api/rides/breakdown-assist/{rideId}` | `rides.view` | Get breakdown assist data |
+
+#### Ride Lifecycle
+
+```
+Draft → Open → Active → Closed
+ ↓
+ CancelRequested → Cancelled
+```
+
+#### List Rides — `GET /api/rides`
+Query params (all optional):
+| Param | Type | Description |
+|---|---|---|
+| `status` | `RideStatus` | Filter by status |
+| `type` | `RideType` | Filter by ride type |
+| `driverProfileId` | `guid` | Filter by driver |
+| `vehicleId` | `guid` | Filter by vehicle |
+| `page` | `int` | Default: 1 |
+| `pageSize` | `int` | Default: 20 |
+
+#### Create Ride — `POST /api/rides`
+```json
+{
+ "rideType": "Delivery",
+ "fK_VehicleId": "guid",
+ "fK_DriverProfileId": "guid",
+ "fK_RouteId": "guid",
+ "fK_SourceWarehouseId": "guid | null"
+}
+```
+
+#### Assign Driver — `PUT /api/rides/{id}/driver`
+```json
+{ "fK_DriverProfileId": "guid" }
+```
+
+#### Open Ride — `POST /api/rides/{id}/open`
+No body required.
+
+#### Activate Ride — `POST /api/rides/{id}/activate`
+```json
+{ "meterstart": 12345 } // odometer reading at start (integer)
+```
+
+#### Close Ride — `POST /api/rides/{id}/close`
+```json
+{ "meterend": 12567 } // odometer reading at end (integer)
+```
+
+#### Raise Cancel Request — `POST /api/rides/{id}/cancel-request`
+```json
+{
+ "typeCode": "VehicleBreakdown", // CancelRequestType enum
+ "reason": "string"
+}
+```
+
+#### List Cancel Requests — `GET /api/rides/cancel-requests`
+Query params: `?status={CancelRequestStatus}&page=1&pageSize=20`
+
+#### Ride Response
+```json
+{
+ "id": "guid",
+ "rideType": "Delivery",
+ "status": "Active",
+ "vehicleId": "guid",
+ "vehicleNumberPlate": "ABC-1234",
+ "driverProfileId": "guid",
+ "driverFullName": "string",
+ "routeId": "guid",
+ "routeName": "string",
+ "sourceWarehouseId": "guid",
+ "sourceWarehouseName": "string",
+ "meterstart": 12345,
+ "meterend": 0,
+ "startedAt": "datetime | null",
+ "activatedAt": "datetime | null",
+ "closedAt": "datetime | null",
+ "createdAt": "datetime"
+}
+```
+
+#### Cancel Request Response
+```json
+{
+ "id": "guid",
+ "rideId": "guid",
+ "typeCode": "VehicleBreakdown",
+ "reason": "string",
+ "requestedBy": "guid",
+ "requestedAt": "datetime",
+ "status": "Pending",
+ "approvedBy": "guid | null",
+ "approvedAt": "datetime | null"
+}
+```
+
+#### Breakdown Assist Response — `GET /api/rides/breakdown-assist/{rideId}`
+Returns active rides on the same route with stock levels, and the open orders for the broken-down ride.
+```json
+{
+ "rideId": "guid",
+ "activeRides": [
+ {
+ "rideId": "guid",
+ "vehicleId": "guid",
+ "vehicleNumberPlate": "string",
+ "driverProfileId": "guid",
+ "driverFullName": "string",
+ "routeId": "guid",
+ "routeName": "string",
+ "stockLevels": [
+ { "itemId": "guid", "itemName": "string", "locationId": "guid", "locationType": "Vehicle", "quantity": 50.0, "updatedAt": "datetime" }
+ ]
+ }
+ ],
+ "openOrders": [
+ {
+ "orderId": "guid",
+ "storeId": "guid",
+ "storeName": "string",
+ "orderDate": "datetime",
+ "totalAmount": 25000.00
+ }
+ ]
+}
+```
+
+---
+
+### 6.25 Loading Sheets
+
+**Base path:** `/api/loading-sheets`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/loading-sheets` | `loading.view` | List loading sheets (paginated, filterable) |
+| `GET` | `/api/loading-sheets/{id}` | `loading.view` | Get loading sheet detail |
+| `POST` | `/api/loading-sheets` | `loading.dispatch` | Create loading sheet for a ride |
+| `PUT` | `/api/loading-sheets/{id}/items` | `loading.dispatch` | Set dispatched items |
+| `POST` | `/api/loading-sheets/{id}/confirm-dispatch` | `loading.dispatch` | Confirm dispatch from warehouse |
+| `PUT` | `/api/loading-sheets/{id}/receipt-items` | `loading.receive` | Set received item quantities |
+| `POST` | `/api/loading-sheets/{id}/confirm-receipt` | `loading.receive` | Driver confirms receipt |
+| `POST` | `/api/loading-sheets/{id}/resolve` | `loading.resolve` | Resolve quantity discrepancy |
+
+#### Loading Sheet Lifecycle
+
+```
+Pending → DispatchConfirmed → ReceiptConfirmed
+ ↓ (if quantities differ)
+ DiscrepancyFlagged → Resolved
+```
+
+#### List Loading Sheets — `GET /api/loading-sheets`
+Query params (all optional):
+| Param | Type | Description |
+|---|---|---|
+| `rideId` | `guid` | Filter by ride |
+| `status` | `LoadingSheetStatus` | Filter by status |
+| `page` | `int` | Default: 1 |
+| `pageSize` | `int` | Default: 20 |
+
+#### Create Loading Sheet — `POST /api/loading-sheets`
+```json
+{ "fK_RideId": "guid" }
+```
+
+#### Set Dispatched Items — `PUT /api/loading-sheets/{id}/items`
+Replaces all items on the loading sheet.
+```json
+{
+ "items": [
+ { "fK_ItemId": "guid", "quantity": 100.0 }
+ ]
+}
+```
+
+#### Confirm Dispatch — `POST /api/loading-sheets/{id}/confirm-dispatch`
+No body required. Transitions status to `DispatchConfirmed`.
+
+#### Set Receipt Items — `PUT /api/loading-sheets/{id}/receipt-items`
+```json
+{
+ "items": [
+ { "fK_ItemId": "guid", "quantityReceived": 98.0 }
+ ]
+}
+```
+
+#### Confirm Receipt — `POST /api/loading-sheets/{id}/confirm-receipt`
+```json
+{ "meterstart": 12345 } // driver's vehicle odometer at receipt
+```
+
+#### Resolve Discrepancy — `POST /api/loading-sheets/{id}/resolve`
+```json
+{
+ "items": [
+ { "fK_ItemId": "guid", "quantityResolved": 98.0 }
+ ],
+ "meterstart": 12345
+}
+```
+
+#### Loading Sheet Response
+```json
+{
+ "id": "guid",
+ "fK_RideId": "guid",
+ "fK_SourceWarehouseId": "guid",
+ "warehouseName": "string",
+ "status": "Pending",
+ "dispatchConfirmedAt": "datetime | null",
+ "dispatchConfirmedBy": "guid | null",
+ "receiptConfirmedAt": "datetime | null",
+ "receiptConfirmedBy": "guid | null",
+ "createdAt": "datetime",
+ "items": [
+ {
+ "id": "guid",
+ "fK_ItemId": "guid",
+ "itemName": "string",
+ "quantityDispatched": 100.0,
+ "quantityReceived": 98.0,
+ "quantityResolved": 98.0
+ }
+ ]
+}
+```
+
+---
+
+### 6.26 Delivery Tasks
+
+**Base path:** `/api` (mixed routes — see below)
+
+| Method | Path | Description |
+|---|---|---|
+| `POST` | `/api/rides/{rideId}/tasks/generate` | Auto-generate delivery tasks from ride's orders |
+| `GET` | `/api/rides/{rideId}/tasks` | List all tasks for a ride |
+| `GET` | `/api/delivery-tasks/{id}` | Get delivery task by ID |
+| `PUT` | `/api/delivery-tasks/{id}/quantities` | Set fulfilled quantities per item |
+| `POST` | `/api/delivery-tasks/{id}/confirm` | Mark task as delivered |
+| `POST` | `/api/delivery-tasks/{id}/fail` | Mark task as failed |
+
+#### Generate Tasks — `POST /api/rides/{rideId}/tasks/generate`
+No body. Generates one `DeliveryTask` per store/order on the ride.
+Returns `400 Bad Request` if ride is not in a valid state, `404 Not Found` if ride not found.
+
+**Response:** Array of `DeliveryTaskResponse`.
+
+#### Set Quantities — `PUT /api/delivery-tasks/{id}/quantities`
+```json
+{
+ "items": [
+ { "itemId": "guid", "quantityFulfilled": 8 }
+ ]
+}
+```
+
+#### Fail Task — `POST /api/delivery-tasks/{id}/fail`
+```json
+{ "note": "string" } // reason for failure
+```
+
+#### Delivery Task Response
+```json
+{
+ "id": "guid",
+ "fK_RideId": "guid",
+ "fK_OrderId": "guid",
+ "storeId": "guid",
+ "storeName": "string",
+ "sequence": 1,
+ "status": "Pending",
+ "customerConfirmed": false,
+ "confirmedAt": "datetime | null",
+ "note": "string | null",
+ "items": [
+ {
+ "itemId": "guid",
+ "itemName": "string",
+ "quantity": 10,
+ "quantityFulfilled": 8,
+ "unitPrice": 150.00
+ }
+ ],
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.27 Sales
+
+**Base path:** `/api/sales`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/sales` | `orders.view` | List all sales |
+| `GET` | `/api/sales/{id}` | `orders.view` | Get sale detail |
+| `GET` | `/api/sales/store/{storeId}` | `orders.view` | Get sales for a store (scope-enforced) |
+| `POST` | `/api/sales` | `orders.create` | Create a new sale |
+
+> `GET /api/sales/store/{storeId}` returns `403 Forbidden` if current user's scope does not include that store.
+
+#### Create Sale — `POST /api/sales`
+```json
+{
+ "storeId": "guid",
+ "saleDate": "datetime",
+ "totalAmount": 45000.00,
+ "fulfillImmediately": false, // if true, immediately fulfills the linked order
+ "rideId": "guid | null", // associate with a ride (for mobile sales)
+ "items": [
+ {
+ "itemId": "guid",
+ "quantity": 10,
+ "unitPrice": null // null = use price list; decimal = override price
+ }
+ ]
+}
+```
+
+**Returns `403 Forbidden`** if current user's scope doesn't include the store.
+
+#### Sale Response
+```json
+{
+ "id": "guid",
+ "saleDate": "datetime",
+ "storeId": "guid",
+ "createdByUserId": "guid",
+ "rideId": "guid | null",
+ "totalAmount": 45000.00,
+ "status": "Pending",
+ "paymentStatus": "Pending",
+ "fulfillImmediately": false,
+ "completedAt": "datetime | null",
+ "orderId": "guid", // the linked Order record
+ "orderStatus": "Pending",
+ "orderFulfilledAt": "datetime | null",
+ "items": [
+ {
+ "itemId": "guid",
+ "quantity": 10,
+ "quantityFulfilled": 0,
+ "unitPrice": 150.00
+ }
+ ],
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.28 Orders
+
+**Base path:** `/api/orders`
+
+| Method | Path | Permission | Description |
+|---|---|---|---|
+| `GET` | `/api/orders` | `orders.view` | List all orders |
+| `GET` | `/api/orders/{id}` | `orders.view` | Get order by ID |
+| `GET` | `/api/orders/store/{storeId}` | `orders.view` | Get orders for a store (scope-enforced) |
+| `POST` | `/api/orders` | `orders.create` | Create order (linked to a sale) |
+| `PUT` | `/api/orders/{id}` | `orders.update` | Update order status |
+| `DELETE` | `/api/orders/{id}` | `orders.delete` | Delete order |
+| `POST` | `/api/orders/{id}/apply-scheme` | — | Apply a scheme to order |
+
+> `GET /api/orders/store/{storeId}` and `POST /api/orders` return `403 Forbidden` if scope is not satisfied.
+
+#### Create Order — `POST /api/orders`
+```json
+{ "saleId": "guid" }
+```
+
+#### Update Order — `PUT /api/orders/{id}`
+```json
+{ "status": "Fulfilled" } // OrderStatus enum
+```
+
+#### Order Response
+```json
+{
+ "id": "guid",
+ "saleId": "guid",
+ "orderDate": "datetime",
+ "storeId": "guid",
+ "totalAmount": 45000.00,
+ "status": "Pending",
+ "fulfilledAt": "datetime | null",
+ "items": [
+ {
+ "itemId": "guid",
+ "quantity": 10,
+ "quantityFulfilled": 0,
+ "unitPrice": 150.00
+ }
+ ],
+ "isActive": true,
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.29 Payments
+
+**Base path:** `/api/sales/{saleId}/payments`
+
+| Method | Path | Description |
+|---|---|---|
+| `GET` | `/api/sales/{saleId}/payments` | Get all payments for a sale |
+| `POST` | `/api/sales/{saleId}/payments` | Record a payment for a sale |
+
+> `GET` returns `404 Not Found` if the sale doesn't exist.
+> `POST` returns `404 Not Found` if the sale doesn't exist, `400 Bad Request` if payment already complete.
+
+#### Create Payment — `POST /api/sales/{saleId}/payments`
+```json
+{
+ "amount": 25000.00,
+ "method": "Cash" // PaymentMethod enum
+}
+```
+
+#### Payment Response
+```json
+{
+ "id": "guid",
+ "saleId": "guid",
+ "storeId": "guid",
+ "amount": 25000.00,
+ "method": "Cash",
+ "collectedAt": "datetime",
+ "collectedBy": "guid", // user who recorded the payment
+ "createdAt": "datetime"
+}
+```
+
+---
+
+### 6.30 Sync (ERP Import)
+
+**Base path:** `/api/sync`
+**Required permission:** `items.create`
+
+These endpoints are for bulk import from an external ERP system. Each payload is idempotent — existing records (matched by `erpId`) are updated; new records are inserted.
+
+| Method | Path | Description |
+|---|---|---|
+| `POST` | `/api/sync/uoms` | Bulk upsert units of measure |
+| `POST` | `/api/sync/categories` | Bulk upsert categories + subcategories |
+| `POST` | `/api/sync/brands` | Bulk upsert brands |
+| `POST` | `/api/sync/items` | Bulk upsert items |
+
+#### Sync UOMs — `POST /api/sync/uoms`
+```json
+{
+ "items": [
+ { "erpId": 101, "name": "Piece" }
+ ]
+}
+```
+
+#### Sync Categories — `POST /api/sync/categories`
+```json
+{
+ "items": [
+ {
+ "erpId": 10,
+ "name": "Beverages",
+ "subCategories": [
+ { "erpId": 101, "name": "Soft Drinks", "parentErpId": 10 }
+ ]
+ }
+ ]
+}
+```
+
+#### Sync Brands — `POST /api/sync/brands`
+```json
+{
+ "items": [
+ { "erpId": 201, "name": "Coca-Cola" }
+ ]
+}
+```
+
+#### Sync Items — `POST /api/sync/items`
+```json
+{
+ "items": [
+ {
+ "erpId": 5001,
+ "sku": "CC-330ML",
+ "name": "Coca-Cola 330ml",
+ "description": "string | null",
+ "categoryErpId": 10,
+ "subCategoryErpId": 101,
+ "brandErpId": 201,
+ "baseUomErpId": 101,
+ "salePrice": 65.00,
+ "isActive": true
+ }
+ ]
+}
+```
+
+#### Sync Result Response (all sync endpoints)
+```json
+{
+ "inserted": 5,
+ "updated": 12,
+ "skipped": 0
+}
+```
+
+---
+
+## 7. Business Flows
+
+End-to-end sequences showing which API calls to make, in order, for each major workflow. Every step maps directly to an endpoint documented in Section 6.
+
+---
+
+### 7.1 Region → Route → Store Setup
+
+This is the master data foundation. Everything else (rides, sales, delivery) depends on it existing first.
+
+```
+1. POST /api/regions → creates a region (geographic area)
+2. POST /api/routes → creates a route inside that region
+ (requires regionId)
+3. POST /api/stores → creates a store on that route
+ (requires routeId)
+4. POST /api/stores/{id}/kyc-documents → upload KYC docs for the store
+5. PUT /api/stores/{id}/kyc/verify → approve/reject KYC
+ (kycStatus: Verified unlocks full ordering)
+```
+
+**Key rules:**
+- A store belongs to exactly one route; a route belongs to exactly one region.
+- Stores with `KycStatus = Pending` can only place orders up to the configured threshold (default 0 — meaning blocked). Verify KYC before the store can transact.
+- Users are scoped to regions/routes/stores via `PUT /api/users/{id}/scope`. Scoped users only see and operate on data within their assigned scope.
+
+---
+
+### 7.2 Sale Flow (Sales Run)
+
+Used when a sales rep visits a store and records a sale on the spot. The sale and its linked order are created atomically.
+
+```
+1. POST /api/sales
+ body: { storeId, saleDate, totalAmount, fulfillImmediately, rideId?, items[] }
+ → creates Sale + Order in one call
+ → Sale.status = Pending, Order.status = Pending (if fulfillImmediately: false)
+ → Sale.status = Completed, Order.status = Fulfilled (if fulfillImmediately: true)
+
+2. (Optional) GET /api/schemes/eligible?storeId=...&orderId=...
+ → find promotions the store qualifies for
+
+3. (Optional) POST /api/orders/{orderId}/apply-scheme
+ body: { schemeId }
+ → applies discount or free-goods scheme to the order
+
+4. POST /api/sales/{saleId}/payments
+ body: { amount, method: "Cash"|"Credit" }
+ → records a payment; Sale.paymentStatus updates automatically:
+ Pending → PartiallyPaid → Paid (based on cumulative total vs totalAmount)
+ → repeat this step for partial payments
+```
+
+**Price resolution (automatic on sale creation):**
+- If `items[].unitPrice` is `null`, the system looks up the active price list for the store's region and uses that price.
+- If `unitPrice` is supplied, it must fall within `[minPrice, price]` from the price list. Prices outside this range cause the sale to be rejected (`null` response → treat as validation error).
+
+**Stock deduction (when `fulfillImmediately: true` + `rideId` supplied):**
+- The system checks that the vehicle has sufficient stock for every item.
+- Stock is deducted from the vehicle immediately and a `Sale` movement is recorded.
+- If any item lacks stock, the entire sale creation fails.
+
+**Scope enforcement:**
+- The creating user must have scope access to the store, otherwise `403 Forbidden` is returned.
+
+---
+
+### 7.3 Delivery Flow (End-to-End Ride Lifecycle)
+
+The full sequence for a delivery run — from creating the ride to closing it out.
+
+#### Step 1 — Set up the ride (Draft)
+```
+POST /api/rides
+body: { rideType: "Delivery", fK_VehicleId, fK_DriverProfileId, fK_RouteId, fK_SourceWarehouseId? }
+→ Ride.status = Draft
+
+PUT /api/rides/{id}/driver ← optional, change driver while still Draft
+body: { fK_DriverProfileId }
+```
+
+#### Step 2 — Open the ride (Draft → Open)
+```
+POST /api/rides/{id}/open
+→ Ride.status = Open
+```
+
+**Blocked if:**
+- The vehicle already has another Open or Active ride.
+- Driver compliance is enforced and the driver's license or medical clearance has expired.
+
+#### Step 3 — Create & confirm the loading sheet (Open ride required)
+```
+POST /api/loading-sheets
+body: { fK_RideId }
+→ LoadingSheet.status = Pending
+ (For Delivery rides: items are auto-populated from pending orders on the route.
+ For Sale rides: items must be added manually in the next step.)
+
+PUT /api/loading-sheets/{id}/items ← set/adjust dispatched quantities
+body: { items: [{ fK_ItemId, quantity }] }
+
+POST /api/loading-sheets/{id}/confirm-dispatch
+→ LoadingSheet.status = DispatchConfirmed
+ (Warehouse side confirms the goods left the warehouse)
+```
+
+#### Step 4 — Driver receives stock & ride goes Active
+```
+PUT /api/loading-sheets/{id}/receipt-items ← driver records what they actually received
+body: { items: [{ fK_ItemId, quantityReceived }] }
+
+POST /api/loading-sheets/{id}/confirm-receipt
+body: { meterstart: 12345 }
+→ if quantities match dispatched:
+ LoadingSheet.status = ReceiptConfirmed
+ Stock transfers from Warehouse → Vehicle (Load movement recorded)
+ Ride.status = Active, Ride.meterstart set
+
+→ if quantities differ:
+ LoadingSheet.status = DiscrepancyFlagged
+ (Ride stays Open; must resolve before activation)
+
+POST /api/loading-sheets/{id}/resolve ← if DiscrepancyFlagged
+body: { items: [{ fK_ItemId, quantityResolved }], meterstart }
+→ LoadingSheet.status = Resolved
+ Stock transfers using resolved quantities
+ Ride.status = Active
+```
+
+#### Step 5 — Generate delivery tasks & execute deliveries (Active ride, Delivery type only)
+```
+POST /api/rides/{rideId}/tasks/generate
+→ creates one DeliveryTask per pending order on the route
+ (idempotent — skips orders that already have a task for this ride)
+
+GET /api/rides/{rideId}/tasks ← list tasks to display the delivery sequence
+
+For each task:
+ PUT /api/delivery-tasks/{id}/quantities
+ body: { items: [{ itemId, quantityFulfilled }] }
+ → set how much was actually delivered per item
+
+ POST /api/delivery-tasks/{id}/confirm
+ → DeliveryTask.status = Delivered (all qty) or PartiallyDelivered
+ Order.status = Fulfilled or PartiallyFulfilled
+ Sale.status = Completed (if fully delivered)
+ Stock deducted from Vehicle (Sale movement recorded)
+
+ — OR —
+
+ POST /api/delivery-tasks/{id}/fail
+ body: { note: "reason" }
+ → DeliveryTask.status = Failed (stock not deducted)
+```
+
+#### Step 6 — Close the ride (Active → Closed)
+```
+POST /api/rides/{id}/close
+body: { meterend: 12567 }
+→ Ride.status = Closed
+```
+
+**Blocked if:** The vehicle still has stock with quantity > 0. All stock must be returned (via transfer, damage, or customer-return endpoints) before closing.
+
+---
+
+### 7.4 Ride Cancellation Flow
+
+Applies when a ride is Active and something goes wrong (breakdown, driver issue, etc.).
+
+```
+POST /api/rides/{id}/cancel-request
+body: { typeCode: "VehicleBreakdown", reason: "string" }
+→ Ride.status = CancelRequested
+ RideCancelRequest.status = Pending
+
+GET /api/rides/cancel-requests?status=Pending ← supervisor polls for pending requests
+GET /api/rides/{id}/cancel-request ← check status for a specific ride
+
+POST /api/rides/cancel-requests/{requestId}/approve
+→ RideCancelRequest.status = Approved
+ Ride.status = Cancelled
+ (Blocked if vehicle still has stock)
+
+— OR —
+
+POST /api/rides/cancel-requests/{requestId}/reject
+→ RideCancelRequest.status = Rejected
+ Ride.status = Active (restored)
+```
+
+**Breakdown Assist** — when a ride is cancelled mid-route, use this to find a replacement:
+```
+GET /api/rides/breakdown-assist/{cancelledRideId}
+→ returns: other Active rides on the same route with their current vehicle stock levels
+ + open orders from the cancelled ride's route
+```
+
+---
+
+### 7.5 Payment Flow
+
+Payments are recorded against a Sale after it is created. Multiple partial payments are supported.
+
+```
+1. POST /api/sales ← sale created; paymentStatus = Pending
+
+2. POST /api/sales/{saleId}/payments
+ body: { amount: 25000.00, method: "Cash" }
+ → payment recorded; sale.paymentStatus updated:
+ sum(payments) == 0 → Pending
+ sum(payments) < totalAmount → PartiallyPaid
+ sum(payments) >= totalAmount → Paid
+
+3. Repeat step 2 for additional instalments.
+
+4. GET /api/sales/{saleId}/payments ← list all payments for the sale
+```
+
+**Rules:**
+- Cannot record payment against a `Cancelled` sale — returns `400 Bad Request`.
+- No upper limit enforced — overpayment is allowed (handle reconciliation in the UI).
+- `collectedBy` is automatically set from the authenticated user's ID.
+
+---
+
+### 7.6 Purchase Order Flow (Procurement)
+
+```
+1. POST /api/purchase-orders
+ body: { supplierId, items: [{ itemId, quantity, unitCost }] }
+ → PO.status = Issued
+
+2. (Optional) PUT /api/purchase-orders/{id} ← edit lines while Issued only
+ body: { items: [{ purchaseOrderItemId?, itemId, quantity, unitCost }] }
+ (purchaseOrderItemId null = add new line, guid = update existing)
+
+3. POST /api/purchase-orders/{id}/goods-receipts ← goods arrive at warehouse
+ body: { warehouseId, items: [{ purchaseOrderItemId, acceptedQuantity, rejectedQuantity }] }
+ → GRN created; stock added to Warehouse (PurchaseReceipt movement)
+ → PO.status = PartiallyReceived or Received (if all lines fully received)
+
+4. POST /api/purchase-orders/{id}/match-invoice ← optional 3-way match
+ query: ?grnId=...&invoiceId=...
+ → returns line-by-line comparison of ordered vs received quantities
+
+5. (if discrepancy) POST /api/purchase-orders/{id}/resolve-variance
+ body: { variance, resolution, adjustedUnitCost?, purchaseOrderItemId? }
+
+6. POST /api/purchase-orders/{id}/close ← manually close when done
+ → PO.status = Closed
+
+ — OR —
+
+ POST /api/purchase-orders/{id}/cancel ← cancel entire PO (Issued only)
+ body: { reason }
+
+ POST /api/purchase-orders/{id}/items/{itemId}/cancel ← cancel one line (Issued only)
+ body: { reason? }
+```
+
+**Returns:** `GET /api/purchase-orders/{id}/returns` / `POST /api/purchase-orders/{id}/returns`
+Record supplier return: `{ reason, items: [{ itemId, quantity }] }` → stock deducted from Warehouse (PurchaseReturn movement).
+
+---
+
+### 7.7 Loading Sheet Flow (Detail)
+
+The loading sheet controls the physical movement of stock from warehouse to vehicle. It sits between "ride opened" and "ride active".
+
+```
+Status machine:
+Pending ──► DispatchConfirmed ──► ReceiptConfirmed (clean)
+ └──► DiscrepancyFlagged ──► Resolved
+```
+
+| Status | Who acts | What happens to stock |
+|---|---|---|
+| `Pending` | Warehouse staff | No stock movement yet; edit items freely |
+| `DispatchConfirmed` | Warehouse staff | Goods physically leave warehouse; no stock change yet |
+| `ReceiptConfirmed` | Driver | Stock transferred Warehouse → Vehicle; ride goes Active |
+| `DiscrepancyFlagged` | System | Quantities differ; ride stays Open; waiting for resolution |
+| `Resolved` | Supervisor | Resolved quantities transferred; ride goes Active |
+
+**Important:** confirming receipt (or resolving discrepancy) is what actually activates the ride and loads stock onto the vehicle. The `meterstart` odometer reading is recorded at this point.
+
+---
+
+### 7.8 Stock Flow (How Stock Moves)
+
+Stock is tracked per item per location (Warehouse or Vehicle). Every write operation creates an immutable `StockMovement` record.
+
+| Trigger | API call | Movement type | Direction |
+|---|---|---|---|
+| GRN received | `POST /api/purchase-orders/{id}/goods-receipts` | `PurchaseReceipt` | → Warehouse |
+| Loading sheet confirmed | `POST /api/loading-sheets/{id}/confirm-receipt` | `Load` | Warehouse → Vehicle |
+| Sale fulfilled (immediate) | `POST /api/sales` (fulfillImmediately: true) | `Sale` | Vehicle → (out) |
+| Delivery task confirmed | `POST /api/delivery-tasks/{id}/confirm` | `Sale` | Vehicle → (out) |
+| Customer returns goods | `POST /api/stock/customer-return` | `CustomerReturn` | → Vehicle |
+| Supplier return | `POST /api/purchase-orders/{id}/returns` | `PurchaseReturn` | Warehouse → (out) |
+| Manual transfer | `POST /api/stock/transfer` | `Transfer` | Any → Any |
+| Damage write-off | `POST /api/stock/damage` | `Damage` | Location → (out) |
+| Manual correction | `POST /api/stock/adjustment` | `Adjustment` | Location ± delta |
+
+**Closing a ride requires zero vehicle stock.** Any remaining stock must be transferred back to a warehouse, recorded as damage, or returned by the customer before `POST /api/rides/{id}/close` will succeed.
+
+---
+
+### 7.9 Scheme / Promotion Flow
+
+```
+1. POST /api/schemes ← create a promotion
+ body: { name, ruleType, ruleConfig?, regionId?, eligibleSegment?,
+ dateRangeFrom, dateRangeTo, agentLimitExempt, baselineExpectedSales?,
+ ...optional free-goods fields }
+
+2. (if BuyXGetY or FreeBundle)
+ PUT /api/schemes/{id}/free-goods-rule
+ PUT /api/schemes/{id}/bundle-components/{itemId}
+
+3. At order time:
+ GET /api/schemes/eligible?storeId=...&orderId=...
+ → returns which schemes the store qualifies for, with discount/free-goods amounts
+
+4. POST /api/orders/{orderId}/apply-scheme
+ body: { schemeId }
+ → scheme applied to the order; SchemeRedemption recorded
+
+5. Analytics:
+ GET /api/schemes/{id}/spend ← total cost of scheme so far
+ GET /api/schemes/{id}/roi ← ROI vs baseline expected sales
+```
+
+**Rule types quick reference:**
+
+| Type | `ruleConfig` JSON | Trigger | Payout |
+|---|---|---|---|
+| `FlatPercent` | `{"discountPercent": 10.0}` | Any order | % off total |
+| `SlabDiscount` | `{"tiers":[{"minOrderAmount":10000,"discountPercent":5},...]}` | Order value reaches slab | % off total |
+| `BuyXGetY` | `null` | Buy N of trigger item | Free qty of free item |
+| `FreeBundle` | `null` | Buy all bundle components | Free qty of free item |
+
+---
+
+## Appendix A — Common Business Rules
+
+1. **Store KYC threshold:** A store with `KycStatus = Pending` has an order threshold of `0` (configurable via `StoreManagement:UnverifiedKycOrderThreshold`). Orders for unverified stores may be blocked or limited.
+
+2. **Credit enforcement:** On sale creation, the system checks `OutstandingBalance + saleAmount ≤ CreditLimit`. Exceeding this will block the sale.
+
+3. **Driver compliance:** When `EnforceLicenseExpiry = true`, a ride cannot be opened/activated if the assigned driver's license has expired. Same for `EnforceMedicalClearance`.
+
+4. **Ride state machine:** Transitions are strictly enforced — calling `open` on a non-Draft ride, `activate` on a non-Open ride, etc. returns `400 Bad Request`.
+
+5. **Loading sheet discrepancy:** When `ConfirmReceipt` is called and received quantities differ from dispatched quantities, the sheet automatically transitions to `DiscrepancyFlagged` instead of `ReceiptConfirmed`.
+
+6. **PO line cancellation:** Individual lines can be cancelled only while the PO is `Issued`. The entire PO can only be cancelled while `Issued`.
+
+7. **Scheme eligibility:** A scheme applies to a store only if the store's segment matches `EligibleSegment` (or the scheme has no segment restriction), the scheme is within its date range, and the region matches (or scheme has no region restriction).
+
+8. **Agent discount ceiling:** A role's `Level` field controls the maximum discount an agent can apply. Schemes with `AgentLimitExempt = true` stack on top regardless of this ceiling.
+
+9. **Scope enforcement:** Users with an empty scope list for a scope type (regions/routes/stores) are assumed to have **no restriction** for that type (system-wide access). Only explicitly listed IDs restrict access.
+
+---
+
+## Appendix B — Frontend Implementation Notes
+
+### Token / Session Strategy
+> ⚠️ **YET TO IMPLEMENT** — Auth mechanism not yet decided. Do not implement token storage until Section 1 is finalized.
+
+### Permission Gating
+Once auth is implemented, call `GET /api/roles/{roleId}/permissions` on login to pre-fetch all permissions for the session. Cache them client-side and use them to show/hide UI elements. The role ID will come from whatever credential the Auth Service issues.
+
+### Enum Serialization
+The API serializes enums as **strings** by default in ASP.NET Core `System.Text.Json` — verify with your actual deployment. If numbers are returned, map them using the tables in Section 4.
+
+### GUID Format
+Always send GUIDs as lowercase hyphenated strings: `"3fa85f64-5717-4562-b3fc-2c963f66afa6"`.
+
+### Date Format
+Send all dates as ISO 8601 strings. For date-only fields (license expiry), include a time component: `"2026-12-31T00:00:00Z"`.
+
+### Pagination
+For paginated endpoints, always implement `page` / `pageSize` query params in the UI. Default `pageSize` is `20`.
+
+### File Upload
+KYC document upload uses `multipart/form-data`. Do not set `Content-Type` manually when using browser `FormData` — the browser sets it with the boundary automatically.
+
+### Error Handling
+- `400` errors include `{ "error": "descriptive message" }` — surface this to the user.
+- `404` — show "not found" state.
+- `409` — show the conflict message from `{ "error": "..." }`.
+- `401` — redirect to login.
+- `403` — show "access denied" / hide the action.