diff --git a/car-ui/.gitignore b/car-ui/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/car-ui/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/car-ui/.oxlintrc.json b/car-ui/.oxlintrc.json new file mode 100644 index 0000000..1255078 --- /dev/null +++ b/car-ui/.oxlintrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["react", "oxc"], + "rules": { + "react/rules-of-hooks": "error", + "react/only-export-components": ["warn", { "allowConstantExport": true }] + } +} diff --git a/car-ui/README.md b/car-ui/README.md new file mode 100644 index 0000000..d937833 --- /dev/null +++ b/car-ui/README.md @@ -0,0 +1,16 @@ +# React + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs) +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the Oxlint configuration + +If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and Oxlint's TypeScript related rules in your project. diff --git a/car-ui/index.html b/car-ui/index.html new file mode 100644 index 0000000..f8a834a --- /dev/null +++ b/car-ui/index.html @@ -0,0 +1,14 @@ + + + + + + + + AutoOracle AI โ€” Sri Lanka Car Valuation + + +
+ + + diff --git a/car-ui/package-lock.json b/car-ui/package-lock.json new file mode 100644 index 0000000..9860587 --- /dev/null +++ b/car-ui/package-lock.json @@ -0,0 +1,1338 @@ +{ + "name": "car-ui", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "car-ui", + "version": "0.0.0", + "dependencies": { + "react": "^19.2.7", + "react-dom": "^19.2.7" + }, + "devDependencies": { + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.3", + "oxlint": "^1.71.0", + "vite": "^8.1.1" + } + }, + "node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.139.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", + "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@oxlint/binding-android-arm-eabi": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.73.0.tgz", + "integrity": "sha512-HZQRN/UMBu+Ut+/9MiAChkbP4qZqrNOWBcNI45vOT40GVhbGR0JgHB87L48D4iAqFQIdVmeQYtV9RF89AjTKkg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-android-arm64": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.73.0.tgz", + "integrity": "sha512-Gp+KJRylv2aW7thRpG5p1KTxZq4ZJFbWowrKzufNq9d3ssl3r3JviYV45/+p+7CN1Nv0zDd1e8Ex0b/HUDq4TQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-arm64": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.73.0.tgz", + "integrity": "sha512-3de96NdtXhxERMjIz7wsp2HYMY6pMQycGxFWac2mFecAx6VeARF/IqFb1QIaqiCRIdfzBwzTed+pCTCoiS+CYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-x64": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.73.0.tgz", + "integrity": "sha512-5zx/uPW32TiaOeVY1dQ/H5iOf0K1HOdFKOJhLqGl4o63+i1fpzoqqu/mKtd7OFgFjNCdhlyTGgjVkQTZm1ELcg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-freebsd-x64": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.73.0.tgz", + "integrity": "sha512-qNe4gKHaGnLuZJ8toUg90JAa0S2vTVvDw+0bRi3q1avXZXDT4u5mMeECf3nD4HYrbdn1O7dXqWut4onY/yx/Xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-gnueabihf": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.73.0.tgz", + "integrity": "sha512-cCehYh5hTbfShm/fxTD6wwrGUWIpvX+N5OxmAMhFhDeTGXvw+BeNj889tpxsFQ9ZLatQ6wImuY8tsKLZ+FMz7w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-musleabihf": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.73.0.tgz", + "integrity": "sha512-d5j5GDU/2dMgjVhw7TQT9ITrsIr1Y02KEXKyVGIXUkD+KiaxE9TP65FS2ZdgTBemQvoRL+gSBdbrIm3cQIeacg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-gnu": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.73.0.tgz", + "integrity": "sha512-Eyf1SrP3+yR1DI3OJgOY2Pvrr9dWP9TK37xPaDYycwTtlGlI45erJAVIfH5/m/xosDt6BupJYEFi47bvbTuuyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-musl": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.73.0.tgz", + "integrity": "sha512-IlT/OJApEDKaMmCooHuncgJZbbCe7T5QIWmTZBEtYscWvzPQuuEinVcid6kwQRVQOUdb7PUCz4jQHnaYXdfJXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-ppc64-gnu": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.73.0.tgz", + "integrity": "sha512-L+JYcb/vdg5fmcH08V6o0YYLU28cTH1SPNulwJdvK9NK49aXSkYy6oNpKBmddArVOXYqNepriDGiZ04G54kh1Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-gnu": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.73.0.tgz", + "integrity": "sha512-Qtk0g3bKV6OwWjIm7R8kQN1uOZRKQt/MODK2a8QfkwhTpXBD53ozx5XLVWLGDQAVyp2otLW4D2wB98XfAfMPGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-musl": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.73.0.tgz", + "integrity": "sha512-wX0NQKZVxltkAOVmzFcpOaMpdaUvsq1Eqpx9tkAfl71UdkTlSo1R4AdAnGccR1Fm2+TzFgZ22CyyGuZ41RDr/A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-s390x-gnu": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.73.0.tgz", + "integrity": "sha512-vPe7UGBMWyiLTtnqS4xxgMQFSFGmtQwhwCxuiw6lXygaO6bVt0D8dFVg8Xv05eaiN3ybC0HXXHUAohFMFvqoCQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-gnu": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.73.0.tgz", + "integrity": "sha512-2CwIWr9cemFC/CbRBWZvuk5mffz6ObmfFkfcC/9rTQ7f+icNhYr2kOjf9Rt8lLvugvkdGDOmkoVoFFHh6ClCTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-musl": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.73.0.tgz", + "integrity": "sha512-nDadfJgg7NBBxG0N560wOe7LLX5QiYp6qBaI7viuk5EUORFBktU/NfV0MbTqU3gTqQDCh4VyxKdo5VADxk9w8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-openharmony-arm64": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.73.0.tgz", + "integrity": "sha512-wGjJC+NLH9xP+IKGn9RDW94ojJR/wPbg5WCnQjj/oReaOtCQthr8ws1zICe77JFmo4ouUdeTHHZL/ESGiF6Pmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-arm64-msvc": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.73.0.tgz", + "integrity": "sha512-I7X47GPGljw225YUQ5SbC/rb1Kkdrd0yQf0x+hYxeKS6DpfjMbo9ccQPQ6LNY6BoJQ1sHhgDUGuMn5Vg5gHT6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-ia32-msvc": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.73.0.tgz", + "integrity": "sha512-5lWj+3h+74Fm1jYOO9qkJA4xkAlZA099DkXppuXsk7UpnpZLttsefrZU469vChGaG6hcSqrkKXQOvMTZtbjeNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-x64-msvc": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.73.0.tgz", + "integrity": "sha512-WaNRvh4f6zY9CvUQk2YoA1O90ieWrIklI84+HXFr9Isjz9CSESrdqo/RtIYt4Dll/cAchqGDMehfaZd0vqEFZw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", + "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", + "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", + "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", + "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", + "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", + "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", + "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", + "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", + "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", + "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", + "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", + "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", + "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", + "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", + "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.3.tgz", + "integrity": "sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } + } + }, + "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/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "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/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/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "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/oxlint": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.73.0.tgz", + "integrity": "sha512-u91G9TJzU6yqKWNZUYprQB07W7YvntZXaRxQ6CkoytepYhLWUXWsr1M8zUJ34VatNPuUAr3Z8GH+O2A331CluQ==", + "dev": true, + "license": "MIT", + "bin": { + "oxlint": "bin/oxlint" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxlint/binding-android-arm-eabi": "1.73.0", + "@oxlint/binding-android-arm64": "1.73.0", + "@oxlint/binding-darwin-arm64": "1.73.0", + "@oxlint/binding-darwin-x64": "1.73.0", + "@oxlint/binding-freebsd-x64": "1.73.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.73.0", + "@oxlint/binding-linux-arm-musleabihf": "1.73.0", + "@oxlint/binding-linux-arm64-gnu": "1.73.0", + "@oxlint/binding-linux-arm64-musl": "1.73.0", + "@oxlint/binding-linux-ppc64-gnu": "1.73.0", + "@oxlint/binding-linux-riscv64-gnu": "1.73.0", + "@oxlint/binding-linux-riscv64-musl": "1.73.0", + "@oxlint/binding-linux-s390x-gnu": "1.73.0", + "@oxlint/binding-linux-x64-gnu": "1.73.0", + "@oxlint/binding-linux-x64-musl": "1.73.0", + "@oxlint/binding-openharmony-arm64": "1.73.0", + "@oxlint/binding-win32-arm64-msvc": "1.73.0", + "@oxlint/binding-win32-ia32-msvc": "1.73.0", + "@oxlint/binding-win32-x64-msvc": "1.73.0" + }, + "peerDependencies": { + "oxlint-tsgolint": ">=0.24.0", + "vite-plus": "*" + }, + "peerDependenciesMeta": { + "oxlint-tsgolint": { + "optional": true + }, + "vite-plus": { + "optional": true + } + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.18.tgz", + "integrity": "sha512-xdB1oSLHbz1vRWgCDalrCqEFTWzFlhqFC5tIHLMOSUIjhm3XXQ1qrFy8S/ESr1JYRRXqM3c1QFiMZUJdUTqyMQ==", + "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.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.7" + } + }, + "node_modules/rolldown": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", + "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.139.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.1.5", + "@rolldown/binding-darwin-arm64": "1.1.5", + "@rolldown/binding-darwin-x64": "1.1.5", + "@rolldown/binding-freebsd-x64": "1.1.5", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", + "@rolldown/binding-linux-arm64-gnu": "1.1.5", + "@rolldown/binding-linux-arm64-musl": "1.1.5", + "@rolldown/binding-linux-ppc64-gnu": "1.1.5", + "@rolldown/binding-linux-s390x-gnu": "1.1.5", + "@rolldown/binding-linux-x64-gnu": "1.1.5", + "@rolldown/binding-linux-x64-musl": "1.1.5", + "@rolldown/binding-openharmony-arm64": "1.1.5", + "@rolldown/binding-wasm32-wasi": "1.1.5", + "@rolldown/binding-win32-arm64-msvc": "1.1.5", + "@rolldown/binding-win32-x64-msvc": "1.1.5" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/vite": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz", + "integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.16", + "rolldown": "~1.1.4", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.3.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + } + } +} diff --git a/car-ui/package.json b/car-ui/package.json new file mode 100644 index 0000000..3dabf63 --- /dev/null +++ b/car-ui/package.json @@ -0,0 +1,23 @@ +{ + "name": "car-ui", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "oxlint", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.2.7", + "react-dom": "^19.2.7" + }, + "devDependencies": { + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.3", + "oxlint": "^1.71.0", + "vite": "^8.1.1" + } +} diff --git a/car-ui/public/favicon.svg b/car-ui/public/favicon.svg new file mode 100644 index 0000000..6893eb1 --- /dev/null +++ b/car-ui/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/car-ui/public/icons.svg b/car-ui/public/icons.svg new file mode 100644 index 0000000..e952219 --- /dev/null +++ b/car-ui/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/car-ui/src/App.css b/car-ui/src/App.css new file mode 100644 index 0000000..67bfcfe --- /dev/null +++ b/car-ui/src/App.css @@ -0,0 +1,61 @@ +/* โ”€โ”€ App Shell โ”€โ”€ */ +.app { + position: relative; + min-height: 100dvh; + display: flex; + flex-direction: column; +} + +/* โ”€โ”€ Navbar โ”€โ”€ */ +.nav { + position: fixed; + top: 0; left: 0; right: 0; + z-index: 100; + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 2.5rem; + border-bottom: 1px solid rgba(255,255,255,0.06) !important; + border-radius: 0 !important; + background: rgba(2,8,23,0.75) !important; +} + +.nav__brand { + font-family: var(--font-display); + font-size: 1.25rem; + font-weight: 800; + color: var(--text-1); + letter-spacing: -0.5px; +} +.nav__brand span { + background: linear-gradient(90deg, #38bdf8, #818cf8); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.nav__links { + display: flex; + align-items: center; + gap: 10px; +} +.nav__pill { + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.08); + border-radius: 100px; + padding: 4px 14px; + font-size: 0.8rem; + font-weight: 600; + color: #94a3b8; +} +.nav__pill--dim { color: #475569; } + +/* โ”€โ”€ Footer โ”€โ”€ */ +.footer { + position: relative; + z-index: 1; + text-align: center; + padding: 2rem; + border-top: 1px solid rgba(255,255,255,0.05); +} +.footer p { font-size: 0.8rem; color: #334155; } diff --git a/car-ui/src/App.jsx b/car-ui/src/App.jsx new file mode 100644 index 0000000..ef91f6c --- /dev/null +++ b/car-ui/src/App.jsx @@ -0,0 +1,54 @@ +import { useRef, useState } from 'react'; +import ParticleBackground from './components/ParticleBackground'; +import HeroSection from './components/HeroSection'; +import InputForm from './components/InputForm'; +import ResultsDashboard from './components/ResultsDashboard'; +import './App.css'; + +export default function App() { + const formRef = useRef(null); + const [result, setResult] = useState(null); + + const scrollToForm = () => + formRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + + return ( +
+ + + {/* Nav */} + + + {/* Hero */} + {!result && } + + {/* Form */} + {!result && ( +
+ +
+ )} + + {/* Results */} + {result && ( + setResult(null)} + /> + )} + + {/* Footer */} + +
+ ); +} diff --git a/car-ui/src/assets/hero.png b/car-ui/src/assets/hero.png new file mode 100644 index 0000000..02251f4 Binary files /dev/null and b/car-ui/src/assets/hero.png differ diff --git a/car-ui/src/assets/react.svg b/car-ui/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/car-ui/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/car-ui/src/assets/vite.svg b/car-ui/src/assets/vite.svg new file mode 100644 index 0000000..5101b67 --- /dev/null +++ b/car-ui/src/assets/vite.svg @@ -0,0 +1 @@ +Vite diff --git a/car-ui/src/components/HeroSection.css b/car-ui/src/components/HeroSection.css new file mode 100644 index 0000000..68de7d2 --- /dev/null +++ b/car-ui/src/components/HeroSection.css @@ -0,0 +1,209 @@ +/* โ”€โ”€ Hero Section โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ +.hero { + position: relative; + min-height: 100dvh; + display: grid; + grid-template-columns: 1fr 1fr; + align-items: center; + gap: 4rem; + padding: 6rem 6rem 4rem; + overflow: hidden; + z-index: 1; +} + +/* Ambient blobs */ +.hero__blob { + position: absolute; + border-radius: 50%; + filter: blur(80px); + pointer-events: none; + z-index: -1; + animation: float 8s ease-in-out infinite; +} +.hero__blob--1 { + width: 500px; height: 500px; + background: rgba(56,189,248,0.08); + top: -10%; left: -5%; + animation-delay: 0s; +} +.hero__blob--2 { + width: 400px; height: 400px; + background: rgba(129,140,248,0.08); + top: 30%; right: 10%; + animation-delay: 2.5s; +} +.hero__blob--3 { + width: 350px; height: 350px; + background: rgba(168,85,247,0.06); + bottom: 5%; left: 40%; + animation-delay: 5s; +} + +/* Content */ +.hero__content { + display: flex; + flex-direction: column; + gap: 1.5rem; + animation: fadeUp 0.8s ease both; +} + +/* Badge */ +.hero__badge { + display: inline-flex; + align-items: center; + gap: 8px; + width: fit-content; + background: rgba(56,189,248,0.08); + border: 1px solid rgba(56,189,248,0.2); + border-radius: 100px; + padding: 6px 16px; + font-size: 0.78rem; + font-weight: 600; + color: #38bdf8; + text-transform: uppercase; + letter-spacing: 1.5px; +} +.hero__badge-dot { + width: 7px; height: 7px; + border-radius: 50%; + background: #38bdf8; + box-shadow: 0 0 8px #38bdf8; + animation: pulse 2s ease-in-out infinite; +} + +/* Title */ +.hero__title { + font-size: clamp(3rem, 6vw, 6rem); + font-weight: 900; + letter-spacing: -3px; + line-height: 1; + color: #f8fafc; +} +.hero__title-line1 { display: block; } +.hero__title-line2 { + display: block; + font-size: clamp(3.5rem, 7vw, 7rem); +} + +/* Subtitle */ +.hero__subtitle { + font-size: 1.15rem; + line-height: 1.75; + color: #94a3b8; + max-width: 520px; +} +.hero__subtitle strong { color: #e2e8f0; } + +/* Stats */ +.hero__stats { + display: flex; + gap: 2.5rem; + padding: 1.5rem 0; + border-top: 1px solid rgba(255,255,255,0.06); + border-bottom: 1px solid rgba(255,255,255,0.06); +} +.hero__stat { display: flex; flex-direction: column; gap: 4px; } +.hero__stat-value { + font-family: var(--font-display); + font-size: 1.6rem; + font-weight: 800; + color: #38bdf8; +} +.hero__stat-label { + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 1px; + color: #475569; +} + +/* CTA */ +.hero__cta { + display: inline-flex; + align-items: center; + gap: 10px; + width: fit-content; + padding: 1rem 2rem; + border-radius: 14px; + border: none; + cursor: pointer; + font-family: var(--font-display); + font-size: 1rem; + font-weight: 700; + color: #fff; + background: linear-gradient(135deg, #0ea5e9, #6366f1 60%, #a855f7); + background-size: 200% 200%; + animation: gradient-x 4s ease infinite; + box-shadow: 0 4px 30px rgba(99,102,241,0.45); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} +.hero__cta:hover { + transform: translateY(-3px); + box-shadow: 0 12px 40px rgba(99,102,241,0.65); +} +.hero__cta:active { transform: translateY(-1px); } + +/* Visual / Decorative card */ +.hero__visual { + display: flex; + justify-content: center; + align-items: center; + animation: fadeIn 1s ease 0.3s both; +} +.hero__card { + width: 340px; + border-radius: 24px; + padding: 2rem; + display: flex; + flex-direction: column; + gap: 1rem; + border: 1px solid rgba(56,189,248,0.15) !important; + box-shadow: 0 24px 80px -20px rgba(56,189,248,0.15), var(--shadow-card); + animation: float 6s ease-in-out infinite; +} +.hero__card-label { + font-size: 0.7rem; + font-weight: 700; + letter-spacing: 2px; + text-transform: uppercase; + color: #38bdf8; +} +.hero__card-value { + font-family: var(--font-display); + font-size: 2.8rem; + font-weight: 900; + color: #f8fafc; + letter-spacing: -1.5px; +} +.hero__card-range { font-size: 0.85rem; color: #64748b; } +.hero__card-bar { + height: 6px; + background: rgba(255,255,255,0.06); + border-radius: 3px; + overflow: hidden; +} +.hero__card-bar-fill { + height: 100%; + width: 67%; + background: linear-gradient(90deg, #10b981, #38bdf8); + border-radius: 3px; +} +.hero__card-tags { display: flex; gap: 8px; flex-wrap: wrap; } + +.tag { + display: inline-flex; + align-items: center; + padding: 4px 12px; + border-radius: 100px; + font-size: 0.78rem; + font-weight: 600; +} +.tag--green { background: rgba(16,185,129,0.1); color: #10b981; border: 1px solid rgba(16,185,129,0.2); } +.tag--blue { background: rgba(56,189,248,0.1); color: #38bdf8; border: 1px solid rgba(56,189,248,0.2); } +.tag--purple { background: rgba(167,139,250,0.1); color: #a78bfa; border: 1px solid rgba(167,139,250,0.2); } + +/* Responsive */ +@media (max-width: 1024px) { + .hero { grid-template-columns: 1fr; padding: 5rem 2rem 3rem; } + .hero__visual { display: none; } +} diff --git a/car-ui/src/components/HeroSection.jsx b/car-ui/src/components/HeroSection.jsx new file mode 100644 index 0000000..4bfd8f7 --- /dev/null +++ b/car-ui/src/components/HeroSection.jsx @@ -0,0 +1,74 @@ +import './HeroSection.css'; + +export default function HeroSection({ onCTAClick }) { + return ( +
+ {/* Ambient blobs */} +
+
+
+ +
+ {/* Badge */} +
+ + ๐Ÿ‡ฑ๐Ÿ‡ฐ   Sri Lanka Edition  ยท  AI Powered +
+ + {/* Headline */} +

+ AutoOracle + AI +

+ +

+ Enterprise-grade machine learning that reveals the true market
+ value of any vehicle in the Sri Lankan automotive market โ€”
+ instantly and accurately. +

+ + {/* Stats row */} +
+ {[ + { value: '~85%', label: 'Model Accuracy' }, + { value: '300+', label: 'Training Records' }, + { value: '3', label: 'ML Algorithms' }, + { value: '15ร—', label: 'LK Market Scale' }, + ].map(s => ( +
+ {s.value} + {s.label} +
+ ))} +
+ + {/* CTA */} + +
+ + {/* Decorative card */} +
+
+
AI VALUATION ENGINE
+
Rs. 87.5L
+
+ Range: Rs. 78.8L โ€“ Rs. 96.3L +
+
+
+
+
+ โœ“ Diesel + โœ“ Automatic + โœ“ 2019 Model +
+
+
+
+ ); +} diff --git a/car-ui/src/components/InputForm.css b/car-ui/src/components/InputForm.css new file mode 100644 index 0000000..7c190fe --- /dev/null +++ b/car-ui/src/components/InputForm.css @@ -0,0 +1,264 @@ +/* โ”€โ”€ Form Section โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ +.form-section { + position: relative; + z-index: 1; + min-height: 100dvh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 2.5rem; + padding: 6rem 2rem; + background: linear-gradient(180deg, transparent 0%, rgba(56,189,248,0.03) 100%); +} + +/* โ”€โ”€ Step Indicator โ”€โ”€ */ +.form-steps { + position: relative; + display: flex; + gap: 2rem; + align-items: flex-start; + width: 100%; + max-width: 640px; +} +.form-steps__line { + position: absolute; + top: 20px; + left: 20px; + right: 20px; + height: 1px; + background: rgba(255,255,255,0.07); + z-index: 0; +} + +.form-step { + display: flex; + align-items: center; + gap: 12px; + z-index: 1; + cursor: default; + flex: 1; +} +.form-step--done { cursor: pointer; } + +.form-step__dot { + width: 40px; height: 40px; + border-radius: 50%; + background: rgba(255,255,255,0.04); + border: 1px solid rgba(255,255,255,0.1); + display: flex; + align-items: center; + justify-content: center; + font-size: 0.85rem; + font-weight: 700; + color: #64748b; + flex-shrink: 0; + transition: all 0.3s ease; +} +.form-step--active .form-step__dot { + background: linear-gradient(135deg, #0ea5e9, #6366f1); + border-color: transparent; + color: #fff; + box-shadow: 0 0 20px rgba(99,102,241,0.5); +} +.form-step--done .form-step__dot { + background: rgba(16,185,129,0.15); + border-color: rgba(16,185,129,0.3); + color: #10b981; +} + +.form-step__info { display: flex; flex-direction: column; gap: 2px; } +.form-step__title { + font-size: 0.88rem; + font-weight: 600; + color: #94a3b8; + transition: color 0.3s; +} +.form-step--active .form-step__title { color: #f8fafc; } +.form-step__sub { font-size: 0.75rem; color: #475569; } + +/* โ”€โ”€ Form Card โ”€โ”€ */ +.form-card { + width: 100%; + max-width: 640px; + border-radius: 28px; + padding: 2.5rem; + border: 1px solid rgba(56,189,248,0.1) !important; + box-shadow: var(--shadow-card), 0 0 60px rgba(56,189,248,0.05); +} + +.form-card__header { + display: flex; + align-items: center; + gap: 1rem; + margin-bottom: 2rem; + padding-bottom: 1.5rem; + border-bottom: 1px solid rgba(255,255,255,0.06); +} +.form-card__icon { + font-size: 2.5rem; + line-height: 1; + animation: float 4s ease-in-out infinite; + display: block; +} +.form-card__title { + font-size: 1.4rem; + font-weight: 700; + color: #f8fafc; +} +.form-card__sub { font-size: 0.88rem; color: #64748b; margin-top: 2px; } + +/* โ”€โ”€ Fields โ”€โ”€ */ +.form-fields { + display: flex; + flex-direction: column; + gap: 1.75rem; + animation: fadeUp 0.4s ease both; +} + +.field { display: flex; flex-direction: column; gap: 8px; } +.field__label { + font-size: 0.85rem; + font-weight: 600; + color: #94a3b8; + text-transform: uppercase; + letter-spacing: 0.5px; +} +.field__unit { font-weight: 400; text-transform: none; letter-spacing: 0; opacity: 0.6; } +.field__hint { font-size: 0.78rem; color: #475569; } + +.field__input { + background: rgba(255,255,255,0.04); + border: 1px solid rgba(255,255,255,0.1); + border-radius: var(--radius-md); + padding: 0.85rem 1.1rem; + font-size: 1rem; + font-family: var(--font-body); + color: #f8fafc; + outline: none; + transition: border-color 0.2s, box-shadow 0.2s; + width: 100%; + appearance: textfield; +} +.field__input:focus { + border-color: rgba(56,189,248,0.5); + box-shadow: 0 0 0 4px rgba(56,189,248,0.08); +} +.field__input::-webkit-inner-spin-button { opacity: 0.4; } + +/* Slider */ +.field__slider-wrap { + display: flex; + align-items: center; + gap: 1rem; +} +.field__slider { + flex: 1; + -webkit-appearance: none; + appearance: none; + height: 6px; + border-radius: 3px; + background: rgba(255,255,255,0.08); + outline: none; + cursor: pointer; +} +.field__slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 22px; height: 22px; + border-radius: 50%; + background: linear-gradient(135deg, #38bdf8, #818cf8); + box-shadow: 0 0 12px rgba(56,189,248,0.5); + cursor: pointer; + transition: transform 0.2s; +} +.field__slider::-webkit-slider-thumb:hover { transform: scale(1.2); } +.field__slider-val { + font-family: var(--font-display); + font-size: 1.3rem; + font-weight: 700; + color: #38bdf8; + min-width: 52px; + text-align: right; +} + +/* Pills */ +.field__pills { display: flex; gap: 10px; flex-wrap: wrap; } +.pill { + padding: 8px 18px; + border-radius: 100px; + border: 1px solid rgba(255,255,255,0.1); + background: rgba(255,255,255,0.03); + color: #94a3b8; + font-size: 0.88rem; + font-weight: 600; + font-family: var(--font-body); + cursor: pointer; + transition: all 0.2s ease; +} +.pill:hover { border-color: rgba(56,189,248,0.3); color: #e2e8f0; } +.pill--active { + background: linear-gradient(135deg, rgba(14,165,233,0.15), rgba(99,102,241,0.15)); + border-color: rgba(56,189,248,0.5); + color: #38bdf8; + box-shadow: 0 0 16px rgba(56,189,248,0.15); +} + +/* Error */ +.form-error { + margin-top: 1rem; + padding: 12px 16px; + background: rgba(244,63,94,0.1); + border: 1px solid rgba(244,63,94,0.2); + border-radius: var(--radius-md); + font-size: 0.88rem; + color: #f87171; +} + +/* Nav */ +.form-nav { + display: flex; + justify-content: flex-end; + gap: 12px; + margin-top: 2rem; + padding-top: 1.5rem; + border-top: 1px solid rgba(255,255,255,0.06); +} + +.btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 0.8rem 1.75rem; + border-radius: var(--radius-md); + font-size: 0.95rem; + font-weight: 700; + font-family: var(--font-display); + cursor: pointer; + transition: all 0.25s ease; + border: none; +} +.btn--ghost { + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.1); + color: #94a3b8; +} +.btn--ghost:hover { background: rgba(255,255,255,0.08); color: #e2e8f0; } +.btn--primary { + background: linear-gradient(135deg, #0ea5e9, #6366f1); + color: #fff; + box-shadow: 0 4px 20px rgba(99,102,241,0.4); +} +.btn--primary:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(99,102,241,0.55); } +.btn--glow { background: linear-gradient(135deg, #0ea5e9, #a855f7); } +.btn:disabled { opacity: 0.6; cursor: not-allowed; transform: none !important; } + +/* Spinner */ +.spinner { + display: inline-block; + width: 18px; height: 18px; + border: 2px solid rgba(255,255,255,0.3); + border-top-color: #fff; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} diff --git a/car-ui/src/components/InputForm.jsx b/car-ui/src/components/InputForm.jsx new file mode 100644 index 0000000..be5d9b5 --- /dev/null +++ b/car-ui/src/components/InputForm.jsx @@ -0,0 +1,211 @@ +import { useState } from 'react'; +import './InputForm.css'; + +const STEPS = [ + { + id: 'basics', + title: 'Basic Details', + subtitle: 'Tell us about the vehicle', + icon: '๐Ÿš—', + }, + { + id: 'specs', + title: 'Specifications', + subtitle: 'Engine & transmission info', + icon: 'โš™๏ธ', + }, +]; + +export default function InputForm({ onResult }) { + const [step, setStep] = useState(0); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + + const [form, setForm] = useState({ + year: 2015, + present_price: 75, + kms_driven: 50000, + fuel_type: 'Petrol', + seller_type: 'Dealer', + transmission: 'Manual', + owner: 0, + }); + + const set = (k, v) => setForm(f => ({ ...f, [k]: v })); + + const handleSubmit = async () => { + setLoading(true); + setError(''); + try { + const res = await fetch('http://localhost:8000/predict', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(form), + }); + if (!res.ok) throw new Error('API error'); + const data = await res.json(); + onResult({ ...data, input: form }); + } catch (e) { + setError('Could not connect to the API. Make sure api.py is running on port 8000.'); + } finally { + setLoading(false); + } + }; + + return ( +
+ {/* Step indicator */} +
+ {STEPS.map((s, i) => ( +
i < step && setStep(i)} + > +
+ {i < step ? ( + + + + ) : ( + {i + 1} + )} +
+
+ {s.title} + {s.subtitle} +
+
+ ))} +
+
+ + {/* Card */} +
+
+ {STEPS[step].icon} +
+

{STEPS[step].title}

+

{STEPS[step].subtitle}

+
+
+ + {/* STEP 0 */} + {step === 0 && ( +
+
+ +
+ set('year', +e.target.value)} + className="field__slider" + /> + {form.year} +
+
{2024 - form.year} years old
+
+ +
+ + set('present_price', +e.target.value)} + className="field__input" + /> +
+ +
+ + set('kms_driven', +e.target.value)} + className="field__input" + /> +
{(form.kms_driven / 1000).toFixed(0)}k km driven
+
+
+ )} + + {/* STEP 1 */} + {step === 1 && ( +
+
+ +
+ {['Petrol', 'Diesel', 'CNG'].map(v => ( + + ))} +
+
+ +
+ +
+ {['Manual', 'Automatic'].map(v => ( + + ))} +
+
+ +
+ +
+ {['Dealer', 'Individual'].map(v => ( + + ))} +
+
+ +
+ +
+ {[0, 1, 2, 3].map(v => ( + + ))} +
+
+
+ )} + + {error &&
{error}
} + + {/* Navigation */} +
+ {step > 0 && ( + + )} + {step < STEPS.length - 1 ? ( + + ) : ( + + )} +
+
+
+ ); +} diff --git a/car-ui/src/components/ParticleBackground.css b/car-ui/src/components/ParticleBackground.css new file mode 100644 index 0000000..201f31f --- /dev/null +++ b/car-ui/src/components/ParticleBackground.css @@ -0,0 +1,6 @@ +.particle-canvas { + position: fixed; + inset: 0; + z-index: 0; + pointer-events: none; +} diff --git a/car-ui/src/components/ParticleBackground.jsx b/car-ui/src/components/ParticleBackground.jsx new file mode 100644 index 0000000..83bfede --- /dev/null +++ b/car-ui/src/components/ParticleBackground.jsx @@ -0,0 +1,75 @@ +import { useEffect, useRef } from 'react'; +import './ParticleBackground.css'; + +export default function ParticleBackground() { + const canvasRef = useRef(null); + + useEffect(() => { + const canvas = canvasRef.current; + const ctx = canvas.getContext('2d'); + let animId; + let particles = []; + + const resize = () => { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + }; + resize(); + window.addEventListener('resize', resize); + + // Spawn particles + for (let i = 0; i < 60; i++) { + particles.push({ + x: Math.random() * canvas.width, + y: Math.random() * canvas.height, + vx: (Math.random() - 0.5) * 0.4, + vy: (Math.random() - 0.5) * 0.4, + r: Math.random() * 1.5 + 0.5, + alpha: Math.random() * 0.5 + 0.1, + }); + } + + const draw = () => { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // Connect nearby particles + for (let i = 0; i < particles.length; i++) { + for (let j = i + 1; j < particles.length; j++) { + const dx = particles[i].x - particles[j].x; + const dy = particles[i].y - particles[j].y; + const dist = Math.sqrt(dx * dx + dy * dy); + if (dist < 120) { + ctx.beginPath(); + ctx.strokeStyle = `rgba(56,189,248,${0.07 * (1 - dist / 120)})`; + ctx.lineWidth = 1; + ctx.moveTo(particles[i].x, particles[i].y); + ctx.lineTo(particles[j].x, particles[j].y); + ctx.stroke(); + } + } + } + + // Draw & move particles + particles.forEach(p => { + ctx.beginPath(); + ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2); + ctx.fillStyle = `rgba(56,189,248,${p.alpha})`; + ctx.fill(); + p.x += p.vx; + p.y += p.vy; + if (p.x < 0 || p.x > canvas.width) p.vx *= -1; + if (p.y < 0 || p.y > canvas.height) p.vy *= -1; + }); + + animId = requestAnimationFrame(draw); + }; + draw(); + + return () => { + cancelAnimationFrame(animId); + window.removeEventListener('resize', resize); + }; + }, []); + + return ; +} diff --git a/car-ui/src/components/ResultsDashboard.css b/car-ui/src/components/ResultsDashboard.css new file mode 100644 index 0000000..f287088 --- /dev/null +++ b/car-ui/src/components/ResultsDashboard.css @@ -0,0 +1,249 @@ +/* โ”€โ”€ Results Dashboard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ +.results { + position: relative; + z-index: 1; + min-height: 100dvh; + display: flex; + flex-direction: column; + align-items: center; + gap: 3rem; + padding: 6rem 4rem; + overflow: hidden; +} + +/* Blobs */ +.results__blob { + position: absolute; + border-radius: 50%; + filter: blur(100px); + pointer-events: none; + z-index: -1; +} +.results__blob--1 { + width: 500px; height: 500px; + background: rgba(16,185,129,0.06); + top: 0; left: -10%; +} +.results__blob--2 { + width: 400px; height: 400px; + background: rgba(56,189,248,0.06); + bottom: 5%; right: -5%; +} + +/* Header */ +.results__header { + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; + animation: fadeUp 0.5s ease both; +} +.results__badge { + display: inline-flex; + align-items: center; + gap: 8px; + background: rgba(16,185,129,0.1); + border: 1px solid rgba(16,185,129,0.25); + border-radius: 100px; + padding: 6px 16px; + font-size: 0.78rem; + font-weight: 600; + color: #10b981; + text-transform: uppercase; + letter-spacing: 1.5px; +} +.results__title { + font-size: 2.5rem; + font-weight: 800; + letter-spacing: -1.5px; +} +.results__sub { color: #64748b; font-size: 0.95rem; } + +/* โ”€โ”€ KPI Row โ”€โ”€ */ +.kpi-row { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1.25rem; + width: 100%; + max-width: 1000px; +} +.kpi { + background: var(--surface); + border-radius: 20px; + padding: 1.75rem; + border: 1px solid var(--border); + backdrop-filter: blur(14px); + transition: transform 0.3s ease, box-shadow 0.3s ease; + animation: scaleIn 0.5s ease both; + cursor: default; +} +.kpi:nth-child(2) { animation-delay: 0.1s; } +.kpi:nth-child(3) { animation-delay: 0.2s; } +.kpi:hover { transform: translateY(-6px); } +.kpi--green { border-top: 3px solid #10b981; } +.kpi--blue { border-top: 3px solid #38bdf8; } +.kpi--red { border-top: 3px solid #f43f5e; } +.kpi--green:hover { box-shadow: 0 20px 50px -10px rgba(16,185,129,0.2); } +.kpi--blue:hover { box-shadow: 0 20px 50px -10px rgba(56,189,248,0.2); } +.kpi--red:hover { box-shadow: 0 20px 50px -10px rgba(244,63,94,0.2); } + +.kpi__icon { font-size: 2rem; margin-bottom: 0.75rem; } +.kpi__label { + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 1.5px; + color: #475569; + margin-bottom: 0.5rem; +} +.kpi__val { + font-family: var(--font-display); + font-size: 1.9rem; + font-weight: 800; + letter-spacing: -1px; + line-height: 1.1; + animation: countUp 0.6s ease both; +} +.kpi__val--green { color: #10b981; } +.kpi__val--blue { color: #38bdf8; } +.kpi__val--red { color: #f43f5e; } +.kpi__sub { font-size: 0.8rem; color: #475569; margin-top: 6px; } + +/* โ”€โ”€ Analysis Grid โ”€โ”€ */ +.analysis-grid { + display: grid; + grid-template-columns: 1fr 1.5fr; + gap: 1.5rem; + width: 100%; + max-width: 1000px; +} + +.analysis-gauge, .analysis-factors { + border-radius: 24px; + padding: 2rem; + border: 1px solid rgba(255,255,255,0.06) !important; + animation: fadeUp 0.6s ease 0.3s both; +} +.analysis-factors { animation-delay: 0.45s; } + +.analysis-gauge__label, .analysis-factors__label { + font-size: 0.7rem; + font-weight: 700; + letter-spacing: 2px; + text-transform: uppercase; + color: #475569; + margin-bottom: 1rem; +} + +/* Gauge SVG */ +.gauge-svg { + width: 100%; + max-width: 220px; + display: block; + margin: 0 auto; +} +.analysis-gauge__center-val { + text-align: center; + font-family: var(--font-display); + font-size: 1.4rem; + font-weight: 800; + color: #f8fafc; + margin-top: -1rem; + margin-bottom: 1.25rem; +} + +/* Range */ +.analysis-range { display: flex; flex-direction: column; gap: 8px; } +.analysis-range__label { font-size: 0.75rem; font-weight: 600; color: #475569; text-transform: uppercase; letter-spacing: 1px; } +.analysis-range__val { font-size: 1.1rem; font-weight: 700; color: #10b981; } +.analysis-range__bar { + height: 6px; + background: rgba(255,255,255,0.06); + border-radius: 3px; + overflow: hidden; +} +.analysis-range__fill { + height: 100%; + background: linear-gradient(90deg, #10b981, #38bdf8); + border-radius: 3px; + transition: width 1.2s cubic-bezier(0.4,0,0.2,1); +} +.analysis-range__ends { + display: flex; + justify-content: space-between; + font-size: 0.78rem; + color: #475569; +} + +/* Factors */ +.factors-list { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 1.5rem; +} +.factor-pill { + display: inline-flex; + align-items: center; + padding: 6px 14px; + border-radius: 100px; + font-size: 0.82rem; + font-weight: 600; + animation: fadeIn 0.4s ease both; +} +.factor-pill--positive { background: rgba(16,185,129,0.08); color: #10b981; border: 1px solid rgba(16,185,129,0.2); } +.factor-pill--neutral { background: rgba(245,158,11,0.08); color: #f59e0b; border: 1px solid rgba(245,158,11,0.2); } +.factor-pill--negative { background: rgba(244,63,94,0.08); color: #f87171; border: 1px solid rgba(244,63,94,0.2); } + +/* Depr bars */ +.depr-bar-section { margin-bottom: 1.5rem; } +.depr-bar-section__label { + font-size: 0.7rem; font-weight: 700; letter-spacing: 2px; + text-transform: uppercase; color: #475569; margin-bottom: 1rem; +} +.depr-bars { display: flex; flex-direction: column; gap: 12px; } +.depr-bar__row { display: grid; grid-template-columns: 100px 1fr 80px; align-items: center; gap: 10px; } +.depr-bar__name { font-size: 0.82rem; font-weight: 600; color: #94a3b8; } +.depr-bar__track { height: 8px; background: rgba(255,255,255,0.06); border-radius: 4px; overflow: hidden; } +.depr-bar__fill { + height: 100%; border-radius: 4px; + transition: width 1.2s cubic-bezier(0.4,0,0.2,1); +} +.depr-bar__fill--green { background: linear-gradient(90deg, #059669, #10b981); } +.depr-bar__fill--red { background: linear-gradient(90deg, #be123c, #f43f5e); } +.depr-bar__num { font-size: 0.82rem; font-weight: 700; color: #94a3b8; text-align: right; } + +/* Summary table */ +.summary-table { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px 1rem; + padding-top: 1rem; + border-top: 1px solid rgba(255,255,255,0.05); +} +.summary-row { display: flex; justify-content: space-between; align-items: center; padding: 4px 0; } +.summary-key { font-size: 0.8rem; color: #475569; font-weight: 500; } +.summary-val { font-size: 0.82rem; color: #94a3b8; font-weight: 600; } + +/* Reset button */ +.results__reset { + background: rgba(255,255,255,0.04); + border: 1px solid rgba(255,255,255,0.1); + color: #94a3b8; + padding: 0.75rem 1.75rem; + border-radius: 12px; + font-size: 0.9rem; + font-weight: 600; + font-family: var(--font-body); + cursor: pointer; + transition: all 0.2s ease; +} +.results__reset:hover { background: rgba(255,255,255,0.08); color: #e2e8f0; transform: translateY(-2px); } + +/* Responsive */ +@media (max-width: 768px) { + .results { padding: 4rem 1.5rem; gap: 2rem; } + .kpi-row { grid-template-columns: 1fr; } + .analysis-grid { grid-template-columns: 1fr; } +} diff --git a/car-ui/src/components/ResultsDashboard.jsx b/car-ui/src/components/ResultsDashboard.jsx new file mode 100644 index 0000000..3e2b371 --- /dev/null +++ b/car-ui/src/components/ResultsDashboard.jsx @@ -0,0 +1,223 @@ +import { useEffect, useState, useRef } from 'react'; +import './ResultsDashboard.css'; + +/* Animated counter */ +function CountUp({ target, prefix = '', suffix = '', decimals = 1 }) { + const [val, setVal] = useState(0); + useEffect(() => { + const dur = 1400; + const start = performance.now(); + const tick = (now) => { + const t = Math.min((now - start) / dur, 1); + const ease = 1 - Math.pow(1 - t, 4); + setVal(target * ease); + if (t < 1) requestAnimationFrame(tick); + }; + requestAnimationFrame(tick); + }, [target]); + return <>{prefix}{val.toFixed(decimals)}{suffix}; +} + +/* SVG Gauge */ +function Gauge({ value, max }) { + const pct = Math.min(value / max, 1); + const R = 80; + const cx = 110; const cy = 110; + const sweep = Math.PI * 1.5; // 270ยฐ + const startAngle = Math.PI + Math.PI * 0.25; + const endAngle = startAngle + sweep; + const angle = startAngle + pct * sweep; + + const polarToCart = (ang, r = R) => ({ + x: cx + r * Math.cos(ang), + y: cy + r * Math.sin(ang), + }); + + const arcPath = (r, a1, a2) => { + const s = polarToCart(a1, r); + const e = polarToCart(a2, r); + const large = a2 - a1 > Math.PI ? 1 : 0; + return `M ${s.x} ${s.y} A ${r} ${r} 0 ${large} 1 ${e.x} ${e.y}`; + }; + + const needle = polarToCart(angle, R - 12); + + return ( + + {/* Track */} + + {/* Red zone */} + + {/* Amber zone */} + + {/* Green zone */} + + {/* Fill */} + + {/* Needle dot */} + + + + + + + + + + + + ); +} + +function FactorPill({ label, type }) { + return {label}; +} + +export default function ResultsDashboard({ data, onReset }) { + const dashRef = useRef(null); + const { predicted_price, depreciation, depreciation_pct, retention_rate, lower_estimate, upper_estimate, input } = data; + const car_age = 2024 - input.year; + + useEffect(() => { + dashRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + }, []); + + /* Build factor pills */ + const factors = []; + if (car_age <= 2) factors.push({ label: '๐ŸŸข Near-new โ€” minimal depreciation', type: 'positive' }); + else if (car_age <= 5) factors.push({ label: '๐ŸŸก Relatively new โ€” good resale', type: 'neutral' }); + else if (car_age <= 10) factors.push({ label: '๐ŸŸ  Moderate age โ€” avg value', type: 'neutral' }); + else factors.push({ label: '๐Ÿ”ด High age โ€” heavy depreciation', type: 'negative' }); + + if (input.kms_driven < 30000) factors.push({ label: '๐ŸŸข Low mileage โ€” value boost', type: 'positive' }); + else if (input.kms_driven < 80000) factors.push({ label: '๐ŸŸก Average mileage', type: 'neutral' }); + else factors.push({ label: '๐Ÿ”ด High mileage โ€” value drop', type: 'negative' }); + + if (input.transmission === 'Automatic') factors.push({ label: '๐ŸŸข Automatic โ€” premium tag', type: 'positive' }); + if (input.fuel_type === 'Diesel') factors.push({ label: '๐ŸŸข Diesel โ€” economy preferred', type: 'positive' }); + else if (input.fuel_type === 'Petrol') factors.push({ label: '๐ŸŸก Petrol โ€” standard', type: 'neutral' }); + if (input.owner === 0) factors.push({ label: '๐ŸŸข First owner โ€” premium', type: 'positive' }); + else if (input.owner >= 2) factors.push({ label: '๐Ÿ”ด Multiple owners โ€” reduced', type: 'negative' }); + + return ( +
+ {/* Blobs */} +
+
+ + {/* Header */} +
+
+ + AI Valuation Complete +
+

Your Vehicle Report

+

Based on {input.year} ยท {input.fuel_type} ยท {input.transmission} ยท {input.kms_driven.toLocaleString()} km

+
+ + {/* KPI row */} +
+
+
๐Ÿ’ฐ
+
Estimated Selling Price
+
+ Rs. L +
+
AI-predicted fair market value
+
+ +
+
๐Ÿท๏ธ
+
Original Showroom Price
+
+ Rs. L +
+
Ex-showroom brand-new value
+
+ +
+
๐Ÿ“‰
+
Total Depreciation
+
+ Rs. L +
+
โ†“ {depreciation_pct}% ยท {retention_rate}% retained
+
+
+ + {/* Analysis section */} +
+ {/* Left: Gauge + range */} +
+
VALUE POSITION
+ +
+ Rs. {predicted_price.toFixed(1)}L +
+
+
Expected Market Range
+
Rs. {lower_estimate}L โ€” Rs. {upper_estimate}L
+
+
+
+
+ Rs. {lower_estimate}L + Rs. {upper_estimate}L +
+
+
+ + {/* Right: Factors + bar */} +
+
VALUE FACTORS
+
+ {factors.map((f, i) => )} +
+ +
+
Depreciation Breakdown
+
+
+ Current Value +
+
+
+ Rs. {predicted_price.toFixed(1)}L +
+
+ Depreciation +
+
+
+ Rs. {depreciation.toFixed(1)}L +
+
+
+ + {/* Summary table */} +
+ {[ + ['Year', input.year], + ['Car Age', `${car_age} years`], + ['Mileage', `${input.kms_driven.toLocaleString()} km`], + ['Fuel', input.fuel_type], + ['Transmission', input.transmission], + ['Seller', input.seller_type], + ['Owners', input.owner === 0 ? 'First Owner' : `${input.owner} previous`], + ].map(([k, v]) => ( +
+ {k} + {v} +
+ ))} +
+
+
+ + {/* Reset */} + +
+ ); +} diff --git a/car-ui/src/index.css b/car-ui/src/index.css new file mode 100644 index 0000000..2bcaa3b --- /dev/null +++ b/car-ui/src/index.css @@ -0,0 +1,99 @@ +/* โ”€โ”€ AutoOracle AI โ€” Design System โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ +@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Space+Grotesk:wght@400;500;700&display=swap'); + +/* โ”€โ”€ Tokens โ”€โ”€ */ +:root { + --bg: #020817; + --bg-2: #0a1628; + --surface: rgba(255,255,255,0.03); + --border: rgba(255,255,255,0.07); + --border-hi: rgba(56,189,248,0.3); + + --cyan: #38bdf8; + --indigo: #818cf8; + --violet: #a78bfa; + --green: #10b981; + --red: #f43f5e; + --amber: #f59e0b; + + --text-1: #f8fafc; + --text-2: #cbd5e1; + --text-3: #64748b; + + --font-body: 'Inter', system-ui, sans-serif; + --font-display: 'Space Grotesk', 'Inter', sans-serif; + + --radius-sm: 8px; + --radius-md: 14px; + --radius-lg: 20px; + --radius-xl: 28px; + + --shadow-glow-cyan: 0 0 40px rgba(56,189,248,0.2); + --shadow-glow-indigo: 0 0 40px rgba(129,140,248,0.2); + --shadow-card: 0 8px 32px -8px rgba(0,0,0,0.6); +} + +/* โ”€โ”€ Reset & Base โ”€โ”€ */ +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + +html { scroll-behavior: smooth; font-size: 16px; } + +body { + font-family: var(--font-body); + background: var(--bg); + color: var(--text-2); + overflow-x: hidden; + min-height: 100dvh; + -webkit-font-smoothing: antialiased; +} + +/* โ”€โ”€ Scrollbar โ”€โ”€ */ +::-webkit-scrollbar { width: 6px; } +::-webkit-scrollbar-track { background: var(--bg); } +::-webkit-scrollbar-thumb { background: #1e293b; border-radius: 3px; } + +/* โ”€โ”€ Typography โ”€โ”€ */ +h1,h2,h3,h4 { font-family: var(--font-display); color: var(--text-1); line-height: 1.1; } + +/* โ”€โ”€ Animations โ”€โ”€ */ +@keyframes fadeUp { from { opacity:0; transform:translateY(32px); } to { opacity:1; transform:translateY(0); } } +@keyframes fadeIn { from { opacity:0; } to { opacity:1; } } +@keyframes scaleIn { from { opacity:0; transform:scale(0.9); } to { opacity:1; transform:scale(1); } } +@keyframes countUp { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:translateY(0); } } +@keyframes spin { to { transform: rotate(360deg); } } +@keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:.5; } } +@keyframes shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } +} +@keyframes gradient-x { + 0%,100% { background-position: 0% 50%; } + 50% { background-position: 100% 50%; } +} +@keyframes float { + 0%,100% { transform: translateY(0px); } + 50% { transform: translateY(-8px); } +} + +/* โ”€โ”€ Grid overlay โ”€โ”€ */ +@keyframes grid-drift { + from { transform: translateY(0); } + to { transform: translateY(60px); } +} + +/* โ”€โ”€ Utility โ”€โ”€ */ +.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; } + +.gradient-text { + background: linear-gradient(135deg, #fff 0%, var(--cyan) 40%, var(--indigo) 80%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.glass { + background: var(--surface); + backdrop-filter: blur(16px) saturate(180%); + -webkit-backdrop-filter: blur(16px) saturate(180%); + border: 1px solid var(--border); +} diff --git a/car-ui/src/main.jsx b/car-ui/src/main.jsx new file mode 100644 index 0000000..b9a1a6d --- /dev/null +++ b/car-ui/src/main.jsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.jsx' + +createRoot(document.getElementById('root')).render( + + + , +) diff --git a/car-ui/vite.config.js b/car-ui/vite.config.js new file mode 100644 index 0000000..8b0f57b --- /dev/null +++ b/car-ui/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +})