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 */}
+
+
+ AutoOracle AI
+
+
+ ๐ฑ๐ฐ Sri Lanka
+ ML-Powered
+
+
+
+ {/* 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 */}
+
+ Get Your Valuation
+
+
+
+
+
+
+ {/* 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 && (
+
+
+
Manufacturing Year
+
+ set('year', +e.target.value)}
+ className="field__slider"
+ />
+ {form.year}
+
+
{2024 - form.year} years old
+
+
+
+ Ex-Showroom Price (Rs. Lakhs)
+ set('present_price', +e.target.value)}
+ className="field__input"
+ />
+
+
+
+
Kilometers Driven
+
set('kms_driven', +e.target.value)}
+ className="field__input"
+ />
+
{(form.kms_driven / 1000).toFixed(0)}k km driven
+
+
+ )}
+
+ {/* STEP 1 */}
+ {step === 1 && (
+
+
+
Fuel Type
+
+ {['Petrol', 'Diesel', 'CNG'].map(v => (
+ set('fuel_type', v)}
+ >{v}
+ ))}
+
+
+
+
+
Transmission
+
+ {['Manual', 'Automatic'].map(v => (
+ set('transmission', v)}
+ >{v}
+ ))}
+
+
+
+
+
Seller Type
+
+ {['Dealer', 'Individual'].map(v => (
+ set('seller_type', v)}
+ >{v}
+ ))}
+
+
+
+
+
Number of Previous Owners
+
+ {[0, 1, 2, 3].map(v => (
+ set('owner', v)}
+ >{v === 0 ? 'First Owner' : `${v} Previous`}
+ ))}
+
+
+
+ )}
+
+ {error &&
{error}
}
+
+ {/* Navigation */}
+
+ {step > 0 && (
+ setStep(s => s - 1)}>
+ โ Back
+
+ )}
+ {step < STEPS.length - 1 ? (
+ setStep(s => s + 1)}>
+ Continue โ
+
+ ) : (
+
+ {loading ? : 'โก Get AI Valuation'}
+
+ )}
+
+
+
+ );
+}
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 */}
+
+ โ Evaluate Another Vehicle
+
+
+ );
+}
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()],
+})