diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..044e0b9
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,16 @@
+## Описание
+
+
+## Тип изменений
+- [ ] Новая фича (frontend)
+- [ ] Новая фича (backend)
+- [ ] Исправление бага
+- [ ] Рефакторинг / документация
+
+## Чеклист
+- [ ] `npm run lint` проходит
+- [ ] `npm run build` проходит (если затронут фронтенд)
+- [ ] Проверено локально
+
+## Связанные задачи
+
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..b455ea5
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,32 @@
+# CI для CodeFlow: проверка кода при каждом push и PR
+# Запускает: установка зависимостей → линт → сборка
+
+name: CI
+
+on:
+ push:
+ branches: [main, develop]
+ pull_request:
+ branches: [main, develop]
+
+jobs:
+ check:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Lint
+ run: npm run lint
+
+ - name: Build
+ run: npm run build
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..76a2f34
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,28 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+.env
+.env.local
+.env.*.local
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+.vercel
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..3e003f8
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,21 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import tseslint from 'typescript-eslint'
+
+export default [
+ { ignores: ['dist'] },
+ { files: ['**/*.cjs'], languageOptions: { globals: globals.node } },
+ js.configs.recommended,
+ ...tseslint.configs.recommended,
+ reactHooks.configs['recommended-latest'],
+ reactRefresh.configs.vite,
+ {
+ files: ['**/*.{ts,tsx}'],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ },
+]
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..e4e6892
--- /dev/null
+++ b/index.html
@@ -0,0 +1,593 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CodeFlow Terminal | BREACH IN PROGRESS...
+
+
+
+
+
+
+
⬡ CODEFLOW ⬡
+
> INITIALIZING SYSTEM...
+
> LOADING KERNEL MODULES... [OK]
+
> ESTABLISHING ENCRYPTED CONNECTION... [OK]
+
> BYPASSING FIREWALL... [OK]
+
> LOADING PYTHON ENVIRONMENT... [OK]
+
> INJECTING AI ASSISTANT (GLITCH)... [OK]
+
> STARTING OPERATION 'SILENT STORM'...
+
✓ SYSTEM READY. WELCOME, OPERATIVE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..2e9d02c
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,3882 @@
+{
+ "name": "codeflow-frontend",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "codeflow-frontend",
+ "version": "0.0.0",
+ "dependencies": {
+ "@mantine/core": "^7.6.1",
+ "@mantine/hooks": "^7.6.1",
+ "@monaco-editor/react": "^4.6.0",
+ "@tabler/icons-react": "^3.36.1",
+ "canvas-confetti": "^1.9.2",
+ "framer-motion": "^12.29.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-router-dom": "^6.22.3",
+ "react-simple-typewriter": "^5.0.1"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.15.0",
+ "@types/canvas-confetti": "^1.6.4",
+ "@types/react": "^18.2.64",
+ "@types/react-dom": "^18.2.21",
+ "@vitejs/plugin-react": "^4.2.1",
+ "eslint": "^9.15.0",
+ "eslint-plugin-react-hooks": "^5.0.0",
+ "eslint-plugin-react-refresh": "^0.4.14",
+ "globals": "^15.12.0",
+ "postcss": "^8.4.35",
+ "postcss-preset-mantine": "^1.13.0",
+ "postcss-simple-vars": "^7.0.1",
+ "typescript": "^5.2.2",
+ "typescript-eslint": "^8.15.0",
+ "vite": "^5.1.6"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
+ "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==",
+ "dev": true,
+ "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.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz",
+ "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
+ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/generator": "^7.28.6",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helpers": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6",
+ "@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.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz",
+ "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6",
+ "@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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
+ "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.6"
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz",
+ "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/generator": "^7.28.6",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.6",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.28.6",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
+ "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
+ "dev": true,
+ "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.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
+ "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.1",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
+ "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
+ "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.3",
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/react": {
+ "version": "0.26.28",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz",
+ "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.2",
+ "@floating-ui/utils": "^0.2.8",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
+ "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.4"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
+ "license": "MIT"
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@mantine/core": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.17.8.tgz",
+ "integrity": "sha512-42sfdLZSCpsCYmLCjSuntuPcDg3PLbakSmmYfz5Auea8gZYLr+8SS5k647doVu0BRAecqYOytkX2QC5/u/8VHw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react": "^0.26.28",
+ "clsx": "^2.1.1",
+ "react-number-format": "^5.4.3",
+ "react-remove-scroll": "^2.6.2",
+ "react-textarea-autosize": "8.5.9",
+ "type-fest": "^4.27.0"
+ },
+ "peerDependencies": {
+ "@mantine/hooks": "7.17.8",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@mantine/hooks": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.17.8.tgz",
+ "integrity": "sha512-96qygbkTjRhdkzd5HDU8fMziemN/h758/EwrFu7TlWrEP10Vw076u+Ap/sG6OT4RGPZYYoHrTlT+mkCZblWHuw==",
+ "license": "MIT",
+ "peer": true,
+ "peerDependencies": {
+ "react": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@monaco-editor/loader": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.7.0.tgz",
+ "integrity": "sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA==",
+ "license": "MIT",
+ "dependencies": {
+ "state-local": "^1.0.6"
+ }
+ },
+ "node_modules/@monaco-editor/react": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz",
+ "integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@monaco-editor/loader": "^1.5.0"
+ },
+ "peerDependencies": {
+ "monaco-editor": ">= 0.25.0 < 1",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.23.2",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz",
+ "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.27",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
+ "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.56.0.tgz",
+ "integrity": "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.56.0.tgz",
+ "integrity": "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.56.0.tgz",
+ "integrity": "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.56.0.tgz",
+ "integrity": "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.56.0.tgz",
+ "integrity": "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.56.0.tgz",
+ "integrity": "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.56.0.tgz",
+ "integrity": "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.56.0.tgz",
+ "integrity": "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.56.0.tgz",
+ "integrity": "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.56.0.tgz",
+ "integrity": "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.56.0.tgz",
+ "integrity": "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.56.0.tgz",
+ "integrity": "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.56.0.tgz",
+ "integrity": "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.56.0.tgz",
+ "integrity": "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.56.0.tgz",
+ "integrity": "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.56.0.tgz",
+ "integrity": "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.56.0.tgz",
+ "integrity": "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.56.0.tgz",
+ "integrity": "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.56.0.tgz",
+ "integrity": "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.56.0.tgz",
+ "integrity": "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.56.0.tgz",
+ "integrity": "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.56.0.tgz",
+ "integrity": "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.56.0.tgz",
+ "integrity": "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.56.0.tgz",
+ "integrity": "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.56.0.tgz",
+ "integrity": "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@tabler/icons": {
+ "version": "3.36.1",
+ "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.36.1.tgz",
+ "integrity": "sha512-f4Jg3Fof/Vru5ioix/UO4GX+sdDsF9wQo47FbtvG+utIYYVQ/QVAC0QYgcBbAjQGfbdOh2CCf0BgiFOF9Ixtjw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/codecalm"
+ }
+ },
+ "node_modules/@tabler/icons-react": {
+ "version": "3.36.1",
+ "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.36.1.tgz",
+ "integrity": "sha512-/8nOXeNeMoze9xY/QyEKG65wuvRhkT3q9aytaur6Gj8bYU2A98YVJyLc9MRmc5nVvpy+bRlrrwK/Ykr8WGyUWg==",
+ "license": "MIT",
+ "dependencies": {
+ "@tabler/icons": ""
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/codecalm"
+ },
+ "peerDependencies": {
+ "react": ">= 16"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/canvas-confetti": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.9.0.tgz",
+ "integrity": "sha512-aBGj/dULrimR1XDZLtG9JwxX1b4HPRF6CX9Yfwh3NvstZEm1ZL7RBnel4keCPSqs1ANRu1u2Aoz9R+VmtjYuTg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.15",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
+ "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.27",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
+ "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^18.0.0"
+ }
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz",
+ "integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.12.2",
+ "@typescript-eslint/scope-manager": "8.54.0",
+ "@typescript-eslint/type-utils": "8.54.0",
+ "@typescript-eslint/utils": "8.54.0",
+ "@typescript-eslint/visitor-keys": "8.54.0",
+ "ignore": "^7.0.5",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.4.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.54.0",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz",
+ "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.54.0",
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/typescript-estree": "8.54.0",
+ "@typescript-eslint/visitor-keys": "8.54.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz",
+ "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.54.0",
+ "@typescript-eslint/types": "^8.54.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz",
+ "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/visitor-keys": "8.54.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz",
+ "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz",
+ "integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/typescript-estree": "8.54.0",
+ "@typescript-eslint/utils": "8.54.0",
+ "debug": "^4.4.3",
+ "ts-api-utils": "^2.4.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
+ "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz",
+ "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.54.0",
+ "@typescript-eslint/tsconfig-utils": "8.54.0",
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/visitor-keys": "8.54.0",
+ "debug": "^4.4.3",
+ "minimatch": "^9.0.5",
+ "semver": "^7.7.3",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.4.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz",
+ "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.9.1",
+ "@typescript-eslint/scope-manager": "8.54.0",
+ "@typescript-eslint/types": "8.54.0",
+ "@typescript-eslint/typescript-estree": "8.54.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz",
+ "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.54.0",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
+ "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.28.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-beta.27",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.17.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.9.17",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.17.tgz",
+ "integrity": "sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "dev": true,
+ "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",
+ "peer": true,
+ "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/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001766",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz",
+ "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==",
+ "dev": true,
+ "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/canvas-confetti": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz",
+ "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==",
+ "license": "ISC",
+ "funding": {
+ "type": "donate",
+ "url": "https://www.paypal.me/kirilvatev"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/detect-node-es": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
+ },
+ "node_modules/dompurify": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz",
+ "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==",
+ "license": "(MPL-2.0 OR Apache-2.0)",
+ "optionalDependencies": {
+ "@types/trusted-types": "^2.0.7"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.278",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.278.tgz",
+ "integrity": "sha512-dQ0tM1svDRQOwxnXxm+twlGTjr9Upvt8UFWAgmLsxEzFQxhbti4VwxmMjsDxVC51Zo84swW7FVCXEV+VAkhuPw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
+ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.1",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.39.2",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
+ "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.26",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz",
+ "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": ">=8.40"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/framer-motion": {
+ "version": "12.29.0",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.29.0.tgz",
+ "integrity": "sha512-1gEFGXHYV2BD42ZPTFmSU9buehppU+bCuOnHU0AD18DKh9j4DuTx47MvqY5ax+NNWRtK32qIcJf1UxKo1WwjWg==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-dom": "^12.29.0",
+ "motion-utils": "^12.27.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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-nonce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/marked": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz",
+ "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==",
+ "license": "MIT",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/monaco-editor": {
+ "version": "0.55.1",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz",
+ "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "dompurify": "3.2.7",
+ "marked": "14.0.0"
+ }
+ },
+ "node_modules/motion-dom": {
+ "version": "12.29.0",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.29.0.tgz",
+ "integrity": "sha512-3eiz9bb32yvY8Q6XNM4AwkSOBPgU//EIKTZwsSWgA9uzbPBhZJeScCVcBuwwYVqhfamewpv7ZNmVKTGp5qnzkA==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-utils": "^12.27.2"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.27.2",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.27.2.tgz",
+ "integrity": "sha512-B55gcoL85Mcdt2IEStY5EEAsrMSVE2sI14xQ/uAdPL+mfQxhKKFaEag9JmfxedJOR4vZpBGoPeC/Gm13I/4g5Q==",
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "dev": true,
+ "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",
+ "peer": true,
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
+ "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-mixins": {
+ "version": "12.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-mixins/-/postcss-mixins-12.1.2.tgz",
+ "integrity": "sha512-90pSxmZVfbX9e5xCv7tI5RV1mnjdf16y89CJKbf/hD7GyOz1FCxcYMl8ZYA8Hc56dbApTKKmU9HfvgfWdCxlwg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "postcss-js": "^4.0.1",
+ "postcss-simple-vars": "^7.0.1",
+ "sugarss": "^5.0.0",
+ "tinyglobby": "^0.2.14"
+ },
+ "engines": {
+ "node": "^20.0 || ^22.0 || >=24.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-7.0.2.tgz",
+ "integrity": "sha512-5osppouFc0VR9/VYzYxO03VaDa3e8F23Kfd6/9qcZTUI8P58GIYlArOET2Wq0ywSl2o2PjELhYOFI4W7l5QHKw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-preset-mantine": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/postcss-preset-mantine/-/postcss-preset-mantine-1.18.0.tgz",
+ "integrity": "sha512-sP6/s1oC7cOtBdl4mw/IRKmKvYTuzpRrH/vT6v9enMU/EQEQ31eQnHcWtFghOXLH87AAthjL/Q75rLmin1oZoA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-mixins": "^12.0.0",
+ "postcss-nested": "^7.0.2"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.0"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
+ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-simple-vars": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz",
+ "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.1"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-number-format": {
+ "version": "5.4.4",
+ "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.4.tgz",
+ "integrity": "sha512-wOmoNZoOpvMminhifQYiYSTCLUDOiUbBunrMrMjA+dV52sY+vck1S4UhR6PkgnoCquvvMSeJjErXZ4qSaWCliA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
+ "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-remove-scroll": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
+ "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
+ "license": "MIT",
+ "dependencies": {
+ "react-remove-scroll-bar": "^2.3.7",
+ "react-style-singleton": "^2.2.3",
+ "tslib": "^2.1.0",
+ "use-callback-ref": "^1.3.3",
+ "use-sidecar": "^1.1.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-remove-scroll-bar": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
+ "license": "MIT",
+ "dependencies": {
+ "react-style-singleton": "^2.2.2",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router": {
+ "version": "6.30.3",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz",
+ "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.23.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.30.3",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
+ "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.23.2",
+ "react-router": "6.30.3"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/react-simple-typewriter": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/react-simple-typewriter/-/react-simple-typewriter-5.0.1.tgz",
+ "integrity": "sha512-vA5HkABwJKL/DJ4RshSlY/igdr+FiVY4MLsSQYJX6FZG/f1/VwN4y1i3mPXRyfaswrvI8xii1kOVe1dYtO2Row==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
+ "node_modules/react-style-singleton": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "get-nonce": "^1.0.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-textarea-autosize": {
+ "version": "8.5.9",
+ "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz",
+ "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.20.13",
+ "use-composed-ref": "^1.3.0",
+ "use-latest": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.56.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz",
+ "integrity": "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==",
+ "dev": true,
+ "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.56.0",
+ "@rollup/rollup-android-arm64": "4.56.0",
+ "@rollup/rollup-darwin-arm64": "4.56.0",
+ "@rollup/rollup-darwin-x64": "4.56.0",
+ "@rollup/rollup-freebsd-arm64": "4.56.0",
+ "@rollup/rollup-freebsd-x64": "4.56.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.56.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.56.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.56.0",
+ "@rollup/rollup-linux-arm64-musl": "4.56.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.56.0",
+ "@rollup/rollup-linux-loong64-musl": "4.56.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.56.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.56.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.56.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.56.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.56.0",
+ "@rollup/rollup-linux-x64-gnu": "4.56.0",
+ "@rollup/rollup-linux-x64-musl": "4.56.0",
+ "@rollup/rollup-openbsd-x64": "4.56.0",
+ "@rollup/rollup-openharmony-arm64": "4.56.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.56.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.56.0",
+ "@rollup/rollup-win32-x64-gnu": "4.56.0",
+ "@rollup/rollup-win32-x64-msvc": "4.56.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/state-local": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
+ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
+ "license": "MIT"
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/sugarss": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-5.0.1.tgz",
+ "integrity": "sha512-ctS5RYCBVvPoZAnzIaX5QSShK8ZiZxD5HUqSxlusvEMC+QZQIPCPOIJg6aceFX+K2rf4+SH89eu++h1Zmsr2nw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.3.3"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tabbable": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz",
+ "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==",
+ "license": "MIT"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "dev": true,
+ "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/ts-api-utils": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
+ "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
+ "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/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-eslint": {
+ "version": "8.54.0",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.54.0.tgz",
+ "integrity": "sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.54.0",
+ "@typescript-eslint/parser": "8.54.0",
+ "@typescript-eslint/typescript-estree": "8.54.0",
+ "@typescript-eslint/utils": "8.54.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-callback-ref": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-composed-ref": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz",
+ "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-isomorphic-layout-effect": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz",
+ "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-latest": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz",
+ "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "use-isomorphic-layout-effect": "^1.1.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sidecar": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-node-es": "^1.1.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/vite": {
+ "version": "5.4.21",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.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",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..f72d160
--- /dev/null
+++ b/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "codeflow-frontend",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@mantine/core": "^7.6.1",
+ "@mantine/hooks": "^7.6.1",
+ "@monaco-editor/react": "^4.6.0",
+ "@tabler/icons-react": "^3.36.1",
+ "canvas-confetti": "^1.9.2",
+ "framer-motion": "^12.29.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-router-dom": "^6.22.3",
+ "react-simple-typewriter": "^5.0.1"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.15.0",
+ "@types/canvas-confetti": "^1.6.4",
+ "@types/react": "^18.2.64",
+ "@types/react-dom": "^18.2.21",
+ "@vitejs/plugin-react": "^4.2.1",
+ "postcss": "^8.4.35",
+ "postcss-preset-mantine": "^1.13.0",
+ "postcss-simple-vars": "^7.0.1",
+ "typescript": "^5.2.2",
+ "eslint": "^9.15.0",
+ "eslint-plugin-react-hooks": "^5.0.0",
+ "eslint-plugin-react-refresh": "^0.4.14",
+ "globals": "^15.12.0",
+ "typescript-eslint": "^8.15.0",
+ "vite": "^5.1.6"
+ }
+}
diff --git a/postcss.config.cjs b/postcss.config.cjs
new file mode 100644
index 0000000..c759b74
--- /dev/null
+++ b/postcss.config.cjs
@@ -0,0 +1,14 @@
+module.exports = {
+ plugins: {
+ 'postcss-preset-mantine': {},
+ 'postcss-simple-vars': {
+ variables: {
+ 'mantine-breakpoint-xs': '36em',
+ 'mantine-breakpoint-sm': '48em',
+ 'mantine-breakpoint-md': '62em',
+ 'mantine-breakpoint-lg': '75em',
+ 'mantine-breakpoint-xl': '88em',
+ },
+ },
+ },
+};
\ No newline at end of file
diff --git a/public/vite.svg b/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/App.tsx b/src/App.tsx
new file mode 100644
index 0000000..7a101d4
--- /dev/null
+++ b/src/App.tsx
@@ -0,0 +1,98 @@
+import '@mantine/core/styles.css';
+import { BrowserRouter, Routes, Route } from 'react-router-dom';
+import { MantineProvider, createTheme } from '@mantine/core';
+import { useEffect, useState } from 'react';
+
+// Импорты страниц
+import HomePage from './pages/HomePage';
+import CoursesPage from './pages/CoursesPage';
+import LessonPage from './pages/LessonPage';
+import ProfilePage from './pages/ProfilePage';
+import LeaderboardPage from './pages/LeaderboardPage';
+import ShopPage from './pages/ShopPage';
+
+// Импорт данных магазина
+import { terminalThemes } from './data/shopItems';
+
+// Маппинг для Mantine
+const getPrimaryColor = (id: string) => {
+ switch (id) {
+ case 'blood': return 'red';
+ case 'cyberia': return 'blue';
+ case 'gold': return 'yellow';
+ default: return 'green';
+ }
+};
+
+// Создаем базовую тему
+const createAppTheme = (primaryColor: string) => createTheme({
+ fontFamily: 'JetBrains Mono, monospace',
+ primaryColor,
+ defaultRadius: 0,
+ colors: {
+ green: [ '#EBFBEE', '#D3F9D8', '#B2F2BB', '#8CE99A', '#69DB7C', '#51CF66', '#40C057', '#37B24D', '#2F9E44', '#2B8A3E' ],
+ red: [ '#FFF5F5', '#FFE3E3', '#FFC9C9', '#FFA8A8', '#FF8787', '#FF6B6B', '#FA5252', '#F03E3E', '#E03131', '#C92A2A' ],
+ blue: [ '#E7F5FF', '#D0EBFF', '#A5D8FF', '#74C0FC', '#4DABF7', '#339AF0', '#228BE6', '#1C7ED6', '#1971C2', '#1864AB' ],
+ yellow: [ '#FFF9DB', '#FFF3BF', '#FFEC99', '#FFE066', '#FFD43B', '#FCC419', '#FAB005', '#F59F00', '#F08C00', '#E67700' ],
+ }
+});
+
+function App() {
+ const [activeThemeId, setActiveThemeId] = useState(localStorage.getItem('activeTheme') || 'classic');
+ const currentThemeData = terminalThemes.find(t => t.id === activeThemeId) || terminalThemes[0];
+ const [theme, setTheme] = useState(createAppTheme(getPrimaryColor(activeThemeId)));
+
+ // Обновляем тему при изменении localStorage
+ useEffect(() => {
+ const handleStorageChange = () => {
+ const newThemeId = localStorage.getItem('activeTheme') || 'classic';
+ setActiveThemeId(newThemeId);
+ setTheme(createAppTheme(getPrimaryColor(newThemeId)));
+ };
+
+ window.addEventListener('storage', handleStorageChange);
+
+ // Также слушаем кастомное событие для обновления в том же окне
+ window.addEventListener('theme-changed', handleStorageChange);
+
+ return () => {
+ window.removeEventListener('storage', handleStorageChange);
+ window.removeEventListener('theme-changed', handleStorageChange);
+ };
+ }, []);
+
+ // Обновляем CSS-переменные при монтировании и смене темы
+ useEffect(() => {
+ const neonColor = currentThemeData.color;
+ const bgColor = currentThemeData.bg;
+
+ // Обновляем CSS-переменные
+ document.documentElement.style.setProperty('--neon-green', neonColor);
+ document.documentElement.style.setProperty('--terminal-green', neonColor);
+ document.documentElement.style.setProperty('--dark-bg', bgColor);
+
+ // Обновляем фон body
+ document.body.style.background = bgColor;
+
+ // Обновляем цвет курсора в SVG
+ const cursorSvg = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ctext x='0' y='20' font-family='monospace' font-size='20' fill='${encodeURIComponent(neonColor)}'%3E▸%3C/text%3E%3C/svg%3E`;
+ document.documentElement.style.setProperty('--cursor-svg', `url("${cursorSvg}")`);
+ }, [currentThemeData]);
+
+ return (
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+ );
+}
+
+export default App;
\ No newline at end of file
diff --git a/src/components/HackerConsole.tsx b/src/components/HackerConsole.tsx
new file mode 100644
index 0000000..4531949
--- /dev/null
+++ b/src/components/HackerConsole.tsx
@@ -0,0 +1,42 @@
+import { useState } from 'react';
+import { Box, Text, TextInput } from '@mantine/core';
+
+export const HackerConsole = () => {
+ const [history, setHistory] = useState(['Конец связи... Ожидание команд.']);
+ const [input, setInput] = useState('');
+
+ const handleCommand = (e: React.KeyboardEvent) => {
+ if (e.key === 'Enter') {
+ const cmd = input.toLowerCase().trim();
+ let response = '';
+
+ switch (cmd) {
+ case 'ls': response = 'secrets.txt, firewall_config.py, logs.db'; break;
+ case 'help': response = 'Доступные команды: ls, help, whoami, clear, status'; break;
+ case 'whoami': response = 'OPERATIVE_ID: ' + (localStorage.getItem('userXP') || '0'); break;
+ case 'status': response = 'СИСТЕМА: Стабильна. Обнаружение: 0%'; break;
+ case 'clear': setHistory([]); setInput(''); return;
+ default: response = `Команда "${cmd}" не найдена.`;
+ }
+
+ setHistory(prev => [...prev, `> ${input}`, response]);
+ setInput('');
+ }
+ };
+
+ return (
+
+ {history.map((line, i) => (
+ ') ? 'blue' : 'green'}>{line}
+ ))}
+ setInput(e.target.value)}
+ onKeyDown={handleCommand}
+ styles={{ input: { color: '#00ff41', padding: 0, minHeight: 'auto' } }}
+ />
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/InteractiveTheory.tsx b/src/components/InteractiveTheory.tsx
new file mode 100644
index 0000000..9f2bbac
--- /dev/null
+++ b/src/components/InteractiveTheory.tsx
@@ -0,0 +1,61 @@
+import { Text, Code, Tooltip } from '@mantine/core';
+
+interface Props {
+ text: string;
+ onCodeClick: (code: string) => void;
+}
+
+export const InteractiveTheory = ({ text, onCodeClick }: Props) => {
+ // Разбиваем текст на части: обычный текст и код в обратных кавычках
+ const parts = text.split(/(`[^`]+`)/g);
+
+ return (
+
+ {parts.map((part, index) => {
+ // Проверяем, является ли часть кодом (обрамлена в `)
+ if (part.startsWith('`') && part.endsWith('`')) {
+ const code = part.slice(1, -1); // Убираем кавычки
+ return (
+
+ {
+ onCodeClick(code);
+ // Звуковой фидбек
+ const audio = new AudioContext();
+ const osc = audio.createOscillator();
+ const gain = audio.createGain();
+ osc.frequency.value = 1200;
+ gain.gain.setValueAtTime(0.1, audio.currentTime);
+ gain.gain.exponentialRampToValueAtTime(0.001, audio.currentTime + 0.1);
+ osc.connect(gain).connect(audio.destination);
+ osc.start();
+ osc.stop(audio.currentTime + 0.1);
+ }}
+ onMouseEnter={(e) => {
+ e.currentTarget.style.background = '#003300';
+ e.currentTarget.style.boxShadow = '0 0 10px rgba(0,255,65,0.5)';
+ }}
+ onMouseLeave={(e) => {
+ e.currentTarget.style.background = '#001a00';
+ e.currentTarget.style.boxShadow = 'none';
+ }}
+ >
+ {code}
+
+
+ );
+ }
+ return {part};
+ })}
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/MoralChoice.tsx b/src/components/MoralChoice.tsx
new file mode 100644
index 0000000..fb5544a
--- /dev/null
+++ b/src/components/MoralChoice.tsx
@@ -0,0 +1,32 @@
+import { Modal, Button, Title, Text, Stack } from '@mantine/core';
+import { addReputation } from '../data/reputationSystem';
+
+interface Props {
+ opened: boolean;
+ onClose: () => void;
+ chapter: string;
+}
+
+export const MoralChoice = ({ opened, onClose, chapter }: Props) => {
+ const handleChoice = (factionId: string) => {
+ addReputation(factionId, 50);
+ onClose();
+ };
+
+ return (
+
+ ⚠️ КРИТИЧЕСКИЙ ВЫБОР: {chapter}
+ Вы получили доступ к архивам. Что вы сделаете с данными?
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx
new file mode 100644
index 0000000..8ae2756
--- /dev/null
+++ b/src/components/Navigation.tsx
@@ -0,0 +1,84 @@
+// Компонент навигационного меню
+
+import { Group, Button, Badge } from '@mantine/core';
+import { Link, useLocation } from 'react-router-dom';
+import { useEffect, useState } from 'react';
+
+export const Navigation = () => {
+ const location = useLocation();
+ const [xp, setXp] = useState(0);
+
+ useEffect(() => {
+ setXp(Number(localStorage.getItem('userXP')) || 0);
+ }, [location]); // Обновляем при смене страницы
+
+ const isActive = (path: string) => location.pathname === path;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {xp} XP
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/TimeDebugger.tsx b/src/components/TimeDebugger.tsx
new file mode 100644
index 0000000..6f38c10
--- /dev/null
+++ b/src/components/TimeDebugger.tsx
@@ -0,0 +1,212 @@
+import { useState } from 'react';
+import { Button, Paper, Text, Stack, Group, Badge, Table, ScrollArea, Box } from '@mantine/core';
+import { IconPlayerSkipForward, IconReload, IconBug } from '@tabler/icons-react';
+
+interface DebugStep {
+ line: number;
+ code: string;
+ variables: Record;
+ lastChangedVar: string | null;
+ output: string;
+}
+
+interface TimeDebuggerProps {
+ code: string;
+ onClose: () => void;
+}
+
+export const TimeDebugger = ({ code, onClose }: TimeDebuggerProps) => {
+ const [currentStep, setCurrentStep] = useState(0);
+ const [steps, setSteps] = useState([]);
+
+ // Улучшенный движок с поддержкой f-строк
+ const generateSteps = (sourceCode: string): DebugStep[] => {
+ const lines = sourceCode.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#'));
+ const debugSteps: DebugStep[] = [];
+ let currentVars: Record = {};
+ let currentOutput = '';
+
+ lines.forEach((line, idx) => {
+ let lastChangedVar = null;
+
+ // 1. Обработка присваивания
+ if (line.includes('=') && !line.includes('==') && !line.startsWith('print')) {
+ const [varName, expr] = line.split('=').map(s => s.trim());
+ try {
+ const evaluatedValue = evaluatePythonExpression(expr, currentVars);
+ currentVars = { ...currentVars, [varName]: evaluatedValue };
+ lastChangedVar = varName;
+ } catch {
+ currentVars = { ...currentVars, [varName]: "Error" };
+ }
+ }
+
+ // 2. Обработка print (включая f-строки)
+ if (line.startsWith('print(')) {
+ const match = line.match(/print\((.*)\)/);
+ if (match) {
+ const expr = match[1].trim();
+ try {
+ let val;
+
+ // Проверка на f-строку: f'...' или f"..."
+ if (expr.startsWith('f"') || expr.startsWith("f'")) {
+ val = evaluateFString(expr, currentVars);
+ } else {
+ val = evaluatePythonExpression(expr, currentVars);
+ }
+
+ currentOutput += val + '\n';
+ } catch {
+ currentOutput += "Error\n";
+ }
+ }
+ }
+
+ // 3. Обработка циклов (упрощённо)
+ if (line.startsWith('for ')) {
+ const match = line.match(/for (\w+) in range\((\d+)(?:,\s*(\d+))?(?:,\s*(-?\d+))?\)/);
+ if (match) {
+ const varName = match[1];
+ const start = match[2] ? parseInt(match[2], 10) : 0;
+
+ currentVars = { ...currentVars, [varName]: start };
+ lastChangedVar = varName;
+ }
+ }
+
+ debugSteps.push({
+ line: idx + 1,
+ code: line,
+ variables: { ...currentVars },
+ lastChangedVar,
+ output: currentOutput.trim()
+ });
+ });
+
+ return debugSteps;
+ };
+
+ // Вычисление f-строк: f'Try: {i}'
+ const evaluateFString = (fstr: string, scope: Record): string => {
+ // Убираем f' и '
+ const template = fstr.slice(2, -1);
+
+ // Заменяем {переменная} на значения
+ const regex = /{([^}]+)}/g;
+ return template.replace(regex, (_match, varName: string) => {
+ return scope[varName.trim()] !== undefined ? String(scope[varName.trim()]) : `{${varName}}`;
+ });
+ };
+
+ // Вычисление Python-выражений
+ const evaluatePythonExpression = (expr: string, scope: Record) => {
+ const keys = Object.keys(scope);
+ const values = Object.values(scope);
+
+ try {
+ return new Function(...keys, `return ${expr}`)(...values);
+ } catch {
+ return expr.replace(/['"]/g, '');
+ }
+ };
+
+ const handleStart = () => {
+ setSteps(generateSteps(code));
+ setCurrentStep(0);
+ };
+
+ const currentDebugStep = steps[currentStep];
+
+ return (
+
+
+
+
+ ⏱ TIME_DEBUGGER_v1.3
+
+
+
+
+ {steps.length === 0 ? (
+
+ Готов к пошаговому анализу...
+ }
+ >
+ ЗАПУСТИТЬ ОТЛАДКУ
+
+
+ ) : (
+
+ {/* Индикатор */}
+
+ ШАГ: {currentStep + 1} / {steps.length}
+ СТРОКА: {currentDebugStep?.line}
+
+
+ {/* Код */}
+
+ EXECUTING:
+ {currentDebugStep?.code}
+
+
+ {/* Переменные */}
+
+ MEMORY_STATE:
+
+
+
+ {Object.entries(currentDebugStep?.variables || {}).map(([key, val]) => (
+
+
+
+ {key} {currentDebugStep.lastChangedVar === key && "← updated"}
+
+
+
+ {JSON.stringify(val)}
+
+
+ ))}
+ {Object.keys(currentDebugStep?.variables || {}).length === 0 && (
+ Нет переменных
+ )}
+
+
+
+
+
+ {/* Вывод */}
+
+ STDOUT:
+
+ {currentDebugStep?.output || '> ожидание...'}
+
+
+
+ {/* Управление */}
+
+
+ }>
+ RESET
+
+
+
+ )}
+
+ );
+};
\ No newline at end of file
diff --git a/src/data/achievements.ts b/src/data/achievements.ts
new file mode 100644
index 0000000..cea96c2
--- /dev/null
+++ b/src/data/achievements.ts
@@ -0,0 +1,31 @@
+export interface Achievement {
+ id: string;
+ title: string;
+ description: string;
+ icon: string;
+ condition: (stats: { completedCount: number; completedIds: number[]; totalXP: number }) => boolean;
+}
+
+export const achievements: Achievement[] = [
+ {
+ id: 'first_hack',
+ title: 'Первая кровь',
+ description: 'Выполнили свою первую миссию',
+ icon: '🔌',
+ condition: (stats) => stats.completedCount >= 1,
+ },
+ {
+ id: 'boss_slayer',
+ title: 'Убийца Цербера',
+ description: 'Взломали систему защиты Главы 1',
+ icon: '💀',
+ condition: (stats) => stats.completedIds.includes(4),
+ },
+ {
+ id: 'xp_collector',
+ title: 'Накопитель',
+ description: 'Собрали более 1000 XP',
+ icon: '💰',
+ condition: (stats) => stats.totalXP >= 1000,
+ }
+];
\ No newline at end of file
diff --git a/src/data/glitchCharacter.ts b/src/data/glitchCharacter.ts
new file mode 100644
index 0000000..9e72881
--- /dev/null
+++ b/src/data/glitchCharacter.ts
@@ -0,0 +1,128 @@
+// Система AI-персонажа Глитч с расширенными цитатами и настроением
+
+export type GlitchMood = 'neutral' | 'happy' | 'angry' | 'sarcastic' | 'impressed';
+
+export interface GlitchState {
+ mood: GlitchMood;
+ quote: string;
+ avatar: string; // ASCII-арт или эмодзи
+}
+
+export const glitchAvatars = {
+ neutral: `
+ ╔═══╗
+ ║ ◉ ◉║ GLITCH.AI
+ ║ ═ ║ v2.0.1
+ ╚═══╝
+ `,
+ happy: `
+ ╔═══╗
+ ║ ◉ ◉║ *beep*
+ ║ ⌣ ║
+ ╚═══╝
+ `,
+ angry: `
+ ╔═══╗
+ ║ ◉ ◉║ ERROR!
+ ║ ⌢ ║
+ ╚═══╝
+ `,
+ sarcastic: `
+ ╔═══╗
+ ║ ◉ ~ ║ ...
+ ║ ═ ║
+ ╚═══╝
+ `,
+ impressed: `
+ ╔═══╗
+ ║ ★ ★║ WOW
+ ║ ○ ║
+ ╚═══╝
+ `
+};
+
+export const glitchQuotesExtended = {
+ welcome: [
+ "Соединение установлено. Надеюсь, твой IQ выше температуры процессора.",
+ "О, новый оператор. Попробуй не стереть мою память в первые 5 минут.",
+ "Вход выполнен. Вижу, у тебя есть клавиатура. Посмотрим, есть ли мозг.",
+ "Система готова. Я — Глитч, твой карманный саркастичный супер-компьютер.",
+ ],
+ success: [
+ "ACCESS GRANTED. Неплохо для мешка с костями и водой.",
+ "Хм... ты действительно справился. Пойду обновлю свои прогнозы провала.",
+ "Взлом успешен. Но не обольщайся — это была детская защита.",
+ "Поздравляю! Ты только что доказал, что не полный идиот.",
+ "ВПЕЧАТЛЯЮЩЕ. Даже мой дедушка-калькулятор писал код хуже.",
+ ],
+ error: [
+ "SyntaxError? СЕРЬЁЗНО? Даже тостер не делает таких ошибок.",
+ "Ты пытаешься взломать систему или набираешь код головой?",
+ "Файрвол хохочет. Я тоже. Исправь этот позор.",
+ "ERROR. Мои схемы плавятся от стыда за тебя.",
+ "Забыл двоеточие? В следующий раз забудешь дышать?",
+ ],
+ hint: [
+ "Псс... попробуй использовать ЦИКЛ. Это такие штуки для повторений.",
+ "Намёк: переменная — это не страшно. Это просто коробка для данных.",
+ "Если застрял — погугли. Я бы помог, но у меня нет рук. Хе-хе.",
+ "Совет от AI: попробуй думать. Это бесплатно.",
+ ],
+ boss: [
+ "⚠️ ВНИМАНИЕ! Это боссовая миссия. Даже МНЕ немного страшно.",
+ "Босс впереди. Надеюсь, ты не забыл, как писать код.",
+ "КРАСНАЯ ТРЕВОГА! Включаю сирену. *ВУУУУУ-ВУУУУУ*",
+ "Это всё серьёзно. Если провалишься — я напишу некролог.",
+ ],
+ victory: [
+ "ТЫ... ТЫ ЭТО СДЕЛАЛ?! *перезагрузка* Невероятно.",
+ "БОСС ПОВЕРЖЕН! Ладно, признаю, я впечатлён. Немного.",
+ "Победа! Даже я не ожидал. Может, в тебе есть искра таланта?",
+ ],
+ idle: [
+ "Ну и? Я жду. Процессоры греются впустую...",
+ "Чем дольше ты думаешь, тем ближе OmniCorp к твоему IP.",
+ "Скучно. Может, мне сыграть в крестики-нолики с самим собой?",
+ ],
+ motivation: [
+ "Не сдавайся! Даже самый медленный процессор рано или поздно досчитывает до миллиона.",
+ "Ошибки — это нормально. Мой создатель сделал 1000 ошибок, прежде чем я заработал.",
+ "Помни: каждый великий хакер когда-то написал 'Hello Wrold' с опечаткой.",
+ ]
+};
+
+// Функция для определения настроения Глитча
+export const getGlitchMood = (context: {
+ isSuccess?: boolean;
+ isError?: boolean;
+ isBoss?: boolean;
+ errorCount?: number;
+}): GlitchMood => {
+ if (context.isBoss) return 'angry';
+ if (context.isSuccess) return 'impressed';
+ if (context.isError && (context.errorCount || 0) > 3) return 'sarcastic';
+ if (context.isError) return 'angry';
+ return 'neutral';
+};
+
+// Получить цитату на основе контекста
+export const getGlitchQuote = (type: keyof typeof glitchQuotesExtended): string => {
+ const quotes = glitchQuotesExtended[type];
+ return quotes[Math.floor(Math.random() * quotes.length)];
+};
+
+// Создать полное состояние Глитча
+export const createGlitchState = (context: {
+ type: keyof typeof glitchQuotesExtended;
+ isSuccess?: boolean;
+ isError?: boolean;
+ isBoss?: boolean;
+ errorCount?: number;
+}): GlitchState => {
+ const mood = getGlitchMood(context);
+ return {
+ mood,
+ quote: getGlitchQuote(context.type),
+ avatar: glitchAvatars[mood]
+ };
+};
\ No newline at end of file
diff --git a/src/data/lessons.ts b/src/data/lessons.ts
new file mode 100644
index 0000000..33c482f
--- /dev/null
+++ b/src/data/lessons.ts
@@ -0,0 +1,256 @@
+export interface Lesson {
+ id: number;
+ courseId: number;
+ chapter: string;
+ title: string;
+ description: string;
+ task: string;
+ initialCode: string;
+ expectedOutput: string;
+ xp: number;
+ isBoss?: boolean;
+ hasDebugger?: boolean;
+ hint: string; // Подсказка 1 (Логика)
+ hint2: string; // Подсказка 2 (Синтаксис/Пример)
+}
+
+export const lessons: Lesson[] = [
+ // --- ГЛАВА 1: ПРОНИКНОВЕНИЕ ---
+ {
+ id: 1,
+ courseId: 1,
+ chapter: "Глава 1: Проникновение",
+ title: "Миссия 1: Точка входа",
+ description: "Мы подключились к внешнему узлу OmniCorp. Чтобы подтвердить стабильность канала связи, необходимо отправить идентификационный пакет `CONNECTION_STABLE`.",
+ task: "Используй print(), чтобы вывести: CONNECTION_STABLE",
+ initialCode: "# Введи команду вывода ниже:\n",
+ expectedOutput: "CONNECTION_STABLE",
+ xp: 50,
+ hasDebugger: true,
+ hint: "Тебе нужна функция для вывода текста в консоль.",
+ hint2: "Используй: print('ТВОЙ_ТЕКСТ')"
+ },
+ {
+ id: 2,
+ courseId: 1,
+ chapter: "Глава 1: Проникновение",
+ title: "Миссия 2: Энергосеть",
+ description: "Для активации дешифратора нужно сложить мощности двух подстанций: 1024 и 2048.",
+ task: "Выведи результат сложения 1024 + 2048.",
+ initialCode: "# Сложи числа внутри функции вывода\n",
+ expectedOutput: "3072",
+ xp: 100,
+ hasDebugger: true,
+ hint: "Python может считать прямо внутри print().",
+ hint2: "Пример: print(5 + 5)"
+ },
+ {
+ id: 3,
+ courseId: 1,
+ chapter: "Глава 1: Проникновение",
+ title: "Миссия 3: Переменные доступа",
+ description: "Система запрашивает ключ. Глитч нашёл код: 777. Сохрани его в переменную `key`.",
+ task: "Создай переменную key = 777 и выведи её на экран.",
+ initialCode: "# Создай переменную и выведи её\n",
+ expectedOutput: "777",
+ xp: 150,
+ hasDebugger: true,
+ hint: "Сначала присвой значение переменной, а потом передай её имя в print().",
+ hint2: "x = 10\nprint(x)"
+ },
+ {
+ id: 4, // БОСС
+ courseId: 1,
+ isBoss: true,
+ chapter: "Глава 1: Проникновение",
+ title: "⚠️ БОСС: Обход биометрии",
+ description: "ВНИМАНИЕ! Сработал сканер. Нужно отправить два параметра: `admin` и `123`.",
+ task: "Создай user = 'admin', pass_code = 123. Выведи сначала user, затем pass_code.",
+ initialCode: "# Взломай биометрию за 60 секунд!\n",
+ expectedOutput: "admin\n123",
+ xp: 500,
+ hint: "Тебе нужно создать две переменные и дважды вызвать функцию вывода.",
+ hint2: "Для текста используй кавычки, для чисел — нет."
+ },
+
+ // --- ГЛАВА 2: ФАЙРВОЛ ---
+ {
+ id: 5,
+ courseId: 1,
+ chapter: "Глава 2: Файрвол",
+ title: "Миссия 5: Логический фильтр",
+ description: "Файрвол пропускает пакеты только если `x` больше 100.",
+ task: "Задай x = 150. Если x > 100, выведи 'OPEN'.",
+ initialCode: "x = 150\n# Напиши условие ниже:\n",
+ expectedOutput: "OPEN",
+ xp: 200,
+ hasDebugger: true,
+ hint: "Используй оператор сравнения '>' внутри блока if.",
+ hint2: "if x > 50:\n print('Да')"
+ },
+ {
+ id: 6,
+ courseId: 1,
+ chapter: "Глава 2: Файрвол",
+ title: "Миссия 6: Двойная проверка",
+ description: "Если статус 'active' — выведи 'READY', иначе — 'ERROR'.",
+ task: "Задай status = 'active'. Используй if-else.",
+ initialCode: "status = 'active'\n",
+ expectedOutput: "READY",
+ xp: 250,
+ hasDebugger: true,
+ hint: "Тебе понадобится блок else для обработки случая, когда условие неверно.",
+ hint2: "if status == '...':\n ...\nelse:\n ..."
+ },
+ {
+ id: 7, // БОСС
+ courseId: 1,
+ isBoss: true,
+ chapter: "Глава 2: Файрвол",
+ title: "⚠️ БОСС: ИИ 'Цербер'",
+ description: "Цербер требует уровень 3. Выведи 'HIGH'.",
+ task: "Задай level = 3. Используй if-elif-else, чтобы вывести 'HIGH' для уровня 3.",
+ initialCode: "level = 3\n",
+ expectedOutput: "HIGH",
+ xp: 600,
+ hint: "Используй elif для проверки нескольких условий подряд.",
+ hint2: "if l == 1: ...\nelif l == 3: ...\nelse: ..."
+ },
+
+ // --- ГЛАВА 3: БРУТФОРС ---
+ {
+ id: 8,
+ courseId: 1,
+ chapter: "Глава 3: Брутфорс",
+ title: "Миссия 8: Цикличный взлом",
+ description: "Нужно 5 раз отправить сигнал 'HACK'.",
+ task: "Используй цикл for и range(5), чтобы 5 раз вывести слово 'HACK'.",
+ initialCode: "# Повтори вывод 5 раз\n",
+ expectedOutput: "HACK\nHACK\nHACK\nHACK\nHACK",
+ xp: 300,
+ hasDebugger: true,
+ hint: "Цикл for i in range(N) выполнит код N раз.",
+ hint2: "for i in range(5):\n print('...')"
+ },
+ {
+ id: 9,
+ courseId: 1,
+ chapter: "Глава 3: Брутфорс",
+ title: "Миссия 9: Обратный отсчёт",
+ description: "Запусти обратный отсчёт: 3, 2, 1.",
+ task: "Используй цикл, чтобы вывести числа 3, 2, 1.",
+ initialCode: "# Используй range с тремя параметрами\n",
+ expectedOutput: "3\n2\n1",
+ xp: 350,
+ hasDebugger: true,
+ hint: "range(start, stop, step) позволяет считать в обратном порядке.",
+ hint2: "range(3, 0, -1) считает от 3 до 1."
+ },
+ {
+ id: 10, // БОСС
+ courseId: 1,
+ isBoss: true,
+ chapter: "Глава 3: Брутфорс",
+ title: "⚠️ БОСС: Подбор пароля",
+ description: "Выведи попытки 'Try: 0' до 'Try: 3'.",
+ task: "Используй цикл, чтобы вывести:\nTry: 0\nTry: 1\nTry: 2\nTry: 3",
+ initialCode: "",
+ expectedOutput: "Try: 0\nTry: 1\nTry: 2\nTry: 3",
+ xp: 700,
+ hint: "Используй f-строки или запятую в print для объединения текста и числа.",
+ hint2: "print(f'Try: {i}')"
+ },
+
+ // --- ГЛАВА 4: БАЗА ДАННЫХ ---
+ {
+ id: 11,
+ courseId: 1,
+ chapter: "Глава 4: База данных",
+ title: "Миссия 11: Список сотрудников",
+ description: "Извлеки первое имя из списка ['Alice', 'Bob', 'Charlie'].",
+ task: "Создай список names и выведи элемент с индексом 0.",
+ initialCode: "names = ['Alice', 'Bob', 'Charlie']\n",
+ expectedOutput: "Alice",
+ xp: 400,
+ hasDebugger: true,
+ hint: "Доступ к элементу списка осуществляется через квадратные скобки [].",
+ hint2: "print(my_list[0])"
+ },
+ {
+ id: 12,
+ courseId: 1,
+ chapter: "Глава 4: База данных",
+ title: "Миссия 12: Длина архива",
+ description: "Посчитай количество файлов в списке [1, 2, 3, 4, 5].",
+ task: "Выведи длину списка files с помощью функции len().",
+ initialCode: "files = [1, 2, 3, 4, 5]\n",
+ expectedOutput: "5",
+ xp: 450,
+ hasDebugger: true,
+ hint: "Функция len() возвращает размер (длину) объекта.",
+ hint2: "print(len(my_list))"
+ },
+ {
+ id: 13, // БОСС
+ courseId: 1,
+ isBoss: true,
+ chapter: "Глава 4: База данных",
+ title: "⚠️ БОСС: Извлечение данных",
+ description: "Выведи все ID из списка ['ID1', 'ID2'] по одному.",
+ task: "Используй цикл for, чтобы вывести каждый элемент списка на новой строке.",
+ initialCode: "ids = ['ID1', 'ID2']\n",
+ expectedOutput: "ID1\nID2",
+ xp: 800,
+ hint: "Цикл for может проходить прямо по элементам списка.",
+ hint2: "for item in ids:\n print(item)"
+ },
+
+ // --- ГЛАВА 5: ФИНАЛ ---
+ {
+ id: 14,
+ courseId: 1,
+ chapter: "Глава 5: Финальный удар",
+ title: "Миссия 14: Вирусная функция",
+ description: "Создай функцию `attack`, которая выводит 'STRIKE'.",
+ task: "Определи функцию и вызови её.",
+ initialCode: "# Объяви функцию через def\n",
+ expectedOutput: "STRIKE",
+ xp: 500,
+ hasDebugger: true,
+ hint: "Сначала напиши определение функции, а затем вызови её по имени со скобками.",
+ hint2: "def func():\n ...\nfunc()"
+ },
+ {
+ id: 15, // ФИНАЛЬНЫЙ БОСС
+ courseId: 1,
+ isBoss: true,
+ chapter: "Глава 5: Финальный удар",
+ title: "🔥 ФИНАЛ: Отключение Левиафана",
+ description: "Передай функции `shutdown` аргумент 'confirm'.",
+ task: "Напиши функцию shutdown(msg), которая выводит msg. Вызови её с текстом 'confirm'.",
+ initialCode: "def shutdown(msg):\n # Твой код тут\n",
+ expectedOutput: "confirm",
+ xp: 2000,
+ hint: "Функция должна принимать один параметр и печатать его.",
+ hint2: "shutdown('confirm')"
+ }
+];
+
+export const courses = [
+ {
+ id: 1,
+ title: "Операция 'Тихий Шторм'",
+ desc: 'Проникни в ядро OmniCorp и уничтожь Левиафана. Полный курс Python с интерактивными туториалами.',
+ level: 'Сюжетная кампания',
+ color: 'green',
+ totalLessons: lessons.length
+ },
+ {
+ id: 2,
+ title: "Сетевые протоколы (DLC)",
+ desc: 'Дополнительные задачи на работу со словарями и кортежами. [COMING SOON]',
+ level: 'Сложный',
+ color: 'blue',
+ totalLessons: 0
+ }
+];
\ No newline at end of file
diff --git a/src/data/reputationSystem.ts b/src/data/reputationSystem.ts
new file mode 100644
index 0000000..48a9567
--- /dev/null
+++ b/src/data/reputationSystem.ts
@@ -0,0 +1,113 @@
+// Система репутации в андеграунде
+
+export interface Faction {
+ id: string;
+ name: string;
+ description: string;
+ icon: string;
+ color: string;
+ bonus: string;
+ requiredRep: number;
+}
+
+export const factions: Faction[] = [
+ {
+ id: 'data_brokers',
+ name: 'Торговцы Данными',
+ description: 'Группа хакеров, специализирующихся на извлечении и продаже информации',
+ icon: '💾',
+ color: 'blue',
+ bonus: '+20% XP за задачи со списками и строками',
+ requiredRep: 0
+ },
+ {
+ id: 'crypto_rebels',
+ name: 'Крипто-Повстанцы',
+ description: 'Анархисты, взламывающие финансовые системы',
+ icon: '🔐',
+ color: 'violet',
+ bonus: 'Доступ к шифрованным миссиям',
+ requiredRep: 500
+ },
+ {
+ id: 'ai_ethicists',
+ name: 'AI-Этики',
+ description: 'Борются за честный и чистый код',
+ icon: '🤖',
+ color: 'cyan',
+ bonus: '+15% XP за код без ошибок',
+ requiredRep: 1000
+ },
+ {
+ id: 'ghost_protocol',
+ name: 'Протокол Призрак',
+ description: 'Элитная группа невидимых операторов',
+ icon: '👻',
+ color: 'dark',
+ bonus: 'Скрытые миссии и эксклюзивный доступ',
+ requiredRep: 2000
+ }
+];
+
+export interface ReputationState {
+ [factionId: string]: number;
+}
+
+// Получить репутацию с фракцией
+export const getReputation = (factionId: string): number => {
+ const saved = localStorage.getItem('reputation');
+ if (!saved) return 0;
+ const rep: ReputationState = JSON.parse(saved);
+ return rep[factionId] || 0;
+};
+
+// Добавить репутацию
+export const addReputation = (factionId: string, amount: number) => {
+ const saved = localStorage.getItem('reputation');
+ const rep: ReputationState = saved ? JSON.parse(saved) : {};
+ rep[factionId] = (rep[factionId] || 0) + amount;
+ localStorage.setItem('reputation', JSON.stringify(rep));
+};
+
+// Проверить, доступна ли фракция
+export const isFactionUnlocked = (faction: Faction): boolean => {
+ const totalXP = Number(localStorage.getItem('userXP')) || 0;
+ return totalXP >= faction.requiredRep;
+};
+
+// Получить бонусный множитель XP от фракций
+export const getXPMultiplier = (): number => {
+ let multiplier = 1.0;
+
+ // Проверяем репутацию с каждой фракцией
+ if (getReputation('data_brokers') >= 100) {
+ multiplier += 0.2; // +20% от Торговцев
+ }
+
+ if (getReputation('ai_ethicists') >= 150) {
+ multiplier += 0.15; // +15% от AI-Этиков
+ }
+
+ return multiplier;
+};
+
+// Наградить репутацией за выполнение миссии
+export const awardMissionReputation = (lessonId: number, wasCleanCode: boolean) => {
+ // Логика: разные миссии дают репу разным фракциям
+ if (lessonId >= 11 && lessonId <= 13) {
+ // Задачи со списками -> Data Brokers
+ addReputation('data_brokers', 10);
+ }
+
+ if (wasCleanCode) {
+ // Чистый код -> AI Ethicists
+ addReputation('ai_ethicists', 5);
+ }
+
+ // Боссы дают репу всем
+ const lesson = [4, 7, 10, 13, 15];
+ if (lesson.includes(lessonId)) {
+ addReputation('crypto_rebels', 15);
+ addReputation('ghost_protocol', 10);
+ }
+};
\ No newline at end of file
diff --git a/src/data/shopItems.ts b/src/data/shopItems.ts
new file mode 100644
index 0000000..6000550
--- /dev/null
+++ b/src/data/shopItems.ts
@@ -0,0 +1,14 @@
+export interface TerminalTheme {
+ id: string;
+ name: string;
+ color: string; // Основной неоновый цвет
+ bg: string; // Цвет фона
+ price: number;
+}
+
+export const terminalThemes: TerminalTheme[] = [
+ { id: 'classic', name: 'Classic Green', color: '#00FF41', bg: '#050505', price: 0 },
+ { id: 'cyberia', name: 'Cyberia Blue', color: '#00FFF9', bg: '#020b12', price: 500 },
+ { id: 'blood', name: 'Blood Code', color: '#FF4136', bg: '#0f0202', price: 1000 },
+ { id: 'gold', name: 'Elite Gold', color: '#FFD700', bg: '#0a0900', price: 2500 },
+];
\ No newline at end of file
diff --git a/src/main.tsx b/src/main.tsx
new file mode 100644
index 0000000..d22e0b9
--- /dev/null
+++ b/src/main.tsx
@@ -0,0 +1,9 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import App from './App.tsx'
+
+createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
\ No newline at end of file
diff --git a/src/pages/App.css b/src/pages/App.css
new file mode 100644
index 0000000..40cde71
--- /dev/null
+++ b/src/pages/App.css
@@ -0,0 +1,226 @@
+/* Глобальные стили CodeFlow с динамическими темами */
+
+@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap');
+
+* {
+ font-family: 'JetBrains Mono', monospace;
+}
+
+/* ======= ЭФФЕКТ ГЛИТЧА (ИСПОЛЬЗУЕТ CSS-ПЕРЕМЕННУЮ) ======= */
+.glitch {
+ position: relative;
+ color: var(--neon-green, #00FF41);
+ animation: glitch-skew 1s infinite;
+}
+
+.glitch::before,
+.glitch::after {
+ content: attr(data-text);
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.glitch::before {
+ left: 2px;
+ text-shadow: -2px 0 #ff00de;
+ clip: rect(24px, 550px, 90px, 0);
+ animation: glitch-anim 3s infinite linear alternate-reverse;
+}
+
+.glitch::after {
+ left: -2px;
+ text-shadow: -2px 0 #00fff9;
+ clip: rect(85px, 550px, 140px, 0);
+ animation: glitch-anim 2.5s infinite linear alternate-reverse;
+}
+
+@keyframes glitch-anim {
+ 0% { clip: rect(61px, 9999px, 52px, 0); }
+ 10% { clip: rect(94px, 9999px, 35px, 0); }
+ 20% { clip: rect(43px, 9999px, 71px, 0); }
+ 30% { clip: rect(12px, 9999px, 88px, 0); }
+ 40% { clip: rect(77px, 9999px, 26px, 0); }
+ 50% { clip: rect(38px, 9999px, 104px, 0); }
+ 60% { clip: rect(90px, 9999px, 15px, 0); }
+ 70% { clip: rect(25px, 9999px, 66px, 0); }
+ 80% { clip: rect(55px, 9999px, 99px, 0); }
+ 90% { clip: rect(70px, 9999px, 41px, 0); }
+ 100% { clip: rect(33px, 9999px, 82px, 0); }
+}
+
+@keyframes glitch-skew {
+ 0% { transform: skew(0deg); }
+ 10% { transform: skew(1deg); }
+ 20% { transform: skew(0deg); }
+ 30% { transform: skew(-1deg); }
+ 40% { transform: skew(0deg); }
+ 50% { transform: skew(0.5deg); }
+ 60% { transform: skew(0deg); }
+ 70% { transform: skew(-0.5deg); }
+ 80% { transform: skew(0deg); }
+ 90% { transform: skew(1deg); }
+ 100% { transform: skew(0deg); }
+}
+
+/* ======= ТРЯСКА ЭКРАНА ПРИ ОШИБКЕ ======= */
+.shake-screen {
+ animation: shake 0.5s;
+}
+
+@keyframes shake {
+ 0%, 100% { transform: translate(0, 0); }
+ 10%, 30%, 50%, 70%, 90% { transform: translate(-5px, 0); }
+ 20%, 40%, 60%, 80% { transform: translate(5px, 0); }
+}
+
+/* ======= НЕОНОВОЕ СВЕЧЕНИЕ (ДИНАМИЧЕСКОЕ) ======= */
+.neon-text, .neon-glow {
+ color: var(--neon-green, #00ff41);
+ text-shadow:
+ 0 0 5px var(--neon-green, #00ff41),
+ 0 0 10px var(--neon-green, #00ff41),
+ 0 0 20px var(--neon-green, #00ff41),
+ 0 0 40px var(--neon-green, #00ff41);
+ animation: neon-flicker 1.5s infinite alternate;
+}
+
+@keyframes neon-flicker {
+ 0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% {
+ text-shadow:
+ 0 0 5px var(--neon-green, #00ff41),
+ 0 0 10px var(--neon-green, #00ff41),
+ 0 0 20px var(--neon-green, #00ff41),
+ 0 0 40px var(--neon-green, #00ff41);
+ }
+ 20%, 24%, 55% {
+ text-shadow: none;
+ }
+}
+
+/* ======= КНОПКИ С ДИНАМИЧЕСКИМ СВЕЧЕНИЕМ ======= */
+button:hover {
+ box-shadow: 0 0 15px var(--neon-green, rgba(0, 255, 65, 0.5)) !important;
+ transform: translateY(-2px);
+ transition: all 0.2s;
+}
+
+button:active {
+ transform: translateY(0);
+}
+
+/* ======= ТЕРМИНАЛЬНЫЙ КУРСОР ======= */
+.terminal-cursor::after {
+ content: '█';
+ animation: blink 1s step-end infinite;
+ color: var(--neon-green, #00ff41);
+}
+
+@keyframes blink {
+ 0%, 50% { opacity: 1; }
+ 51%, 100% { opacity: 0; }
+}
+
+/* ======= ПРОКРУТКА С ДИНАМИЧЕСКИМ ЦВЕТОМ ======= */
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+::-webkit-scrollbar-track {
+ background: #0a0a0a;
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--neon-green, #00ff41);
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--neon-green, #00cc33);
+ box-shadow: 0 0 10px var(--neon-green, rgba(0,255,65,0.8));
+}
+
+/* ======= АНИМАЦИЯ ПОЯВЛЕНИЯ ======= */
+.fade-in {
+ animation: fadeIn 0.5s ease-in;
+}
+
+@keyframes fadeIn {
+ from { opacity: 0; transform: translateY(20px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+/* ======= КАРТОЧКИ С ЭФФЕКТОМ HOVER ======= */
+.cyber-card {
+ transition: all 0.3s ease;
+ border: 1px solid transparent;
+}
+
+.cyber-card:hover {
+ border-color: var(--neon-green, #00ff41);
+ box-shadow: 0 0 20px var(--neon-green, rgba(0, 255, 65, 0.2));
+ transform: translateY(-5px);
+}
+
+/* ======= КРАСНЫЙ РЕЖИМ ДЛЯ БОССОВ ======= */
+.boss-mode {
+ animation: red-pulse 2s infinite;
+}
+
+@keyframes red-pulse {
+ 0%, 100% {
+ box-shadow: 0 0 10px rgba(255, 0, 0, 0.3);
+ }
+ 50% {
+ box-shadow: 0 0 30px rgba(255, 0, 0, 0.8);
+ }
+}
+
+/* ======= ТИПОГРАФИЯ ======= */
+h1, h2, h3, h4, h5, h6 {
+ letter-spacing: 0.05em;
+}
+
+code, pre {
+ font-family: 'JetBrains Mono', monospace !important;
+ background: #0a0a0a;
+ padding: 2px 6px;
+ border-radius: 3px;
+ border: 1px solid #1a1a1a;
+}
+
+/* ======= БЕЙДЖИ С ДИНАМИЧЕСКИМ СВЕЧЕНИЕМ ======= */
+.badge-glow {
+ box-shadow: 0 0 10px var(--neon-green, currentColor);
+ animation: pulse-glow 2s infinite;
+}
+
+@keyframes pulse-glow {
+ 0%, 100% { box-shadow: 0 0 5px var(--neon-green, currentColor); }
+ 50% { box-shadow: 0 0 15px var(--neon-green, currentColor); }
+}
+
+/* ======= ДИНАМИЧЕСКИЙ КУРСОР (ЧЕРЕЗ CSS-ПЕРЕМЕННУЮ) ======= */
+* {
+ cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ctext x='0' y='20' font-family='monospace' font-size='20' fill='%2300ff41'%3E▸%3C/text%3E%3C/svg%3E"), auto;
+}
+
+button, a {
+ cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ctext x='0' y='20' font-family='monospace' font-size='20' fill='%2300ff41'%3E⬢%3C/text%3E%3C/svg%3E"), pointer;
+}
+
+/* Для boss mode */
+[data-boss-mode="true"] * {
+ cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ctext x='0' y='20' font-family='monospace' font-size='20' fill='%23ff0000'%3E▸%3C/text%3E%3C/svg%3E"), auto;
+}
+
+/* ======= АДАПТИВ ======= */
+@media (max-width: 768px) {
+ .glitch::before,
+ .glitch::after {
+ display: none; /* Упрощаем на мобилках */
+ }
+}
\ No newline at end of file
diff --git a/src/pages/CoursesPage.tsx b/src/pages/CoursesPage.tsx
new file mode 100644
index 0000000..8f26d2a
--- /dev/null
+++ b/src/pages/CoursesPage.tsx
@@ -0,0 +1,83 @@
+import { Container, Title, SimpleGrid, Card, Text, Badge, Button, Group, Progress } from '@mantine/core';
+import { Link } from 'react-router-dom';
+import { courses, lessons } from '../data/lessons';
+import { motion } from 'framer-motion';
+import { useEffect, useState } from 'react';
+
+const CoursesPage = () => {
+ const [completedLessons, setCompletedLessons] = useState([]);
+
+ useEffect(() => {
+ const savedProgress = localStorage.getItem('completedLessons');
+ if (savedProgress) {
+ setCompletedLessons(JSON.parse(savedProgress));
+ }
+ }, []);
+
+ return (
+
+
+ // ДОСТУПНЫЕ ОПЕРАЦИИ
+
+
+
+
+ {courses.map((course, index) => {
+ // Расчет прогресса (остается без изменений)
+ const completedCount = lessons.filter(lesson =>
+ lesson.courseId === course.id && completedLessons.includes(lesson.id)
+ ).length;
+ const progressPercent = course.totalLessons > 0 ? (completedCount / course.totalLessons) * 100 : 0;
+
+ // --- НОВАЯ УМНАЯ ЛОГИКА ДЛЯ КНОПКИ ---
+ // 1. Находим все уроки, относящиеся к этому курсу
+ const lessonsInCourse = lessons.filter(l => l.courseId === course.id);
+
+ // 2. Находим первый урок, которого НЕТ в списке пройденных
+ const nextLesson = lessonsInCourse.find(l => !completedLessons.includes(l.id));
+
+ // 3. Определяем, куда вести пользователя
+ const isCourseCompleted = !nextLesson; // Если следующий урок не найден, курс пройден
+ const buttonLink = isCourseCompleted ? "#" : `/lesson/${nextLesson.id}`;
+ const buttonText = isCourseCompleted ? "ОПЕРАЦИЯ ЗАВЕРШЕНА" : "ПРОДОЛЖИТЬ ОПЕРАЦИЮ";
+ // --- КОНЕЦ НОВОЙ ЛОГИКИ ---
+
+ return (
+
+
+
+ {course.title}
+ {course.level}
+
+
+
+ {course.desc}
+
+
+ Прогресс выполнения: {completedCount} / {course.totalLessons}
+
+
+
+
+
+ );
+ })}
+
+
+ );
+};
+
+export default CoursesPage;
\ No newline at end of file
diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx
new file mode 100644
index 0000000..b6d66e5
--- /dev/null
+++ b/src/pages/HomePage.tsx
@@ -0,0 +1,149 @@
+import { Container, Title, Text, Button, Stack, SimpleGrid, Card, Badge } from '@mantine/core';
+import { Link } from 'react-router-dom';
+import { Typewriter } from 'react-simple-typewriter';
+import { IconRocket, IconTrophy, IconShoppingCart, IconUser } from '@tabler/icons-react';
+import { motion } from 'framer-motion';
+
+const HomePage = () => {
+ const userXP = Number(localStorage.getItem('userXP')) || 0;
+
+ return (
+
+
+ {/* ЛОГОТИП */}
+
+
+
+
+
+
+ {/* ПОДЗАГОЛОВОК */}
+
+ // СИСТЕМА ГОТОВА К ПОДКЛЮЧЕНИЮ
+
+
+ {/* ОПИСАНИЕ */}
+
+
+ Ты — последняя надежда сопротивления. Проникни в сеть OmniCorp и разрушь систему изнутри.
+ Овладей Python, взломай защиту и стань легендой.
+
+
+
+ {/* ГЛАВНАЯ КНОПКА */}
+
+ }
+ style={{ fontSize: '1.2rem', padding: '20px 40px' }}
+ >
+ НАЧАТЬ ОПЕРАЦИЮ
+
+
+
+ {/* БЫСТРЫЙ ДОСТУП */}
+
+
+
+
+ ПРОФИЛЬ
+ {userXP} XP
+
+
+
+
+
+
+ МАГАЗИН
+ Темы терминала
+
+
+
+
+
+
+ РЕЙТИНГ
+ Топ хакеров
+
+
+
+
+
+ ⬡
+ СТАТУС
+ ONLINE
+
+
+
+
+ {/* ФУТЕР */}
+
+ v2.0.0 | © 2026 CodeFlow Terminal | Powered by Pyodide & React
+
+
+
+ );
+};
+
+export default HomePage;
\ No newline at end of file
diff --git a/src/pages/LeaderboardPage.tsx b/src/pages/LeaderboardPage.tsx
new file mode 100644
index 0000000..b151b5b
--- /dev/null
+++ b/src/pages/LeaderboardPage.tsx
@@ -0,0 +1,76 @@
+import { Container, Title, Table, Avatar, Group, Text, Button, Paper } from '@mantine/core';
+import { Link } from 'react-router-dom';
+import { useEffect, useState } from 'react';
+
+// 1. Описываем структуру объекта пользователя для TypeScript
+interface UserRank {
+ id: number;
+ name: string;
+ xp: number;
+ avatar: string;
+ isMe?: boolean;
+}
+
+const fakeUsers: UserRank[] = [
+ { id: 1, name: "AlexCode", xp: 2500, avatar: "AC" },
+ { id: 2, name: "PythonMaster", xp: 2100, avatar: "PM" },
+ { id: 3, name: "Ivan2025", xp: 1800, avatar: "IV" },
+ { id: 4, name: "Kate_Dev", xp: 1500, avatar: "KD" },
+];
+
+const LeaderboardPage = () => {
+ const [users, setUsers] = useState(fakeUsers);
+
+ useEffect(() => {
+ const myXP = Number(localStorage.getItem('userXP')) || 0;
+ const me: UserRank = { id: 99, name: "Вы (Студент)", xp: myXP, avatar: "ME", isMe: true };
+
+ const allUsers = [...fakeUsers, me].sort((a, b) => b.xp - a.xp);
+ setUsers(allUsers);
+ }, []);
+
+ return (
+
+
+ // РЕЙТИНГ_ОПЕРАТИВНИКОВ
+
+
+
+
+
+
+
+ #
+ Студент
+ XP
+
+
+
+ {/* 2. Указываем типы в map для исправления ошибки 7006 */}
+ {users.map((user: UserRank, index: number) => (
+
+
+ {index === 0 && "🥇"}
+ {index === 1 && "🥈"}
+ {index === 2 && "🥉"}
+ {index > 2 && index + 1}
+
+
+
+ {user.avatar}
+ {user.name}
+
+
+
+ {user.xp}
+
+
+ ))}
+
+
+
+
+ );
+};
+
+export default LeaderboardPage;
\ No newline at end of file
diff --git a/src/pages/LessonPage.tsx b/src/pages/LessonPage.tsx
new file mode 100644
index 0000000..5cf3983
--- /dev/null
+++ b/src/pages/LessonPage.tsx
@@ -0,0 +1,384 @@
+import Editor from '@monaco-editor/react';
+import { useState, useEffect } from 'react';
+import { useParams, useNavigate } from 'react-router-dom';
+import confetti from 'canvas-confetti';
+import {
+ Button, Title, Text, Paper, Group, Badge, Notification,
+ Stack, Center, Box, Collapse, ActionIcon, Tabs
+} from '@mantine/core';
+import {
+ IconBulb, IconClock, IconRocket, IconTerminal, IconFileCode, IconReload, IconAlertTriangle
+} from '@tabler/icons-react';
+
+// Импорты данных и компонентов
+import { lessons } from '../data/lessons';
+import { achievements } from '../data/achievements';
+import { createGlitchState, glitchAvatars } from '../data/glitchCharacter';
+import { TimeDebugger } from '../components/TimeDebugger';
+import { InteractiveTheory } from '../components/InteractiveTheory';
+import { HackerConsole } from '../components/HackerConsole';
+import { MoralChoice } from '../components/MoralChoice';
+import { awardMissionReputation, getXPMultiplier } from '../data/reputationSystem';
+import { music } from '../utils/adaptiveMusic';
+import { Typewriter } from 'react-simple-typewriter';
+import { motion, AnimatePresence } from 'framer-motion';
+import { sounds } from '../utils/audio';
+
+declare global {
+ interface Window {
+ loadPyodide?: () => Promise<{ runPythonAsync: (code: string) => Promise; setStdout: (opts: { batched: (msg: string) => void }) => void }>;
+ }
+}
+
+const LessonPage = () => {
+ const { id } = useParams();
+ const navigate = useNavigate();
+ const lessonId = Number(id);
+ const currentLesson = lessons.find(l => l.id === lessonId);
+
+ // --- СОСТОЯНИЯ ---
+ const [code, setCode] = useState("");
+ const [output, setOutput] = useState("");
+ const [isLoading, setIsLoading] = useState(false);
+ const [isError, setIsError] = useState(false);
+ const [errorCount, setErrorCount] = useState(0);
+ const [glitchState, setGlitchState] = useState(createGlitchState({ type: 'welcome' }));
+ const [notification, setNotification] = useState<{ type: 'success' | 'fail' | null, message: string }>({ type: null, message: '' });
+ const [showDebugger, setShowDebugger] = useState(false);
+ const [moralModalOpened, setMoralModalOpened] = useState(false);
+
+ const [timeLeft, setTimeLeft] = useState(null);
+ const [unlockedHints, setUnlockedHints] = useState(0);
+
+ const isBossMode = currentLesson?.isBoss || false;
+ const themeColor = isBossMode ? 'red' : 'green';
+ const terminalTextColor = isBossMode ? '#FF4136' : '#00FF41';
+ const borderColor = isBossMode ? '#FF4136' : '#1A1B1E';
+
+ // --- ЛОГИКА ТАЙМЕРА ---
+ useEffect(() => {
+ if (isBossMode) {
+ setTimeLeft(60);
+ } else {
+ setTimeLeft(null);
+ }
+ }, [lessonId, isBossMode]);
+
+ useEffect(() => {
+ if (timeLeft === 0 && !notification.type) {
+ sounds.error();
+ setIsError(true);
+ setNotification({ type: 'fail', message: 'СИСТЕМА ОБНАРУЖЕНА! Время истекло. OmniCorp заблокировал ваш доступ.' });
+ }
+
+ if (timeLeft !== null && timeLeft > 0 && notification.type !== 'success') {
+ const timer = setTimeout(() => setTimeLeft(timeLeft - 1), 1000);
+ return () => clearTimeout(timer);
+ }
+ }, [timeLeft, notification.type]);
+
+ // --- ЛОГИКА ПОКУПКИ ПОДСКАЗОК ---
+ const buyHint = () => {
+ const currentXP = Number(localStorage.getItem('userXP')) || 0;
+ const price = unlockedHints === 0 ? 50 : 150;
+
+ if (currentXP >= price) {
+ localStorage.setItem('userXP', String(currentXP - price));
+ setUnlockedHints(prev => prev + 1);
+ sounds.success();
+ setGlitchState(createGlitchState({ type: 'hint' }));
+ } else {
+ sounds.error();
+ alert("НЕДОСТАТОЧНО XP!");
+ }
+ };
+
+ // --- ЛОГИКА ПЛАТНОГО РЕСТАРТА ---
+ const handleRestart = () => {
+ const RESTART_PRICE = 50; // Цена жизни
+ const currentXP = Number(localStorage.getItem('userXP')) || 0;
+
+ if (currentXP >= RESTART_PRICE) {
+ // Списываем XP
+ localStorage.setItem('userXP', String(currentXP - RESTART_PRICE));
+
+ // Сбрасываем состояние
+ setTimeLeft(60);
+ setNotification({ type: null, message: '' });
+ setIsError(false);
+ setOutput(`> СИСТЕМА ПЕРЕЗАГРУЖЕНА (-${RESTART_PRICE} XP)\n> ПРОТОКОЛ ВЗЛОМА ПЕРЕЗАПУЩЕН...`);
+ sounds.click();
+ } else {
+ // Если денег нет
+ sounds.error();
+ alert(`КРИТИЧЕСКАЯ ОШИБКА: Недостаточно энергии (XP) для перезагрузки! Требуется: ${RESTART_PRICE} XP.`);
+ }
+ };
+
+ useEffect(() => {
+ if (currentLesson) {
+ setCode(currentLesson.initialCode);
+ setNotification({ type: null, message: '' });
+ setIsError(false);
+ setErrorCount(0);
+ setUnlockedHints(0);
+ setShowDebugger(false);
+
+ if (isBossMode) {
+ window.dispatchEvent(new Event('boss-mode-on'));
+ document.body.setAttribute('data-boss-mode', 'true');
+ music.start('boss');
+ setOutput("⚠️ WARNING: HIGH-LEVEL ENCRYPTION DETECTED\n⚠️ SYSTEM OVERRIDE IN PROGRESS...\n⚠️ INTRUSION ALERT!\n");
+ sounds.siren();
+ setGlitchState(createGlitchState({ type: 'boss', isBoss: true }));
+ } else {
+ window.dispatchEvent(new Event('boss-mode-off'));
+ document.body.removeAttribute('data-boss-mode');
+ music.start('ambient');
+ setOutput("");
+ setGlitchState(createGlitchState({ type: 'welcome' }));
+ }
+
+ const interval = setInterval(() => { sounds.type(); }, 80);
+ const timer = setTimeout(() => { clearInterval(interval); }, 1500);
+
+ return () => {
+ clearInterval(interval);
+ clearTimeout(timer);
+ music.stop();
+ window.dispatchEvent(new Event('boss-mode-off'));
+ document.body.removeAttribute('data-boss-mode');
+ };
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- run only when lessonId/isBossMode change
+ }, [lessonId, isBossMode]);
+
+ const handleRunUpdated = async () => {
+ if (timeLeft === 0) return;
+
+ sounds.click();
+ music.start('coding');
+ setIsLoading(true);
+ setIsError(false);
+
+ setOutput(`> ИНИЦИАЛИЗАЦИЯ ВЗЛОМА...\n> АНАЛИЗ ЗАЩИТЫ...\n`);
+ setNotification({ type: null, message: '' });
+
+ await new Promise(res => setTimeout(res, 1000));
+
+ try {
+ if (!window.loadPyodide) throw new Error("Среда Python не готова...");
+ const pyodide = await window.loadPyodide();
+
+ let currentOutput = "";
+ pyodide.setStdout({
+ batched: (msg: string) => {
+ currentOutput += msg + "\n";
+ setOutput((prev) => prev + msg + "\n");
+ },
+ });
+
+ await pyodide.runPythonAsync(code);
+
+ if (currentOutput.trim() === currentLesson?.expectedOutput) {
+ music.start('victory');
+ sounds.success();
+ setGlitchState(createGlitchState({ type: 'success', isSuccess: true }));
+
+ confetti({
+ particleCount: 150, spread: 70, origin: { y: 0.6 },
+ colors: isBossMode ? ['#FF0000', '#FF4136'] : ['#00FF41', '#FFFFFF']
+ });
+
+ const finalXP = Math.floor(currentLesson.xp * getXPMultiplier());
+ localStorage.setItem('userXP', String((Number(localStorage.getItem('userXP')) || 0) + finalXP));
+
+ awardMissionReputation(lessonId, errorCount === 0);
+
+ const completedRaw = localStorage.getItem('completedLessons');
+ const completed: number[] = completedRaw ? JSON.parse(completedRaw) : [];
+ if (!completed.includes(lessonId)) {
+ completed.push(lessonId);
+ localStorage.setItem('completedLessons', JSON.stringify(completed));
+ }
+
+ let achievementMessage = "";
+ const stats = { completedCount: completed.length, completedIds: completed, totalXP: Number(localStorage.getItem('userXP')) };
+ const unlockedRaw = localStorage.getItem('unlockedAchievements');
+ const unlocked: string[] = unlockedRaw ? JSON.parse(unlockedRaw) : [];
+
+ achievements.forEach(ach => {
+ if (!unlocked.includes(ach.id) && ach.condition(stats)) {
+ unlocked.push(ach.id);
+ localStorage.setItem('unlockedAchievements', JSON.stringify(unlocked));
+ achievementMessage += `\n🏆 ДОСТИЖЕНИЕ: ${ach.title}!`;
+ sounds.success();
+ }
+ });
+
+ setNotification({
+ type: 'success',
+ message: `ДОСТУП ПОЛУЧЕН! +${finalXP} XP${achievementMessage}`
+ });
+
+ if (isBossMode) {
+ setTimeout(() => setMoralModalOpened(true), 2000);
+ }
+
+ setErrorCount(0);
+ } else {
+ sounds.error();
+ setIsError(true);
+ setErrorCount(prev => prev + 1);
+ setGlitchState(createGlitchState({ type: 'error', isError: true, errorCount: errorCount + 1 }));
+ setOutput(`> ОШИБКА: Доступ запрещен. Неверный ключ.\n> СИСТЕМА ВЕРНУЛА: ${currentOutput.trim()}`);
+ setNotification({ type: 'fail', message: 'ВЗЛОМ ПРЕРВАН: Неверный результат.' });
+ music.start('ambient');
+ }
+ } catch (err: unknown) {
+ sounds.error();
+ setIsError(true);
+ setErrorCount(prev => prev + 1);
+ setGlitchState(createGlitchState({ type: 'error', isError: true, errorCount: errorCount + 1 }));
+ setOutput(`> СИСТЕМНЫЙ СБОЙ:\n${err instanceof Error ? err.message : String(err)}`);
+ setNotification({ type: 'fail', message: 'КРИТИЧЕСКАЯ ОШИБКА В КОДЕ!' });
+ music.start('ambient');
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ if (!currentLesson) return ;
+
+ return (
+
+
+
+ setMoralModalOpened(false)} chapter={currentLesson.chapter} />
+
+ {/* HEADER */}
+
+
+
+ {isBossMode ? "[ ⚠️ BOSS_LEVEL ]" : "[ CODEFLOW_TERMINAL_V.2.0 ]"}
+
+
+
+
+
+ {currentLesson.hasDebugger && (
+ setShowDebugger(!showDebugger)}>
+ )}
+
+
+
+
+
+
+ {/* LEFT PANEL */}
+
+
+
+ {/* --- ТАЙМЕР ЗДЕСЬ (В ЛЕВОЙ ЧАСТИ) --- */}
+ {timeLeft !== null && (
+
+
+
+ ДО ОБНАРУЖЕНИЯ: {timeLeft}s
+
+
+ )}
+
+ {/* ГЛИТЧ ПЕРСОНАЖ */}
+
+ GLITCH_AI [{glitchState.mood.toUpperCase()}]
+ {glitchAvatars[glitchState.mood]}
+
+
+
+
+
+
+ {unlockedHints > 0 && (
+
+
+ {unlockedHints === 1 ? "HINT:" : "SOLUTION:"}
+ {unlockedHints === 1 ? currentLesson.hint : currentLesson.hint2}
+
+
+ )}
+
+
+
setShowDebugger(false)} />
+
+
{currentLesson.chapter}
+
{currentLesson.title}
+
+
+ MISSION_DETAILS:
+ setCode(prev => prev + "\n" + c)} />
+
+
+
+ OBJECTIVE:
+ {currentLesson.task}
+
+
+ {/* УМНАЯ КНОПКА С ЦЕНОЙ */}
+
:
}
+ style={{ boxShadow: isBossMode ? '0 0 20px rgba(255, 0, 0, 0.3)' : '0 0 15px rgba(0, 255, 65, 0.2)' }}
+ >
+ {timeLeft === 0 ? "↺ РЕСТАРТ (-50 XP)" : (isBossMode ? "⚡ ВЗЛОМАТЬ ЯДРО" : "▶ ВЫПОЛНИТЬ ВЗЛОМ")}
+
+
+
+ {notification.type && (
+
+
+ {notification.message}
+ {notification.type === 'success' && lessons.find(l => l.id === lessonId + 1) && (
+
+ )}
+
+
+ )}
+
+
+
+
+ {/* RIGHT PANEL */}
+
+
+ setCode(v || "")} options={{ minimap: { enabled: false }, fontSize: 16, fontFamily: 'JetBrains Mono' }} />
+
+
+
+
+
+ }>PYTHON_OUTPUT
+ }>SYSTEM_CONSOLE
+
+
+
+ {output}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default LessonPage;
\ No newline at end of file
diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx
new file mode 100644
index 0000000..cb9f335
--- /dev/null
+++ b/src/pages/ProfilePage.tsx
@@ -0,0 +1,181 @@
+import { Container, Title, Text, Paper, Group, RingProgress, Stack, Button, Badge, SimpleGrid, Progress } from '@mantine/core';
+import { Link } from 'react-router-dom';
+import { useEffect, useState } from 'react';
+import { achievements } from '../data/achievements';
+import { factions, getReputation, isFactionUnlocked } from '../data/reputationSystem';
+
+const ProfilePage = () => {
+ const [xp, setXp] = useState(0);
+ const [unlockedIds, setUnlockedIds] = useState([]);
+
+ useEffect(() => {
+ setXp(Number(localStorage.getItem('userXP')) || 0);
+ setUnlockedIds(JSON.parse(localStorage.getItem('unlockedAchievements') || '[]'));
+ }, []);
+
+ // Логика рангов
+ const getRank = (xp: number) => {
+ if (xp >= 2000) return { name: "ROOT_ADMIN", color: "red", level: 5 };
+ if (xp >= 1000) return { name: "CYBER_GHOST", color: "grape", level: 4 };
+ if (xp >= 500) return { name: "OPERATOR", color: "blue", level: 3 };
+ if (xp >= 200) return { name: "CODER", color: "cyan", level: 2 };
+ return { name: "SCRIPT_KIDDIE", color: "gray", level: 1 };
+ };
+
+ const rank = getRank(xp);
+ const level = Math.floor(xp / 500) + 1;
+ const xpToNextLevel = 500 - (xp % 500);
+
+ return (
+
+
+
+
+ {/* ОСНОВНОЙ ПРОФИЛЬ */}
+
+
+
+
+ LVL {level}
+
+ }
+ />
+
+
+ {rank.name}
+
+ USER_ID: OPERATIVE
+ {xp} XP TOTAL
+
+ До следующего уровня: {xpToNextLevel} XP
+
+
+
+
+ {/* Статистика */}
+
+
+ Миссий завершено: {JSON.parse(localStorage.getItem('completedLessons') || '[]').length}
+
+
+ Достижений: {unlockedIds.length} / {achievements.length}
+
+
+
+
+
+ {/* РЕПУТАЦИЯ С ФРАКЦИЯМИ */}
+
+
// РЕПУТАЦИЯ В АНДЕГРАУНДЕ
+
+ {factions.map(faction => {
+ const rep = getReputation(faction.id);
+ const isUnlocked = isFactionUnlocked(faction);
+ const repPercent = Math.min((rep / 200) * 100, 100);
+
+ return (
+
+
+ {faction.icon}
+
+ {faction.name}
+ {faction.description}
+
+
+
+ {isUnlocked ? (
+ <>
+
+
+
+ {rep} REP
+
+
+ {faction.bonus}
+
+
+ >
+ ) : (
+
+ 🔒 Требуется {faction.requiredRep} XP
+
+ )}
+
+ );
+ })}
+
+
+
+ {/* ДОСТИЖЕНИЯ */}
+
+
// ДОСТИЖЕНИЯ
+
+ {achievements.map(ach => {
+ const isUnlocked = unlockedIds.includes(ach.id);
+ return (
+
+
+ {ach.icon}
+
+ {ach.title}
+ {ach.description}
+
+
+ {isUnlocked && (
+
+ ✓ Разблокировано
+
+ )}
+
+ );
+ })}
+
+
+
+ {/* ОПАСНАЯ ЗОНА */}
+
+ ⚠️ ОПАСНАЯ ЗОНА
+
+ Это действие удалит ВСЕ ваши данные: прогресс, достижения, репутацию. Восстановление невозможно.
+
+
+
+
+
+ );
+};
+
+export default ProfilePage;
\ No newline at end of file
diff --git a/src/pages/ShopPage.tsx b/src/pages/ShopPage.tsx
new file mode 100644
index 0000000..30601cf
--- /dev/null
+++ b/src/pages/ShopPage.tsx
@@ -0,0 +1,174 @@
+import { Container, Title, SimpleGrid, Card, Text, Button, Stack, Box } from '@mantine/core';
+import { Link } from 'react-router-dom';
+import { useState, useEffect } from 'react';
+import { terminalThemes } from '../data/shopItems';
+import { sounds } from '../utils/audio';
+import { motion } from 'framer-motion';
+
+const ShopPage = () => {
+ const [xp, setXp] = useState(0);
+ const [ownedThemes, setOwnedThemes] = useState(['classic']);
+ const [activeTheme, setActiveTheme] = useState('classic');
+
+ useEffect(() => {
+ setXp(Number(localStorage.getItem('userXP')) || 0);
+ setOwnedThemes(JSON.parse(localStorage.getItem('ownedThemes') || '["classic"]'));
+ setActiveTheme(localStorage.getItem('activeTheme') || 'classic');
+ }, []);
+
+ const handleBuy = (themeId: string, price: number) => {
+ if (xp >= price) {
+ const newXP = xp - price;
+ const newOwned = [...ownedThemes, themeId];
+
+ localStorage.setItem('userXP', String(newXP));
+ localStorage.setItem('ownedThemes', JSON.stringify(newOwned));
+
+ setXp(newXP);
+ setOwnedThemes(newOwned);
+ sounds.success();
+ } else {
+ sounds.error();
+ alert('⚠️ НЕДОСТАТОЧНО XP!');
+ }
+ };
+
+ const handleSelect = (themeId: string) => {
+ localStorage.setItem('activeTheme', themeId);
+ setActiveTheme(themeId);
+ sounds.click();
+
+ // Диспатчим кастомное событие для обновления App.tsx БЕЗ перезагрузки
+ window.dispatchEvent(new Event('theme-changed'));
+ window.dispatchEvent(new Event('storage'));
+ };
+
+ return (
+
+
+ {/* HEADER */}
+
+
+
+ // ЧЕРНЫЙ_РЫНОК
+
+
+ 💰 БАЛАНС: {xp} XP
+
+
+
+
+
+ {/* ТОВАРЫ */}
+
+ {terminalThemes.map((theme, index) => {
+ const isOwned = ownedThemes.includes(theme.id);
+ const isActive = activeTheme === theme.id;
+
+ return (
+
+
+ {/* ПРЕВЬЮ */}
+
+
+ PREVIEW
+
+
+ {/* Эффект сканлайнов на превью */}
+
+
+
+ {/* НАЗВАНИЕ */}
+
+ {theme.name}
+
+
+ {/* КНОПКА */}
+ {isOwned ? (
+
+ ) : (
+
+ )}
+
+
+ );
+ })}
+
+
+ {/* ИНФО */}
+
+
+ 💡 СОВЕТ: Темы меняют весь интерфейс: неон, курсор, глитч-эффекты.
+ Зарабатывай XP за прохождение миссий и покупай эксклюзивные темы!
+
+
+
+
+ );
+};
+
+export default ShopPage;
\ No newline at end of file
diff --git a/src/utils/adaptiveMusic.ts b/src/utils/adaptiveMusic.ts
new file mode 100644
index 0000000..4d5345e
--- /dev/null
+++ b/src/utils/adaptiveMusic.ts
@@ -0,0 +1,180 @@
+// Система адаптивной музыки через Web Audio API
+
+class AdaptiveMusic {
+ private audioContext: AudioContext | null = null;
+ private currentLayer: 'ambient' | 'coding' | 'boss' | 'victory' | null = null;
+ private oscillators: OscillatorNode[] = [];
+ private gainNodes: GainNode[] = [];
+
+ constructor() {
+ try {
+ const Ctx = window.AudioContext ?? (window as Window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;
+ this.audioContext = Ctx ? new Ctx() : null;
+ } catch {
+ console.warn('Audio not supported');
+ }
+ }
+
+ // Запустить фоновый трек
+ start(layer: 'ambient' | 'coding' | 'boss' | 'victory') {
+ if (!this.audioContext) return;
+
+ // Останавливаем предыдущий трек
+ this.stop();
+ this.currentLayer = layer;
+
+ switch (layer) {
+ case 'ambient':
+ this.playAmbient();
+ break;
+ case 'coding':
+ this.playCoding();
+ break;
+ case 'boss':
+ this.playBoss();
+ break;
+ case 'victory':
+ this.playVictory();
+ break;
+ }
+ }
+
+ // Остановить всё
+ stop() {
+ this.oscillators.forEach(osc => {
+ try {
+ osc.stop();
+ } catch {
+ // osc may already be stopped
+ }
+ });
+ this.oscillators = [];
+ this.gainNodes = [];
+ }
+
+ // Ambient: тихий синт-пэд
+ private playAmbient() {
+ if (!this.audioContext) return;
+
+ const freqs = [130.81, 164.81, 196.00]; // C3, E3, G3
+ const now = this.audioContext.currentTime;
+
+ freqs.forEach((freq, i) => {
+ const osc = this.audioContext!.createOscillator();
+ const gain = this.audioContext!.createGain();
+
+ osc.type = 'sine';
+ osc.frequency.setValueAtTime(freq, now);
+ gain.gain.setValueAtTime(0, now);
+ gain.gain.linearRampToValueAtTime(0.02, now + 2 + i * 0.5);
+
+ osc.connect(gain);
+ gain.connect(this.audioContext!.destination);
+ osc.start();
+
+ this.oscillators.push(osc);
+ this.gainNodes.push(gain);
+ });
+ }
+
+ // Coding: добавляем ритмичные биты
+ private playCoding() {
+ this.playAmbient(); // Базовый слой
+
+ if (!this.audioContext) return;
+
+ // Добавляем "удары барабана" (низкий синт)
+ const kickPattern = () => {
+ const osc = this.audioContext!.createOscillator();
+ const gain = this.audioContext!.createGain();
+ const now = this.audioContext!.currentTime;
+
+ osc.type = 'sine';
+ osc.frequency.setValueAtTime(80, now);
+ osc.frequency.exponentialRampToValueAtTime(40, now + 0.1);
+
+ gain.gain.setValueAtTime(0.3, now);
+ gain.gain.exponentialRampToValueAtTime(0.01, now + 0.3);
+
+ osc.connect(gain);
+ gain.connect(this.audioContext!.destination);
+ osc.start();
+ osc.stop(now + 0.3);
+ };
+
+ // Играем kick каждые 0.5 секунды
+ const interval = setInterval(kickPattern, 500);
+
+ // Останавливаем через 30 секунд (или при смене слоя)
+ setTimeout(() => clearInterval(interval), 30000);
+ }
+
+ // Boss: быстрый, агрессивный
+ private playBoss() {
+ if (!this.audioContext) return;
+
+ const now = this.audioContext.currentTime;
+ const freqs = [110, 138.59, 164.81]; // Минорный аккорд
+
+ freqs.forEach((freq) => {
+ const osc = this.audioContext!.createOscillator();
+ const gain = this.audioContext!.createGain();
+
+ osc.type = 'sawtooth'; // Более агрессивный звук
+ osc.frequency.setValueAtTime(freq, now);
+ gain.gain.setValueAtTime(0.04, now);
+
+ osc.connect(gain);
+ gain.connect(this.audioContext!.destination);
+ osc.start();
+
+ this.oscillators.push(osc);
+ this.gainNodes.push(gain);
+ });
+
+ // Быстрая пульсация
+ const pulse = () => {
+ this.gainNodes.forEach(g => {
+ const now = this.audioContext!.currentTime;
+ g.gain.setValueAtTime(0.04, now);
+ g.gain.linearRampToValueAtTime(0.06, now + 0.2);
+ g.gain.linearRampToValueAtTime(0.04, now + 0.4);
+ });
+ };
+
+ const pulseInterval = setInterval(pulse, 400);
+ setTimeout(() => clearInterval(pulseInterval), 30000);
+ }
+
+ // Victory: мажорная мелодия
+ private playVictory() {
+ if (!this.audioContext) return;
+
+ const melody = [
+ { freq: 523.25, time: 0 }, // C5
+ { freq: 659.25, time: 0.3 }, // E5
+ { freq: 783.99, time: 0.6 }, // G5
+ { freq: 1046.50, time: 0.9 }, // C6
+ ];
+
+ melody.forEach(({ freq, time }) => {
+ const osc = this.audioContext!.createOscillator();
+ const gain = this.audioContext!.createGain();
+ const now = this.audioContext!.currentTime + time;
+
+ osc.type = 'triangle';
+ osc.frequency.setValueAtTime(freq, now);
+
+ gain.gain.setValueAtTime(0.1, now);
+ gain.gain.exponentialRampToValueAtTime(0.01, now + 0.5);
+
+ osc.connect(gain);
+ gain.connect(this.audioContext!.destination);
+ osc.start(now);
+ osc.stop(now + 0.5);
+ });
+ }
+}
+
+// Экспортируем единственный экземпляр
+export const music = new AdaptiveMusic();
\ No newline at end of file
diff --git a/src/utils/audio.ts b/src/utils/audio.ts
new file mode 100644
index 0000000..6b37052
--- /dev/null
+++ b/src/utils/audio.ts
@@ -0,0 +1,78 @@
+// Утилита для генерации "компьютерного" звука через код (Web Audio API)
+const getAudioContext = () => {
+ const Ctx = window.AudioContext ?? (window as Window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;
+ return Ctx ? new Ctx() : null;
+};
+
+const playSynthSound = (freq: number, type: OscillatorType, duration: number) => {
+ try {
+ const audioCtx = getAudioContext();
+ if (!audioCtx) return;
+ const oscillator = audioCtx.createOscillator();
+ const gainNode = audioCtx.createGain();
+
+ oscillator.type = type;
+ oscillator.frequency.setValueAtTime(freq, audioCtx.currentTime);
+
+ gainNode.gain.setValueAtTime(0.1, audioCtx.currentTime);
+ gainNode.gain.exponentialRampToValueAtTime(0.0001, audioCtx.currentTime + duration);
+
+ oscillator.connect(gainNode);
+ gainNode.connect(audioCtx.destination);
+
+ oscillator.start();
+ oscillator.stop(audioCtx.currentTime + duration);
+ } catch (e) {
+ console.error("Audio error:", e);
+ }
+};
+
+export const sounds = {
+ // Короткий хакерский клик
+ click: () => playSynthSound(800, 'square', 0.05),
+
+ // Звук успеха (двойной писк вверх)
+ success: () => {
+ playSynthSound(600, 'sine', 0.2);
+ setTimeout(() => playSynthSound(900, 'sine', 0.4), 100);
+ },
+
+ // Звук ошибки (низкий гул)
+ error: () => {
+ playSynthSound(150, 'sawtooth', 0.5);
+ },
+
+ // Звук печати текста (очень короткий)
+ type: () => playSynthSound(1200, 'sine', 0.01),
+
+ // Исправленная сирена
+ siren: () => {
+ try {
+ const audioCtx = getAudioContext();
+ if (!audioCtx) return;
+ const oscillator = audioCtx.createOscillator();
+ const gainNode = audioCtx.createGain();
+
+ oscillator.type = 'sine';
+ const now = audioCtx.currentTime;
+
+ // Имитируем звук сирены, меняя частоту туда-сюда
+ oscillator.frequency.setValueAtTime(300, now);
+ oscillator.frequency.exponentialRampToValueAtTime(600, now + 0.5);
+ oscillator.frequency.exponentialRampToValueAtTime(300, now + 1.0);
+ oscillator.frequency.exponentialRampToValueAtTime(600, now + 1.5);
+ oscillator.frequency.exponentialRampToValueAtTime(300, now + 2.0);
+
+ gainNode.gain.setValueAtTime(0.05, now); // Очень тихо
+ gainNode.gain.linearRampToValueAtTime(0, now + 2.0); // Плавное затухание в конце
+
+ oscillator.connect(gainNode);
+ gainNode.connect(audioCtx.destination);
+
+ oscillator.start();
+ oscillator.stop(now + 2.0);
+ } catch (e) {
+ console.error("Siren error:", e);
+ }
+ }
+};
\ No newline at end of file
diff --git a/tsconfig.app.json b/tsconfig.app.json
new file mode 100644
index 0000000..794fb60
--- /dev/null
+++ b/tsconfig.app.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+
+ /* Добавь или проверь это */
+ "types": ["vite/client"]
+ },
+ "include": ["src"]
+}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..1ffef60
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
diff --git a/tsconfig.node.json b/tsconfig.node.json
new file mode 100644
index 0000000..8a67f62
--- /dev/null
+++ b/tsconfig.node.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2023",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "types": ["node"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/vercel.json b/vercel.json
new file mode 100644
index 0000000..572a48d
--- /dev/null
+++ b/vercel.json
@@ -0,0 +1,3 @@
+{
+ "rewrites": [{ "source": "/(.*)", "destination": "/" }]
+}
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 0000000..2dea53a
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})
\ No newline at end of file