commit 8511fd0e89a93b78cb1e2bf476c62785cf9f7187 Author: s.esmaeili Date: Sun Oct 4 07:23:11 2026 +0330 feat: initial commit for Kerf Studio with IRANSans typography, Persian localization, and RTL support diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5cbd415 --- /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* + +# Dependencies +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Vite / Build outputs +.artifact diff --git a/index.html b/index.html new file mode 100644 index 0000000..4b7b4c2 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + Kerf Studio — استودیو طراحی و مهندسی محصول کِرف + + + + + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..5d5de3b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2812 @@ +{ + "name": "kerf-studio", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "kerf-studio", + "version": "0.0.0", + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.17", + "vite": "^6.0.11" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.3.0.tgz", + "integrity": "sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "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.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "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/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "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.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.64.0.tgz", + "integrity": "sha512-FLLpX941CD/7aBvX3GqLGBM9OvY5PGXTryPJkG5r5/OuBpZpV5k45Uo3RxAvqd35tsyc3hH1bhtz921IKzoIzg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.64.0.tgz", + "integrity": "sha512-iI32XM/jnDYJsvx5ai/za/7gWO9XoSeFFtU06/ZCaRgyilfJOjaopD3nOpk2WrTCGOyeDt4hleUiGOAnd5tHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.64.0.tgz", + "integrity": "sha512-dRBZlbt2sEtF8Mn4MODThze9fIPdDoOhVSlXMAKy5dQbOYK9pOOoPY4Fat3OTtr0+8zbJo5TTZwlsfxY/kDNJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.64.0.tgz", + "integrity": "sha512-Y3whrJOMucfkhgNkvcM93M6j8C53iEAMmPMYD99C6G1kUy4ELigLWk9ar2/4aCBSRgsql0zdlOemLgW2m5GZgQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.64.0.tgz", + "integrity": "sha512-S6S1GEzPjFF6IONYJX3AKt/799+8RgBgCcwRnUo+Ep1IvBxUbw5M51iU0TDdK2NWWVnSvCQ8yi6Em0fGASMOng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.64.0.tgz", + "integrity": "sha512-Ed1DPoFENkXj4IGzSB12SesV40iP6LxCCrbTIkSGIQBpOOxpBM+0kj62lmaeIHfMWTDoddqTOtqc7s8LYfn+Pw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.64.0.tgz", + "integrity": "sha512-J/6xhutJPtFyIkmHdf4olOdHHKH5kOJNumojdWn+Elv5ICEYTVOa362Vw27TxsK0BLzb1le3EDlO3UbvFK1lnQ==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.64.0.tgz", + "integrity": "sha512-G4L/Nnx59d2LvDoV/P4S5lZ7oVLT6hodOHMacqjiq2LL2gts86KbkEBTYL53+fBt0odhf7XPIbIATGoYiJctxg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.64.0.tgz", + "integrity": "sha512-zF16pvJDEUksGYRbfnXne7pdklAyj2XDmJeYKgP93oq0cUyX9Y8O7lUo1R+IY1GagP/YBvCEDCe7eEcAKpw//g==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.64.0.tgz", + "integrity": "sha512-nIggWn8n+w12+R5lsV+PYYoUY8vuObxPAQqJI7WES+9v0qspYuAHoZMfYM0yLxlipasT5BY9ht5W8t5c/rSCkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.64.0.tgz", + "integrity": "sha512-WLOTiHPzszP0dxIMsHpFeDSOSB5I49Mj8K4+yKE3H1X/D0JRG5XZ5jrctJLMjnUc/LUzaKiwq6EHWNJ8pup8PA==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.64.0.tgz", + "integrity": "sha512-35RK9aRhh7g7Pmeu5gQ01aCvrhXzj9LoBE6xtUcEH1ns+nyTaSzxSpADmBQINu4QiTDGvmQYwo1j5hlg1rRXFw==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.64.0.tgz", + "integrity": "sha512-RqTfnpoTjuWfPAmqK5p2edt2AMCDJWm6oTn7sKfmyx+6tRga0ip05SJ977o6udTcIiDeF/CJMUfkaN4gtWt6Aw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.64.0.tgz", + "integrity": "sha512-RQjZPigjxFvFZDijG6rjlSXxhRaTf9zLYVpGK+lVcga64oMqP1GbgVqCb46eHTTceSIgp89Ja0y5aPe3GFBYHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.64.0.tgz", + "integrity": "sha512-tjL58mgQcTRnDRpeky+Sth1MKQeYi2Ct6r3Luq9E5aTSjnM/i/JbozqZkKqp9thM5+oDSZxo+05f9kdQedfTGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.64.0.tgz", + "integrity": "sha512-ictoRyVaoZ8C67myHef+8hhCa6IplXJJ/xUCkVCxziV4zxMZh+jvhkhGsPBLqj1S72fnqD0QH5zL4lcaa4X7DQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.64.0.tgz", + "integrity": "sha512-8aVvZ2hfr9RLFzBQkQNmYeHLDja8fLeQAmLt757zdKN/B+8L809KlLJKctQjS22wZotptV8G6o7fVPuAs8S1tQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.64.0.tgz", + "integrity": "sha512-2dEF8GAcDKwshUfydD+GhosppNyBzhVUHkdFF3CXd3FpOkzj/RZzF5aoEtzklujklT5qFVRU2GK/cFeLaTNKVg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.64.0.tgz", + "integrity": "sha512-3XHTvoo2hKkh0MiOfS7SkhHjMaaWF7P4F3drocZZaho/Z8w7h/jpnuBHm91BOQLfvrKHs1yR+zir4E8RI3XzTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.64.0.tgz", + "integrity": "sha512-HKtkzodL4a3KFWDXDoO61cRynAWTR3LnAE0oGtfG9lcNFpNuVYUFOByxDgNqEvic9rvaQbAj+SFwTEWDptRaIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.64.0.tgz", + "integrity": "sha512-JBsxqiY16uyyCujtoC3s7zL+SrYyNElptD7K4V+KUoJ2V8/XG3hPWpheK+SuPwNh1cikJvIZmIdsrYXvD6PLJw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.64.0.tgz", + "integrity": "sha512-S5Qrijh37qhnUYQ0ay8WN3LuWeKjow7wTUyCOPMZtnXiBXYXdsZETI6ZLfYnQAKovltckPLBFdNeD61P2rJc7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.64.0.tgz", + "integrity": "sha512-zbZ6iMmLFEsCtTdc2/y1F/cDFVNNCPF7Ae8PCT/wdPE//hGwYp6r+MyCLMFX+kOeIe09Pz6ASfnnfpSTN1FJQQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.64.0.tgz", + "integrity": "sha512-L6Hw69oNpuYaOr1zCG30v0/DqKYCSRwodPGwIcVZ/6f8SOzq9rxtL/xNVI5MO4wjli+Ko0ErK9uHJL3mNPt8wQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.64.0.tgz", + "integrity": "sha512-nl+CTWIgOGszQmUz/kanfgrfFZ4qiwxKIfT/ryl3N3Ewk5tqizmYtNXiqb7Bu/fDtNgu1kyxdFiAUJNur3iysg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "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/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.31", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz", + "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==", + "dev": true, + "license": "MIT", + "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/@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/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.6.1.tgz", + "integrity": "sha512-cL1Qz6ADZhcEbny/8HPfe99J6HhNoYtpX2LFLIbhgGE7Q1hlQVkYFdetDN7Id3KiQxhDrHwzlHr/YQCnZ8+xSA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.9", + "caniuse-lite": "^1.0.30001810", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.27", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.27.tgz", + "integrity": "sha512-ElY12DaROGuan+lMmZ8Cvo/ZUbXPe7Enc/9VU/b1T3Kp4dwytRcNdR8DoSJN5SNJT/CuvcCA0DHDVmMOCePdRQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.29.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz", + "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", + "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": { + "baseline-browser-mapping": "^2.11.26", + "caniuse-lite": "^1.0.30001813", + "electron-to-chromium": "^1.5.439", + "node-releases": "^2.0.57", + "update-browserslist-db": "^1.3.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "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.30001814", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001814.tgz", + "integrity": "sha512-/Uaf1lAzr59XcMpW0o96WoEfr+VXK2OX4U9AgFoiSHsVJ4HppnIFUjtYzsyDH2+tgANaQb2/oxYGwCPapN1FpA==", + "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/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.444", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.444.tgz", + "integrity": "sha512-5ss/uJfoDYDHT0lfJzT6FbcskIzROIOPf0BbbFkGcvDzoJU7i//9GDrwwIHQVmIsrAGiF3ihpADBRIsrEFt1rQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", + "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/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/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/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/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz", + "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "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/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "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/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "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/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.19", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz", + "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", + "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/node-releases": { + "version": "2.0.57", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.57.tgz", + "integrity": "sha512-kQK9LGGFiHtrWiNhZtA7Qbw17AQz+dmsEKODRIVTXA9+e5MS/2gZEBhYJt13GrAz5/IOZKddH/0Z3TP/Zgo+yw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/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": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", + "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", + "dependencies": { + "nanoid": "^3.3.18", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "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-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/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", + "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", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "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/read-cache": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.2.tgz", + "integrity": "sha512-/peqiBB/n07gQGLsWaHho3WfvUyRscw0gYTsEFMhrIe/nWLkYaf5SbKYjGYqtRV3aPwykJgF2VEMo1ac4bnsGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.64.0.tgz", + "integrity": "sha512-gjA/kFeDfffII8COoPsvLPvE16hWDTEc1+0QKQNKUkuV8iJjqsC4xXs8/FzuL0v9EV39kuxTbAgcFoTRyy2TGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.64.0", + "@rollup/rollup-android-arm64": "4.64.0", + "@rollup/rollup-darwin-arm64": "4.64.0", + "@rollup/rollup-darwin-x64": "4.64.0", + "@rollup/rollup-freebsd-arm64": "4.64.0", + "@rollup/rollup-freebsd-x64": "4.64.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.64.0", + "@rollup/rollup-linux-arm-musleabihf": "4.64.0", + "@rollup/rollup-linux-arm64-gnu": "4.64.0", + "@rollup/rollup-linux-arm64-musl": "4.64.0", + "@rollup/rollup-linux-loong64-gnu": "4.64.0", + "@rollup/rollup-linux-loong64-musl": "4.64.0", + "@rollup/rollup-linux-ppc64-gnu": "4.64.0", + "@rollup/rollup-linux-ppc64-musl": "4.64.0", + "@rollup/rollup-linux-riscv64-gnu": "4.64.0", + "@rollup/rollup-linux-riscv64-musl": "4.64.0", + "@rollup/rollup-linux-s390x-gnu": "4.64.0", + "@rollup/rollup-linux-x64-gnu": "4.64.0", + "@rollup/rollup-linux-x64-musl": "4.64.0", + "@rollup/rollup-openbsd-x64": "4.64.0", + "@rollup/rollup-openharmony-arm64": "4.64.0", + "@rollup/rollup-win32-arm64-msvc": "4.64.0", + "@rollup/rollup-win32-ia32-msvc": "4.64.0", + "@rollup/rollup-win32-x64-gnu": "4.64.0", + "@rollup/rollup-win32-x64-msvc": "4.64.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/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/source-map-js": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/update-browserslist-db": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.3.tgz", + "integrity": "sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ==", + "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/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": "6.4.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/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/vite/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4b25ab7 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "kerf-studio", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.17", + "vite": "^6.0.11" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/public/fonts/IRANSans-Bold.ttf b/public/fonts/IRANSans-Bold.ttf new file mode 100644 index 0000000..12557c4 Binary files /dev/null and b/public/fonts/IRANSans-Bold.ttf differ diff --git a/public/fonts/IRANSans-DemiBold.ttf b/public/fonts/IRANSans-DemiBold.ttf new file mode 100644 index 0000000..18b50f0 Binary files /dev/null and b/public/fonts/IRANSans-DemiBold.ttf differ diff --git a/public/fonts/IRANSans-Light.ttf b/public/fonts/IRANSans-Light.ttf new file mode 100644 index 0000000..9defe1f Binary files /dev/null and b/public/fonts/IRANSans-Light.ttf differ diff --git a/public/fonts/IRANSans-Medium.ttf b/public/fonts/IRANSans-Medium.ttf new file mode 100644 index 0000000..d0b1af7 Binary files /dev/null and b/public/fonts/IRANSans-Medium.ttf differ diff --git a/public/fonts/IRANSans-Regular.ttf b/public/fonts/IRANSans-Regular.ttf new file mode 100644 index 0000000..9c9f0f6 Binary files /dev/null and b/public/fonts/IRANSans-Regular.ttf differ diff --git a/public/fonts/IRANSansWeb(FaNum).ttf b/public/fonts/IRANSansWeb(FaNum).ttf new file mode 100644 index 0000000..3835c1d Binary files /dev/null and b/public/fonts/IRANSansWeb(FaNum).ttf differ diff --git a/public/fonts/IRANSansWeb(FaNum)_Black.ttf b/public/fonts/IRANSansWeb(FaNum)_Black.ttf new file mode 100644 index 0000000..42af658 Binary files /dev/null and b/public/fonts/IRANSansWeb(FaNum)_Black.ttf differ diff --git a/public/fonts/IRANSansWeb(FaNum)_Bold.ttf b/public/fonts/IRANSansWeb(FaNum)_Bold.ttf new file mode 100644 index 0000000..adbf9e4 Binary files /dev/null and b/public/fonts/IRANSansWeb(FaNum)_Bold.ttf differ diff --git a/public/fonts/IRANSansWeb(FaNum)_Light.ttf b/public/fonts/IRANSansWeb(FaNum)_Light.ttf new file mode 100644 index 0000000..fae92bd Binary files /dev/null and b/public/fonts/IRANSansWeb(FaNum)_Light.ttf differ diff --git a/public/fonts/IRANSansWeb(FaNum)_Medium.ttf b/public/fonts/IRANSansWeb(FaNum)_Medium.ttf new file mode 100644 index 0000000..9622928 Binary files /dev/null and b/public/fonts/IRANSansWeb(FaNum)_Medium.ttf differ diff --git a/public/fonts/IRANSansWeb(FaNum)_UltraLight.ttf b/public/fonts/IRANSansWeb(FaNum)_UltraLight.ttf new file mode 100644 index 0000000..59dfb58 Binary files /dev/null and b/public/fonts/IRANSansWeb(FaNum)_UltraLight.ttf differ diff --git a/public/fonts/IRANSansXFaNum-Black.ttf b/public/fonts/IRANSansXFaNum-Black.ttf new file mode 100644 index 0000000..9d585cb Binary files /dev/null and b/public/fonts/IRANSansXFaNum-Black.ttf differ diff --git a/public/fonts/IRANSansXFaNum-BlackD4.ttf b/public/fonts/IRANSansXFaNum-BlackD4.ttf new file mode 100644 index 0000000..f42a32a Binary files /dev/null and b/public/fonts/IRANSansXFaNum-BlackD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-Bold.ttf b/public/fonts/IRANSansXFaNum-Bold.ttf new file mode 100644 index 0000000..12557c4 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-Bold.ttf differ diff --git a/public/fonts/IRANSansXFaNum-BoldD4.ttf b/public/fonts/IRANSansXFaNum-BoldD4.ttf new file mode 100644 index 0000000..e302c33 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-BoldD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-DemiBold.ttf b/public/fonts/IRANSansXFaNum-DemiBold.ttf new file mode 100644 index 0000000..18b50f0 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-DemiBold.ttf differ diff --git a/public/fonts/IRANSansXFaNum-DemiBoldD4.ttf b/public/fonts/IRANSansXFaNum-DemiBoldD4.ttf new file mode 100644 index 0000000..aa1efd8 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-DemiBoldD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-ExtraBlack.ttf b/public/fonts/IRANSansXFaNum-ExtraBlack.ttf new file mode 100644 index 0000000..5e9faae Binary files /dev/null and b/public/fonts/IRANSansXFaNum-ExtraBlack.ttf differ diff --git a/public/fonts/IRANSansXFaNum-ExtraBlackD4.ttf b/public/fonts/IRANSansXFaNum-ExtraBlackD4.ttf new file mode 100644 index 0000000..b2b2966 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-ExtraBlackD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-ExtraBold.ttf b/public/fonts/IRANSansXFaNum-ExtraBold.ttf new file mode 100644 index 0000000..91bddcf Binary files /dev/null and b/public/fonts/IRANSansXFaNum-ExtraBold.ttf differ diff --git a/public/fonts/IRANSansXFaNum-ExtraBoldD4.ttf b/public/fonts/IRANSansXFaNum-ExtraBoldD4.ttf new file mode 100644 index 0000000..ee414be Binary files /dev/null and b/public/fonts/IRANSansXFaNum-ExtraBoldD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-Heavy.ttf b/public/fonts/IRANSansXFaNum-Heavy.ttf new file mode 100644 index 0000000..8ac395d Binary files /dev/null and b/public/fonts/IRANSansXFaNum-Heavy.ttf differ diff --git a/public/fonts/IRANSansXFaNum-HeavyD4.ttf b/public/fonts/IRANSansXFaNum-HeavyD4.ttf new file mode 100644 index 0000000..0ced2c5 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-HeavyD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-Light.ttf b/public/fonts/IRANSansXFaNum-Light.ttf new file mode 100644 index 0000000..9defe1f Binary files /dev/null and b/public/fonts/IRANSansXFaNum-Light.ttf differ diff --git a/public/fonts/IRANSansXFaNum-LightD4.ttf b/public/fonts/IRANSansXFaNum-LightD4.ttf new file mode 100644 index 0000000..ad7d623 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-LightD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-Medium.ttf b/public/fonts/IRANSansXFaNum-Medium.ttf new file mode 100644 index 0000000..d0b1af7 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-Medium.ttf differ diff --git a/public/fonts/IRANSansXFaNum-MediumD4.ttf b/public/fonts/IRANSansXFaNum-MediumD4.ttf new file mode 100644 index 0000000..97b7713 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-MediumD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-Regular.ttf b/public/fonts/IRANSansXFaNum-Regular.ttf new file mode 100644 index 0000000..9c9f0f6 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-Regular.ttf differ diff --git a/public/fonts/IRANSansXFaNum-RegularD4.ttf b/public/fonts/IRANSansXFaNum-RegularD4.ttf new file mode 100644 index 0000000..cb02931 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-RegularD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-Thin.ttf b/public/fonts/IRANSansXFaNum-Thin.ttf new file mode 100644 index 0000000..c07dad5 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-Thin.ttf differ diff --git a/public/fonts/IRANSansXFaNum-ThinD4.ttf b/public/fonts/IRANSansXFaNum-ThinD4.ttf new file mode 100644 index 0000000..e2609ed Binary files /dev/null and b/public/fonts/IRANSansXFaNum-ThinD4.ttf differ diff --git a/public/fonts/IRANSansXFaNum-UltraLight.ttf b/public/fonts/IRANSansXFaNum-UltraLight.ttf new file mode 100644 index 0000000..82429a7 Binary files /dev/null and b/public/fonts/IRANSansXFaNum-UltraLight.ttf differ diff --git a/public/fonts/IRANSansXFaNum-UltraLightD4.ttf b/public/fonts/IRANSansXFaNum-UltraLightD4.ttf new file mode 100644 index 0000000..8f6329c Binary files /dev/null and b/public/fonts/IRANSansXFaNum-UltraLightD4.ttf differ diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..b964793 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,49 @@ +import "./styles.css"; +import { LanguageProvider, useLang } from "./LanguageContext"; +import Hero from "./components/Hero"; +import Product from "./components/Product"; +import Method from "./components/Method"; +import Proof from "./components/Proof"; +import Stack from "./components/Stack"; +import Studio from "./components/Studio"; +import Contact from "./components/Contact"; +import Vernier from "./components/Vernier"; + +function AppMain() { + const { strings, isRtl } = useLang(); + + return ( +
+ + {strings.skipToProducts} + +
+ +
+ {strings.products.map((p, i) => ( + + ))} +
+ + + + + +
+ +
+ ); +} + +export default function App() { + return ( + + + + ); +} diff --git a/src/LanguageContext.jsx b/src/LanguageContext.jsx new file mode 100644 index 0000000..829a4ee --- /dev/null +++ b/src/LanguageContext.jsx @@ -0,0 +1,33 @@ +import React, { createContext, useContext, useState, useEffect } from "react"; +import { t } from "./translations"; + +const LanguageContext = createContext(); + +export function LanguageProvider({ children }) { + const [lang, setLang] = useState(() => { + try { + return localStorage.getItem("kerf_lang") || "fa"; + } catch { + return "fa"; + } + }); + + useEffect(() => { + try { + localStorage.setItem("kerf_lang", lang); + } catch {} + document.documentElement.lang = lang; + document.documentElement.dir = lang === "fa" ? "rtl" : "ltr"; + }, [lang]); + + const toggleLang = () => setLang((prev) => (prev === "fa" ? "en" : "fa")); + const strings = t[lang] || t.fa; + + return ( + + {children} + + ); +} + +export const useLang = () => useContext(LanguageContext); diff --git a/src/components/Contact.jsx b/src/components/Contact.jsx new file mode 100644 index 0000000..1f6de92 --- /dev/null +++ b/src/components/Contact.jsx @@ -0,0 +1,35 @@ +import Mark from "./Mark"; +import { useLang } from "../LanguageContext"; + +export default function Contact() { + const { strings } = useLang(); + + return ( +
+

{strings.contactTag}

+
+

+ {strings.contactTitle} +

+
+ + {strings.contactEmail} + + + {strings.contactCallBtn} + +
+
+
+ +

{strings.contactFooter}

+
+
+ ); +} diff --git a/src/components/Hero.jsx b/src/components/Hero.jsx new file mode 100644 index 0000000..af16f43 --- /dev/null +++ b/src/components/Hero.jsx @@ -0,0 +1,118 @@ +import { useRef } from "react"; +import { useFrame, pinProgress, ease, clamp, reducedMotion } from "../scroll"; +import Scaled from "./Scaled"; +import { LedgerUI, TideUI, QuireUI, HaldenUI } from "./ProductUIs"; +import Mark from "./Mark"; +import { useLang } from "../LanguageContext"; + +const UI_MAP = { + ledger: LedgerUI, + tide: TideUI, + quire: QuireUI, + halden: HaldenUI, +}; + +export default function Hero() { + const { strings, lang, toggleLang } = useLang(); + const sec = useRef(null), top = useRef(null), bot = useRef(null), inner = useRef(null), read = useRef(null), hint = useRef(null); + + useFrame(() => { + if (!sec.current) return; + const p = reducedMotion() ? 0 : pinProgress(sec.current); + const e = ease(clamp(p / 0.72)); + top.current.style.transform = `translate3d(0, ${-e * 100}%, 0)`; + bot.current.style.transform = `translate3d(0, ${e * 100}%, 0)`; + const r = clamp((p - 0.12) / 0.7); + inner.current.style.transform = `scale(${0.86 + 0.14 * ease(r)})`; + inner.current.style.opacity = String(clamp(r * 1.6)); + read.current.textContent = (e * window.innerHeight * 0.2645).toFixed(1).padStart(5, "0"); + hint.current.style.opacity = String(1 - clamp(p * 8)); + }); + + return ( +
+
+ {/* the chamber: what is inside the cut */} +
+
+

+ {strings.insideChamberTitle} +

+

+ {strings.insideChamberDesc} +

+
+ +
+ + {/* top half */} +
+
+
+ + +
+

+ {strings.studioSubtitle} +

+
+
+

+ {strings.heroTitle1} +

+
+
+
+
+
+ + {/* bottom half */} +
+
+
+ +
+
+

+ {strings.heroTitle2} +

+
+
+

+ {strings.heroLead} +

+
+ {strings.kerfWidth} + 000.0 mm + + {strings.scrollToCut} +
+
+
+
+
+ ); +} diff --git a/src/components/Mark.jsx b/src/components/Mark.jsx new file mode 100644 index 0000000..6784c30 --- /dev/null +++ b/src/components/Mark.jsx @@ -0,0 +1,9 @@ +// Wordmark: KERF with the saw's notch taken out of the F. +export default function Mark({ dark = false, size = 22, notch = "var(--blaze)" }) { + return ( + + KER + F + + ); +} diff --git a/src/components/Method.jsx b/src/components/Method.jsx new file mode 100644 index 0000000..b52141c --- /dev/null +++ b/src/components/Method.jsx @@ -0,0 +1,66 @@ +import { useRef } from "react"; +import { useFrame, pinProgress, reducedMotion } from "../scroll"; +import { useLang } from "../LanguageContext"; + +const Glyph = ({ i }) => ( + + + {i >= 0 && } + {i >= 1 && } + {i >= 2 && } + {i >= 3 && } + +); + +export default function Method() { + const { strings, isRtl } = useLang(); + const sec = useRef(null), track = useRef(null), meter = useRef(null); + + useFrame(() => { + if (!sec.current || reducedMotion()) return; + const p = pinProgress(sec.current); + const max = track.current.scrollWidth - window.innerWidth; + const offset = isRtl ? p * Math.max(0, max) : -p * Math.max(0, max); + track.current.style.transform = `translate3d(${offset}px,0,0)`; + meter.current.style.transform = `scaleX(${p})`; + }); + + return ( +
+
+
+

{strings.methodTitle}

+

+ {strings.methodSubtitle} +

+
+
+ {strings.methodItems.map((m, i) => ( +
+
+ + {strings.methodStage.replace("{i}", i + 1).replace("{d}", m.d)} + + +
+
+

{m.v}

+

{m.t}

+

+ {isRtl ? "← " : "→ "} + {m.out} +

+
+
+ ))} +
+

{strings.methodFooter}

+
+
+
+
+
+
+
+ ); +} diff --git a/src/components/Product.jsx b/src/components/Product.jsx new file mode 100644 index 0000000..77b0d63 --- /dev/null +++ b/src/components/Product.jsx @@ -0,0 +1,70 @@ +import { useRef } from "react"; +import { usePinStep } from "../scroll"; +import Scaled from "./Scaled"; +import { LedgerUI, TideUI, QuireUI, HaldenUI } from "./ProductUIs"; +import { useLang } from "../LanguageContext"; + +const UIS = { ledger: LedgerUI, tide: TideUI, quire: QuireUI, halden: HaldenUI }; + +export default function Product({ p, index, total }) { + const { strings, isRtl } = useLang(); + const sec = useRef(null), bar = useRef(null); + const step = usePinStep(sec, 3, (v) => { if (bar.current) bar.current.style.transform = `scaleX(${v})`; }); + const UI = UIS[p.key] || LedgerUI; + const states = strings.productStates; + + return ( +
+
+ {/* blueprint grid that fades as the object becomes real */} +
+ +
+ {/* text column */} +
+
+ {String(index + 1).padStart(2, "0")}/{String(total).padStart(2, "0")} + + {p.field} +
+

{p.name}

+

{p.owner}

+ +
    + {states.map((s, i) => ( +
  1. + {s} + +
  2. + ))} +
+ +
+ {p.steps.map((s, i) => ( +
+

{s.k}

+

{s.t}

+ {s.m && ( +

+ {s.m} + {s.ml} +

+ )} +
+ ))} +
+
+ + {/* the object */} +
+ +
+
+ +
+
+
+
+
+ ); +} diff --git a/src/components/ProductUIs.jsx b/src/components/ProductUIs.jsx new file mode 100644 index 0000000..be7f2ca --- /dev/null +++ b/src/components/ProductUIs.jsx @@ -0,0 +1,523 @@ +import { useLang } from "../LanguageContext"; + +// Four product interfaces drawn at 720x460. Each moves through three states: +// 0 drawing (dashed blueprint + dimensions), 1 object (filled), 2 running (live + measured callout). +const Bar = ({ w, h = 6, c = "rgba(18,20,19,.14)", className = "", style }) => ( +
+); + +const Win = ({ children, title, crumb, right }) => ( +
+
+
+ {title} + / + {crumb} +
+
{right}
+
+ {children} +
+); + +const Dim = ({ children, style }) => {children}; + +const Callout = ({ children, style, side = "left" }) => ( +
+ {side === "right" && } +
{children}
+ {side === "left" && } +
+); + +const Live = ({ label = "Live" }) => ( + + + {label} + +); + +/* ---------------- Ledgerline : treasury ---------------- */ +export function LedgerUI({ step }) { + const { isRtl } = useLang(); + const pts = [62, 58, 64, 60, 70, 66, 74, 71, 80, 77, 86, 83, 92, 96]; + const path = pts.map((v, i) => `${i ? "L" : "M"}${(i / (pts.length - 1)) * 420} ${140 - v * 1.25}`).join(" "); + const rows = isRtl + ? [ + ["شرکت نورث‌ویند", "€ ۱,۲۰۴,۰۰۰.۰۰"], + ["آکیرو کی‌کی", "¥ ۸۸,۴۰۰,۰۰۰"], + ["هالورسن آ‌اس", "kr ۳,۹۰۰,۵۰۰"], + ["اورتیز و واله", "$ ۶۴۰,۲۱۰.۰۰"], + ["بانکا لومه", "€ ۹۲,۰۰۰.۰۰"], + ] + : [ + ["Northwind GmbH", "€ 1,204,000.00"], + ["Akiro KK", "¥ 88,400,000"], + ["Halvorsen AS", "kr 3,900,500"], + ["Ortiz & Vale", "$ 640,210.00"], + ["Banca Lume", "€ 92,000.00"], + ]; + + return ( +
+ + EUR + · + + + } + > +
+
+
+ {isRtl ? "تراز تجمیعی · ۲۳ حساب · ۹ ارز بین‌الملل" : "Consolidated · 23 accounts · 9 currencies"} +
+
+ €48,213,940.12 +
+ h 100 +
+
+
+ {isRtl ? "وضعیت ۹۰ روزه" : "90 DAY POSITION"} + +12.8% +
+ + {[0, 1, 2, 3].map((g) => ( + + ))} + + + + +
+ {isRtl ? "تیر" : "JUL"} + {isRtl ? "مرداد" : "AUG"} + {isRtl ? "شهریور" : "SEP"} +
+ w 440 · chart 90d +
+
+
+
+ {isRtl ? "تسویه‌ها" : "SETTLEMENTS"} + {isRtl ? "امروز ۲۱۴" : "today 214"} +
+ {rows.map(([n, a], i) => ( +
+
+ {n} +
+
+ {a} + + {step === 2 && i === 2 + ? isRtl ? "تسویه ۱۴۰ms" : "settled 138ms" + : i < 2 + ? isRtl ? "در انتظار" : "pending" + : isRtl ? "تسویه شد" : "settled"} + +
+
+ ))} + w 232 · list ×n +
+
+ + {isRtl ? "تاخیر p99 تسویه" : "p99 settlement"} +
+ 140 ms +
+
+ ); +} + +/* ---------------- Tidewater : berth planning ---------------- */ +export function TideUI({ step }) { + const { isRtl } = useLang(); + const ships = [ + { b: 0, x: 30, w: 170, n: "MSC Aurelia", t: "ETA 02:10" }, + { b: 0, x: 240, w: 210, n: "Kobe Express", t: "ETA 09:40" }, + { b: 1, x: 90, w: 150, n: "Nordlys", t: "ETA 04:00" }, + { b: 1, x: 260, w: 140, n: "Cap Ferro", t: "ETA 11:20", conflict: true }, + { b: 2, x: 20, w: 260, n: "Ever Lumen", t: "ETA 00:30" }, + { b: 3, x: 300, w: 180, n: "Saga Viking", t: "ETA 13:00" }, + { b: 4, x: 60, w: 200, n: "Atlantic Wren", t: "ETA 03:15" }, + { b: 4, x: 300, w: 120, n: "Hanse 7", t: "ETA 12:30" }, + ]; + const tabs = isRtl ? ["اسکله‌ها", "جرثقیل‌ها", "محوطه کانتینر", "گیت‌ها"] : ["Berths", "Cranes", "Yard", "Gates"]; + + return ( +
+ + {isRtl ? "۳۲ شناور" : "32 calls"} + · + + + } + > +
+ {tabs.map((t, i) => ( +
+ {t} +
+ ))} +
+ + {isRtl ? `بهره‌وری ${step === 2 ? "۹۱٪" : "۷۴٪"}` : `utilisation ${step === 2 ? "91%" : "74%"}`} + +
+
+
+
+ {["00", "04", "08", "12", "16", "20", "24"].map((h) => ( + {h}:00 + ))} +
+ {[0, 1, 2, 3, 4].map((b) => ( +
+ + {isRtl ? `اسکله ${b + 1}` : `Berth ${b + 1}`} + +
+ ))} +
+ + {isRtl ? "اکنون" : "NOW"} + +
+ {ships.map((s, i) => { + const moved = step === 2 && s.conflict; + return ( +
+ {s.n} + + {moved + ? isRtl ? "تغییر اسکله · بدون توقف" : "re-berthed · 0 wait" + : s.conflict && step === 1 + ? isRtl ? "تداخل ۲س ۱۰د" : "overlap 2h 10m" + : s.t} + +
+ ); + })} + + {isRtl ? "ارتفاع ۶۲ · ۵ اسکله · محور ۲۴ ساعته" : "row h 62 · 5 berths · 24h axis"} + +
+
+ + {isRtl ? "معطلی اسکله" : "berth idle time"} +
+ −31% +
+
+ ); +} + +/* ---------------- Quire : contract review ---------------- */ +export function QuireUI({ step }) { + const { isRtl } = useLang(); + const para = (ws, key, hl) => ( +
+ {ws.map((w, i) => ( + + ))} +
+ ); + + return ( +
+ + {isRtl ? "۴۸ ص" : "48 pp"} + · + {isRtl ? "شیوه‌نامه: استاندارد" : "Playbook: Standard"} + + } + > +
+
+ {isRtl ? "بند ۱۴ · مسئولیت طرفین" : "§ 14 · LIABILITY"} +
+
+ {isRtl ? "۱۴.۲ سقف مسئولیت مدنی" : "14.2 Limitation of liability"} +
+ {para([360, 340, 352, 210], "a")} +
+ {isRtl ? ( + <> + مجموع مسئولیت تامین‌کننده نباید از{" "} + + کارمزدهای پرداخت‌شده در سه (۳) ماه گذشته + + {step === 2 && ( + + {" "}دو برابر (۲×) مجموع کارمزدهای پرداخت‌شده در دوازده (۱۲) ماه گذشته فراتر رود. + + )} + + ) : ( + <> + Supplier’s aggregate liability shall not exceed{" "} + + fees paid in the preceding three (3) months + + {step === 2 && ( + + {" "}two times (2×) the fees paid in the preceding twelve (12) months + + )} + . + + )} +
+ {para([350, 362, 300], "b")} + {para([340, 356, 120], "c")} + page w 420 · measure 62ch +
+
+
+
+ {isRtl ? "بازبینی خودکار" : "REVIEW"} +
+
+ + {step === 2 ? "0" : "3"} + + + {step === 2 + ? isRtl ? "انحراف باز" : "open deviations" + : isRtl ? "انحراف از شیوه‌نامه" : "deviations from playbook"} + +
+
+
+
+
+ {[ + [ + "14.2", + isRtl ? "سقف مسئولیت کمتر از ۱۲ ماه" : "Liability cap below 12-month fees", + true, + ], + [ + "9.1", + isRtl ? "تمدید خودکار بدون اعلام قبلی" : "Auto-renewal without notice", + false, + ], + [ + "21.4", + isRtl ? "قانون حاکم: نامشخص" : "Governing law: unlisted", + false, + ], + ].map(([c, t, main], i) => ( +
= 1 ? "!border-[var(--blaze)]" : ""}`} + style={{ "--i": 3 + i }} + > +
+ § {c} + + {step === 2 + ? isRtl ? "حل شد" : "resolved" + : main + ? isRtl ? "ریسک بالا" : "high" + : isRtl ? "عادی" : "low"} + +
+
{t}
+
+ ))} + panel w 244 +
+ + + {isRtl ? "میانگین زمان بازبینی" : "median review"} +
+ + {isRtl ? "۶ ساعت ← ۴۰ دقیقه" : "6 h → 40 min"} + +
+
+ ); +} + +/* ---------------- Halden : clinical trial ops ---------------- */ +export function HaldenUI({ step }) { + const { isRtl } = useLang(); + const sites = [ + [60, 70, 9], + [120, 50, 6], + [170, 110, 12], + [90, 160, 7], + [230, 80, 5], + [280, 140, 10], + [210, 200, 8], + [330, 60, 4], + [350, 190, 9], + [140, 230, 6], + [300, 250, 11], + [390, 120, 5], + [60, 250, 4], + [250, 30, 6], + ]; + const flagged = 5; + + return ( +
+ + {isRtl ? "۱۴ مرکز" : "14 sites"} + · + + + } + > +
+ + {Array.from({ length: 12 }).map((_, i) => ( + + ))} + {Array.from({ length: 10 }).map((_, i) => ( + + ))} + + + {sites.map(([x, y, r], i) => ( + + ))} +
+ {isRtl ? "پذیرش به تفکیک مرکز بالینی · نقطه = بیماران" : "ENROLMENT BY SITE · DOT = PATIENTS"} +
+
+ {isRtl ? "۴۱۲ پذیرش‌شده" : "412 enrolled"} + {isRtl ? "هدف ۶۰۰" : "target 600"} + {isRtl ? "روز ۲۱۴" : "day 214"} +
+ map 440 × 390 +
+
+
+ {isRtl ? "سیگنال‌ها و هشدارها" : "SIGNALS"} +
+ {[ + [ + isRtl ? "مرکز ۰۶ · لیدن" : "Site 06 · Leiden", + isRtl ? "ریسک انحراف از پروتکل" : "Visit window drift", + 0.72, + true, + ], + [isRtl ? "مرکز ۰۳ · پورتو" : "Site 03 · Porto", isRtl ? "مطابق برنامه" : "On track", 0.9], + [isRtl ? "مرکز ۱۱ · لیون" : "Site 11 · Lyon", isRtl ? "مطابق برنامه" : "On track", 0.64], + [isRtl ? "مرکز ۰۹ · گراتس" : "Site 09 · Graz", isRtl ? "مطابق برنامه" : "On track", 0.58], + [isRtl ? "مرکز ۰۱ · تورکو" : "Site 01 · Turku", isRtl ? "مطابق برنامه" : "On track", 0.81], + ].map(([n, s, v, f], i) => ( +
+
+ {n} +
+
+ {step === 2 && f ? (isRtl ? "ریسک انحراف · ۳ بیمار" : "Deviation risk · 3 pts") : s} +
+
+
+
+
+ ))} + w 232 · signal ×n +
+ + + {isRtl ? "کشف انحرافات" : "deviations caught"} +
+ + {isRtl ? "۹ روز زودتر" : "9 days earlier"} + +
+
+ ); +} diff --git a/src/components/Proof.jsx b/src/components/Proof.jsx new file mode 100644 index 0000000..d40b47d --- /dev/null +++ b/src/components/Proof.jsx @@ -0,0 +1,53 @@ +import { useInView } from "../scroll"; +import { useLang } from "../LanguageContext"; + +export default function Proof() { + const { strings, isRtl } = useLang(); + const [ref, seen] = useInView({ threshold: 0.15 }); + + return ( +
+
+

+ {strings.proofTitle} {strings.proofTitleSub} +

+
    + {strings.proofItems.map((r, i) => ( +
  • +
    +

    {r.l}

    +

    + {r.n} + {r.u && {r.u}} +

    +
    +
    +
    + + +
    +
  • + ))} +
  • +
    +

    + {strings.proofQuote} +

    +
    {strings.proofAuthor}
    +
    +
  • +
+
+
+ ); +} diff --git a/src/components/Scaled.jsx b/src/components/Scaled.jsx new file mode 100644 index 0000000..1ae7b68 --- /dev/null +++ b/src/components/Scaled.jsx @@ -0,0 +1,25 @@ +import { useEffect, useRef, useState } from "react"; + +// Renders a fixed 720x460 interface and scales it to fit its box, so the +// product looks identical (just smaller) on a phone and a 5K display. +export const W = 720, H = 460; +export default function Scaled({ children, className = "" }) { + const box = useRef(null); + const [s, setS] = useState(0); + useEffect(() => { + const el = box.current; + const ro = new ResizeObserver(([e]) => { + const { width, height } = e.contentRect; + setS(Math.min(width / W, height ? height / H : Infinity)); + }); + ro.observe(el); + return () => ro.disconnect(); + }, []); + return ( +
+
+ {children} +
+
+ ); +} diff --git a/src/components/Stack.jsx b/src/components/Stack.jsx new file mode 100644 index 0000000..8e23947 --- /dev/null +++ b/src/components/Stack.jsx @@ -0,0 +1,39 @@ +import { useInView } from "../scroll"; +import { useLang } from "../LanguageContext"; + +export default function Stack() { + const { strings, isRtl } = useLang(); + const [ref, seen] = useInView({ threshold: 0.1 }); + const headers = strings.tableHeaders; + + return ( +
+
+

{strings.stackTitle}

+

{strings.stackSubtitle}

+
+ + + + + + + + + + + + {strings.bom.map(([part, job, tol, used], i) => ( + + + + + + + + ))} + +
{headers.item}{headers.part}{headers.job}{headers.tolerance}{headers.usedIn}
{String(i + 1).padStart(2, "0")}{part}{job}{tol}
+
+ ); +} diff --git a/src/components/Studio.jsx b/src/components/Studio.jsx new file mode 100644 index 0000000..2b19ba1 --- /dev/null +++ b/src/components/Studio.jsx @@ -0,0 +1,26 @@ +import { useInView } from "../scroll"; +import { useLang } from "../LanguageContext"; + +export default function Studio() { + const { strings, isRtl } = useLang(); + const [ref, seen] = useInView({ threshold: 0.2 }); + + return ( +
+

+ {strings.studioTitle} {strings.studioTitleSub} +

+

+ {strings.studioLead} +

+
+ {strings.studioCells.map(([k, v]) => ( +
+
{k}
+
{v}
+
+ ))} +
+
+ ); +} diff --git a/src/components/Vernier.jsx b/src/components/Vernier.jsx new file mode 100644 index 0000000..0b87f2d --- /dev/null +++ b/src/components/Vernier.jsx @@ -0,0 +1,139 @@ +import { useEffect, useRef, useState } from "react"; +import { useFrame, clamp } from "../scroll"; +import { useLang } from "../LanguageContext"; + +export default function Vernier() { + const { strings, isRtl, lang, toggleLang } = useLang(); + const [cur, setCur] = useState({ i: 0, sub: "" }); + const [open, setOpen] = useState(false); + const idx = useRef(null), last = useRef(""); + + const sections = strings.vernierSections; + const states = strings.productStates; + + const tick = () => { + const doc = document.documentElement; + const p = clamp(window.scrollY / Math.max(1, doc.scrollHeight - window.innerHeight)); + if (idx.current) { + idx.current.style.transform = `translateX(${p * 100}%)`; + } + let i = 0; + sections.forEach(([id], k) => { + const el = document.getElementById(id); + if (el && el.getBoundingClientRect().top <= window.innerHeight * 0.5) i = k; + }); + const el = document.getElementById(sections[i]?.[0]); + const sub = el?.dataset.step != null ? states[+el.dataset.step] : ""; + const key = i + sub; + if (key !== last.current) { + last.current = key; + setCur({ i, sub }); + } + }; + + useFrame(tick); + useEffect(() => { + const t = setInterval(tick, 250); + return () => clearInterval(t); + }, [sections, states]); + + useEffect(() => { + const k = (e) => e.key === "Escape" && setOpen(false); + window.addEventListener("keydown", k); + return () => window.removeEventListener("keydown", k); + }, []); + + const go = (id) => { + setOpen(false); + document.getElementById(id)?.scrollIntoView({ + behavior: window.matchMedia("(prefers-reduced-motion: reduce)").matches ? "auto" : "smooth", + }); + }; + + const onContact = cur.i === sections.length - 1; + + return ( + + ); +} diff --git a/src/data.js b/src/data.js new file mode 100644 index 0000000..701edb9 --- /dev/null +++ b/src/data.js @@ -0,0 +1,7 @@ +import { t } from "./translations"; + +export const products = t.fa.products; +export const method = t.fa.methodItems; +export const proof = t.fa.proofItems; +export const bom = t.fa.bom; +export const studioCells = t.fa.studioCells; diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 0000000..fa62691 --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.jsx' +import './styles.css' + +ReactDOM.createRoot(document.getElementById('root')).render( + + + , +) diff --git a/src/scroll.js b/src/scroll.js new file mode 100644 index 0000000..52a1149 --- /dev/null +++ b/src/scroll.js @@ -0,0 +1,64 @@ +import { useEffect, useRef, useState } from "react"; + +// One shared rAF loop for every scroll-linked element (no per-component listeners). +const subs = new Set(); +let ticking = false; +const run = () => { ticking = false; subs.forEach((f) => f()); }; +const request = () => { if (!ticking) { ticking = true; requestAnimationFrame(run); } }; +if (typeof window !== "undefined") { + window.addEventListener("scroll", request, { passive: true }); + window.addEventListener("resize", request); +} + +export const clamp = (v, a = 0, b = 1) => Math.min(b, Math.max(a, v)); +export const ease = (t) => (t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2); + +export const reducedMotion = () => + typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches; + +// progress 0..1 of a tall section while its sticky child is pinned +export function pinProgress(el) { + const r = el.getBoundingClientRect(); + const total = r.height - window.innerHeight; + return total <= 0 ? 0 : clamp(-r.top / total); +} + +export function useFrame(fn) { + const ref = useRef(fn); + ref.current = fn; + useEffect(() => { + const f = () => ref.current(); + subs.add(f); + f(); + return () => subs.delete(f); + }, []); +} + +// Discrete step from a pinned section, re-rendering only when the step changes. +export function usePinStep(sectionRef, steps, onProgress) { + const [step, setStep] = useState(reducedMotion() ? steps - 1 : 0); + const last = useRef(step); + useFrame(() => { + const el = sectionRef.current; + if (!el) return; + const p = pinProgress(el); + onProgress && onProgress(p); + if (reducedMotion()) return; + const s = Math.min(steps - 1, Math.floor(p * steps * 0.999 + 0.0001)); + if (s !== last.current) { last.current = s; setStep(s); } + }); + return step; +} + +export function useInView(opts = { threshold: 0.3 }) { + const ref = useRef(null); + const [seen, setSeen] = useState(false); + useEffect(() => { + const el = ref.current; + if (!el) return; + const io = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setSeen(true); io.disconnect(); } }, opts); + io.observe(el); + return () => io.disconnect(); + }, []); + return [ref, seen]; +} diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..bacfe57 --- /dev/null +++ b/src/styles.css @@ -0,0 +1,223 @@ +@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=IBM+Plex+Sans:wght@400;500;600&display=swap"); + +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* ========================================================================== + IRANSans Typography Declarations + ========================================================================== */ +@font-face { + font-family: 'IRANSans'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('/fonts/IRANSansXFaNum-Light.ttf') format('truetype'), + url('/fonts/IRANSans-Light.ttf') format('truetype'); +} +@font-face { + font-family: 'IRANSans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('/fonts/IRANSansXFaNum-Regular.ttf') format('truetype'), + url('/fonts/IRANSans-Regular.ttf') format('truetype'); +} +@font-face { + font-family: 'IRANSans'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url('/fonts/IRANSansXFaNum-Medium.ttf') format('truetype'), + url('/fonts/IRANSans-Medium.ttf') format('truetype'); +} +@font-face { + font-family: 'IRANSans'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url('/fonts/IRANSansXFaNum-DemiBold.ttf') format('truetype'), + url('/fonts/IRANSans-DemiBold.ttf') format('truetype'); +} +@font-face { + font-family: 'IRANSans'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('/fonts/IRANSansXFaNum-Bold.ttf') format('truetype'), + url('/fonts/IRANSans-Bold.ttf') format('truetype'); +} +@font-face { + font-family: 'IRANSans'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url('/fonts/IRANSansXFaNum-ExtraBold.ttf') format('truetype'); +} +@font-face { + font-family: 'IRANSans'; + font-style: normal; + font-weight: 900; + font-display: swap; + src: url('/fonts/IRANSansXFaNum-Black.ttf') format('truetype'); +} + +@font-face { + font-family: 'IRANSansX'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('/fonts/IRANSansXFaNum-Regular.ttf') format('truetype'); +} +@font-face { + font-family: 'iransans'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('/fonts/IRANSansXFaNum-Regular.ttf') format('truetype'); +} + +:root { + --alu: #e3e4e0; + --paper: #f2f2ef; + --ink: #121413; + --steel: #565b57; + --blaze: #ff5b14; + --chamber: #0f1110; + --chamber-2: #181b19; + --fog: #a9aea9; + --line: rgba(18, 20, 19, 0.14); + --line-d: rgba(242, 242, 239, 0.12); + --sans: "IRANSans", "IRANSansX", "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif; + --mono: "IRANSans", "IBM Plex Mono", ui-monospace, monospace; +} + +html { + scroll-behavior: smooth; +} +@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } } + +body { + margin: 0; + background: var(--alu); + color: var(--ink); + font-family: var(--sans); + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} + +::selection { + background: var(--blaze); + color: var(--ink); +} + +.mono { + font-family: var(--mono); + letter-spacing: 0.01em; +} + +.display { + font-family: var(--sans); + font-weight: 700; + letter-spacing: -0.04em; + line-height: 1.05; +} + +[dir="rtl"] .display { + letter-spacing: -0.02em; + line-height: 1.15; +} + +.label { + font-family: var(--mono); + font-size: 14px; + letter-spacing: 0.03em; + text-transform: uppercase; +} + +a, button { + -webkit-tap-highlight-color: transparent; +} +:focus-visible { + outline: 2px solid var(--blaze); + outline-offset: 3px; + border-radius: 4px; +} + +/* ---------- HERO : the cut ---------- */ +.cut-line { + transform-origin: left center; + animation: saw 1.4s cubic-bezier(.7,0,.2,1) .25s both; +} +[dir="rtl"] .cut-line { + transform-origin: right center; +} +@keyframes saw { from { transform: scaleX(0); } to { transform: scaleX(1); } } + +.rise-up { animation: riseUp 1.1s cubic-bezier(.2,.7,.1,1) 1.05s both; } +.rise-down { animation: riseDown 1.1s cubic-bezier(.2,.7,.1,1) 1.15s both; } +@keyframes riseUp { from { transform: translateY(105%); } to { transform: none; } } +@keyframes riseDown { from { transform: translateY(-105%); } to { transform: none; } } + +.fade-in { animation: fadeIn 1s ease 1.7s both; } +@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } + +.saw-head { + animation: sawHead 1.4s cubic-bezier(.7,0,.2,1) .25s both; +} +@keyframes sawHead { + from { left: 0%; opacity: 1; } + 92% { opacity: 1; } + to { left: 100%; opacity: 0; } +} + +[dir="rtl"] .saw-head { + animation: sawHeadRtl 1.4s cubic-bezier(.7,0,.2,1) .25s both; +} +@keyframes sawHeadRtl { + from { right: 0%; left: auto; opacity: 1; } + 92% { opacity: 1; } + to { right: 100%; left: auto; opacity: 0; } +} + +/* ---------- PRODUCT UI : drawing -> object ---------- */ +.ui { --t: 700ms; font-family: var(--sans); color: var(--ink); } +.ui .bp { border: 1px solid rgba(18,20,19,.12); background: #fbfbf9; border-radius: 6px; transition: border-color var(--t), background-color var(--t), box-shadow var(--t); transition-delay: calc(var(--i, 0) * 45ms); } +.ui .bp.bp-sunk { background: #f1f2ee; } +.ui .fill { transition: opacity var(--t) cubic-bezier(.2,.7,.1,1), transform var(--t) cubic-bezier(.2,.7,.1,1); transition-delay: calc(var(--i, 0) * 45ms + 120ms); } +.ui .dim { opacity: 0; transition: opacity 400ms; font-family: var(--mono); font-size: 10px; color: var(--blaze); position: absolute; white-space: nowrap; letter-spacing: .04em; } +.ui .callout { opacity: 0; transform: translateY(8px); transition: opacity 600ms 250ms, transform 600ms 250ms cubic-bezier(.2,.7,.1,1); } +.ui .live { transition: background-color 600ms, color 600ms, transform 900ms cubic-bezier(.65,0,.2,1), border-color 600ms; } + +.ui[data-step="0"] .bp { border: 1px dashed rgba(255,91,20,.75); background: transparent; box-shadow: none; } +.ui[data-step="0"] .fill { opacity: 0; transform: translateY(6px); } +.ui[data-step="0"] .dim { opacity: 1; } +.ui[data-step="2"] .callout { opacity: 1; transform: none; } +.ui-window { box-shadow: 0 1px 0 rgba(255,255,255,.04), 0 40px 80px -30px rgba(0,0,0,.6); } +.ui[data-step="0"] .ui-window { box-shadow: none; } +.pulse { animation: pulse 2.2s ease-out infinite; } +@keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(255,91,20,.55); } 70%,100% { box-shadow: 0 0 0 14px rgba(255,91,20,0); } } + +/* chapter text swap */ +.swap { transition: opacity 500ms ease, transform 600ms cubic-bezier(.2,.7,.1,1); } +.swap[data-on="false"] { opacity: 0; transform: translateY(14px); pointer-events: none; } +.swap[data-on="true"] { opacity: 1; transform: none; } + +/* measured lines */ +.measure { transform-origin: left; transform: scaleX(0); transition: transform 1.4s cubic-bezier(.65,0,.2,1); } +[dir="rtl"] .measure { transform-origin: right; } +.seen .measure { transform: scaleX(1); } +.reveal { opacity: 0; transform: translateY(20px); transition: opacity 900ms ease, transform 900ms cubic-bezier(.2,.7,.1,1); } +.seen .reveal, .reveal.seen { opacity: 1; transform: none; } + +.no-scrollbar::-webkit-scrollbar { display: none; } +.no-scrollbar { scrollbar-width: none; } + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { animation-duration: 1ms !important; animation-delay: 0ms !important; transition-duration: 1ms !important; transition-delay: 0ms !important; } + .measure { transform: scaleX(1); } + .reveal { opacity: 1; transform: none; } +} + +html, body { height: auto !important; overflow-x: clip; } +#root { height: auto !important; min-height: 100%; overflow: visible !important; } diff --git a/src/translations.js b/src/translations.js new file mode 100644 index 0000000..034fc99 --- /dev/null +++ b/src/translations.js @@ -0,0 +1,313 @@ +export const t = { + fa: { + // Header & Meta + skipToProducts: "پرش به محصولات", + // Hero + heroTitle1: "ما نرم‌افزار می‌سازیم", + heroTitle2: "بدون کوچک‌ترین افزونگی.", + studioSubtitle: "استودیو مستقل طراحی و مهندسی محصول\nرتردام · مونترال", + heroLead: "استودیو کِرف (Kerf) محصولات نرم‌افزاری اختصاصی را برای امور مالی، لجستیک بنادر، حقوقی و پزشکی بالینی طراحی، مهندسی و مدیریت می‌کند. ۱۱ محصول عملیاتی در محیط تولید.", + kerfWidth: "عرض برش (کِرف)", + scrollToCut: "برای برش اسکرول کنید", + insideChamberTitle: "درون برش: محصول، نه پروژه.", + insideChamberDesc: "دو محصول متعلق به خودمان؛ دو محصول اختصاصی برای مشتریان. هر چهار محصول هر شب بدون وقفه در حال پردازش زنده هستند.", + minis: [ + { key: "ledger", name: "لجرلاین", field: "خزانه‌داری" }, + { key: "tide", name: "تایدواتر", field: "لجستیک بندری" }, + { key: "quire", name: "کوایر", field: "امور حقوقی" }, + { key: "halden", name: "هالدن", field: "کارآزمایی بالینی" }, + ], + + // Products + productStates: ["طرح اولیه (نقشه)", "کالبد شیء", "اجرای زنده"], + products: [ + { + key: "ledger", + name: "لجرلاین (Ledgerline)", + shortName: "لجرلاین", + field: "خزانه‌داری بین‌الملل", + owner: "محصول مستقل خودمان · از ۲۰۱۹", + steps: [ + { k: "صورت مسئله", t: "تیم‌های مالی حساب‌های ماهانه را با اکسل‌هایی می‌بندند که تا روز سه‌شنبه منقضی و غلط می‌شوند." }, + { k: "جامعه هدف", t: "خزانه‌دارانی که بیش از ۲۰ حساب بانکی را در ۹ ارز مختلف بین‌المللی مدیریت می‌کنند." }, + { k: "ارزش افزوده", t: "مشاهده لحظه‌ای وضعیت نقدینگی؛ تسویه کلیه تراکنش‌ها پیش از سرد شدن قهوه صبحگاهی.", m: "۲.۱ میلیارد یورو", ml: "تسویه ماهانه تراکنش‌ها" }, + ], + }, + { + key: "tide", + name: "تایدواتر (Tidewater)", + shortName: "تایدواتر", + field: "لجستیک ترمینال‌های بندری", + owner: "توسعه اختصاصی برای ترمینال‌های دریای شمال", + steps: [ + { k: "صورت مسئله", t: "یک کشتی کانتینری معطل در لنگرگاه روزانه ۴۰٬۰۰۰ یورو سوخت می‌سوزاند." }, + { k: "جامعه هدف", t: "برنامه‌ریزان ترمینال که ماهانه بیش از ۳۰۰ تردد شناور سنگین را زمان‌بندی می‌کنند." }, + { k: "ارزش افزوده", t: "حل و فصل تداخلات پهلوگیری پیش از آنکه کشتی به محدوده رادیویی برسد.", m: "۳۱٪−", ml: "کاهش زمان معطلی اسکله در ۶ ترمینال" }, + ], + }, + { + key: "quire", + name: "کوایر (Quire)", + shortName: "کوایر", + field: "تحلیل قراردادهای حقوقی", + owner: "محصول مستقل خودمان · از ۲۰۲۲", + steps: [ + { k: "صورت مسئله", t: "وکلا تک‌تک بندها را می‌خوانند، از جمله ۹۰ درصدی که دقیقاً منطبق بر شیوه‌نامه استاندارد است." }, + { k: "جامعه هدف", t: "تیم‌های حقوقی درون‌سازمانی با بازبینی بیش از ۲۰۰ قرارداد تامین در هر فصل." }, + { k: "ارزش افزوده", t: "کوایر ۹۰٪ استاندارد را می‌خواند؛ وکلا روی ۱۰٪ چالش‌برانگیز تمرکز می‌کنند.", m: "۴۰ دقیقه", ml: "میانگین زمان بازبینی، در برابر ۶ ساعت قبلی" }, + ], + }, + { + key: "halden", + name: "هالدن (Halden)", + shortName: "هالدن", + field: "کارآزمایی‌های بالینی پزشکی", + owner: "توسعه مشترک با مرکز تحقیقات آرکادیا (Arcadia CRO)", + steps: [ + { k: "صورت مسئله", t: "انحراف از پروتکل بالینی در ویزیت‌های ماهانه کشف می‌شود؛ یعنی هفته‌ها دیرتر." }, + { k: "جامعه هدف", t: "تیم‌های راهبری عملیات بالینی که ۳۰ تا ۴۰۰ مرکز درمانی را همزمان اداره می‌کنند." }, + { k: "ارزش افزوده", t: "انحراف در همان روز وقوع ثبت و هشدار داده می‌شود، نه ماهی که دیر شده است.", m: "۹ روز", ml: "شناسایی سریع‌تر هرگونه انحراف از پروتکل" }, + ], + }, + ], + + // Method + methodTitle: "از پیش‌طرح تا کالبد واقعی.", + methodSubtitle: "چهار مرحله بنیادین. همان تیم کوچک و متمرکز از نخستین اسکچ تا آماده‌باش ساعت ۳ بامداد.", + methodStage: "مرحله {i} از ۴ · {d}", + methodItems: [ + { v: "قاب‌بندی", d: "۱ هفته", t: "برش اساسی و دقیق را پیدا می‌کنیم و به سایر موارد غیرضروری نه می‌گوییم.", out: "یک مستند تک‌صفحه‌ای مستدل و قابل دفاع" }, + { v: "رسم نقشه", d: "۳ هفته", t: "طراحی پیش‌نمونه‌ها با کد آماده تولید، نه اسلایدهای نمایشی.", out: "یک محصول تعاملی کلیک‌پذیر با داده‌های واقعی" }, + { v: "تراش و ساخت", d: "۸ تا ۱۶ هفته", t: "طراحان و مهندسان در یک تیم پیوسته، با تحویل هفتگی کد به محیط زنده.", out: "نرم‌افزار کامل و پایدار در محیط پروداکشن" }, + { v: "پایش مداوم", d: "سال‌ها", t: "همیشه پاسخگو و پای کار می‌مانیم. بیشتر مشتریان شش سال با ما ادامه می‌دهند.", out: "توافقنامه سطح خدمات (SLA) با تعهد شخصی ما" }, + ], + methodFooter: "سپس آن را بدون وقفه در مدار نگه می‌داریم.", + + // Proof + proofTitle: "اندازه‌گیری‌شده؛", + proofTitleSub: "نه صرفاً ادعا.", + proofItems: [ + { n: "۱۹", u: "روز", l: "از نخستین تماس تا استقرار کد در محیط پروداکشن", w: 0.38 }, + { n: "۹/۱۱", u: "", l: "محصولاتی که پس از ۵ سال همچنان در محیط عملیاتی فعالند", w: 0.82 }, + { n: "۶.۴", u: "سال", l: "میانگین طول دوره همکاری با هر مشتری", w: 0.64 }, + { n: "۹۹.۹۸", u: "٪", l: "پایداری بدون وقفه در تمامی محصولات طی ۳۶ ماه", w: 1 }, + ], + proofQuote: "«آن‌ها با استدلال نیمی از نقشه راه ما را حذف کردند. همان نیمی که ساخته شد، دلیل اصلی تصاحب تجاری شرکت ما شد.»", + proofAuthor: "اینس وارت · مدیر ارشد سابق محصول در Fernhill Payments", + + // Stack / Bill of Materials + stackTitle: "صورت متریال و فناوری.", + stackSubtitle: "ساده و اثبات‌شده در جاهایی که باید باشد؛ فوق‌العاده سریع در گلوگاه‌ها. فناوری‌هایی که خودمان مستقیماً اجرا می‌کنیم.", + tableHeaders: { + item: "ردیف", + part: "بخش فناوری", + job: "وظیفه مهندسی", + tolerance: "معیار و کارایی", + usedIn: "کاربرد در محصولات", + }, + bom: [ + ["Rust", "موتورهای تسویه مالی و زمان‌بندی ترددها", "تاخیر p99 کمتر از ۵ میلی‌ثانیه", "لجرلاین · تایدواتر"], + ["TypeScript · React", "رابط‌های کاربری تمامی محصولات", "اجرای نرم ۶۰ فریم بر ثانیه", "همه محصولات"], + ["PostgreSQL", "پایگاه داده اصلی و سیستم ثبت وقایع", "بازیابی نقطه‌ای ۳۰ روزه", "همه محصولات"], + ["Event streams", "تله‌متری بلادرنگ شناورها، بانک‌ها و مراکز", "۲.۱ میلیارد رویداد روزانه", "تایدواتر · هالدن"], + ["On-device models", "دسته‌بندی خودکار بندهای حقوقی", "پردازش کاملاً آفلاین · ۴۰ مگابایت", "کوایر"], + ["Bare Metal + Terraform", "زیرساخت سرور و خودکارسازی", "۹۹.۹۸٪ پایداری طی ۳۶ ماه", "همه محصولات"], + ], + + // Studio + studioTitle: "کوچک به انتخاب خود.", + studioTitleSub: "دقیق بر حسب عادت.", + studioLead: "کِرف (Kerf) به معنای عرض برش اره است: مقداری از متریال که فدا می‌کنید تا قطعه نهایی دقیق و میلی‌متری حاصل شود. ما مقیاس انبوه را فدا کرده‌ایم تا هر محصول مستقیماً توسط همان کسانی توسعه یابد که آن را ترسیم کرده‌اند.", + studioCells: [ + ["استودیو", "Kerf B.V."], + ["سال تاسیس", "۲۰۱۴ (۱۳۹۳)"], + ["دفاتر طراحی", "رتردام · مونترال"], + ["نفرات", "۴۲ نفر · ۳۱ مهندس، ۱۱ طراح"], + ["تعهدات سالانه", "حداکثر ۴ پروژه در سال"], + ["مقیاس", "۱ : ۱ (واقعی)"], + ], + + // Contact + contactTag: "پذیرش دو پروژه کاری برای بهار ۲۰۲۷", + contactTitle: "پروژه سخت و پیچیده‌تان را\nبه ما بسپارید.", + contactEmail: "hello@kerf.studio", + contactSubjectHard: "یک_پروژه_سخت", + contactSubjectCall: "جلسه_۳۰_دقیقه‌ای", + contactCallBtn: "رزرو جلسه گفتگو (۳۰ دقیقه)", + contactFooter: "© ۲۰۲۶ استودیو کِرف (Kerf B.V.) · شیت ۷ از ۷", + + // Vernier Navigation + vernierSections: [ + ["cut", "کِرف"], + ["p-ledgerline", "لجرلاین"], + ["p-tidewater", "تایدواتر"], + ["p-quire", "کوایر"], + ["p-halden", "هالدن"], + ["method", "روش‌شناسی"], + ["proof", "سنجش"], + ["stack", "متریال"], + ["studio", "استودیو"], + ["contact", "تماس"], + ], + startProject: "شروع پروژه", + nowViewing: "در حال مشاهده", + langButton: "EN", + langName: "انگلیسی", + }, + + en: { + // Header & Meta + skipToProducts: "Skip to products", + // Hero + heroTitle1: "We build \nsoftware", + heroTitle2: "with nothing \nto spare.", + studioSubtitle: "Independent product studio\nRotterdam · Montréal", + heroLead: "Kerf designs, engineers and runs software products for finance, logistics, law and medicine. Eleven in production.", + kerfWidth: "kerf width", + scrollToCut: "scroll to cut", + insideChamberTitle: "Inside the cut: products, not projects.", + insideChamberDesc: "Two we own. Two we built for clients. All four we still run, every night.", + minis: [ + { key: "ledger", name: "Ledgerline", field: "Treasury" }, + { key: "tide", name: "Tidewater", field: "Port logistics" }, + { key: "quire", name: "Quire", field: "Legal" }, + { key: "halden", name: "Halden", field: "Clinical trials" }, + ], + + // Products + productStates: ["Drawing", "Object", "Running"], + products: [ + { + key: "ledger", + name: "Ledgerline", + shortName: "Ledgerline", + field: "Treasury", + owner: "Ours · since 2019", + steps: [ + { k: "The problem", t: "Finance teams close the month in spreadsheets that are wrong by Tuesday." }, + { k: "Who it’s for", t: "Treasurers running 20+ bank accounts across nine currencies." }, + { k: "What it’s worth", t: "One live cash position. Every settlement confirmed before the coffee cools.", m: "€2.1B", ml: "settled every month" }, + ], + }, + { + key: "tide", + name: "Tidewater", + shortName: "Tidewater", + field: "Port logistics", + owner: "Built for North Sea Terminals", + steps: [ + { k: "The problem", t: "A container ship waiting at anchor burns €40,000 a day." }, + { k: "Who it’s for", t: "Terminal planners scheduling 300+ vessel calls a month." }, + { k: "What it’s worth", t: "Conflicts resolved before the ship is in radio range.", m: "−31%", ml: "berth idle time, six terminals" }, + ], + }, + { + key: "quire", + name: "Quire", + shortName: "Quire", + field: "Legal", + owner: "Ours · since 2022", + steps: [ + { k: "The problem", t: "Lawyers read every clause, including the 90% that already matches the playbook." }, + { k: "Who it’s for", t: "In-house teams reviewing 200+ supplier contracts a quarter." }, + { k: "What it’s worth", t: "Quire reads the 90%. People argue the 10%.", m: "40 min", ml: "median review, from 6 hours" }, + ], + }, + { + key: "halden", + name: "Halden", + shortName: "Halden", + field: "Clinical trials", + owner: "Built with Arcadia CRO", + steps: [ + { k: "The problem", t: "Trials spot protocol deviations at the monthly visit. Weeks too late." }, + { k: "Who it’s for", t: "Trial operations teams running 30 to 400 sites." }, + { k: "What it’s worth", t: "Drift is flagged the day it starts, not the month it’s found.", m: "9 days", ml: "earlier deviation detection" }, + ], + }, + ], + + // Method + methodTitle: "From drawing to object.", + methodSubtitle: "Four stages. The same small team from the first sketch to the 3 a.m. pager.", + methodStage: "Stage {i} of 4 · {d}", + methodItems: [ + { v: "Frame", d: "1 week", t: "We find the one cut that matters and say no to the rest.", out: "A one-page brief you can defend" }, + { v: "Draw", d: "3 weeks", t: "Prototypes in production code. Never slides.", out: "A clickable product on real data" }, + { v: "Machine", d: "8–16 weeks", t: "Designers and engineers in one team, shipping weekly.", out: "Software in production" }, + { v: "Run", d: "Years", t: "We stay on call. Most clients keep us for six years.", out: "An SLA with our names on it" }, + ], + methodFooter: "Then we keep it running.", + + // Proof + proofTitle: "Measured,", + proofTitleSub: "not claimed.", + proofItems: [ + { n: "19", u: "days", l: "First call to code in production", w: 0.38 }, + { n: "9/11", u: "", l: "Products still in production after five years", w: 0.82 }, + { n: "6.4", u: "years", l: "Median client relationship", w: 0.64 }, + { n: "99.98", u: "%", l: "Uptime across every product we run, 36 months", w: 1 }, + ], + proofQuote: "“They argued us out of half the roadmap. The half that shipped is why we were acquired.”", + proofAuthor: "Ines Vaart · former CPO, Fernhill Payments", + + // Stack / Bill of Materials + stackTitle: "Bill of materials.", + stackSubtitle: "Boring where it should be. Fast where it matters. Nothing we can’t run ourselves.", + tableHeaders: { + item: "Item", + part: "Part", + job: "Job", + tolerance: "Tolerance", + usedIn: "Used in", + }, + bom: [ + ["Rust", "Settlement and scheduling engines", "p99 under 5 ms", "Ledgerline · Tidewater"], + ["TypeScript · Vue · Nuxt", "Every product interface", "60 fps on a 2019 phone", "All"], + ["PostgreSQL", "System of record", "30-day point-in-time recovery", "All"], + ["Event streams", "Vessel, bank and site telemetry", "2.1 B events a day", "Tidewater · Halden"], + ["On-device models", "Clause classification", "Runs offline · 40 MB", "Quire"], + ["Own metal + Terraform", "Infrastructure", "99.98% over 36 months", "All"], + ], + + // Studio + studioTitle: "Small on purpose.", + studioTitleSub: "Precise by habit.", + studioLead: "A kerf is the width of a saw cut: the material you give up to make something exact. We give up scale, so every product gets the people who drew it.", + studioCells: [ + ["Studio", "Kerf B.V."], + ["Established", "2014"], + ["Studios", "Rotterdam · Montréal"], + ["People", "42 · 31 engineers, 11 designers"], + ["Engagements", "Four a year"], + ["Scale", "1 : 1"], + ], + + // Contact + contactTag: "Taking two engagements for spring 2027", + contactTitle: "Bring us\nthe hard one.", + contactEmail: "hello@kerf.studio", + contactSubjectHard: "A%20hard%20one", + contactSubjectCall: "30-minute%20call", + contactCallBtn: "Book a 30-minute call", + contactFooter: "© 2026 Kerf B.V. · Sheet 7 of 7", + + // Vernier Navigation + vernierSections: [ + ["cut", "Kerf"], + ["p-ledgerline", "Ledgerline"], + ["p-tidewater", "Tidewater"], + ["p-quire", "Quire"], + ["p-halden", "Halden"], + ["method", "Method"], + ["proof", "Proof"], + ["stack", "Materials"], + ["studio", "Studio"], + ["contact", "Contact"], + ], + startProject: "Start a project", + nowViewing: "Now viewing", + langButton: "فا", + langName: "فارسی", + }, +}; diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..b7fef5d --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,26 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: { + colors: { + alu: "#e3e4e0", + paper: "#f2f2ef", + ink: "#121413", + steel: "#565b57", + blaze: "#ff5b14", + chamber: "#0f1110", + "chamber-2": "#181b19", + fog: "#a9aea9", + }, + fontFamily: { + sans: ['IRANSans', 'IRANSansX', '"IBM Plex Sans"', 'ui-sans-serif', 'system-ui', 'sans-serif'], + mono: ['IRANSans', 'IRANSansX', '"IBM Plex Mono"', 'ui-monospace', 'monospace'], + }, + }, + }, + plugins: [], +} diff --git a/tests/artifact.spec.js b/tests/artifact.spec.js new file mode 100644 index 0000000..103564b --- /dev/null +++ b/tests/artifact.spec.js @@ -0,0 +1,23 @@ +import { expect, test } from "@playwright/test"; + +test("loads without browser or network errors", async ({ page }) => { + const problems = []; + const report = (kind, detail) => problems.push(`${kind}: ${detail}`); + + page.on("console", (message) => { + if (message.type() === "error") { + report("Console error", message.text()); + } + }); + page.on("pageerror", (error) => report("Uncaught exception", error.message)); + page.on("requestfailed", (request) => report("Request failed", `${request.method()} ${request.url()}`)); + page.on("response", (response) => { + if (response.status() >= 400) { + report("HTTP error", `${response.status()} ${response.url()}`); + } + }); + + await page.goto("/"); + await expect(page.locator("#root > *").first()).toBeAttached(); + expect(problems).toEqual([]); +}); diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..81f7fac --- /dev/null +++ b/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import path from 'path'; + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, + server: { + port: 5180, + host: true, + open: true, + }, +});