From a2e8733693dfa2326ac4c4d7a34432e9c1cb30d6 Mon Sep 17 00:00:00 2001
From: David Strejc
Date: Sun, 8 Mar 2026 16:11:17 +0100
Subject: [PATCH 01/26] feat: scaffold website with Vite + React + Tailwind
design system
Co-Authored-By: Claude Opus 4.6
---
website/index.html | 17 +
website/package-lock.json | 2612 +++++++++++++++++++++++++++++
website/package.json | 34 +
website/public/favicon.svg | 10 +
website/src/App.tsx | 15 +
website/src/components/Layout.tsx | 35 +
website/src/i18n/index.ts | 18 +
website/src/index.css | 32 +
website/src/main.tsx | 11 +
website/src/pages/HomePage.tsx | 3 +
website/tsconfig.json | 19 +
website/vite.config.ts | 13 +
12 files changed, 2819 insertions(+)
create mode 100644 website/index.html
create mode 100644 website/package-lock.json
create mode 100644 website/package.json
create mode 100644 website/public/favicon.svg
create mode 100644 website/src/App.tsx
create mode 100644 website/src/components/Layout.tsx
create mode 100644 website/src/i18n/index.ts
create mode 100644 website/src/index.css
create mode 100644 website/src/main.tsx
create mode 100644 website/src/pages/HomePage.tsx
create mode 100644 website/tsconfig.json
create mode 100644 website/vite.config.ts
diff --git a/website/index.html b/website/index.html
new file mode 100644
index 0000000..09c6055
--- /dev/null
+++ b/website/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+ AigisCode — AI-Powered Code Guardian
+
+
+
+
+
+
diff --git a/website/package-lock.json b/website/package-lock.json
new file mode 100644
index 0000000..240ece7
--- /dev/null
+++ b/website/package-lock.json
@@ -0,0 +1,2612 @@
+{
+ "name": "aigiscode-website",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "aigiscode-website",
+ "version": "1.0.0",
+ "dependencies": {
+ "@phosphor-icons/react": "^2.1.10",
+ "@tailwindcss/vite": "^4.1.14",
+ "@vitejs/plugin-react": "^5.0.4",
+ "i18next": "^25.8.13",
+ "i18next-browser-languagedetector": "^8.2.1",
+ "motion": "^12.23.24",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "react-i18next": "^16.5.4",
+ "react-router-dom": "^7.13.0",
+ "vite": "^6.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^22.14.0",
+ "@types/react": "^19.0.0",
+ "@types/react-dom": "^19.0.0",
+ "autoprefixer": "^10.4.21",
+ "tailwindcss": "^4.1.14",
+ "typescript": "~5.8.2"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
+ "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helpers": "^7.28.6",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@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.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@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-compilation-targets": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.28.6",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
+ "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
+ "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
+ "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "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/@phosphor-icons/react": {
+ "version": "2.1.10",
+ "resolved": "https://registry.npmjs.org/@phosphor-icons/react/-/react-2.1.10.tgz",
+ "integrity": "sha512-vt8Tvq8GLjheAZZYa+YG/pW7HDbov8El/MANW8pOAz4eGxrwhnbfrQZq0Cp4q8zBEu8NIhHdnr+r8thnfRSNYA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8",
+ "react-dom": ">= 16.8"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
+ "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==",
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
+ "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
+ "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
+ "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
+ "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
+ "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
+ "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
+ "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
+ "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
+ "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
+ "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
+ "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
+ "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
+ "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
+ "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
+ "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
+ "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
+ "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
+ "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
+ "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
+ "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
+ "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
+ "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
+ "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@tailwindcss/node": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz",
+ "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.5",
+ "enhanced-resolve": "^5.19.0",
+ "jiti": "^2.6.1",
+ "lightningcss": "1.31.1",
+ "magic-string": "^0.30.21",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.2.1"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz",
+ "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.2.1",
+ "@tailwindcss/oxide-darwin-arm64": "4.2.1",
+ "@tailwindcss/oxide-darwin-x64": "4.2.1",
+ "@tailwindcss/oxide-freebsd-x64": "4.2.1",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.2.1",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.2.1",
+ "@tailwindcss/oxide-linux-x64-musl": "4.2.1",
+ "@tailwindcss/oxide-wasm32-wasi": "4.2.1",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.2.1"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz",
+ "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz",
+ "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz",
+ "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz",
+ "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz",
+ "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz",
+ "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz",
+ "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz",
+ "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz",
+ "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz",
+ "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.8.1",
+ "@emnapi/runtime": "^1.8.1",
+ "@emnapi/wasi-threads": "^1.1.0",
+ "@napi-rs/wasm-runtime": "^1.1.1",
+ "@tybys/wasm-util": "^0.10.1",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz",
+ "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz",
+ "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/vite": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.1.tgz",
+ "integrity": "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==",
+ "license": "MIT",
+ "dependencies": {
+ "@tailwindcss/node": "4.2.1",
+ "@tailwindcss/oxide": "4.2.1",
+ "tailwindcss": "4.2.1"
+ },
+ "peerDependencies": {
+ "vite": "^5.2.0 || ^6 || ^7"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.19.15",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz",
+ "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.14",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz",
+ "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.29.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-rc.3",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.18.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+ }
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.27",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz",
+ "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.1",
+ "caniuse-lite": "^1.0.30001774",
+ "fraction.js": "^5.3.4",
+ "picocolors": "^1.1.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
+ "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==",
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "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.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001777",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz",
+ "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==",
+ "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/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": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.307",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz",
+ "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==",
+ "license": "ISC"
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz",
+ "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==",
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.3.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
+ }
+ },
+ "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/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/fraction.js": {
+ "version": "5.3.4",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
+ "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/framer-motion": {
+ "version": "12.35.1",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.35.1.tgz",
+ "integrity": "sha512-rL8cLrjYZNShZqKV3U0Qj6Y5WDiZXYEM5giiTLfEqsIZxtspzMDCkKmrO5po76jWfvOg04+Vk+sfBvTD0iMmLw==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-dom": "^12.35.1",
+ "motion-utils": "^12.29.2",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "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/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/html-parse-stringify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
+ "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
+ "license": "MIT",
+ "dependencies": {
+ "void-elements": "3.1.0"
+ }
+ },
+ "node_modules/i18next": {
+ "version": "25.8.14",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.14.tgz",
+ "integrity": "sha512-paMUYkfWJMsWPeE/Hejcw+XLhHrQPehem+4wMo+uELnvIwvCG019L9sAIljwjCmEMtFQQO3YeitJY8Kctei3iA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.28.4"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/i18next-browser-languagedetector": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz",
+ "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
+ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "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/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/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/lightningcss": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz",
+ "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==",
+ "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.31.1",
+ "lightningcss-darwin-arm64": "1.31.1",
+ "lightningcss-darwin-x64": "1.31.1",
+ "lightningcss-freebsd-x64": "1.31.1",
+ "lightningcss-linux-arm-gnueabihf": "1.31.1",
+ "lightningcss-linux-arm64-gnu": "1.31.1",
+ "lightningcss-linux-arm64-musl": "1.31.1",
+ "lightningcss-linux-x64-gnu": "1.31.1",
+ "lightningcss-linux-x64-musl": "1.31.1",
+ "lightningcss-win32-arm64-msvc": "1.31.1",
+ "lightningcss-win32-x64-msvc": "1.31.1"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz",
+ "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==",
+ "cpu": [
+ "arm64"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz",
+ "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==",
+ "cpu": [
+ "arm64"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz",
+ "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==",
+ "cpu": [
+ "x64"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz",
+ "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==",
+ "cpu": [
+ "x64"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz",
+ "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==",
+ "cpu": [
+ "arm"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz",
+ "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==",
+ "cpu": [
+ "arm64"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz",
+ "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==",
+ "cpu": [
+ "arm64"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz",
+ "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==",
+ "cpu": [
+ "x64"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz",
+ "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==",
+ "cpu": [
+ "x64"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz",
+ "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==",
+ "cpu": [
+ "arm64"
+ ],
+ "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.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz",
+ "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/motion": {
+ "version": "12.35.1",
+ "resolved": "https://registry.npmjs.org/motion/-/motion-12.35.1.tgz",
+ "integrity": "sha512-yEt/49kWC0VU/IEduDfeZw82eDemlPwa1cyo/gcEEUCN4WgpSJpUcxz6BUwakGabvJiTzLQ58J73515I5tfykQ==",
+ "license": "MIT",
+ "dependencies": {
+ "framer-motion": "^12.35.1",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/motion-dom": {
+ "version": "12.35.1",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.35.1.tgz",
+ "integrity": "sha512-7n6r7TtNOsH2UFSAXzTkfzOeO5616v9B178qBIjmu/WgEyJK0uqwytCEhwKBTuM/HJA40ptAw7hLFpxtPAMRZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-utils": "^12.29.2"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.29.2",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.29.2.tgz",
+ "integrity": "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==",
+ "license": "MIT"
+ },
+ "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.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "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/node-releases": {
+ "version": "2.0.36",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
+ "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
+ "license": "MIT"
+ },
+ "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": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.8",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
+ "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "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.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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-i18next": {
+ "version": "16.5.6",
+ "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.6.tgz",
+ "integrity": "sha512-Ua7V2/efA88ido7KyK51fb8Ki8M/sRfW8LR/rZ/9ZKr2luhuTI7kwYZN5agT1rWG7aYm5G0RYE/6JR8KJoCMDw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.28.4",
+ "html-parse-stringify": "^3.0.1",
+ "use-sync-external-store": "^1.6.0"
+ },
+ "peerDependencies": {
+ "i18next": ">= 25.6.2",
+ "react": ">= 16.8.0",
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
+ "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "7.13.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz",
+ "integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.13.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.1.tgz",
+ "integrity": "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.13.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
+ "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.59.0",
+ "@rollup/rollup-android-arm64": "4.59.0",
+ "@rollup/rollup-darwin-arm64": "4.59.0",
+ "@rollup/rollup-darwin-x64": "4.59.0",
+ "@rollup/rollup-freebsd-arm64": "4.59.0",
+ "@rollup/rollup-freebsd-x64": "4.59.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.59.0",
+ "@rollup/rollup-linux-arm64-musl": "4.59.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.59.0",
+ "@rollup/rollup-linux-loong64-musl": "4.59.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.59.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.59.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-musl": "4.59.0",
+ "@rollup/rollup-openbsd-x64": "4.59.0",
+ "@rollup/rollup-openharmony-arm64": "4.59.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.59.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.59.0",
+ "@rollup/rollup-win32-x64-gnu": "4.59.0",
+ "@rollup/rollup-win32-x64-msvc": "4.59.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "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/set-cookie-parser": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
+ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
+ "license": "MIT"
+ },
+ "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/tailwindcss": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz",
+ "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==",
+ "license": "MIT"
+ },
+ "node_modules/tapable": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
+ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "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/typescript": {
+ "version": "5.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "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==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "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/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/vite": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
+ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2",
+ "postcss": "^8.5.3",
+ "rollup": "^4.34.9",
+ "tinyglobby": "^0.2.13"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/void-elements": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
+ "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "license": "ISC"
+ }
+ }
+}
diff --git a/website/package.json b/website/package.json
new file mode 100644
index 0000000..84a1c91
--- /dev/null
+++ b/website/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "aigiscode-website",
+ "private": true,
+ "version": "1.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite --port=3000 --host=0.0.0.0",
+ "build": "vite build",
+ "preview": "vite preview",
+ "clean": "rm -rf dist",
+ "lint": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@phosphor-icons/react": "^2.1.10",
+ "@tailwindcss/vite": "^4.1.14",
+ "@vitejs/plugin-react": "^5.0.4",
+ "i18next": "^25.8.13",
+ "i18next-browser-languagedetector": "^8.2.1",
+ "motion": "^12.23.24",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "react-i18next": "^16.5.4",
+ "react-router-dom": "^7.13.0",
+ "vite": "^6.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^22.14.0",
+ "@types/react": "^19.0.0",
+ "@types/react-dom": "^19.0.0",
+ "autoprefixer": "^10.4.21",
+ "tailwindcss": "^4.1.14",
+ "typescript": "~5.8.2"
+ }
+}
diff --git a/website/public/favicon.svg b/website/public/favicon.svg
new file mode 100644
index 0000000..13a280b
--- /dev/null
+++ b/website/public/favicon.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/website/src/App.tsx b/website/src/App.tsx
new file mode 100644
index 0000000..011c9c4
--- /dev/null
+++ b/website/src/App.tsx
@@ -0,0 +1,15 @@
+import { BrowserRouter, Routes, Route } from 'react-router-dom';
+import Layout from './components/Layout';
+import HomePage from './pages/HomePage';
+
+export default function App() {
+ return (
+
+
+ }>
+ } />
+
+
+
+ );
+}
diff --git a/website/src/components/Layout.tsx b/website/src/components/Layout.tsx
new file mode 100644
index 0000000..118202e
--- /dev/null
+++ b/website/src/components/Layout.tsx
@@ -0,0 +1,35 @@
+import { useState, useEffect } from 'react';
+import { Outlet } from 'react-router-dom';
+import { IconContext } from '@phosphor-icons/react';
+
+export default function Layout() {
+ const [isDark, setIsDark] = useState(() => window.matchMedia('(prefers-color-scheme: dark)').matches);
+
+ useEffect(() => {
+ if (isDark) {
+ document.documentElement.classList.add('dark');
+ } else {
+ document.documentElement.classList.remove('dark');
+ }
+ }, [isDark]);
+
+ const toggleTheme = () => setIsDark(!isDark);
+
+ return (
+
+
+
+ );
+}
diff --git a/website/src/i18n/index.ts b/website/src/i18n/index.ts
new file mode 100644
index 0000000..e34406e
--- /dev/null
+++ b/website/src/i18n/index.ts
@@ -0,0 +1,18 @@
+import i18n from 'i18next';
+import { initReactI18next } from 'react-i18next';
+import LanguageDetector from 'i18next-browser-languagedetector';
+
+i18n
+ .use(LanguageDetector)
+ .use(initReactI18next)
+ .init({
+ resources: {},
+ fallbackLng: 'en',
+ interpolation: { escapeValue: false },
+ detection: {
+ order: ['localStorage', 'navigator'],
+ caches: ['localStorage'],
+ },
+ });
+
+export default i18n;
diff --git a/website/src/index.css b/website/src/index.css
new file mode 100644
index 0000000..c45f9c5
--- /dev/null
+++ b/website/src/index.css
@@ -0,0 +1,32 @@
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap');
+@import "tailwindcss";
+
+@custom-variant dark (&:where(.dark, .dark *));
+
+@theme {
+ --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
+ --font-display: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
+}
+
+html {
+ scroll-behavior: smooth;
+ -webkit-text-size-adjust: 100%;
+}
+
+button, a, input, textarea, select {
+ -webkit-tap-highlight-color: transparent;
+}
+
+*:focus-visible {
+ outline: 2px solid #6366f1;
+ outline-offset: 2px;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ *, *::before, *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
diff --git a/website/src/main.tsx b/website/src/main.tsx
new file mode 100644
index 0000000..0382cae
--- /dev/null
+++ b/website/src/main.tsx
@@ -0,0 +1,11 @@
+import { StrictMode } from 'react';
+import { createRoot } from 'react-dom/client';
+import App from './App';
+import './index.css';
+import './i18n';
+
+createRoot(document.getElementById('root')!).render(
+
+
+
+);
diff --git a/website/src/pages/HomePage.tsx b/website/src/pages/HomePage.tsx
new file mode 100644
index 0000000..26e4079
--- /dev/null
+++ b/website/src/pages/HomePage.tsx
@@ -0,0 +1,3 @@
+export default function HomePage() {
+ return Coming soon
;
+}
diff --git a/website/tsconfig.json b/website/tsconfig.json
new file mode 100644
index 0000000..e38ce54
--- /dev/null
+++ b/website/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "paths": {
+ "@/*": ["./src/*"]
+ },
+ "allowImportingTsExtensions": true,
+ "noEmit": true
+ },
+ "include": ["src"]
+}
diff --git a/website/vite.config.ts b/website/vite.config.ts
new file mode 100644
index 0000000..7b701f2
--- /dev/null
+++ b/website/vite.config.ts
@@ -0,0 +1,13 @@
+import tailwindcss from '@tailwindcss/vite';
+import react from '@vitejs/plugin-react';
+import path from 'path';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [react(), tailwindcss()],
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './src'),
+ },
+ },
+});
From bc952f1233ce9e0c79835372c6ea0543aba47c80 Mon Sep 17 00:00:00 2001
From: David Strejc
Date: Sun, 8 Mar 2026 16:12:11 +0100
Subject: [PATCH 02/26] docs: add SEO-optimized README with full project
documentation
Co-Authored-By: Claude Opus 4.6
---
README.md | 260 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 260 insertions(+)
create mode 100644 README.md
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0bb8cff
--- /dev/null
+++ b/README.md
@@ -0,0 +1,260 @@
+
+
+ AigisCode
+
+ AI-powered code guardian — static analysis that watches your entire codebase
+
+
+
+
+
+
+
+
+
+
+
+---
+
+**Aigis** (Αἰγίς) is the ancient Greek word for _Aegis_ — the divine shield.
+The first two letters happen to be **AI**.
+
+AigisCode is a whole-codebase evaluator for large, mixed-language projects.
+It combines deterministic static indexing with structural analysis, detector passes,
+policy-driven adaptation, and AI-assisted review to find the problems that
+single-file linters miss: circular dependencies, dead code, hardwired values,
+layer violations, and architectural bottlenecks.
+
+## Quick Start
+
+```bash
+pip install aigiscode
+cd your-project
+aigiscode analyze .
+```
+
+That's it. AigisCode indexes your source, builds a dependency graph, runs
+detectors, applies policy rules, optionally asks an AI backend to review
+the results, and generates both human-readable and machine-readable reports.
+
+## What Does AigisCode Find?
+
+| Category | Examples |
+|---|---|
+| **Circular dependencies** | Module A imports B, B imports C, C imports A — both strong (architectural) and total (runtime/load) cycles |
+| **Dead code** | Unused imports, unreferenced private methods, orphaned properties, abandoned classes |
+| **Hardwired values** | Magic strings, repeated literals, hardcoded IPs and URLs, env access outside config |
+| **Layer violations** | A controller importing directly from a view, a model reaching into middleware |
+| **Structural risks** | God classes, bottleneck files, orphan modules with no inbound dependencies |
+| **Runtime contracts** | Routes, hooks, env vars, config keys — extracted and cross-referenced against findings |
+
+Every finding includes file path, line number, category, confidence level, and a
+suggested fix. False positive rates are driven down by contract-aware filtering
+and optional AI review.
+
+## How It Works
+
+AigisCode runs a six-stage pipeline:
+
+```
+ Source Code
+ |
+ v
+ +---------+ +----------+ +----------+ +---------+ +-----------+ +----------+
+ | Index | --> | Graph | --> | Detect | --> | Rules | --> | AI Review | --> | Report |
+ +---------+ +----------+ +----------+ +---------+ +-----------+ +----------+
+ tree-sitter dependency dead code saved rules classify JSON + MD
+ Python AST analysis hardwiring pre-filter true_positive contract
+ SQLite store cycles, magic strings false false_positive inventory
+ symbols, coupling, positives needs_context metrics
+ dependencies layers
+```
+
+**1. Index** — Parses source files with tree-sitter (PHP, TypeScript, JavaScript, Vue) and Python AST. Stores files, symbols, dependencies, and semantic envelopes in a local SQLite database. Supports incremental re-indexing.
+
+**2. Graph** — Builds a file-level dependency graph with NetworkX. Computes circular dependencies (strong vs. total), coupling metrics, bottleneck files, layer violations, god classes, orphan files, and runtime entry candidates.
+
+**3. Detect** — Runs generic detector passes for dead code and hardwiring. Detectors emit candidates with confidence levels; they do not encode project-specific logic.
+
+**4. Rules** — Applies saved exclusion rules from `.aigiscode/rules.json` to pre-filter known false positives. Rules are the durable memory of prior audits.
+
+**5. AI Review** — Sends a sample of remaining findings to an AI backend (OpenAI Codex or Anthropic Claude) for classification as `true_positive`, `false_positive`, or `needs_context`. Proposes new exclusion rules from confirmed false positives.
+
+**6. Report** — Generates a structured JSON report and a human-readable Markdown summary. Includes a contract inventory (routes, hooks, env keys, config keys) and full metric breakdowns.
+
+## Supported Languages
+
+| Language | Index | Dead Code | Hardwiring | Parser |
+|---|:---:|:---:|:---:|---|
+| PHP | yes | yes | yes | tree-sitter |
+| Python | yes | yes | yes | Python AST |
+| TypeScript | yes | yes | yes | tree-sitter |
+| JavaScript | yes | yes | yes | tree-sitter |
+| Vue | yes | yes | yes | tree-sitter |
+| Ruby | yes | -- | yes | tree-sitter |
+
+Detector coverage is reported explicitly. When a language is indexed but a
+detector does not yet support it, the report flags partial coverage instead of
+silently treating it as fully analyzed.
+
+## CLI Commands
+
+```
+aigiscode index Parse and store the codebase index
+aigiscode analyze Full pipeline: index + graph + detect + review + report
+aigiscode report Re-generate report from existing index (fast re-evaluation)
+aigiscode tune AI-guided policy tuning with regression guards
+aigiscode info Show index stats and detector coverage
+aigiscode plugins List available plugins and their policy fields
+```
+
+Key flags:
+
+```
+--skip-ai Run without AI backends (deterministic only)
+--analytical-mode Ask AI to propose a policy patch
+--reset Full re-index (ignore incremental cache)
+-P Select a built-in plugin profile
+--plugin-module Load an external Python plugin module
+--policy-file Override policy from a JSON file
+-v / --verbose Enable debug logging
+```
+
+## Configuration
+
+AigisCode is policy-driven. Instead of hard-coding project-specific behavior
+into the analyzer, you express it through a JSON policy file with four sections:
+
+```json
+{
+ "graph": {
+ "js_import_aliases": { "@/": "src/" },
+ "orphan_entry_patterns": ["src/bootstrap/**/*.ts"],
+ "layer_violation_excludes": ["resources/js/**"]
+ },
+ "dead_code": {
+ "abandoned_entry_patterns": ["/Contracts/"],
+ "abandoned_languages": ["php"]
+ },
+ "hardwiring": {
+ "repeated_literal_min_occurrences": 4,
+ "skip_path_patterns": ["app/Console/*"],
+ "js_env_allow_names": ["DEV", "PROD", "MODE"]
+ },
+ "ai": {
+ "allow_claude_fallback": true
+ }
+}
+```
+
+Policy is merged in layers: built-in defaults, selected plugins, auto-detected
+plugins, external plugin modules, project file (`.aigiscode/policy.json`),
+and ad-hoc `--policy-file`. Later layers override earlier ones.
+
+### Built-in Plugins
+
+| Plugin | Description |
+|---|---|
+| `generic` | Safe defaults for mixed-language repositories (always loaded) |
+| `django` | Django-aware runtime conventions and entry points |
+| `wordpress` | WordPress admin and hook conventions |
+| `laravel` | Laravel-specific entry points and dynamic contexts |
+
+### External Plugins
+
+Write a Python module with `build_policy_patch()` and optional runtime hooks:
+
+```python
+def build_policy_patch(project_path, selected_plugins):
+ return {
+ "dead_code": {
+ "abandoned_entry_patterns": ["/app/Legacy/"]
+ }
+ }
+
+# Optional: refine results at runtime
+def refine_graph_result(graph_result, graph, store, project_path, policy):
+ return graph_result
+
+def refine_dead_code_result(dead_code_result, store, project_path, policy):
+ return dead_code_result
+```
+
+```bash
+aigiscode analyze /repo --plugin-module ./my_plugin.py
+```
+
+## For AI Agents
+
+AigisCode is designed to be consumed by other AI agents, not just humans.
+
+The primary machine interface is the JSON report:
+
+```
+.aigiscode/aigiscode-report.json
+```
+
+It contains structured data for every finding category, metric, and contract
+inventory — ready for downstream planning, triage, and automated remediation
+without parsing prose.
+
+Recommended agent workflow:
+
+1. `aigiscode analyze /repo` — generate baseline
+2. Read `.aigiscode/aigiscode-report.json` — parse structured findings
+3. Sample findings and classify (true positive / false positive / uncertain)
+4. Encode narrow policy for repeated false positives
+5. `aigiscode report /repo` — fast re-evaluation after policy changes
+6. `aigiscode tune /repo -i 2` — optional AI-guided policy refinement
+
+Key JSON fields for agents:
+
+- `graph_analysis.strong_circular_dependencies` — architectural cycle triage
+- `graph_analysis.circular_dependencies` — broader runtime context
+- `dead_code` — unused imports, methods, properties, classes
+- `hardwiring` — magic strings, repeated literals, hardcoded network
+- `extensions.contract_inventory` — routes, hooks, env keys, config keys
+
+See [docs/AI_AGENT_USAGE.md](docs/AI_AGENT_USAGE.md) for the full agent integration guide.
+
+## Architecture
+
+The system separates generic analysis from project-specific interpretation
+across four layers of responsibility:
+
+1. **Index and graph construction** — generic, language-aware parsing
+2. **Generic detectors** — emit candidates, not verdicts
+3. **Policy and exclusion rules** — project-specific adaptation
+4. **AI review and tuning** — final-stage classification
+
+Design principles: decoupling over convenience, explainable heuristics over
+opaque model-only decisions, partial but explicit coverage over false certainty.
+
+See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the full design document.
+
+## Requirements
+
+- Python 3.12+
+- Optional: `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` for AI-assisted review
+
+Core dependencies: tree-sitter, NetworkX, Pydantic, Typer, Rich.
+
+## Contributing
+
+Contributions are welcome. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for
+guidelines on development setup, testing, and pull request conventions.
+
+Before patching the analyzer core, consider whether the issue can be expressed
+through policy or a plugin module. The design boundary is intentional:
+generic analysis logic belongs in the core, project-specific behavior belongs
+in policy.
+
+## License
+
+[MIT](LICENSE)
+
+---
+
+
+ AigisCode — your codebase's shield against architectural decay.
+
From 5cb851d98a6fb94ce09d9d6fe6f94b82616c30b8 Mon Sep 17 00:00:00 2001
From: David Strejc
Date: Sun, 8 Mar 2026 16:13:32 +0100
Subject: [PATCH 03/26] docs: add GitHub issue and PR templates
Co-Authored-By: Claude Opus 4.6
---
.github/ISSUE_TEMPLATE/bug_report.md | 36 +++++++++++++++++++++++
.github/ISSUE_TEMPLATE/feature_request.md | 23 +++++++++++++++
.github/PULL_REQUEST_TEMPLATE.md | 21 +++++++++++++
3 files changed, 80 insertions(+)
create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md
create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md
create mode 100644 .github/PULL_REQUEST_TEMPLATE.md
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..5c19b0f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,36 @@
+---
+name: Bug Report
+about: Report a bug in AigisCode
+title: '[Bug] '
+labels: bug
+assignees: ''
+---
+
+## Description
+
+A clear description of what the bug is.
+
+## Steps to Reproduce
+
+1. Run `aigiscode ...`
+2. ...
+3. See error
+
+## Expected Behavior
+
+What you expected to happen.
+
+## Actual Behavior
+
+What actually happened. Include error messages or output.
+
+## Environment
+
+- **AigisCode version:** (`aigiscode --version`)
+- **Python version:** (`python --version`)
+- **OS:** (e.g., Ubuntu 24.04, macOS 15)
+- **Project languages:** (e.g., PHP + TypeScript)
+
+## Additional Context
+
+Any other context, logs, or screenshots.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..9533e7c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,23 @@
+---
+name: Feature Request
+about: Suggest a new feature for AigisCode
+title: '[Feature] '
+labels: enhancement
+assignees: ''
+---
+
+## Problem
+
+What problem does this feature solve? What's your use case?
+
+## Proposed Solution
+
+How would you like this to work?
+
+## Alternatives Considered
+
+Any other approaches you've thought about.
+
+## Additional Context
+
+Examples, links, or references that might help.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..ce35828
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,21 @@
+## Description
+
+What does this PR do? Link to related issues.
+
+## Type of Change
+
+- [ ] Bug fix
+- [ ] New feature
+- [ ] Breaking change
+- [ ] Documentation update
+
+## Testing
+
+What tests were added or modified?
+
+## Checklist
+
+- [ ] Tests pass (`python -m pytest tests/ -v`)
+- [ ] Type hints added for new code
+- [ ] Documentation updated (if applicable)
+- [ ] Follows existing code patterns
From d8dc121196a50d935ae5add7dfe788bddbec49d0 Mon Sep 17 00:00:00 2001
From: David Strejc
Date: Sun, 8 Mar 2026 16:16:14 +0100
Subject: [PATCH 04/26] feat(website): add Navbar and Footer components
Glass-morphism navbar with mobile menu, language switcher, theme toggle,
and gradient logo. Footer with 3-column link grid and social icons.
Layout updated to render both components with fixed navbar offset.
Co-Authored-By: Claude Opus 4.6
---
website/src/components/Footer.tsx | 101 ++++++++++++++++++
website/src/components/Layout.tsx | 8 +-
website/src/components/Navbar.tsx | 163 ++++++++++++++++++++++++++++++
3 files changed, 271 insertions(+), 1 deletion(-)
create mode 100644 website/src/components/Footer.tsx
create mode 100644 website/src/components/Navbar.tsx
diff --git a/website/src/components/Footer.tsx b/website/src/components/Footer.tsx
new file mode 100644
index 0000000..009218e
--- /dev/null
+++ b/website/src/components/Footer.tsx
@@ -0,0 +1,101 @@
+import { useTranslation } from 'react-i18next';
+import { GithubLogo, XLogo, ShieldCheck } from '@phosphor-icons/react';
+
+export default function Footer() {
+ const { t } = useTranslation();
+ const year = new Date().getFullYear();
+
+ const columns = [
+ {
+ title: t('footer.product'),
+ links: [
+ { label: t('footer.features'), href: '#features' },
+ { label: t('footer.docs'), href: '#get-started' },
+ { label: t('footer.changelog'), href: 'https://github.com/AigisCode/AigisCode/releases' },
+ ],
+ },
+ {
+ title: t('footer.community'),
+ links: [
+ { label: 'GitHub', href: 'https://github.com/AigisCode/AigisCode' },
+ { label: t('footer.contributing'), href: 'https://github.com/AigisCode/AigisCode/blob/main/CONTRIBUTING.md' },
+ { label: t('footer.issues'), href: 'https://github.com/AigisCode/AigisCode/issues' },
+ ],
+ },
+ {
+ title: t('footer.legal'),
+ links: [
+ { label: t('footer.license'), href: 'https://github.com/AigisCode/AigisCode/blob/main/LICENSE' },
+ { label: t('footer.codeOfConduct'), href: 'https://github.com/AigisCode/AigisCode/blob/main/CODE_OF_CONDUCT.md' },
+ ],
+ },
+ ];
+
+ return (
+
+ );
+}
diff --git a/website/src/components/Layout.tsx b/website/src/components/Layout.tsx
index 118202e..f83dce9 100644
--- a/website/src/components/Layout.tsx
+++ b/website/src/components/Layout.tsx
@@ -1,6 +1,8 @@
import { useState, useEffect } from 'react';
import { Outlet } from 'react-router-dom';
import { IconContext } from '@phosphor-icons/react';
+import Navbar from './Navbar';
+import Footer from './Footer';
export default function Layout() {
const [isDark, setIsDark] = useState(() => window.matchMedia('(prefers-color-scheme: dark)').matches);
@@ -26,9 +28,13 @@ export default function Layout() {
-
+
+
+
+
+
);
diff --git a/website/src/components/Navbar.tsx b/website/src/components/Navbar.tsx
new file mode 100644
index 0000000..ad3a01e
--- /dev/null
+++ b/website/src/components/Navbar.tsx
@@ -0,0 +1,163 @@
+import { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { motion, AnimatePresence } from 'motion/react';
+import { List, X, Moon, Sun, GithubLogo, Globe, ShieldCheck } from '@phosphor-icons/react';
+
+interface NavbarProps {
+ isDark: boolean;
+ toggleTheme: () => void;
+}
+
+const languages = [
+ { code: 'en', label: 'EN' },
+ { code: 'cs', label: 'CS' },
+ { code: 'fr', label: 'FR' },
+ { code: 'es', label: 'ES' },
+];
+
+export default function Navbar({ isDark, toggleTheme }: NavbarProps) {
+ const { t, i18n } = useTranslation();
+ const [mobileOpen, setMobileOpen] = useState(false);
+ const [langOpen, setLangOpen] = useState(false);
+
+ const navLinks = [
+ { href: '#features', label: t('nav.features') },
+ { href: '#how-it-works', label: t('nav.howItWorks') },
+ { href: '#languages', label: t('nav.languages') },
+ { href: 'https://github.com/AigisCode/AigisCode', label: 'GitHub', external: true },
+ ];
+
+ return (
+
+
+
+ {/* Logo */}
+
+
+
+ Aigis
+ Code
+
+
+
+ {/* Desktop Nav */}
+
+ {navLinks.map((link) => (
+
+ {link.label === 'GitHub' && }
+ {link.label}
+
+ ))}
+
+ {/* Language Switcher */}
+
+
setLangOpen(!langOpen)}
+ className="flex items-center gap-1 text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-white transition-colors"
+ >
+
+ {i18n.language?.toUpperCase().slice(0, 2) || 'EN'}
+
+
+ {langOpen && (
+
+ {languages.map((lang) => (
+ { i18n.changeLanguage(lang.code); setLangOpen(false); }}
+ className={`block w-full px-3 py-1.5 text-sm text-left hover:bg-zinc-100 dark:hover:bg-white/5 transition-colors ${
+ i18n.language?.startsWith(lang.code) ? 'text-indigo-500 font-medium' : 'text-zinc-600 dark:text-zinc-400'
+ }`}
+ >
+ {lang.label}
+
+ ))}
+
+ )}
+
+
+
+ {/* Theme Toggle */}
+
+ {isDark ? : }
+
+
+ {/* CTA */}
+
+ {t('nav.getStarted')}
+
+
+
+ {/* Mobile Menu Button */}
+
setMobileOpen(!mobileOpen)}
+ className="md:hidden p-2 rounded-lg hover:bg-zinc-100 dark:hover:bg-white/5 transition-colors"
+ aria-label="Toggle menu"
+ >
+ {mobileOpen ? :
}
+
+
+
+
+ {/* Mobile Menu */}
+
+ {mobileOpen && (
+
+
+
+ )}
+
+
+ );
+}
From 7cd2aeacba3b78351b6c990a3852e49a63c543a8 Mon Sep 17 00:00:00 2001
From: David Strejc
Date: Sun, 8 Mar 2026 16:22:26 +0100
Subject: [PATCH 05/26] feat(website): create full HomePage with hero,
features, pipeline, terminal demo
Six production-quality sections: animated hero with gradient title and
copy-to-clipboard install command, supported languages bar, feature bento
grid with Phosphor icons and hover glow, pipeline stages with connectors,
animated terminal demo, and CTA with gradient glow button. All text uses
i18n t() keys, responsive across mobile/tablet/desktop, dark mode support.
Co-Authored-By: Claude Opus 4.6
---
website/src/pages/HomePage.tsx | 451 ++++++++++++++++++++++++++++++++-
1 file changed, 450 insertions(+), 1 deletion(-)
diff --git a/website/src/pages/HomePage.tsx b/website/src/pages/HomePage.tsx
index 26e4079..f8de400 100644
--- a/website/src/pages/HomePage.tsx
+++ b/website/src/pages/HomePage.tsx
@@ -1,3 +1,452 @@
+import { useState, useRef } from 'react';
+import { useTranslation } from 'react-i18next';
+import { motion, useInView } from 'motion/react';
+import {
+ ArrowsClockwise,
+ Trash,
+ LinkBreak,
+ Robot,
+ Sliders,
+ Code,
+ Copy,
+ Check,
+ ArrowRight,
+ GithubLogo,
+} from '@phosphor-icons/react';
+
+/* -------------------------------------------------------------------------- */
+/* Constants */
+/* -------------------------------------------------------------------------- */
+
+const featureKeys = [
+ { key: 'circular', Icon: ArrowsClockwise },
+ { key: 'deadCode', Icon: Trash },
+ { key: 'hardwiring', Icon: LinkBreak },
+ { key: 'aiReview', Icon: Robot },
+ { key: 'policy', Icon: Sliders },
+ { key: 'multiLang', Icon: Code },
+] as const;
+
+const pipelineStageKeys = ['index', 'graph', 'detect', 'rules', 'review', 'report'] as const;
+
+const supportedLanguages = ['PHP', 'Python', 'TypeScript', 'JavaScript', 'Vue'];
+
+const terminalLines = [
+ { text: '$ aigiscode analyze .', color: 'text-zinc-300', delay: 0 },
+ { text: '', color: '', delay: 0.15 },
+ { text: ' AigisCode v0.1.0', color: 'text-indigo-400', delay: 0.3 },
+ { text: '', color: '', delay: 0.35 },
+ { text: ' Indexing... 127 files parsed', color: 'text-zinc-400', delay: 0.5 },
+ { text: ' Graphing... 843 dependencies mapped', color: 'text-zinc-400', delay: 0.65 },
+ { text: ' Detecting... dead code, hardwiring', color: 'text-zinc-400', delay: 0.8 },
+ { text: ' Reviewing... AI classifying 23 findings', color: 'text-zinc-400', delay: 0.95 },
+ { text: '', color: '', delay: 1.05 },
+ { text: ' Results:', color: 'text-emerald-400', delay: 1.15 },
+ { text: ' \u251c\u2500\u2500 3 circular dependencies (strong)', color: 'text-amber-400', delay: 1.3 },
+ { text: ' \u251c\u2500\u2500 12 unused imports', color: 'text-amber-400', delay: 1.45 },
+ { text: ' \u251c\u2500\u2500 5 magic strings', color: 'text-amber-400', delay: 1.6 },
+ { text: ' \u2514\u2500\u2500 3 findings reclassified by AI', color: 'text-emerald-400', delay: 1.75 },
+ { text: '', color: '', delay: 1.85 },
+ { text: ' Report: .aigiscode/aigiscode-report.md', color: 'text-zinc-500', delay: 1.95 },
+];
+
+/* -------------------------------------------------------------------------- */
+/* Hero Section */
+/* -------------------------------------------------------------------------- */
+
+function HeroSection() {
+ const { t } = useTranslation();
+ const [copied, setCopied] = useState(false);
+
+ const handleCopy = async () => {
+ try {
+ await navigator.clipboard.writeText('pip install aigiscode');
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ } catch {
+ /* clipboard not available */
+ }
+ };
+
+ return (
+
+
+ {/* Title */}
+
+ {t('hero.title1')}{' '}
+
+ {t('hero.title2')}
+
+
+
+ {/* Subtitle */}
+
+ {t('hero.subtitle')}
+
+
+ {/* CTAs */}
+
+
+ {t('hero.cta1')}
+
+
+
+
+ {t('hero.cta2')}
+
+
+
+ {/* Install Command */}
+
+ $
+ {t('hero.install')}
+
+ {copied ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ );
+}
+
+/* -------------------------------------------------------------------------- */
+/* Trusted Languages Bar */
+/* -------------------------------------------------------------------------- */
+
+function TrustedBar() {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+ {t('trustedBy.title')}
+
+
+ {supportedLanguages.map((lang, i) => (
+
+ {lang}
+
+ ))}
+
+
+
+
+ );
+}
+
+/* -------------------------------------------------------------------------- */
+/* Feature Bento Grid */
+/* -------------------------------------------------------------------------- */
+
+function FeatureCard({ featureKey, Icon, index }: { featureKey: string; Icon: React.ElementType; index: number }) {
+ const { t } = useTranslation();
+
+ return (
+
+ {/* Hover glow */}
+
+
+
+
+
+
+
+ {t(`features.${featureKey}.title`)}
+
+
+ {t(`features.${featureKey}.description`)}
+
+
+
+ );
+}
+
+function FeaturesSection() {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+ {t('features.title')}
+
+
+ {t('features.subtitle')}
+
+
+
+
+ {featureKeys.map(({ key, Icon }, index) => (
+
+ ))}
+
+
+
+ );
+}
+
+/* -------------------------------------------------------------------------- */
+/* Pipeline / How It Works */
+/* -------------------------------------------------------------------------- */
+
+function PipelineStage({ stageKey, index }: { stageKey: string; index: number }) {
+ const { t } = useTranslation();
+
+ return (
+
+ {/* Number circle */}
+
+ {index + 1}
+
+
+ {t(`pipeline.stages.${stageKey}.title`)}
+
+
+ {t(`pipeline.stages.${stageKey}.description`)}
+
+
+ );
+}
+
+function PipelineConnector({ index }: { index: number }) {
+ return (
+
+
+
+ );
+}
+
+function PipelineSection() {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+ {t('pipeline.title')}
+
+
+ {t('pipeline.subtitle')}
+
+
+
+ {/* Desktop: horizontal flow */}
+
+ {pipelineStageKeys.map((key, i) => (
+
+
+ {i < pipelineStageKeys.length - 1 &&
}
+
+ ))}
+
+
+ {/* Mobile / Tablet: vertical list */}
+
+ {pipelineStageKeys.map((key, i) => (
+
+ ))}
+
+
+
+ );
+}
+
+/* -------------------------------------------------------------------------- */
+/* Terminal Demo */
+/* -------------------------------------------------------------------------- */
+
+function TerminalLine({ line, index }: { line: (typeof terminalLines)[number]; index: number }) {
+ return (
+
+ {line.text || '\u00A0'}
+
+ );
+}
+
+function TerminalDemo() {
+ const termRef = useRef(null);
+ const isInView = useInView(termRef, { once: true, margin: '-100px' });
+
+ return (
+
+
+
+ {/* Title bar */}
+
+
+ {/* Terminal content */}
+
+ {isInView &&
+ terminalLines.map((line, i) => )}
+
+
+
+
+ );
+}
+
+/* -------------------------------------------------------------------------- */
+/* CTA Section */
+/* -------------------------------------------------------------------------- */
+
+function CtaSection() {
+ const { t } = useTranslation();
+
+ return (
+
+ {/* Glow */}
+
+
+
+
+
+ {t('cta.title')}
+
+
+ {t('cta.subtitle')}
+
+
+
+
+
+ );
+}
+
+/* -------------------------------------------------------------------------- */
+/* HomePage */
+/* -------------------------------------------------------------------------- */
+
export default function HomePage() {
- return Coming soon
;
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
}
From d95693dd9207b2caf2062f3f309be32a830170cd Mon Sep 17 00:00:00 2001
From: David Strejc
Date: Sun, 8 Mar 2026 16:28:37 +0100
Subject: [PATCH 06/26] =?UTF-8?q?feat(website):=20add=20anime.js=20animati?=
=?UTF-8?q?ons=20=E2=80=94=20shield=20SVG,=20particles,=20typewriter,=20pi?=
=?UTF-8?q?peline=20drawing?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add spectacular visual effects powered by anime.js v4:
- ShieldBackground: SVG shield that draws itself on load with gradient glow breathing
- ParticleField: Canvas-based floating constellation with connecting lines
- PipelineSVG: Animated gradient line drawing between pipeline stages
- Typewriter terminal: Character-by-character reveal with counter animations
- Feature cards: Staggered wave entrance using anime.js grid stagger
- useAnime hook: Reusable React integration (useAnimate, useCountUp, useIntersectionAnimate)
All animations respect prefers-reduced-motion and clean up properly.
Co-Authored-By: Claude Opus 4.6
---
website/src/components/ParticleField.tsx | 173 ++++++++++++
website/src/components/PipelineSVG.tsx | 77 ++++++
website/src/components/ShieldBackground.tsx | 142 ++++++++++
website/src/hooks/useAnime.ts | 169 ++++++++++++
website/src/pages/HomePage.tsx | 277 +++++++++++++++-----
5 files changed, 776 insertions(+), 62 deletions(-)
create mode 100644 website/src/components/ParticleField.tsx
create mode 100644 website/src/components/PipelineSVG.tsx
create mode 100644 website/src/components/ShieldBackground.tsx
create mode 100644 website/src/hooks/useAnime.ts
diff --git a/website/src/components/ParticleField.tsx b/website/src/components/ParticleField.tsx
new file mode 100644
index 0000000..407e50e
--- /dev/null
+++ b/website/src/components/ParticleField.tsx
@@ -0,0 +1,173 @@
+import { useEffect, useRef, useMemo } from 'react';
+import { animate } from 'animejs';
+import { prefersReducedMotion } from '@/hooks/useAnime';
+
+/* -------------------------------------------------------------------------- */
+/* Floating Particle Constellation */
+/* -------------------------------------------------------------------------- */
+
+interface Particle {
+ x: number;
+ y: number;
+ el: HTMLDivElement | null;
+}
+
+interface ParticleFieldProps {
+ /** Number of particles (default 40) */
+ count?: number;
+ /** Max line connection distance in px (default 120) */
+ connectionDistance?: number;
+ /** CSS class for the container */
+ className?: string;
+}
+
+export default function ParticleField({
+ count = 40,
+ connectionDistance = 120,
+ className = '',
+}: ParticleFieldProps) {
+ const containerRef = useRef(null);
+ const canvasRef = useRef(null);
+ const particlesRef = useRef([]);
+ const rafRef = useRef(0);
+ const animsRef = useRef[]>([]);
+
+ // Generate stable random initial positions
+ const initialPositions = useMemo(() => {
+ return Array.from({ length: count }, () => ({
+ x: Math.random() * 100,
+ y: Math.random() * 100,
+ }));
+ }, [count]);
+
+ useEffect(() => {
+ if (!containerRef.current || !canvasRef.current) return;
+ if (prefersReducedMotion()) return;
+
+ const container = containerRef.current;
+ const canvas = canvasRef.current;
+ const ctx = canvas.getContext('2d');
+ if (!ctx) return;
+
+ // Size canvas to container
+ const resizeCanvas = () => {
+ const rect = container.getBoundingClientRect();
+ canvas.width = rect.width * window.devicePixelRatio;
+ canvas.height = rect.height * window.devicePixelRatio;
+ canvas.style.width = `${rect.width}px`;
+ canvas.style.height = `${rect.height}px`;
+ ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
+ };
+ resizeCanvas();
+
+ // Create particle data objects (anime.js will animate these plain objects)
+ const particles: Particle[] = initialPositions.map((pos) => ({
+ x: (pos.x / 100) * container.offsetWidth,
+ y: (pos.y / 100) * container.offsetHeight,
+ el: null,
+ }));
+ particlesRef.current = particles;
+
+ // Animate each particle to drift around
+ const anims = particles.map((p) => {
+ const w = container.offsetWidth;
+ const h = container.offsetHeight;
+ const driftRange = 80;
+ return animate(p, {
+ x: [p.x, p.x + (Math.random() - 0.5) * driftRange * 2],
+ y: [p.y, p.y + (Math.random() - 0.5) * driftRange * 2],
+ duration: 4000 + Math.random() * 6000,
+ ease: 'inOutSine',
+ loop: true,
+ alternate: true,
+ // Keep within bounds via modifier
+ modifier: (v: number) => {
+ const maxDim = Math.max(w, h);
+ return ((v % maxDim) + maxDim) % maxDim;
+ },
+ });
+ });
+ animsRef.current = anims;
+
+ // Draw connections on a rAF loop
+ const containerWidth = container.offsetWidth;
+ const containerHeight = container.offsetHeight;
+ const maxDistSq = connectionDistance * connectionDistance;
+
+ // Get computed style for dark mode detection
+ const isDark = () => document.documentElement.classList.contains('dark');
+
+ function drawFrame() {
+ if (!ctx) return;
+ // Clear at physical resolution
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ const dpr = window.devicePixelRatio;
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
+
+ const dark = isDark();
+
+ // Draw connection lines
+ for (let i = 0; i < particles.length; i++) {
+ for (let j = i + 1; j < particles.length; j++) {
+ const dx = particles[i].x - particles[j].x;
+ const dy = particles[i].y - particles[j].y;
+ const distSq = dx * dx + dy * dy;
+ if (distSq < maxDistSq) {
+ const dist = Math.sqrt(distSq);
+ const opacity = (1 - dist / connectionDistance) * 0.2;
+ ctx.beginPath();
+ ctx.moveTo(particles[i].x, particles[i].y);
+ ctx.lineTo(particles[j].x, particles[j].y);
+ ctx.strokeStyle = dark
+ ? `rgba(129, 140, 248, ${opacity})`
+ : `rgba(99, 102, 241, ${opacity})`;
+ ctx.lineWidth = 0.5;
+ ctx.stroke();
+ }
+ }
+ }
+
+ // Draw particles as dots
+ for (const p of particles) {
+ ctx.beginPath();
+ ctx.arc(p.x, p.y, 1.5, 0, Math.PI * 2);
+ ctx.fillStyle = dark
+ ? 'rgba(165, 180, 252, 0.4)'
+ : 'rgba(99, 102, 241, 0.25)';
+ ctx.fill();
+ }
+
+ rafRef.current = requestAnimationFrame(drawFrame);
+ }
+
+ rafRef.current = requestAnimationFrame(drawFrame);
+
+ // Handle resize
+ const handleResize = () => {
+ resizeCanvas();
+ };
+ window.addEventListener('resize', handleResize);
+
+ return () => {
+ cancelAnimationFrame(rafRef.current);
+ anims.forEach((a) => a.pause());
+ window.removeEventListener('resize', handleResize);
+ };
+ }, [initialPositions, connectionDistance, count]);
+
+ if (prefersReducedMotion()) return null;
+
+ return (
+
+
+
+ );
+}
diff --git a/website/src/components/PipelineSVG.tsx b/website/src/components/PipelineSVG.tsx
new file mode 100644
index 0000000..eade4a3
--- /dev/null
+++ b/website/src/components/PipelineSVG.tsx
@@ -0,0 +1,77 @@
+import { useEffect, useRef } from 'react';
+import { animate } from 'animejs';
+import { createDrawable } from 'animejs/svg';
+import { prefersReducedMotion } from '@/hooks/useAnime';
+
+/* -------------------------------------------------------------------------- */
+/* Pipeline Connection SVG — animated line connecting stages */
+/* -------------------------------------------------------------------------- */
+
+interface PipelineSVGProps {
+ /** Number of pipeline stages to connect */
+ stageCount: number;
+ /** Whether the section is in view */
+ isInView: boolean;
+}
+
+export default function PipelineSVG({ stageCount, isInView }: PipelineSVGProps) {
+ const svgRef = useRef(null);
+ const hasAnimated = useRef(false);
+
+ useEffect(() => {
+ if (!svgRef.current || !isInView || hasAnimated.current) return;
+ if (prefersReducedMotion()) return;
+
+ hasAnimated.current = true;
+
+ const path = svgRef.current.querySelector('.pipeline-line');
+ if (!path) return;
+
+ const drawables = createDrawable(path);
+
+ animate(drawables, {
+ draw: '0 1',
+ duration: 2000,
+ delay: 300,
+ ease: 'inOutQuart',
+ });
+ }, [isInView, stageCount]);
+
+ // Build a smooth curved path across all stages
+ // Each stage is spaced equally. We create a gentle sine wave.
+ const points = stageCount;
+ const segWidth = 100 / (points - 1);
+
+ // Build SVG path: horizontal line with small bumps at each node
+ let d = `M 0 50`;
+ for (let i = 1; i < points; i++) {
+ const x = i * segWidth;
+ const cpx1 = (i - 0.5) * segWidth;
+ d += ` C ${cpx1} 50, ${cpx1} 50, ${x} 50`;
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/website/src/components/ShieldBackground.tsx b/website/src/components/ShieldBackground.tsx
new file mode 100644
index 0000000..7a12506
--- /dev/null
+++ b/website/src/components/ShieldBackground.tsx
@@ -0,0 +1,142 @@
+import { useEffect, useRef } from 'react';
+import { animate, createTimeline } from 'animejs';
+import { createDrawable } from 'animejs/svg';
+import { prefersReducedMotion } from '@/hooks/useAnime';
+
+/* -------------------------------------------------------------------------- */
+/* Animated Shield SVG — draws itself on page load */
+/* -------------------------------------------------------------------------- */
+
+/**
+ * A large, subtle SVG shield that draws its outline with anime.js,
+ * then pulses with a gentle glow. Placed absolutely behind the hero text.
+ */
+export default function ShieldBackground() {
+ const svgRef = useRef(null);
+ const glowRef = useRef(null);
+
+ useEffect(() => {
+ if (!svgRef.current || prefersReducedMotion()) return;
+
+ const pathEls = svgRef.current.querySelectorAll('.shield-path');
+ if (!pathEls.length) return;
+
+ // Create drawable wrappers for SVG path drawing
+ const drawables = createDrawable(pathEls);
+
+ // Timeline: draw outline, then fade in fill glow
+ const tl = createTimeline({ autoplay: true });
+
+ // Phase 1: Draw the shield outline
+ tl.add(drawables, {
+ draw: '0 1',
+ duration: 2000,
+ ease: 'inOutQuart',
+ });
+
+ // Phase 2: Fade in the glow fill
+ tl.add('.shield-fill', {
+ opacity: [0, 0.12],
+ duration: 1000,
+ ease: 'inOutSine',
+ }, '-=400');
+
+ // Phase 3: Subtle breathing pulse on the glow (loops forever)
+ const breathe = animate('.shield-fill', {
+ opacity: [0.12, 0.06],
+ duration: 3000,
+ ease: 'inOutSine',
+ loop: true,
+ alternate: true,
+ autoplay: false,
+ });
+
+ // Start breathing after timeline completes
+ tl.then(() => {
+ breathe.play();
+ });
+
+ return () => {
+ tl.pause();
+ breathe.pause();
+ };
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Fill (starts invisible, faded in by timeline) */}
+
+
+ {/* Outer shield outline (drawn by anime.js) */}
+
+
+ {/* Inner shield detail line */}
+
+
+ {/* Central cross / emblem lines */}
+
+
+
+
+ );
+}
diff --git a/website/src/hooks/useAnime.ts b/website/src/hooks/useAnime.ts
new file mode 100644
index 0000000..718c2b0
--- /dev/null
+++ b/website/src/hooks/useAnime.ts
@@ -0,0 +1,169 @@
+import { useEffect, useRef, useCallback } from 'react';
+import { animate, createTimeline } from 'animejs';
+import type { AnimationParams, TimelineParams } from 'animejs';
+import type { JSAnimation } from 'animejs';
+import type { Timeline } from 'animejs';
+
+/* -------------------------------------------------------------------------- */
+/* Reduced-motion preference */
+/* -------------------------------------------------------------------------- */
+
+export function prefersReducedMotion(): boolean {
+ if (typeof window === 'undefined') return false;
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
+}
+
+/* -------------------------------------------------------------------------- */
+/* useAnimate — run an anime.js animation on a ref element */
+/* -------------------------------------------------------------------------- */
+
+type AnimateOptions = {
+ /** Animation params (excluding targets) */
+ params: AnimationParams;
+ /** Skip animation entirely if prefers-reduced-motion */
+ respectMotionPref?: boolean;
+ /** Only run once (default true) */
+ once?: boolean;
+};
+
+export function useAnimate(
+ options: AnimateOptions,
+ deps: React.DependencyList = [],
+) {
+ const ref = useRef(null);
+ const hasRun = useRef(false);
+
+ useEffect(() => {
+ if (!ref.current) return;
+ if (options.once !== false && hasRun.current) return;
+ if (options.respectMotionPref !== false && prefersReducedMotion()) return;
+
+ hasRun.current = true;
+ const anim = animate(ref.current, options.params);
+
+ return () => {
+ anim.pause();
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, deps);
+
+ return ref;
+}
+
+/* -------------------------------------------------------------------------- */
+/* useTimeline — create and return a timeline ref */
+/* -------------------------------------------------------------------------- */
+
+export function useTimeline(
+ params?: TimelineParams,
+ respectMotionPref = true,
+): React.RefObject {
+ const tlRef = useRef(null);
+
+ useEffect(() => {
+ if (respectMotionPref && prefersReducedMotion()) return;
+ const tl = createTimeline(params);
+ tlRef.current = tl;
+
+ return () => {
+ tl.pause();
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ return tlRef;
+}
+
+/* -------------------------------------------------------------------------- */
+/* useIntersectionAnimate — animate when element scrolls into view */
+/* -------------------------------------------------------------------------- */
+
+type IntersectionAnimateOptions = {
+ params: AnimationParams;
+ /** IntersectionObserver threshold (default 0.1) */
+ threshold?: number;
+ /** Root margin (default '-80px') */
+ rootMargin?: string;
+ /** Respect reduced motion (default true) */
+ respectMotionPref?: boolean;
+};
+
+export function useIntersectionAnimate(
+ options: IntersectionAnimateOptions,
+) {
+ const ref = useRef(null);
+ const hasAnimated = useRef(false);
+
+ useEffect(() => {
+ if (!ref.current) return;
+ if (options.respectMotionPref !== false && prefersReducedMotion()) return;
+
+ const el = ref.current;
+
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ if (entry.isIntersecting && !hasAnimated.current) {
+ hasAnimated.current = true;
+ animate(el, options.params);
+ observer.disconnect();
+ }
+ },
+ {
+ threshold: options.threshold ?? 0.1,
+ rootMargin: options.rootMargin ?? '-80px',
+ },
+ );
+
+ observer.observe(el);
+
+ return () => {
+ observer.disconnect();
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ return ref;
+}
+
+/* -------------------------------------------------------------------------- */
+/* useCountUp — animate a number from 0 to target */
+/* -------------------------------------------------------------------------- */
+
+export function useCountUp(
+ target: number,
+ duration = 1200,
+ shouldStart = false,
+): [React.RefObject, number] {
+ const ref = useRef(null);
+ const valueRef = useRef({ val: 0 });
+ const animRef = useRef(null);
+ const currentVal = useRef(0);
+
+ const update = useCallback(() => {
+ if (ref.current) {
+ ref.current.textContent = String(Math.round(valueRef.current.val));
+ }
+ }, []);
+
+ useEffect(() => {
+ if (!shouldStart || prefersReducedMotion()) {
+ if (ref.current) ref.current.textContent = String(target);
+ return;
+ }
+
+ valueRef.current.val = 0;
+ animRef.current = animate(valueRef.current, {
+ val: target,
+ duration,
+ ease: 'outExpo',
+ modifier: (v: number) => Math.round(v),
+ onUpdate: update,
+ });
+
+ return () => {
+ animRef.current?.pause();
+ };
+ }, [shouldStart, target, duration, update]);
+
+ return [ref, currentVal.current];
+}
diff --git a/website/src/pages/HomePage.tsx b/website/src/pages/HomePage.tsx
index f8de400..0b41809 100644
--- a/website/src/pages/HomePage.tsx
+++ b/website/src/pages/HomePage.tsx
@@ -1,6 +1,7 @@
-import { useState, useRef } from 'react';
+import { useState, useRef, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { motion, useInView } from 'motion/react';
+import { animate, stagger, createTimeline } from 'animejs';
import {
ArrowsClockwise,
Trash,
@@ -13,6 +14,10 @@ import {
ArrowRight,
GithubLogo,
} from '@phosphor-icons/react';
+import ShieldBackground from '@/components/ShieldBackground';
+import ParticleField from '@/components/ParticleField';
+import PipelineSVG from '@/components/PipelineSVG';
+import { prefersReducedMotion, useCountUp } from '@/hooks/useAnime';
/* -------------------------------------------------------------------------- */
/* Constants */
@@ -31,23 +36,24 @@ const pipelineStageKeys = ['index', 'graph', 'detect', 'rules', 'review', 'repor
const supportedLanguages = ['PHP', 'Python', 'TypeScript', 'JavaScript', 'Vue'];
+/* Terminal lines with embedded numeric targets for count-up animation */
const terminalLines = [
- { text: '$ aigiscode analyze .', color: 'text-zinc-300', delay: 0 },
- { text: '', color: '', delay: 0.15 },
- { text: ' AigisCode v0.1.0', color: 'text-indigo-400', delay: 0.3 },
- { text: '', color: '', delay: 0.35 },
- { text: ' Indexing... 127 files parsed', color: 'text-zinc-400', delay: 0.5 },
- { text: ' Graphing... 843 dependencies mapped', color: 'text-zinc-400', delay: 0.65 },
- { text: ' Detecting... dead code, hardwiring', color: 'text-zinc-400', delay: 0.8 },
- { text: ' Reviewing... AI classifying 23 findings', color: 'text-zinc-400', delay: 0.95 },
- { text: '', color: '', delay: 1.05 },
- { text: ' Results:', color: 'text-emerald-400', delay: 1.15 },
- { text: ' \u251c\u2500\u2500 3 circular dependencies (strong)', color: 'text-amber-400', delay: 1.3 },
- { text: ' \u251c\u2500\u2500 12 unused imports', color: 'text-amber-400', delay: 1.45 },
- { text: ' \u251c\u2500\u2500 5 magic strings', color: 'text-amber-400', delay: 1.6 },
- { text: ' \u2514\u2500\u2500 3 findings reclassified by AI', color: 'text-emerald-400', delay: 1.75 },
- { text: '', color: '', delay: 1.85 },
- { text: ' Report: .aigiscode/aigiscode-report.md', color: 'text-zinc-500', delay: 1.95 },
+ { text: '$ aigiscode analyze .', color: 'text-zinc-300', delay: 0, numbers: [] as { value: number; label: string }[] },
+ { text: '', color: '', delay: 0.15, numbers: [] as { value: number; label: string }[] },
+ { text: ' AigisCode v0.1.0', color: 'text-indigo-400', delay: 0.3, numbers: [] as { value: number; label: string }[] },
+ { text: '', color: '', delay: 0.35, numbers: [] as { value: number; label: string }[] },
+ { text: ' Indexing... {127} files parsed', color: 'text-zinc-400', delay: 0.5, numbers: [{ value: 127, label: 'files' }] },
+ { text: ' Graphing... {843} dependencies mapped', color: 'text-zinc-400', delay: 0.65, numbers: [{ value: 843, label: 'deps' }] },
+ { text: ' Detecting... dead code, hardwiring', color: 'text-zinc-400', delay: 0.8, numbers: [] as { value: number; label: string }[] },
+ { text: ' Reviewing... AI classifying {23} findings', color: 'text-zinc-400', delay: 0.95, numbers: [{ value: 23, label: 'findings' }] },
+ { text: '', color: '', delay: 1.05, numbers: [] as { value: number; label: string }[] },
+ { text: ' Results:', color: 'text-emerald-400', delay: 1.15, numbers: [] as { value: number; label: string }[] },
+ { text: ' \u251c\u2500\u2500 {3} circular dependencies (strong)', color: 'text-amber-400', delay: 1.3, numbers: [{ value: 3, label: 'circular' }] },
+ { text: ' \u251c\u2500\u2500 {12} unused imports', color: 'text-amber-400', delay: 1.45, numbers: [{ value: 12, label: 'unused' }] },
+ { text: ' \u251c\u2500\u2500 {5} magic strings', color: 'text-amber-400', delay: 1.6, numbers: [{ value: 5, label: 'magic' }] },
+ { text: ' \u2514\u2500\u2500 {3} findings reclassified by AI', color: 'text-emerald-400', delay: 1.75, numbers: [{ value: 3, label: 'reclass' }] },
+ { text: '', color: '', delay: 1.85, numbers: [] as { value: number; label: string }[] },
+ { text: ' Report: .aigiscode/aigiscode-report.md', color: 'text-zinc-500', delay: 1.95, numbers: [] as { value: number; label: string }[] },
];
/* -------------------------------------------------------------------------- */
@@ -70,7 +76,13 @@ function HeroSection() {
return (
-
+ {/* Particle constellation background */}
+
+
+ {/* Animated shield SVG */}
+
+
+
{/* Title */}
{/* Hover glow */}
@@ -214,12 +223,50 @@ function FeatureCard({ featureKey, Icon, index }: { featureKey: string; Icon: Re
{t(`features.${featureKey}.description`)}
-
+
);
}
function FeaturesSection() {
const { t } = useTranslation();
+ const gridRef = useRef(null);
+ const hasAnimated = useRef(false);
+
+ useEffect(() => {
+ if (!gridRef.current || prefersReducedMotion()) {
+ // If reduced motion, just show all cards immediately
+ if (gridRef.current) {
+ gridRef.current.querySelectorAll('[data-feature-card]').forEach((el) => {
+ (el as HTMLElement).style.opacity = '1';
+ });
+ }
+ return;
+ }
+
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ if (entry.isIntersecting && !hasAnimated.current) {
+ hasAnimated.current = true;
+
+ const cards = gridRef.current!.querySelectorAll('[data-feature-card]');
+ animate(cards, {
+ opacity: [0, 1],
+ scale: [0.85, 1],
+ translateY: [40, 0],
+ duration: 600,
+ delay: stagger(80, { grid: [3, 2], from: 'first' }),
+ ease: 'outQuart',
+ });
+
+ observer.disconnect();
+ }
+ },
+ { threshold: 0.15, rootMargin: '-60px' },
+ );
+
+ observer.observe(gridRef.current);
+ return () => observer.disconnect();
+ }, []);
return (
@@ -239,7 +286,7 @@ function FeaturesSection() {
-
+
{featureKeys.map(({ key, Icon }, index) => (
))}
@@ -250,7 +297,7 @@ function FeaturesSection() {
}
/* -------------------------------------------------------------------------- */
-/* Pipeline / How It Works */
+/* Pipeline / How It Works — with animated SVG connection */
/* -------------------------------------------------------------------------- */
function PipelineStage({ stageKey, index }: { stageKey: string; index: number }) {
@@ -265,7 +312,7 @@ function PipelineStage({ stageKey, index }: { stageKey: string; index: number })
className="flex flex-col items-center text-center flex-1 min-w-0"
>
{/* Number circle */}
-