diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..96f1d1d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+node_modules/
+dist/
+.env
+.env.local
+.DS_Store
+*.log
diff --git a/README.md b/README.md
index b1900a9..e8ac2ca 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,66 @@
-# gxchatindia
\ No newline at end of file
+# Gothwad Tech — Official Website
+
+Official website for **Gothwad Tech** — India's sovereign software collective.
+
+**Live:** https://gothwadtech.com
+
+## ✨ What this site is
+
+- **Official portal:** Everything Gothwad in one place. One Gothwad Account unlocks Mail, Drive, Meet, Store, Tube, GrixChat, Indogram, Browser, Education, AI Studio, Docs and CEO.
+- **Ecosystem directory:** All 25+ products with direct subdomain links (`{host}.gothwadtech.com`), category filters and GitHub source links.
+- **Product access hub:** Every card has a live “Open” button and a “Source” link — just like the Docs portal.
+- **Same design language:** Matches `gothwadtech` (corporate) and `docs` (developer portal) repos — zinc + `#0494f4` brand, light/dark theme, responsive.
+
+## 🗺️ Routes
+
+| Path | Description |
+|------|-------------|
+| `/` | Home — hero + quick access + app shortcuts (search + category filter) |
+| `/ecosystem` | Full product directory — all Gothwad apps with direct links |
+| `/products` | Sovereign flagships: Browser, GrixChat, Indogram + full catalog |
+| `/solutions` | School ERP, restaurant POS, shop billing, custom enterprise & deep-tech |
+| `/docs` | Developer documentation index (mirrors docs.gothwadtech.com structure) |
+| `/company` | About + leadership (Pawan Gothwad, Yuvkesh Meena, Vishnu) |
+| `/contact` | Official inboxes + direct founder/leadership + WhatsApp/Phone |
+
+Deep links and refreshes work via `_redirects` SPA fallback on Cloudflare Pages.
+
+## 🎨 Assets
+
+Moved from `GothwadTech/gothwadtech` repo per request:
+
+- `public/assets/` root: `apple-touch-icon.png`, `favicon.ico`, `icon-192*.png`, `icon-512*.png`, `logo.png` (all PNG/icon images outside the two subfolders)
+- `public/assets/brand/` + `public/assets/icons/` — kept as-is (two existing subfolders)
+- `public/manifest.json`, `favicon.ico`, `logo.svg`, `robots.txt`, `sitemap.xml`, `_redirects`, `_headers`
+
+## 🛠 Stack
+
+- Vite 6 + React 19 + TypeScript 5
+- Tailwind CSS 4 via `@tailwindcss/vite` (same as `gothwadtech` + `docs`)
+- `lucide-react` icons, `motion` for micro-interactions
+
+## 🚀 Run
+
+```bash
+npm install
+npm run dev # http://localhost:3000
+npm run build # → dist/
+npm run preview # serve built site
+npm run typecheck
+```
+
+## 🔗 Ecosystem quick links
+
+- Accounts: https://accounts.gothwadtech.com
+- Mail: https://mail.gothwadtech.com
+- Drive: https://drive.gothwadtech.com
+- Meet: https://meet.gothwadtech.com
+- Tube: https://tube.gothwadtech.com
+- GrixChat: https://grixchat.gothwadtech.com
+- Indogram: https://indogram.gothwadtech.com
+- Browser: https://browser.gothwadtech.com
+- Docs: https://docs.gothwadtech.com
+- CEO: https://ceo.gothwadtech.com
+- GitHub: https://github.com/GothwadTech
+
+© 2026 Gothwad Tech Private Limited. Aatmanirbhar Bharat.
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..76b3432
--- /dev/null
+++ b/index.html
@@ -0,0 +1,284 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Gothwad Tech — Official Website | Sovereign Software, Browser & AI from India
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..2ba13fa
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2551 @@
+{
+ "name": "gothwadtech-website",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "gothwadtech-website",
+ "version": "1.0.0",
+ "dependencies": {
+ "lucide-react": "^0.546.0",
+ "motion": "^12.23.24",
+ "react": "^19.0.1",
+ "react-dom": "^19.0.1"
+ },
+ "devDependencies": {
+ "@tailwindcss/vite": "^4.1.14",
+ "@types/node": "^22.14.0",
+ "@types/react": "^19.0.0",
+ "@types/react-dom": "^19.0.0",
+ "@vitejs/plugin-react": "^5.0.4",
+ "tailwindcss": "^4.1.14",
+ "typescript": "~5.8.2",
+ "vite": "^6.2.3"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-compilation-targets": "^7.29.7",
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helpers": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
+ "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.8",
+ "@babel/types": "^7.29.8",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
+ "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.11",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.11.tgz",
+ "integrity": "sha512-snZbO7MEDOof+hvNa97EjEY7qD7h2kwvQr5AJC3ZhQudKW5dnej6k3kP9NQV88hJwaS8vDqRLFo9rivLEhle2g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.10",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.10.tgz",
+ "integrity": "sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.8"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.11",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.11.tgz",
+ "integrity": "sha512-OZ6+oaK7GMyg3IfCpj8JOmn8n+w2rJbDT0LLfVDTLb1ZFeKDh3AiNELgCMUw175IJHSkLl74hG0M0VLsvx+gag==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.11"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz",
+ "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz",
+ "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.10",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.10.tgz",
+ "integrity": "sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.8",
+ "@babel/helper-globals": "^7.29.7",
+ "@babel/parser": "^7.29.9",
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.8",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.11",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.11.tgz",
+ "integrity": "sha512-WCsemW40Cpc6gouC1SrY6PBaZ+oLRlEVY9XBvZBI7il/HyUrb2nJ505wE1MHEFyDZNnrWDEuy4jL50WVHfTTSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.11",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
+ "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@napi-rs/lzma-linux-x64-gnu": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz",
+ "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^22.20 || ^24.12 || >=25"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
+ "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.65.0.tgz",
+ "integrity": "sha512-t2AnVba25baFdq7gczzS13JyVcdubLVbFX1X04mxrggDrTQPUXNv3XM0k9H1hr5tqvg7AVvtQ720QHAj0iYqhg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.65.0.tgz",
+ "integrity": "sha512-dNONUaEwPGhl/nuO2KV8VABWlcjYyU6KtZGN8dQv5OS5JU7JSCxPijVNKXbRJd0iuTzTiJ4TjPt/4bbvDRNiMQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.65.0.tgz",
+ "integrity": "sha512-zWQqUH+9zavr2Bxuzfpuv2SIF3X31cr58TvSQC9o1GhpOvkqRwr60GkZdQcudyT/BEgdpdSafjgd2I13MbTL7g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.65.0.tgz",
+ "integrity": "sha512-RQYreBFWtO4//hIuOaZkYUnF/lPU4lz35dveDimDshWCJvVisVtJ/shmT9bkXK8wFJY+FJF89X6F3Cq1qI3LCw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.65.0.tgz",
+ "integrity": "sha512-A0NfMj6Cuh/9BE5k3awJKv6HoxFVXIcLAb6SZqAMoxUHPA1ZNNK4RsGuUPD/vL7nEAm9LG+ZzXWWTrnC0XtkpA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.65.0.tgz",
+ "integrity": "sha512-BI6/H7q3aP0I7S7GOrjyxTjgEJlSnovXE38+bdxBpuKN6z+d//uF+T+VQ3Q7ltJL/71p17ufartARX9Ja5gOGQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.65.0.tgz",
+ "integrity": "sha512-W1vUprf09RWaVWnsFP1vlUkEWJzTZlpObOEAYZXt9Fq0UVAOYEkeGr7wBX7McKqqIQskXdBnpiOMgwPujordgA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.65.0.tgz",
+ "integrity": "sha512-s8QTcZWgrl9haFzEGIqyE5BWyo89pFDGLMBFZ752WYxk8DJwNU/O1X6pZgPw829d9/sm6CCHyrMP3aurt76p1Q==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.65.0.tgz",
+ "integrity": "sha512-ke1f6dLRzkqveyjjF2fkEwQYZvxHtNNwjegY8nJrwcO0Bdqr8CzFO/pKE0Bns13cx0qz2Ba2Y0Hs3dSwMdnHxA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.65.0.tgz",
+ "integrity": "sha512-926SMeUcy4y18Rz/w2aJiUKOnyAnm6czg72bXkQEaeemsll+Wr0hnsjb2BGRpHvWgwAMYy5ACJCotbvfLCfj0A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.65.0.tgz",
+ "integrity": "sha512-6T7JNRP1hc4hqF2dUsEoVLOt9K8tmODoCLldtQRYnrddGGQY8Gqe2pM/qMMUo7EMowpP7oa2N95k0/8sYK/ipw==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.65.0.tgz",
+ "integrity": "sha512-SImGFl1Je5kpyAgOCPONVT7h6ASV8mAUwGRjY7eZvVjPg//PfHOXgI+P241RF/+HqsA4PP3qD527ysWFKNQyhQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.65.0.tgz",
+ "integrity": "sha512-XeDTbmPF1Yu5asfXGPrMkWoxTDhgryQbmw5Q1+R582O51VNCk23J6f2pDrsAp5YkneBVBwtExx6ZGOb9D2aQ6A==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.65.0.tgz",
+ "integrity": "sha512-VS55JUI/1nsljmV/jfqNkLZXFw8uMO8nNlfoHmSevNf6fO3neuhyDvx9dv3c/Ytt8r/431SL8Qax1dpYvOMZTg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.65.0.tgz",
+ "integrity": "sha512-Vblw84TbX7RS4la1Y4+yQ7aore/oSyaNtFbppuBr5Vs/4LfBeXKq9dIfoExw6zOvRERqd2rRAjnZRaMhH/0x5w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.65.0.tgz",
+ "integrity": "sha512-7+gHjtONvKgwR9InTKFaLq53f6YzBJkgeMRBENdWTsQr+spahGqQm8HF5aXpq8i4JaRrOqYyv6Zn1WltDTxaZQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.65.0.tgz",
+ "integrity": "sha512-KvNDC0J6s4vVHhtJ6KrDXU0Er0au/hmRIBq/+1maCV8TseGupeKizq0bWcrbp2HE1T8xoknvN0Q/KZ/YF0qX3w==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.65.0.tgz",
+ "integrity": "sha512-GExdD15WPvu/x/drELjVam7vX8EsPgvTMOa/iJL/p/4m/oOqzbb7JXZg8fXR4hlXtg/sF2zyTZ3bR0AEtEMlhQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.65.0.tgz",
+ "integrity": "sha512-8sT9PemIZfIMED4Vd4KGoOXVDj5CMSWNcGdbheRUx9TYS03yOWdT2Q0lXPyEyNBB9YTilwewIQKNIBk6Nxi0Kg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.65.0.tgz",
+ "integrity": "sha512-pO6Ehi0jo5yE0R6PltKhJhv9mlIiyzBJk5N5NUF2OF6xtVKI+1bdXxj/rb0jGXy3hck1ELVT0QPY3tzkAm360w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.65.0.tgz",
+ "integrity": "sha512-vo7N3/+cjjPDYr8vtxC+qSNgWa9sDvJ7g8N8R5SWqFY4WiNH1ULcAU70SKVyHeiIZOYYwNP9pTipmhN5sl1NPw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.65.0.tgz",
+ "integrity": "sha512-ArwvgFAbjKcDM7qqotZ4OVYf+UMT9xH2YzkCzK4+AuZSDihMlz1Ekoe4INwBVXzn2mnJzuIYOcSx07iTBijGRQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.65.0.tgz",
+ "integrity": "sha512-QGMmK4/cxKE/36FoLMSHQBCyymv/eFTnsCvvsBF0rgmOvVbvX78VWZRerL3dHa77f4pM6Xcc2iGDhJ10w/svKQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.65.0.tgz",
+ "integrity": "sha512-XfKYFWHIPs4HPODIMsGF1IKlS3H1e3WokUZIgpmn4+uNnZBlnRDDHEylNyazbQXwhMKZre68OjtRYbKqb5+j8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.65.0.tgz",
+ "integrity": "sha512-wPWi++K4Bs1VR4XihOhfGi4IGX6Cub7FlerTf8X2v+2BtDHddgSqWCXwGD+h2yAe4/niIhNDwAltioOC+wEogQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@tailwindcss/node": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz",
+ "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.5",
+ "enhanced-resolve": "^5.24.1",
+ "jiti": "^2.7.0",
+ "lightningcss": "1.32.0",
+ "magic-string": "^0.30.21",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.3.3"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz",
+ "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.3.3",
+ "@tailwindcss/oxide-darwin-arm64": "4.3.3",
+ "@tailwindcss/oxide-darwin-x64": "4.3.3",
+ "@tailwindcss/oxide-freebsd-x64": "4.3.3",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.3.3",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.3.3",
+ "@tailwindcss/oxide-linux-x64-musl": "4.3.3",
+ "@tailwindcss/oxide-wasm32-wasi": "4.3.3",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.3.3"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz",
+ "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz",
+ "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz",
+ "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz",
+ "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz",
+ "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz",
+ "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz",
+ "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz",
+ "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz",
+ "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz",
+ "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.11.1",
+ "@emnapi/runtime": "^1.11.1",
+ "@emnapi/wasi-threads": "^1.2.2",
+ "@napi-rs/wasm-runtime": "^1.1.4",
+ "@tybys/wasm-util": "^0.10.2",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz",
+ "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz",
+ "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/vite": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz",
+ "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@tailwindcss/node": "4.3.3",
+ "@tailwindcss/oxide": "4.3.3",
+ "tailwindcss": "4.3.3"
+ },
+ "peerDependencies": {
+ "vite": "^5.2.0 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.20.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.5.tgz",
+ "integrity": "sha512-U2+DNr+wSjpsTS/wZGYHq7GcwfuSmKiKvoPvK22zwTlRhU91yOniN4qRR5KhIjvif7ysw/dz/hKmfDH0Ris4aA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.3.0",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz",
+ "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.3.0",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz",
+ "integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.3.0"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
+ "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.29.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-rc.3",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.18.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.11.32",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.32.tgz",
+ "integrity": "sha512-UvuxFU9P3hM29LrQdwu0cD6w6/+SFr+UlB9s/knI7+O2rK9xFxKUwSDWxGdbbqQ9/V7BJ5s0NI5nQAE4uJp3gQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.29.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.4.tgz",
+ "integrity": "sha512-2TcbbiwXEq+N0kD36tykpCfyyQigUXmuwNQbnPp4Xk4PX9JOqVIKjJlIDjpH7uY6tmRGoAd+apeT1p60T8wsdA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.11.29",
+ "caniuse-lite": "^1.0.30001816",
+ "electron-to-chromium": "^1.5.459",
+ "node-releases": "^2.0.59",
+ "update-browserslist-db": "^1.3.4"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001819",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001819.tgz",
+ "integrity": "sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/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/electron-to-chromium": {
+ "version": "1.5.464",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.464.tgz",
+ "integrity": "sha512-nRa65aFge40viPAKxMKULIY8tcXKwKboJWNn4RoKwyWXJ6SP7BnrDGKUTzc64818jIciH0PK7LSF8QzZes19GA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.26.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.26.0.tgz",
+ "integrity": "sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/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/framer-motion": {
+ "version": "12.43.0",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.43.0.tgz",
+ "integrity": "sha512-1eaL3RvR/kAlbG7UYcpMptEyzPoENO0c6w7ZnB3/hh2vSAz/6uGAFn6fdoqTBguNstf3MsFhJHsD/0DHiclG+g==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-dom": "^12.43.0",
+ "motion-utils": "^12.39.0",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/jiti": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
+ "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/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/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.546.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.546.0.tgz",
+ "integrity": "sha512-Z94u6fKT43lKeYHiVyvyR8fT7pwCzDu7RyMPpTvh054+xahSgj4HFQ+NmflvzdXsoAjYGdCguGaFKYuvq0ThCQ==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/motion": {
+ "version": "12.43.0",
+ "resolved": "https://registry.npmjs.org/motion/-/motion-12.43.0.tgz",
+ "integrity": "sha512-BQgQbSa9Hn3/mtbib0MK53y6JSANa+YKUKlaYnWzAVDH424RYQ5LVpV3pNiWH00BA2z4ojsSdMzqT7g2FQwjuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "framer-motion": "^12.43.0",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/motion-dom": {
+ "version": "12.43.0",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.43.0.tgz",
+ "integrity": "sha512-azKON4d9S65PEoFUiQTMTgPheEmzf2QngdRc50AKfJp9Q9mmcBVw22c8eMq9k8kxOFHdL7+WZY7N/5F/lwiDag==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-utils": "^12.39.0"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.39.0",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz",
+ "integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==",
+ "license": "MIT"
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.20",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz",
+ "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.60",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.60.tgz",
+ "integrity": "sha512-OmO8+GM1JUZqXET720VrJCwkjUCXmCMQm0Z3UDDRbfNLHS4NEAvY60j5jiFv0tkKw2PNNlqOLhahVmwJIOLDIQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "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.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz",
+ "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==",
+ "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.20",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.3.1.tgz",
+ "integrity": "sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.1.tgz",
+ "integrity": "sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.28.0"
+ },
+ "peerDependencies": {
+ "react": "^19.3.1"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
+ "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.65.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.65.0.tgz",
+ "integrity": "sha512-QVCvQUTGDN6JRwi3jVGCY3H4aTHvi9rX0LyoBMkGUvdh/Z6O51CzcLz85BWZaTCDGhl6ySGqYZs+xI1jmPqGcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.9"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@napi-rs/lzma-linux-x64-gnu": "1.5.1",
+ "@rollup/rollup-android-arm-eabi": "4.65.0",
+ "@rollup/rollup-android-arm64": "4.65.0",
+ "@rollup/rollup-darwin-arm64": "4.65.0",
+ "@rollup/rollup-darwin-x64": "4.65.0",
+ "@rollup/rollup-freebsd-arm64": "4.65.0",
+ "@rollup/rollup-freebsd-x64": "4.65.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.65.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.65.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.65.0",
+ "@rollup/rollup-linux-arm64-musl": "4.65.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.65.0",
+ "@rollup/rollup-linux-loong64-musl": "4.65.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.65.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.65.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.65.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.65.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.65.0",
+ "@rollup/rollup-linux-x64-gnu": "4.65.0",
+ "@rollup/rollup-linux-x64-musl": "4.65.0",
+ "@rollup/rollup-openbsd-x64": "4.65.0",
+ "@rollup/rollup-openharmony-arm64": "4.65.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.65.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.65.0",
+ "@rollup/rollup-win32-x64-gnu": "4.65.0",
+ "@rollup/rollup-win32-x64-msvc": "4.65.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz",
+ "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
+ "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz",
+ "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tapable": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+ "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "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==",
+ "license": "0BSD"
+ },
+ "node_modules/typescript": {
+ "version": "5.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz",
+ "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "6.4.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.5.tgz",
+ "integrity": "sha512-4enwjFfi4IwtEh0w+jPzpLVOFQiPHmmzPxcHXQOyEur47o6u0jE573DmGpjA+7irXoMLYRZD5ZaFUEneS3abPg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2",
+ "postcss": "^8.5.3",
+ "rollup": "^4.34.9",
+ "tinyglobby": "^0.2.13"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..a5fb702
--- /dev/null
+++ b/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "gothwadtech-website",
+ "private": true,
+ "version": "1.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite --port=3000 --host=0.0.0.0",
+ "build": "vite build",
+ "preview": "vite preview --host 0.0.0.0 --port 3000",
+ "typecheck": "tsc --noEmit",
+ "lint": "eslint .",
+ "verify": "npm run typecheck && npm run build"
+ },
+ "dependencies": {
+ "lucide-react": "^0.546.0",
+ "motion": "^12.23.24",
+ "react": "^19.0.1",
+ "react-dom": "^19.0.1"
+ },
+ "devDependencies": {
+ "@tailwindcss/vite": "^4.1.14",
+ "@types/node": "^22.14.0",
+ "@types/react": "^19.0.0",
+ "@types/react-dom": "^19.0.0",
+ "@vitejs/plugin-react": "^5.0.4",
+ "tailwindcss": "^4.1.14",
+ "typescript": "~5.8.2",
+ "vite": "^6.2.3"
+ }
+}
diff --git a/public/.well-known/robots.txt b/public/.well-known/robots.txt
new file mode 100644
index 0000000..e659d57
--- /dev/null
+++ b/public/.well-known/robots.txt
@@ -0,0 +1,35 @@
+# Gothwad Tech — https://gothwadtech.com
+# Primary domain is gothwadtech.com (non-www). www → apex 301.
+
+User-agent: *
+Allow: /
+# Allow all important SEO assets explicitly (prevents accidental noindex on icons/manifest)
+Allow: /favicon.ico
+Allow: /favicon-*.png
+Allow: /apple-touch-icon.png
+Allow: /icon-*.png
+Allow: /logo.svg
+Allow: /manifest.json
+Allow: /assets/
+Allow: /sitemap.xml
+# Block private/internal areas
+Disallow: /api/
+Disallow: /admin/
+Disallow: /*?*utm_*
+Disallow: /*?*fbclid*
+Disallow: /*?*gclid*
+
+# Crawlers: obey crawl-friendly sitemap
+Sitemap: https://gothwadtech.com/sitemap.xml
+
+# Host directive (legacy Bing support — canonical is via link rel=canonical + 301 in _redirects)
+Host: https://gothwadtech.com
+
+User-agent: GPTBot
+Allow: /
+User-agent: Claude-Web
+Allow: /
+User-agent: PerplexityBot
+Allow: /
+User-agent: Google-Extended
+Allow: /
diff --git a/public/.well-known/security.txt b/public/.well-known/security.txt
new file mode 100644
index 0000000..ccada0a
--- /dev/null
+++ b/public/.well-known/security.txt
@@ -0,0 +1,5 @@
+Contact: mailto:security@gothwadtech.com
+Contact: mailto:contact@gothwadtech.com
+Expires: 2027-10-24T00:00:00+05:30
+Preferred-Languages: en, hi
+Canonical: https://gothwadtech.com/.well-known/security.txt
diff --git a/public/_headers b/public/_headers
new file mode 100644
index 0000000..21207d8
--- /dev/null
+++ b/public/_headers
@@ -0,0 +1,88 @@
+/*
+ # Security & SEO headers for gothwadtech.com (apex canonical)
+ X-Robots-Tag: all
+ X-Content-Type-Options: nosniff
+ X-Frame-Options: DENY
+ Referrer-Policy: strict-origin-when-cross-origin
+ Permissions-Policy: camera=(), microphone=(), geolocation=(), interest-cohort=(), payment=()
+ Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
+ Cross-Origin-Opener-Policy: same-origin
+ Cross-Origin-Resource-Policy: same-origin
+ Link: ; rel="canonical"
+ Cache-Control: no-cache
+
+/assets/brand/*
+ Cache-Control: public, max-age=31536000, immutable
+ Content-Type: image/png
+
+/assets/icons/*
+ Cache-Control: public, max-age=31536000, immutable
+ Content-Type: image/png
+
+/assets/*
+ Cache-Control: public, max-age=31536000, immutable
+
+/favicon.ico
+ Cache-Control: public, max-age=86400
+ Content-Type: image/x-icon
+
+/favicon-*.png
+ Cache-Control: public, max-age=86400
+ Content-Type: image/png
+
+/icon-*.png
+ Cache-Control: public, max-age=86400
+ Content-Type: image/png
+
+/apple-touch-icon*
+ Cache-Control: public, max-age=86400
+ Content-Type: image/png
+
+/logo.svg
+ Cache-Control: public, max-age=31536000, immutable
+ Content-Type: image/svg+xml
+
+/manifest.json
+ Cache-Control: public, max-age=3600
+ Content-Type: application/manifest+json
+
+/sitemap.xml
+ Cache-Control: public, max-age=3600
+ Content-Type: application/xml
+ X-Robots-Tag: all
+
+/robots.txt
+ Cache-Control: public, max-age=3600
+ Content-Type: text/plain
+
+/opensearch.xml
+ Cache-Control: public, max-age=86400
+ Content-Type: application/opensearchdescription+xml
+
+/llms.txt
+ Cache-Control: public, max-age=3600
+ Content-Type: text/plain
+
+/humans.txt
+ Cache-Control: public, max-age=86400
+ Content-Type: text/plain
+
+/browserconfig.xml
+ Cache-Control: public, max-age=86400
+ Content-Type: application/xml
+
+/security.txt
+ Cache-Control: public, max-age=86400
+ Content-Type: text/plain
+
+/.well-known/*
+ Cache-Control: public, max-age=86400
+
+/*.js
+ Cache-Control: public, max-age=31536000, immutable
+
+/*.css
+ Cache-Control: public, max-age=31536000, immutable
+
+/*.html
+ Cache-Control: no-cache
diff --git a/public/_redirects b/public/_redirects
new file mode 100644
index 0000000..b5e25e1
--- /dev/null
+++ b/public/_redirects
@@ -0,0 +1,29 @@
+# ============================================================
+# Gothwad Tech — Cloudflare Pages redirects & SEO canonical
+# Primary domain is https://gothwadtech.com (non-www).
+# We 301 redirect www → apex for canonical consistency (fixes Google
+# showing www.gothwadtech.com instead of gothwadtech.com).
+# Order matters: specific redirects first, SPA fallback last.
+# ============================================================
+
+# 1) Enforce HTTPS + non-www canonical (SEO: stops www duplicate index)
+https://www.gothwadtech.com/* https://gothwadtech.com/:splat 301!
+http://www.gothwadtech.com/* https://gothwadtech.com/:splat 301!
+http://gothwadtech.com/* https://gothwadtech.com/:splat 301!
+
+# 2) Legacy path aliases (keep old links alive, pass link equity)
+# These used to be hash links — now they are real paths.
+/about /company 301!
+/portfolio /ecosystem 301!
+/browser /products 301!
+/leadership /company 301!
+/legacy /ecosystem 301!
+
+# 3) www subdomain direct (fallback if protocol not matched above)
+www.gothwadtech.com/* https://gothwadtech.com/:splat 301!
+
+# 4) SPA fallback — every unmatched path serves index.html so deep links
+# and hard-refresh on /ecosystem, /products etc. never 404.
+# Cloudflare Pages serves real assets first, so /favicon.ico,
+# /assets/*, /manifest.json etc. bypass this rule.
+/* /index.html 200
diff --git a/public/apple-touch-icon-180x180.png b/public/apple-touch-icon-180x180.png
new file mode 100644
index 0000000..f53aefb
Binary files /dev/null and b/public/apple-touch-icon-180x180.png differ
diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
new file mode 100644
index 0000000..f53aefb
Binary files /dev/null and b/public/apple-touch-icon.png differ
diff --git a/public/assets/README.txt b/public/assets/README.txt
new file mode 100644
index 0000000..3bdd02f
--- /dev/null
+++ b/public/assets/README.txt
@@ -0,0 +1,18 @@
+Add this to your HTML :
+
+
+
+
+Add this to your app's manifest.json:
+
+ ...
+ {
+ "icons": [
+ { "src": "/favicon.ico", "type": "image/x-icon", "sizes": "16x16 32x32" },
+ { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
+ { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" },
+ { "src": "/icon-192-maskable.png", "type": "image/png", "sizes": "192x192", "purpose": "maskable" },
+ { "src": "/icon-512-maskable.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" }
+ ]
+ }
+ ...
diff --git a/public/assets/apple-touch-icon.png b/public/assets/apple-touch-icon.png
new file mode 100644
index 0000000..b369885
Binary files /dev/null and b/public/assets/apple-touch-icon.png differ
diff --git a/public/assets/brand/logo.png b/public/assets/brand/logo.png
new file mode 100644
index 0000000..6b16e59
Binary files /dev/null and b/public/assets/brand/logo.png differ
diff --git a/public/assets/brand/og-image.png b/public/assets/brand/og-image.png
new file mode 100644
index 0000000..6b16e59
Binary files /dev/null and b/public/assets/brand/og-image.png differ
diff --git a/public/assets/favicon.ico b/public/assets/favicon.ico
new file mode 100644
index 0000000..8f685be
Binary files /dev/null and b/public/assets/favicon.ico differ
diff --git a/public/assets/icon-192-maskable.png b/public/assets/icon-192-maskable.png
new file mode 100644
index 0000000..2c715f7
Binary files /dev/null and b/public/assets/icon-192-maskable.png differ
diff --git a/public/assets/icon-192.png b/public/assets/icon-192.png
new file mode 100644
index 0000000..b07496d
Binary files /dev/null and b/public/assets/icon-192.png differ
diff --git a/public/assets/icon-512-maskable.png b/public/assets/icon-512-maskable.png
new file mode 100644
index 0000000..329e1a1
Binary files /dev/null and b/public/assets/icon-512-maskable.png differ
diff --git a/public/assets/icon-512.png b/public/assets/icon-512.png
new file mode 100644
index 0000000..271e7b0
Binary files /dev/null and b/public/assets/icon-512.png differ
diff --git a/public/assets/icons/icon-144-maskable.png b/public/assets/icons/icon-144-maskable.png
new file mode 100644
index 0000000..e2cfd49
Binary files /dev/null and b/public/assets/icons/icon-144-maskable.png differ
diff --git a/public/assets/icons/icon-144.png b/public/assets/icons/icon-144.png
new file mode 100644
index 0000000..e2cfd49
Binary files /dev/null and b/public/assets/icons/icon-144.png differ
diff --git a/public/assets/icons/icon-192-maskable.png b/public/assets/icons/icon-192-maskable.png
new file mode 100644
index 0000000..03ef7f2
Binary files /dev/null and b/public/assets/icons/icon-192-maskable.png differ
diff --git a/public/assets/icons/icon-192.png b/public/assets/icons/icon-192.png
new file mode 100644
index 0000000..03ef7f2
Binary files /dev/null and b/public/assets/icons/icon-192.png differ
diff --git a/public/assets/icons/icon-384-maskable.png b/public/assets/icons/icon-384-maskable.png
new file mode 100644
index 0000000..4478072
Binary files /dev/null and b/public/assets/icons/icon-384-maskable.png differ
diff --git a/public/assets/icons/icon-384.png b/public/assets/icons/icon-384.png
new file mode 100644
index 0000000..4478072
Binary files /dev/null and b/public/assets/icons/icon-384.png differ
diff --git a/public/assets/icons/icon-48-maskable.png b/public/assets/icons/icon-48-maskable.png
new file mode 100644
index 0000000..72c3f58
Binary files /dev/null and b/public/assets/icons/icon-48-maskable.png differ
diff --git a/public/assets/icons/icon-48.png b/public/assets/icons/icon-48.png
new file mode 100644
index 0000000..72c3f58
Binary files /dev/null and b/public/assets/icons/icon-48.png differ
diff --git a/public/assets/icons/icon-512-maskable.png b/public/assets/icons/icon-512-maskable.png
new file mode 100644
index 0000000..02f3265
Binary files /dev/null and b/public/assets/icons/icon-512-maskable.png differ
diff --git a/public/assets/icons/icon-512.png b/public/assets/icons/icon-512.png
new file mode 100644
index 0000000..02f3265
Binary files /dev/null and b/public/assets/icons/icon-512.png differ
diff --git a/public/assets/icons/icon-72-maskable.png b/public/assets/icons/icon-72-maskable.png
new file mode 100644
index 0000000..6877e90
Binary files /dev/null and b/public/assets/icons/icon-72-maskable.png differ
diff --git a/public/assets/icons/icon-72.png b/public/assets/icons/icon-72.png
new file mode 100644
index 0000000..6877e90
Binary files /dev/null and b/public/assets/icons/icon-72.png differ
diff --git a/public/assets/icons/icon-96-maskable.png b/public/assets/icons/icon-96-maskable.png
new file mode 100644
index 0000000..f9e2535
Binary files /dev/null and b/public/assets/icons/icon-96-maskable.png differ
diff --git a/public/assets/icons/icon-96.png b/public/assets/icons/icon-96.png
new file mode 100644
index 0000000..f9e2535
Binary files /dev/null and b/public/assets/icons/icon-96.png differ
diff --git a/public/assets/logo.png b/public/assets/logo.png
new file mode 100644
index 0000000..6b16e59
Binary files /dev/null and b/public/assets/logo.png differ
diff --git a/public/browserconfig.xml b/public/browserconfig.xml
new file mode 100644
index 0000000..813fbc8
--- /dev/null
+++ b/public/browserconfig.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ #0494f4
+
+
+
+ 30
+ 1
+
+
+
diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png
new file mode 100644
index 0000000..f3850c5
Binary files /dev/null and b/public/favicon-16x16.png differ
diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png
new file mode 100644
index 0000000..ba96b0b
Binary files /dev/null and b/public/favicon-32x32.png differ
diff --git a/public/favicon-48x48.png b/public/favicon-48x48.png
new file mode 100644
index 0000000..72c3f58
Binary files /dev/null and b/public/favicon-48x48.png differ
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..5f112cc
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/humans.txt b/public/humans.txt
new file mode 100644
index 0000000..ddad460
--- /dev/null
+++ b/public/humans.txt
@@ -0,0 +1,28 @@
+/* the humans behind Gothwad Tech */
+Site: https://gothwadtech.com — Official website of Gothwad Tech
+Location: Jaipur, Rajasthan, India
+
+/* team */
+Founder & Product Architect: Pawan Gothwad — pawan@gothwadtech.com — https://github.com/GothwadTech
+CEO: Yuvkesh Meena — ceo.gothwadtech.com — Dausa, Rajasthan, India
+Co-Founder & CTO: Vishnu Meena — vishnu@gothwadtech.com
+CEO: Nishant — nishant@gothwadtech.com
+
+/* contact */
+Contact: contact@gothwadtech.com
+Support: support@gothwadtech.com
+Help: help@gothwadtech.com
+Phone: +91 73399 04665
+WhatsApp: https://wa.me/917339904665
+
+/* technology */
+Stack: Vite, React 19, TypeScript, Tailwind CSS, Cloudflare Pages
+Design: Gothwad Design System — #0494f4 brand, zinc, light/dark
+
+/* thanks */
+Thanks to Aatmanirbhar Bharat — sovereign tech for India.
+
+/* site */
+Docs: https://docs.gothwadtech.com
+GitHub: https://github.com/GothwadTech
+CEO: https://ceo.gothwadtech.com
diff --git a/public/icon-192x192.png b/public/icon-192x192.png
new file mode 100644
index 0000000..03ef7f2
Binary files /dev/null and b/public/icon-192x192.png differ
diff --git a/public/icon-512x512.png b/public/icon-512x512.png
new file mode 100644
index 0000000..02f3265
Binary files /dev/null and b/public/icon-512x512.png differ
diff --git a/public/llms.txt b/public/llms.txt
new file mode 100644
index 0000000..ed43637
--- /dev/null
+++ b/public/llms.txt
@@ -0,0 +1,61 @@
+# Gothwad Tech — llms.txt
+# https://gothwadtech.com/llms.txt
+# Machine-readable overview for LLM & AI crawlers.
+
+> Gothwad Tech is India's sovereign software collective from Jaipur, Rajasthan (founded 2023, founder Pawan Gothwad, CEO Yuvkesh Meena).
+> One Gothwad Account powers a unified ecosystem: Mail, Drive, Meet, Store, Tube, GrixChat, Indogram, Browser, Education, AI Studio, Remote Desktop, Docs and more.
+> All products are documented and mostly open-source at https://github.com/GothwadTech.
+
+## Official domains (canonical is https://gothwadtech.com — non-www)
+- Main: https://gothwadtech.com
+- Accounts (auth): https://accounts.gothwadtech.com
+- Mail: https://mail.gothwadtech.com
+- Drive: https://drive.gothwadtech.com
+- Meet: https://meet.gothwadtech.com
+- Calendar: https://calender.gothwadtech.com (note spelling in DNS)
+- Contacts: https://contacts.gothwadtech.com
+- Notes: https://notes.gothwadtech.com
+- Store: https://store.gothwadtech.com
+- Tube: https://tube.gothwadtech.com
+- GrixChat: https://grixchat.gothwadtech.com
+- Indogram: https://indogram.gothwadtech.com
+- Browser: https://browser.gothwadtech.com
+- Education: https://education.gothwadtech.com
+- AI Studio: https://ai.gothwadtech.com
+- Remote Desktop: https://remotedesk.gothwadtech.com
+- Docs: https://docs.gothwadtech.com
+- CEO: https://ceo.gothwadtech.com
+
+## Site sections
+- / : Home — hero, quick-access tiles, search + filter shortcuts
+- /ecosystem : Directory of all 25+ products with direct subdomain links + GitHub source
+- /products : Sovereign flagships (Browser 11.8MB, GrixChat <15ms, Indogram 200k members)
+- /solutions : School ERP, restaurant POS, kirana billing/Khata, enterprise ERP, sovereign engines
+- /docs : Developer docs index (Accounts OAuth PKCE, Mail setup & REST, Tube, Meet, etc.)
+- /company : About, mission Aatmanirbhar Bharat, leadership
+- /contact : Business, support, help, info inboxes + founder contacts + WhatsApp
+
+## Structured data
+- Organization JSON-LD at https://gothwadtech.com/#organization
+- WebSite with SearchAction (query: /ecosystem?q={search_term_string})
+- BreadcrumbList per route
+- ItemList for ecosystem products
+
+## Docs & source
+- Docs site: https://docs.gothwadtech.com
+- Docs repo: https://github.com/GothwadTech/docs (source-cited, SOURCES.md)
+- Main org: https://github.com/GothwadTech
+- This website repo: https://github.com/GothwadTech/website
+
+## Brand & contact
+- Logo: https://gothwadtech.com/assets/brand/logo.png
+- OG image: https://gothwadtech.com/assets/brand/og-image.png
+- Contact: contact@gothwadtech.com, pawan@gothwadtech.com, +91 73399 04665
+- Address: Jaipur, Rajasthan, India
+
+## Markdown for AI
+See also:
+- https://gothwadtech.com/sitemap.xml
+- https://gothwadtech.com/robots.txt
+- https://gothwadtech.com/humans.txt
+- https://gothwadtech.com/manifest.json
diff --git a/public/logo.svg b/public/logo.svg
new file mode 100644
index 0000000..000bc7f
--- /dev/null
+++ b/public/logo.svg
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/manifest.json b/public/manifest.json
new file mode 100644
index 0000000..b4fc48b
--- /dev/null
+++ b/public/manifest.json
@@ -0,0 +1,48 @@
+{
+ "id": "https://gothwadtech.com/",
+ "name": "Gothwad Tech — Official Website",
+ "short_name": "Gothwad Tech",
+ "description": "Official portal of Gothwad Tech — one account for Mail, Drive, Meet, Store, Tube, GrixChat, Indogram, Browser, Education, AI and Docs. Sovereign tech from India.",
+ "start_url": "/",
+ "scope": "/",
+ "display": "standalone",
+ "display_override": ["window-controls-overlay", "standalone", "browser"],
+ "orientation": "any",
+ "background_color": "#ffffff",
+ "theme_color": "#0494f4",
+ "lang": "en-IN",
+ "dir": "ltr",
+ "categories": ["business", "productivity", "utilities", "developer-tools", "education", "social"],
+ "handle_links": "preferred",
+ "launch_handler": { "client_mode": ["auto", "navigate-new", "focus-existing"] },
+ "icons": [
+ { "src": "/favicon.ico", "type": "image/x-icon", "sizes": "16x16 32x32 48x48" },
+ { "src": "/favicon-16x16.png", "type": "image/png", "sizes": "16x16" },
+ { "src": "/favicon-32x32.png", "type": "image/png", "sizes": "32x32" },
+ { "src": "/favicon-48x48.png", "type": "image/png", "sizes": "48x48" },
+ { "src": "/assets/icons/icon-48.png", "type": "image/png", "sizes": "48x48" },
+ { "src": "/assets/icons/icon-72.png", "type": "image/png", "sizes": "72x72" },
+ { "src": "/assets/icons/icon-96.png", "type": "image/png", "sizes": "96x96" },
+ { "src": "/assets/icons/icon-144.png", "type": "image/png", "sizes": "144x144" },
+ { "src": "/assets/icons/icon-192.png", "type": "image/png", "sizes": "192x192", "purpose": "any" },
+ { "src": "/assets/icons/icon-384.png", "type": "image/png", "sizes": "384x384", "purpose": "any" },
+ { "src": "/assets/icons/icon-512.png", "type": "image/png", "sizes": "512x512", "purpose": "any" },
+ { "src": "/assets/icons/icon-192-maskable.png", "type": "image/png", "sizes": "192x192", "purpose": "maskable" },
+ { "src": "/assets/icons/icon-512-maskable.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" },
+ { "src": "/apple-touch-icon.png", "type": "image/png", "sizes": "180x180" }
+ ],
+ "screenshots": [
+ { "src": "/assets/brand/og-image.png", "type": "image/png", "sizes": "512x512", "form_factor": "wide", "label": "Gothwad Tech — everything Gothwad, in one place" }
+ ],
+ "shortcuts": [
+ { "name": "Ecosystem — All Products", "short_name": "Ecosystem", "description": "Browse all Gothwad products with direct links", "url": "/ecosystem", "icons": [{ "src": "/assets/icons/icon-192.png", "sizes": "192x192" }] },
+ { "name": "Gothwad Mail", "short_name": "Mail", "description": "Open your Gothwad inbox", "url": "https://mail.gothwadtech.com", "icons": [{ "src": "/assets/icons/icon-192.png", "sizes": "192x192" }] },
+ { "name": "Gothwad Docs", "short_name": "Docs", "description": "Developer documentation", "url": "https://docs.gothwadtech.com", "icons": [{ "src": "/assets/icons/icon-192.png", "sizes": "192x192" }] },
+ { "name": "Gothwad Tube", "short_name": "Tube", "description": "A better way to watch", "url": "https://tube.gothwadtech.com", "icons": [{ "src": "/assets/icons/icon-192.png", "sizes": "192x192" }] }
+ ],
+ "related_applications": [],
+ "prefer_related_applications": false,
+ "edge_side_panel": { "preferred_width": 400 },
+ "file_handlers": [],
+ "protocol_handlers": []
+}
diff --git a/public/opensearch.xml b/public/opensearch.xml
new file mode 100644
index 0000000..3ada913
--- /dev/null
+++ b/public/opensearch.xml
@@ -0,0 +1,13 @@
+
+
+ Gothwad Tech
+ Search all Gothwad products — Mail, Drive, Meet, Tube, Browser, GrixChat and more.
+ UTF-8
+ https://gothwadtech.com/favicon.ico
+
+
+ Gothwad Tech Private Limited
+ © 2026 Gothwad Tech — gothwadtech.com
+ en-IN
+
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..e659d57
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,35 @@
+# Gothwad Tech — https://gothwadtech.com
+# Primary domain is gothwadtech.com (non-www). www → apex 301.
+
+User-agent: *
+Allow: /
+# Allow all important SEO assets explicitly (prevents accidental noindex on icons/manifest)
+Allow: /favicon.ico
+Allow: /favicon-*.png
+Allow: /apple-touch-icon.png
+Allow: /icon-*.png
+Allow: /logo.svg
+Allow: /manifest.json
+Allow: /assets/
+Allow: /sitemap.xml
+# Block private/internal areas
+Disallow: /api/
+Disallow: /admin/
+Disallow: /*?*utm_*
+Disallow: /*?*fbclid*
+Disallow: /*?*gclid*
+
+# Crawlers: obey crawl-friendly sitemap
+Sitemap: https://gothwadtech.com/sitemap.xml
+
+# Host directive (legacy Bing support — canonical is via link rel=canonical + 301 in _redirects)
+Host: https://gothwadtech.com
+
+User-agent: GPTBot
+Allow: /
+User-agent: Claude-Web
+Allow: /
+User-agent: PerplexityBot
+Allow: /
+User-agent: Google-Extended
+Allow: /
diff --git a/public/security.txt b/public/security.txt
new file mode 100644
index 0000000..ccada0a
--- /dev/null
+++ b/public/security.txt
@@ -0,0 +1,5 @@
+Contact: mailto:security@gothwadtech.com
+Contact: mailto:contact@gothwadtech.com
+Expires: 2027-10-24T00:00:00+05:30
+Preferred-Languages: en, hi
+Canonical: https://gothwadtech.com/.well-known/security.txt
diff --git a/public/sitemap.xml b/public/sitemap.xml
new file mode 100644
index 0000000..01e480f
--- /dev/null
+++ b/public/sitemap.xml
@@ -0,0 +1,80 @@
+
+
+
+
+ https://gothwadtech.com/
+ 2026-10-24
+ daily
+ 1.0
+
+ https://gothwadtech.com/assets/brand/logo.png
+ Gothwad Tech — sovereign software collective logo
+ Gothwad Tech
+
+
+ https://gothwadtech.com/assets/brand/og-image.png
+ Gothwad Tech — everything Gothwad, in one place
+ Gothwad Tech official website
+
+
+
+
+
+
+
+ https://gothwadtech.com/ecosystem
+ 2026-10-24
+ daily
+ 0.95
+
+ https://gothwadtech.com/assets/brand/og-image.png
+ Gothwad Ecosystem — all products
+
+
+
+
+
+
+ https://gothwadtech.com/products
+ 2026-10-24
+ weekly
+ 0.90
+
+ https://gothwadtech.com/assets/brand/logo.png
+ Gothwad Browser, GrixChat, Indogram — sovereign apps
+
+
+
+
+ https://gothwadtech.com/solutions
+ 2026-10-24
+ weekly
+ 0.85
+
+
+
+ https://gothwadtech.com/docs
+ 2026-10-24
+ weekly
+ 0.90
+
+
+
+ https://gothwadtech.com/company
+ 2026-10-24
+ monthly
+ 0.80
+
+
+
+ https://gothwadtech.com/contact
+ 2026-10-24
+ monthly
+ 0.80
+
+
diff --git a/src/App.tsx b/src/App.tsx
new file mode 100644
index 0000000..fbdbbdd
--- /dev/null
+++ b/src/App.tsx
@@ -0,0 +1,395 @@
+import React, { useEffect, useState, Suspense, lazy } from 'react';
+import { ThemeProvider } from './context/ThemeContext';
+import { Navbar } from './components/Navbar';
+import { Footer } from './components/Footer';
+
+const HomePage = lazy(() => import('./pages/HomePage').then((m) => ({ default: m.HomePage })));
+const EcosystemPage = lazy(() => import('./pages/EcosystemPage').then((m) => ({ default: m.EcosystemPage })));
+const ProductsPage = lazy(() => import('./pages/ProductsPage').then((m) => ({ default: m.ProductsPage })));
+const SolutionsPage = lazy(() => import('./pages/SolutionsPage').then((m) => ({ default: m.SolutionsPage })));
+const DocsPage = lazy(() => import('./pages/DocsPage').then((m) => ({ default: m.DocsPage })));
+const CompanyPage = lazy(() => import('./pages/CompanyPage').then((m) => ({ default: m.CompanyPage })));
+const ContactPage = lazy(() => import('./pages/ContactPage').then((m) => ({ default: m.ContactPage })));
+
+const ROUTES = ['home', 'ecosystem', 'products', 'solutions', 'docs', 'company', 'contact'];
+
+const ROUTE_ALIASES: Record = {
+ '': 'home',
+ '/': 'home',
+ about: 'company',
+ portfolio: 'ecosystem',
+ browser: 'products',
+ leadership: 'company',
+};
+
+import { parseAuthuserFromUrl, stripAuthuserPath, buildAccountSlotPath } from './config/brand';
+
+function pageFromPathname(pathname: string): string {
+ const clean = stripAuthuserPath(pathname);
+ const seg = clean.split('/').filter(Boolean)[0]?.toLowerCase() ?? '';
+ if (!seg) return 'home';
+ const target = ROUTE_ALIASES[seg] ?? seg;
+ return ROUTES.includes(target) ? target : 'home';
+}
+
+function pageFromHash(hash: string): string | null {
+ const raw = hash.replace(/^#/, '').toLowerCase().trim();
+ if (!raw) return null;
+ const target = ROUTE_ALIASES[raw] ?? raw;
+ return ROUTES.includes(target) ? target : null;
+}
+
+const pathForPage = (page: string) => {
+ const base = page === 'home' ? '/' : `/${page}`;
+ // Preserve /u// slot like Gmail so authuser stays in URL (and for SSO header)
+ try {
+ const { authuser, hasExplicitSlot } = parseAuthuserFromUrl(window.location.pathname, window.location.search);
+ if (hasExplicitSlot) return `${buildAccountSlotPath(authuser)}${base === '/' ? '' : base.slice(1)}`.replace(/\/\//g, '/') || '/';
+ } catch {}
+ return base;
+};
+
+type PageMeta = {
+ title: string;
+ description: string;
+ ogType?: string;
+ keywords?: string;
+ breadcrumbs: { name: string; path: string }[];
+ jsonLdExtra?: Record | null;
+};
+
+// Exhaustive per-route meta — 55-60 char titles, 150-160 char descriptions, brand included
+const PAGE_META: Record = {
+ home: {
+ title: 'Gothwad Tech — Official Website | Sovereign Software from India',
+ description:
+ 'Official site of Gothwad Tech — Jaipur-based sovereign collective. One account for Mail, Drive, Meet, Store, Tube, GrixChat, Indogram, Browser, Education, AI & Docs.',
+ keywords:
+ 'Gothwad Tech, gothwadtech.com, gothwadtech official, Pawan Gothwad, sovereign software India, Gothwad Browser, Gothwad Accounts',
+ breadcrumbs: [{ name: 'Home', path: '/' }],
+ },
+ ecosystem: {
+ title: 'Gothwad Ecosystem — All Products & Direct Links | Gothwad Tech',
+ description:
+ 'Browse the full Gothwad ecosystem — Accounts, Mail, Drive, Meet, Tube, Browser, GrixChat, Indogram, Launcher, Education, AI & more with live links.',
+ keywords:
+ 'Gothwad ecosystem, Gothwad products, gothwadtech.com products, Gothwad Mail, Gothwad Drive, Gothwad Tube, GrixChat, Indogram',
+ breadcrumbs: [
+ { name: 'Home', path: '/' },
+ { name: 'Ecosystem', path: '/ecosystem' },
+ ],
+ jsonLdExtra: {
+ '@type': 'CollectionPage',
+ name: 'Gothwad Ecosystem Directory',
+ },
+ },
+ products: {
+ title: 'Products — Browser, GrixChat, Indogram | Gothwad Tech',
+ description:
+ 'Sovereign apps by Gothwad Tech: Browser (11.8 MB, 75% less RAM), GrixChat (<15ms), Indogram (200k members) plus Mail, Drive, Meet & Tube.',
+ keywords:
+ 'Gothwad Browser, GrixChat, Indogram, sovereign browser India, Gothwad products, Aatmanirbhar Bharat apps',
+ breadcrumbs: [
+ { name: 'Home', path: '/' },
+ { name: 'Products', path: '/products' },
+ ],
+ },
+ solutions: {
+ title: 'Solutions — School ERP, Restaurant POS & Enterprise | Gothwad Tech',
+ description:
+ 'Solutions for Bharat: School ERP, Restaurant POS & ordering, Kirana billing & Khata, Business CRM & custom sovereign browser engines.',
+ keywords:
+ 'Gothwad solutions, school ERP India, restaurant POS, shop billing, business ERP, sovereign systems, Gothwad Tech solutions',
+ breadcrumbs: [
+ { name: 'Home', path: '/' },
+ { name: 'Solutions', path: '/solutions' },
+ ],
+ },
+ docs: {
+ title: 'Docs — Developer Documentation | Gothwad Tech',
+ description:
+ 'Gothwad Tech developer docs: Accounts OAuth PKCE, Mail REST, Tube web, GrixChat, Meet, Cloudflare deploy — source-cited guides.',
+ keywords:
+ 'Gothwad docs, Gothwad documentation, docs.gothwadtech.com, Gothwad Accounts OAuth, Gothwad Mail API',
+ breadcrumbs: [
+ { name: 'Home', path: '/' },
+ { name: 'Docs', path: '/docs' },
+ ],
+ },
+ company: {
+ title: 'Company — Leadership & Aatmanirbhar Mission | Gothwad Tech',
+ description:
+ 'About Gothwad Tech: mission to build sovereign tech for India. Leadership by Pawan Gothwad & CEO Yuvkesh Meena from Jaipur, Rajasthan.',
+ keywords:
+ 'Gothwad Tech company, Pawan Gothwad, Yuvkesh Meena, about Gothwad Tech, Aatmanirbhar Bharat, Jaipur tech company',
+ breadcrumbs: [
+ { name: 'Home', path: '/' },
+ { name: 'Company', path: '/company' },
+ ],
+ },
+ contact: {
+ title: 'Contact — Talk to Gothwad Tech | Support & Business',
+ description:
+ 'Contact Gothwad Tech: contact@gothwadtech.com, +91 73399 04665 WhatsApp/Call. Business, support, help & media desks — reply in 2-4 hours.',
+ keywords:
+ 'contact Gothwad Tech, Gothwad Tech phone, Gothwad support, Gothwad help, pawan@gothwadtech.com, contact@gothwadtech.com',
+ breadcrumbs: [
+ { name: 'Home', path: '/' },
+ { name: 'Contact', path: '/contact' },
+ ],
+ },
+};
+
+function setMeta(selector: string, attr: 'content' | 'href', value: string) {
+ let el = document.querySelector(selector) as HTMLElement | null;
+ if (!el) {
+ const isLink = selector.startsWith('link');
+ el = document.createElement(isLink ? 'link' : 'meta');
+ if (isLink) {
+ // infer rel from selector
+ const relMatch = selector.match(/rel="([^"]+)"/);
+ el.setAttribute('rel', relMatch?.[1] ?? 'canonical');
+ } else {
+ const name = selector.includes('property=') ? 'property' : 'name';
+ const m = selector.match(/\[(?:name|property)="([^"]+)"\]/);
+ const raw = m?.[1];
+ if (raw) el.setAttribute(name, raw);
+ }
+ document.head.appendChild(el);
+ }
+ el.setAttribute(attr, value);
+}
+
+function upsertJsonLd(id: string, data: unknown) {
+ let el = document.getElementById(id) as HTMLScriptElement | null;
+ if (!el) {
+ el = document.createElement('script');
+ el.id = id;
+ el.type = 'application/ld+json';
+ document.head.appendChild(el);
+ }
+ el.textContent = JSON.stringify(data);
+}
+
+function removeJsonLd(id: string) {
+ document.getElementById(id)?.remove();
+}
+
+function buildBreadcrumbJsonLd(breadcrumbs: { name: string; path: string }[]) {
+ return {
+ '@context': 'https://schema.org',
+ '@type': 'BreadcrumbList',
+ '@id': 'https://gothwadtech.com/#breadcrumb',
+ itemListElement: breadcrumbs.map((b, i) => ({
+ '@type': 'ListItem',
+ position: i + 1,
+ name: b.name,
+ item: `https://gothwadtech.com${b.path}`,
+ })),
+ };
+}
+
+function buildWebPageJsonLd(page: string, meta: PageMeta, canonical: string) {
+ const base: Record = {
+ '@context': 'https://schema.org',
+ '@type': meta.jsonLdExtra?.['@type'] ?? 'WebPage',
+ '@id': `${canonical}#webpage`,
+ url: canonical,
+ name: meta.title,
+ description: meta.description,
+ isPartOf: { '@id': 'https://gothwadtech.com/#website' },
+ about: { '@id': 'https://gothwadtech.com/#organization' },
+ inLanguage: 'en-IN',
+ datePublished: '2023-01-01T00:00:00+05:30',
+ dateModified: '2026-10-24T00:00:00+05:30',
+ primaryImageOfPage: { '@id': 'https://gothwadtech.com/#logo' },
+ breadcrumb: { '@id': 'https://gothwadtech.com/#breadcrumb' },
+ ...(meta.jsonLdExtra ?? {}),
+ };
+ // attach canonical breadcrumb id
+ return base;
+}
+
+function RouteFallback() {
+ return (
+
+ );
+}
+
+function AppContent() {
+ const [activePage, setActivePage] = useState(() => {
+ if (typeof window !== 'undefined') {
+ const legacy = pageFromHash(window.location.hash);
+ if (legacy) return legacy;
+ return pageFromPathname(window.location.pathname);
+ }
+ return 'home';
+ });
+
+ const handleNavigate = (page: string) => {
+ const norm = ROUTES.includes(page) ? page : 'home';
+ setActivePage(norm);
+ const path = pathForPage(norm);
+ if (window.location.pathname !== path) {
+ window.history.pushState({}, '', path);
+ }
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ };
+
+ useEffect(() => {
+ const legacy = pageFromHash(window.location.hash);
+ if (legacy) {
+ window.history.replaceState({}, '', pathForPage(legacy));
+ setActivePage(legacy);
+ } else {
+ setActivePage(pageFromPathname(window.location.pathname));
+ }
+ const sync = () => setActivePage(pageFromPathname(window.location.pathname));
+ window.addEventListener('popstate', sync);
+ return () => window.removeEventListener('popstate', sync);
+ }, []);
+
+ useEffect(() => {
+ const meta = PAGE_META[activePage] ?? PAGE_META.home;
+ const canonical = `https://gothwadtech.com${pathForPage(activePage)}`;
+ const ogImage = 'https://gothwadtech.com/assets/brand/og-image.png';
+
+ // Core title & description
+ document.title = meta.title;
+ setMeta('meta[name="description"]', 'content', meta.description);
+ if (meta.keywords) setMeta('meta[name="keywords"]', 'content', meta.keywords);
+ setMeta('meta[name="title"]', 'content', meta.title);
+
+ // Canonical + hreflang
+ setMeta('link[rel="canonical"]', 'href', canonical);
+ setMeta('link[rel="alternate"][hreflang="x-default"]', 'href', canonical);
+ setMeta('link[rel="alternate"][hreflang="en-IN"]', 'href', canonical);
+
+ // Open Graph
+ setMeta('meta[property="og:title"]', 'content', meta.title);
+ setMeta('meta[property="og:description"]', 'content', meta.description);
+ setMeta('meta[property="og:url"]', 'content', canonical);
+ setMeta('meta[property="og:image"]', 'content', ogImage);
+ setMeta('meta[property="og:image:secure_url"]', 'content', ogImage);
+ setMeta('meta[property="og:updated_time"]', 'content', new Date().toISOString());
+
+ // Twitter
+ setMeta('meta[name="twitter:title"]', 'content', meta.title);
+ setMeta('meta[name="twitter:description"]', 'content', meta.description);
+ setMeta('meta[name="twitter:url"]', 'content', canonical);
+ setMeta('meta[name="twitter:image"]', 'content', ogImage);
+
+ // Robots hints per route (all indexable; no noindex anywhere)
+ setMeta('meta[name="robots"]', 'content', 'index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1');
+ setMeta('meta[name="googlebot"]', 'content', 'index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1');
+
+ // JSON-LD — WebPage + Breadcrumb for every route
+ upsertJsonLd('ld-webpage-dynamic', buildWebPageJsonLd(activePage, meta, canonical));
+ upsertJsonLd('ld-breadcrumb-dynamic', buildBreadcrumbJsonLd(meta.breadcrumbs));
+
+ // Route-specific extra ItemList for ecosystem/products/docs to boost rich results
+ if (activePage === 'ecosystem') {
+ upsertJsonLd('ld-itemlist-ecosystem', {
+ '@context': 'https://schema.org',
+ '@type': 'ItemList',
+ '@id': `${canonical}#products`,
+ name: 'Gothwad Ecosystem — All Products',
+ description: 'Complete list of Gothwad Tech products: Accounts, Mail, Drive, Meet, Tube, Browser, GrixChat, Indogram, Launcher, Manager, Education, AI and more.',
+ numberOfItems: 25,
+ itemListElement: [
+ 'Accounts',
+ 'Mail',
+ 'Drive',
+ 'Meet',
+ 'Calendar',
+ 'Contacts',
+ 'Notes',
+ 'Store',
+ 'Tube',
+ 'GrixChat',
+ 'Indogram',
+ 'Browser',
+ 'Launcher',
+ 'Manager',
+ 'Remote Desktop',
+ 'Internet',
+ 'Computer',
+ 'Education',
+ 'ClashDrive',
+ 'AI Studio',
+ 'Docs',
+ 'CEO',
+ ].map((name, i) => ({
+ '@type': 'ListItem',
+ position: i + 1,
+ name,
+ url: `https://gothwadtech.com/ecosystem#${name.toLowerCase().replace(/\s/g, '-')}`,
+ })),
+ });
+ } else {
+ removeJsonLd('ld-itemlist-ecosystem');
+ }
+
+ if (activePage === 'contact') {
+ upsertJsonLd('ld-contact', {
+ '@context': 'https://schema.org',
+ '@type': 'ContactPage',
+ '@id': `${canonical}#contactpage`,
+ url: canonical,
+ name: meta.title,
+ description: meta.description,
+ isPartOf: { '@id': 'https://gothwadtech.com/#website' },
+ about: { '@id': 'https://gothwadtech.com/#organization' },
+ });
+ } else {
+ removeJsonLd('ld-contact');
+ }
+
+ if (activePage === 'company') {
+ upsertJsonLd('ld-about', {
+ '@context': 'https://schema.org',
+ '@type': 'AboutPage',
+ '@id': `${canonical}#aboutpage`,
+ url: canonical,
+ name: meta.title,
+ description: meta.description,
+ isPartOf: { '@id': 'https://gothwadtech.com/#website' },
+ about: { '@id': 'https://gothwadtech.com/#organization' },
+ mainEntity: { '@id': 'https://gothwadtech.com/#organization' },
+ });
+ } else {
+ removeJsonLd('ld-about');
+ }
+ }, [activePage]);
+
+ return (
+
+
+
+
+ }>
+ {activePage === 'home' && }
+ {activePage === 'ecosystem' && }
+ {activePage === 'products' && }
+ {activePage === 'solutions' && }
+ {activePage === 'docs' && }
+ {activePage === 'company' && }
+ {activePage === 'contact' && }
+
+
+
+
+
+ );
+}
+
+export default function App() {
+ return (
+
+
+
+ );
+}
diff --git a/src/components/AppShortcuts.tsx b/src/components/AppShortcuts.tsx
new file mode 100644
index 0000000..5ca8b46
--- /dev/null
+++ b/src/components/AppShortcuts.tsx
@@ -0,0 +1,112 @@
+import React, { useMemo, useState } from 'react';
+import { ArrowUpRight, Search } from 'lucide-react';
+import { ECOSYSTEM_APPS, CATEGORIES } from '../data/ecosystem';
+import type { CategoryId } from '../data/ecosystem';
+
+function filterApps(category: CategoryId, query: string) {
+ const q = query.trim().toLowerCase();
+ return ECOSYSTEM_APPS.filter((app) => {
+ const byCat = category === 'all' ? true : app.category === category;
+ if (!byCat) return false;
+ if (!q) return true;
+ return (
+ app.name.toLowerCase().includes(q) ||
+ app.tagline.toLowerCase().includes(q) ||
+ app.description.toLowerCase().includes(q) ||
+ app.host.toLowerCase().includes(q)
+ );
+ });
+}
+
+export const AppShortcuts: React.FC<{ compact?: boolean }> = ({ compact }) => {
+ const [category, setCategory] = useState('all');
+ const [query, setQuery] = useState('');
+
+ const apps = useMemo(() => filterApps(category, query), [category, query]);
+
+ return (
+
+ {/* Controls: category pills + search — matches docs/portal aesthetic */}
+
+
+ {CATEGORIES.map((c) => (
+ setCategory(c.id as CategoryId)}
+ className={`px-3 py-1.5 rounded-xl text-xs font-semibold whitespace-nowrap transition-colors border cursor-pointer ${
+ category === c.id
+ ? 'bg-[#0494f4] text-white border-[#0494f4] shadow-xs'
+ : 'bg-white dark:bg-zinc-900 text-zinc-600 dark:text-zinc-400 border-zinc-200 dark:border-zinc-800 hover:bg-zinc-50 dark:hover:bg-zinc-800'
+ }`}
+ >
+ {c.label}
+
+ ))}
+
+
+
+
+ setQuery(e.target.value)}
+ placeholder="Search products, e.g. Mail, Tube…"
+ className="w-full pl-9 pr-3 py-2 rounded-xl bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 text-xs text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:border-[#0494f4] focus:ring-2 focus:ring-[#0494f4]/20"
+ />
+
+
+
+ {/* Grid — 2→3→4 cols, card design like gothwadtech/portal */}
+
+
+ {apps.length === 0 && (
+
+
No products found
+
Try a different keyword or category.
+
{ setQuery(''); setCategory('all'); }} className="mt-4 px-4 py-2 rounded-xl bg-[#0494f4] text-white text-xs font-bold cursor-pointer">
+ Reset filters
+
+
+ )}
+
+ );
+};
diff --git a/src/components/Breadcrumbs.tsx b/src/components/Breadcrumbs.tsx
new file mode 100644
index 0000000..2c3dc6f
--- /dev/null
+++ b/src/components/Breadcrumbs.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import { ChevronRight, Home } from 'lucide-react';
+
+type Crumb = { name: string; path?: string };
+
+export const Breadcrumbs: React.FC<{ items: Crumb[]; onNavigate?: (path: string) => void }> = ({ items, onNavigate }) => {
+ // Always prepend Home unless already present
+ const full = items[0]?.name === 'Home' ? items : [{ name: 'Home', path: '/' }, ...items];
+ return (
+
+
+ {full.map((c, i) => {
+ const isLast = i === full.length - 1;
+ const isHome = c.name === 'Home';
+ return (
+
+ {i > 0 && }
+ {isLast || !c.path ? (
+
+ {isHome ? : null}
+ {c.name}
+
+ ) : (
+ onNavigate?.(c.path!)}
+ className="hover:text-[#0494f4] hover:underline flex items-center gap-1 cursor-pointer text-left"
+ >
+ {isHome ? : null}
+ {c.name}
+
+ )}
+
+ );
+ })}
+
+
+ );
+};
diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx
new file mode 100644
index 0000000..acc9957
--- /dev/null
+++ b/src/components/Footer.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { Github, BookOpen } from 'lucide-react';
+import { COMPANY_INFO } from '../data/companyData';
+
+export const Footer: React.FC<{ onNavigate: (page: string) => void }> = ({ onNavigate }) => {
+ return (
+
+ );
+};
diff --git a/src/components/Logo.tsx b/src/components/Logo.tsx
new file mode 100644
index 0000000..c173398
--- /dev/null
+++ b/src/components/Logo.tsx
@@ -0,0 +1,82 @@
+import React, { useState } from 'react';
+import { COMPANY_INFO } from '../data/companyData';
+
+interface LogoProps {
+ className?: string;
+ showText?: boolean;
+ size?: 'sm' | 'md' | 'lg' | 'xl';
+ imageSrc?: string;
+}
+
+export const Logo: React.FC = ({
+ className = '',
+ showText = true,
+ size = 'md',
+ imageSrc = '/assets/icons/icon-512.png',
+}) => {
+ const [imageError, setImageError] = useState(false);
+
+ const containerSizes = {
+ sm: 'w-9 h-9 sm:w-10 sm:h-10 rounded-[10px]',
+ md: 'w-11 h-11 sm:w-12 sm:h-12 rounded-[12px]',
+ lg: 'w-14 h-14 sm:w-16 sm:h-16 rounded-[16px]',
+ xl: 'w-20 h-20 rounded-[18px]',
+ };
+
+ const textSizes = {
+ sm: 'text-lg sm:text-xl tracking-tight',
+ md: 'text-xl sm:text-2xl tracking-tight',
+ lg: 'text-2xl sm:text-3xl tracking-tight',
+ xl: 'text-3xl sm:text-4xl tracking-tight',
+ };
+
+ return (
+
+
+ {!imageError && imageSrc ? (
+
{
+ if (imageSrc !== '/assets/icons/icon-512.png') {
+ const img = new Image();
+ img.src = '/assets/icons/icon-512.png';
+ img.onload = () => setImageError(false);
+ img.onerror = () => setImageError(true);
+ } else {
+ setImageError(true);
+ }
+ }}
+ className="w-full h-full object-cover block"
+ />
+ ) : (
+
+
+
+
+
+
+ )}
+
+
+ {showText && (
+
+
+
+ GOTHWAD
+
+ TECH
+
+ {size === 'lg' || size === 'xl' ? (
+
+ Official • Sovereign Tech
+
+ ) : null}
+
+ )}
+
+ );
+};
diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx
new file mode 100644
index 0000000..ef628e3
--- /dev/null
+++ b/src/components/Navbar.tsx
@@ -0,0 +1,124 @@
+import React, { useRef } from 'react';
+import { Logo } from './Logo';
+import { useGothwadSession } from '../hooks/useGothwadSession';
+import { openGothwadAccountMenu, avatarColorFor, initialsFromAccount } from '../lib/accountMenuWidget';
+import { ACCOUNTS_WEB_ORIGIN, ACCOUNTS_API_ORIGIN, buildSignInUrl, buildAccountSlotPath } from '../config/brand';
+import { signOutGothwadSlot, switchGothwadAccountSlot } from '../lib/gothwadSso';
+import { useTheme as useThemeCtx } from '../context/ThemeContext';
+
+interface NavbarProps {
+ activePage: string;
+ onNavigate: (page: string) => void;
+}
+
+export const Navbar: React.FC = ({ activePage, onNavigate }) => {
+ const isHome = activePage === 'home';
+ const { data, loading, authuser, authenticated } = useGothwadSession();
+ const { isDark } = useThemeCtx();
+ const avatarBtnRef = useRef(null);
+
+ const handleAvatarClick = () => {
+ if (!avatarBtnRef.current || !data?.user) return;
+ const effectiveUser = data.user;
+ const effectiveAccounts = data.accounts.length ? data.accounts : [{
+ id: data.activeId || 'a',
+ authuser,
+ username: effectiveUser.username || '',
+ name: effectiveUser.name || effectiveUser.username || 'Account',
+ firstName: effectiveUser.firstName,
+ lastName: effectiveUser.lastName,
+ email: effectiveUser.email,
+ avatarUrl: effectiveUser.avatarUrl,
+ avatar_url: effectiveUser.avatar_url,
+ } as any];
+
+ openGothwadAccountMenu(
+ { user: effectiveUser as any, accounts: effectiveAccounts as any, activeId: data.activeId || effectiveAccounts[0]?.id || 'a', authuser },
+ {
+ theme: (isDark ? 'dark' : 'light') as any,
+ anchorEl: avatarBtnRef.current,
+ nextUrl: window.location.href,
+ manageAccountHref: `${ACCOUNTS_WEB_ORIGIN}/u/${authuser}/me`,
+ accountsWebOrigin: ACCOUNTS_WEB_ORIGIN,
+ accountsApiOrigin: `${ACCOUNTS_API_ORIGIN}/api`,
+ appDomain: 'gothwadtech.com',
+ accountHref: (acct: any) => buildAccountSlotPath(acct.authuser ?? 0),
+ onSwitchAccount: async (target: any) => {
+ const res = await switchGothwadAccountSlot(target.id, target.authuser ?? 0);
+ if (res.ok) {
+ const path = buildAccountSlotPath(target.authuser ?? 0);
+ // preserve SPA route after the slot prefix
+ const current = window.location.pathname.replace(/^\/u\/[0-5]/, '') || '/';
+ window.location.href = `${path}${current.replace(/^\//, '') ? current.slice(1) ? `/${current.replace(/^\//,'')}` : '/' : '/'}`.replace('//','/');
+ // fallback reload
+ setTimeout(() => window.location.reload(), 300);
+ } else {
+ window.location.href = buildAccountSlotPath(target.authuser ?? 0);
+ }
+ },
+ onSignOutAccount: async (slotId: string) => {
+ await signOutGothwadSlot(slotId, authuser);
+ window.location.reload();
+ },
+ onSignOutAll: async () => {
+ await signOutGothwadSlot(undefined, authuser);
+ window.location.reload();
+ },
+ }
+ );
+ };
+
+ const signInHref = buildSignInUrl(typeof window !== 'undefined' ? window.location.href : 'https://gothwadtech.com');
+
+ return (
+
+
+
+ {!isHome && (
+
onNavigate('home')} className="flex items-center gap-2 cursor-pointer" aria-label="Gothwad Tech home">
+
+
+ )}
+
+ onNavigate('company')} className="hover:underline cursor-pointer">About
+ Store
+
+
+
+
+ onNavigate('ecosystem')} className="hidden sm:inline hover:underline cursor-pointer text-zinc-700 dark:text-zinc-300">Ecosystem
+ onNavigate('docs')} className="hidden sm:inline hover:underline cursor-pointer text-zinc-700 dark:text-zinc-300">Docs
+ GitHub
+
+ {/* Auth-aware right end: Google rule — Sign in only when anonymous, else avatar */}
+ {loading ? (
+
+ ) : authenticated && data?.user ? (
+
+ {data.user.avatarUrl ? (
+
+ ) : (
+ initialsFromAccount(data.user as any)
+ )}
+
+ ) : (
+
+ Sign in
+
+ )}
+
+
+
+ );
+};
diff --git a/src/components/PortalBar.tsx b/src/components/PortalBar.tsx
new file mode 100644
index 0000000..57f323f
--- /dev/null
+++ b/src/components/PortalBar.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import { ArrowUpRight, Github, BookOpen, Mail } from 'lucide-react';
+
+export const PortalBar: React.FC = () => {
+ return (
+
+
+
+
+ Official Portal
+
+ One Account for Mail, Drive, Meet, Tube, GrixChat, Browser & more
+
+
+
+
+ );
+};
diff --git a/src/config/brand.ts b/src/config/brand.ts
new file mode 100644
index 0000000..5da3cc5
--- /dev/null
+++ b/src/config/brand.ts
@@ -0,0 +1,77 @@
+export const DEFAULT_APP_DOMAIN = "gothwadtech.com";
+
+function readViteEnv(key: string): string {
+ try {
+ if (typeof import.meta !== "undefined" && (import.meta as any).env) {
+ const val = (import.meta as any).env[key];
+ if (typeof val === "string" && val.trim()) return val.trim();
+ }
+ } catch {}
+ return "";
+}
+
+export const APP_DOMAIN = (readViteEnv("VITE_APP_DOMAIN") || DEFAULT_APP_DOMAIN)
+ .toLowerCase()
+ .replace(/^https?:\/\//, "")
+ .replace(/\/+$/, "");
+
+export const ACCOUNTS_WEB_ORIGIN = (
+ readViteEnv("VITE_ACCOUNTS_WEB_URL") || `https://accounts.${APP_DOMAIN}`
+).replace(/\/+$/, "");
+
+export const ACCOUNTS_API_ORIGIN = (
+ readViteEnv("VITE_ACCOUNTS_API_URL") || `https://api.${APP_DOMAIN}`
+).replace(/\/+$/, "");
+
+export const ECOSYSTEM_NAME = "Gothwad";
+export const ACCOUNT_WIDGET_URL = `${ACCOUNTS_WEB_ORIGIN}/widget/account-menu.js`;
+
+export function formatGothwadEmail(username: string, domain = APP_DOMAIN): string {
+ const clean = String(username || "").trim().toLowerCase();
+ if (!clean) return "";
+ return clean.includes("@") ? clean : `${clean}@${domain}`;
+}
+
+export function buildAccountSlotPath(authuser: number): string {
+ const slot = Number.isInteger(authuser) && authuser >= 0 && authuser <= 5 ? authuser : 0;
+ return `/u/${slot}/`;
+}
+
+export function parseAuthuserFromUrl(
+ pathname = typeof window !== "undefined" ? window.location.pathname : "/",
+ search = typeof window !== "undefined" ? window.location.search : ""
+): { authuser: number; hasExplicitSlot: boolean } {
+ const pathMatch = pathname.match(/^\/u\/([0-5])(?:\/|$)/);
+ if (pathMatch) return { authuser: Number.parseInt(pathMatch[1], 10), hasExplicitSlot: true };
+ try {
+ const params = new URLSearchParams(search);
+ const q = params.get("authuser")?.trim() || params.get("u")?.trim();
+ if (q && /^[0-5]$/.test(q)) return { authuser: Number.parseInt(q, 10), hasExplicitSlot: true };
+ } catch {}
+ return { authuser: 0, hasExplicitSlot: false };
+}
+
+export function buildSignInUrl(
+ nextUrl = typeof window !== "undefined" ? window.location.href : `https://${APP_DOMAIN}`,
+ opts: { choose?: boolean; add?: boolean } = {}
+): string {
+ const params = new URLSearchParams();
+ if (opts.choose) params.set("choose", "1");
+ if (opts.add) params.set("add", "1");
+ params.set("next", nextUrl);
+ return `${ACCOUNTS_WEB_ORIGIN}/signin?${params.toString()}`;
+}
+
+export function buildManageAccountUrl(authuser = 0): string {
+ const slot = Number.isInteger(authuser) && authuser >= 0 && authuser <= 5 ? authuser : 0;
+ return `${ACCOUNTS_WEB_ORIGIN}/u/${slot}/me`;
+}
+
+// strip /u// prefix for SPA routing
+export function stripAuthuserPath(pathname: string): string {
+ if (/^\/u\/[0-5](?:\/|$)/.test(pathname)) {
+ const rest = pathname.replace(/^\/u\/[0-5]/, "") || "/";
+ return rest.startsWith("/") ? rest : `/${rest}`;
+ }
+ return pathname;
+}
diff --git a/src/context/ThemeContext.tsx b/src/context/ThemeContext.tsx
new file mode 100644
index 0000000..1e25ebe
--- /dev/null
+++ b/src/context/ThemeContext.tsx
@@ -0,0 +1,89 @@
+import React, { createContext, useContext, useEffect, useState } from 'react';
+
+type ThemeMode = 'light' | 'dark' | 'system';
+
+interface ThemeContextType {
+ themeMode: ThemeMode;
+ isDark: boolean;
+ setThemeMode: (mode: ThemeMode) => void;
+ toggleTheme: () => void;
+}
+
+const ThemeContext = createContext(undefined);
+
+function getSystemIsDark(): boolean {
+ if (typeof window === 'undefined') return false;
+ return window.matchMedia('(prefers-color-scheme: dark)').matches;
+}
+
+function applyTheme(isDark: boolean) {
+ const root = document.documentElement;
+ root.classList.remove('light', 'dark');
+ root.classList.add(isDark ? 'dark' : 'light');
+ root.style.colorScheme = isDark ? 'dark' : 'light';
+ try {
+ localStorage.setItem('gothwad-theme', isDark ? 'dark' : 'light');
+ } catch {}
+}
+
+export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ const [themeMode, setThemeModeState] = useState(() => {
+ try {
+ const stored = localStorage.getItem('gothwad-theme') as 'light' | 'dark' | null;
+ if (stored === 'dark' || stored === 'light') return stored;
+ } catch {}
+ return 'system';
+ });
+
+ const [isDark, setIsDark] = useState(false);
+
+ useEffect(() => {
+ const compute = () => {
+ if (themeMode === 'system') return getSystemIsDark();
+ return themeMode === 'dark';
+ };
+ setIsDark(compute());
+
+ if (themeMode === 'system') {
+ const mql = window.matchMedia('(prefers-color-scheme: dark)');
+ const handler = () => setIsDark(getSystemIsDark());
+ mql.addEventListener('change', handler);
+ return () => mql.removeEventListener('change', handler);
+ }
+ }, [themeMode]);
+
+ useEffect(() => {
+ applyTheme(isDark);
+ }, [isDark]);
+
+ const setThemeMode = (mode: ThemeMode) => {
+ setThemeModeState(mode);
+ if (mode === 'system') {
+ try {
+ localStorage.removeItem('gothwad-theme');
+ } catch {}
+ } else {
+ try {
+ localStorage.setItem('gothwad-theme', mode);
+ } catch {}
+ }
+ };
+
+ const toggleTheme = () => {
+ // Toggle between light/dark directly for one-click UX, like gothwadtech site
+ const next = isDark ? 'light' : 'dark';
+ setThemeMode(next as ThemeMode);
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useTheme = () => {
+ const ctx = useContext(ThemeContext);
+ if (!ctx) throw new Error('useTheme must be used within ThemeProvider');
+ return ctx;
+};
diff --git a/src/data/companyData.ts b/src/data/companyData.ts
new file mode 100644
index 0000000..1fcd88b
--- /dev/null
+++ b/src/data/companyData.ts
@@ -0,0 +1,36 @@
+export const COMPANY_INFO = {
+ name: 'Gothwad Tech',
+ domain: 'gothwadtech.com',
+ legalName: 'Gothwad Tech Private Limited',
+ tagline: 'Digital Solutions for Indian Businesses & Sovereign Tech Platforms',
+ slogan: 'Empowering Indian Businesses & Building Sovereign Tech — Aatmanirbhar Bharat',
+ shortDescription:
+ 'One Gothwad Account for everything. Access Mail, Drive, Meet, Store, Tube, GrixChat, Indogram, Browser, Education, AI Studio and the full Gothwad ecosystem — with docs, guides and direct product links.',
+ foundedYear: '2023',
+ headquarters: 'Jaipur, Rajasthan, India',
+ phone: '+91 73399 04665',
+ phoneRaw: '07339904665',
+ whatsappNumberOnly: '917339904665',
+ email: 'contact@gothwadtech.com',
+ supportEmail: 'support@gothwadtech.com',
+ helpEmail: 'help@gothwadtech.com',
+ infoEmail: 'info@gothwadtech.com',
+ docsEmail: 'docs@gothwadtech.com',
+ founderEmail: 'pawan@gothwadtech.com',
+ ceoEmail: 'nishant@gothwadtech.com',
+ coFounderEmail: 'vishnu@gothwadtech.com',
+ stats: [
+ { label: 'Ecosystem Apps', value: '13+ Products', helper: 'Mail, Drive, Meet, Tube +' },
+ { label: 'Open Repos', value: '30+ Repos', helper: 'Public on GitHub' },
+ { label: 'Engineering Team', value: '12 Specialists', helper: 'Web, Mobile, AI, Cloud' },
+ { label: 'Satisfaction', value: '4.95 / 5', helper: 'Verified client reviews' },
+ ],
+ socials: [
+ { label: 'GitHub', href: 'https://github.com/GothwadTech' },
+ { label: 'X (Twitter)', href: 'https://x.com/gothwadtech' },
+ { label: 'LinkedIn', href: 'https://linkedin.com/company/gothwadtech' },
+ { label: 'Dribbble', href: 'https://github.com/GothwadTech' },
+ ],
+};
+
+export const ROOT_DOMAIN = 'gothwadtech.com';
diff --git a/src/data/ecosystem.ts b/src/data/ecosystem.ts
new file mode 100644
index 0000000..b43ac63
--- /dev/null
+++ b/src/data/ecosystem.ts
@@ -0,0 +1,569 @@
+import {
+ Fingerprint,
+ Mail,
+ HardDrive,
+ Video,
+ ShoppingBag,
+ CalendarDays,
+ Users,
+ NotebookText,
+ Play,
+ MessageCircle,
+ Send,
+ Globe,
+ GraduationCap,
+ Sparkles,
+ HardDriveIcon,
+ MonitorSmartphone,
+ FileText,
+ Bot,
+ Computer,
+ Wifi,
+ LayoutGrid,
+ BookOpen,
+ ShieldCheck,
+ Terminal,
+ Building2,
+ Github,
+ ExternalLink,
+ Smartphone,
+} from 'lucide-react';
+import type { LucideIcon } from 'lucide-react';
+
+export interface EcosystemApp {
+ id: string;
+ name: string;
+ tagline: string;
+ description: string;
+ host: string; // subdomain
+ href: string; // full https url
+ githubRepo?: string;
+ githubUrl?: string;
+ icon: LucideIcon;
+ accent: string; // tailwind bg for tile
+ iconBg: string;
+ iconText: string;
+ category: 'identity' | 'productivity' | 'communication' | 'media' | 'devices' | 'education' | 'devtools' | 'company';
+ core?: boolean; // can't be disconnected (account-connected)
+ badge?: string;
+ platforms: string[];
+ available: boolean; // true if subdomain exists
+}
+
+export const ROOT_DOMAIN = 'gothwadtech.com';
+
+function url(host: string) {
+ return `https://${host}.${ROOT_DOMAIN}`;
+}
+
+function repoUrl(repo: string) {
+ return `https://github.com/GothwadTech/${repo}`;
+}
+
+export const ECOSYSTEM_APPS: EcosystemApp[] = [
+ // ——————————————————————————————————
+ // Identity & Core (account-connected)
+ // ——————————————————————————————————
+ {
+ id: 'accounts',
+ name: 'Gothwad Accounts',
+ tagline: 'One identity for everything',
+ description: 'Sign in once. OAuth 2.0 + PKCE, session management and connected apps directory.',
+ host: 'accounts',
+ href: url('accounts'),
+ githubRepo: 'accounts',
+ githubUrl: repoUrl('accounts'),
+ icon: Fingerprint,
+ accent: 'bg-orange-500',
+ iconBg: 'bg-orange-500/10 border-orange-500/20',
+ iconText: 'text-orange-600 dark:text-orange-400',
+ category: 'identity',
+ core: true,
+ badge: 'Identity',
+ platforms: ['Web', 'OAuth 2.0'],
+ available: true,
+ },
+ {
+ id: 'mail',
+ name: 'Gothwad Mail',
+ tagline: 'Your Gothwad inbox',
+ description: 'Edge-powered inbox. Send, receive and manage @gothwadtech.com email on Cloudflare.',
+ host: 'mail',
+ href: url('mail'),
+ githubRepo: 'mail',
+ githubUrl: repoUrl('mail'),
+ icon: Mail,
+ accent: 'bg-[#0494f4]',
+ iconBg: 'bg-[#0494f4]/10 border-[#0494f4]/20',
+ iconText: 'text-[#0494f4]',
+ category: 'productivity',
+ core: true,
+ badge: 'Core',
+ platforms: ['Web', 'Cloudflare Workers'],
+ available: true,
+ },
+ {
+ id: 'drive',
+ name: 'Gothwad Drive',
+ tagline: 'Files and folders',
+ description: 'Cloud file storage with sharing, previews and Telegram-backed ClashDrive extension.',
+ host: 'drive',
+ href: url('drive'),
+ githubRepo: 'drive',
+ githubUrl: repoUrl('drive'),
+ icon: HardDrive,
+ accent: 'bg-emerald-500',
+ iconBg: 'bg-emerald-500/10 border-emerald-500/20',
+ iconText: 'text-emerald-600 dark:text-emerald-400',
+ category: 'productivity',
+ core: true,
+ badge: 'Core',
+ platforms: ['Web', 'Cloud'],
+ available: true,
+ },
+ {
+ id: 'meet',
+ name: 'Gothwad Meet',
+ tagline: 'Video meetings',
+ description: 'WebRTC peer-to-peer meetings. No installs. Share links and meet face to face.',
+ host: 'meet',
+ href: url('meet'),
+ githubRepo: 'meet',
+ githubUrl: repoUrl('meet'),
+ icon: Video,
+ accent: 'bg-amber-500',
+ iconBg: 'bg-amber-500/10 border-amber-500/20',
+ iconText: 'text-amber-600 dark:text-amber-400',
+ category: 'communication',
+ core: true,
+ badge: 'Core',
+ platforms: ['Web', 'WebRTC'],
+ available: true,
+ },
+ {
+ id: 'calendar',
+ name: 'Gothwad Calendar',
+ tagline: 'Events and reminders',
+ description: 'Schedule events, invites and reminders — synced with your Gothwad Account.',
+ host: 'calender', // DNS record is actually spelled calender (kept compatible)
+ href: url('calender'),
+ githubRepo: 'calendar',
+ githubUrl: repoUrl('calender'),
+ icon: CalendarDays,
+ accent: 'bg-violet-500',
+ iconBg: 'bg-violet-500/10 border-violet-500/20',
+ iconText: 'text-violet-600 dark:text-violet-400',
+ category: 'productivity',
+ core: true,
+ badge: 'Core',
+ platforms: ['Web'],
+ available: true,
+ },
+ {
+ id: 'contacts',
+ name: 'Gothwad Contacts',
+ tagline: 'People and addresses',
+ description: 'Manage contacts and address book, synced across Gothwad apps.',
+ host: 'contacts',
+ href: url('contacts'),
+ githubRepo: 'contacts',
+ githubUrl: repoUrl('contacts'),
+ icon: Users,
+ accent: 'bg-cyan-500',
+ iconBg: 'bg-cyan-500/10 border-cyan-500/20',
+ iconText: 'text-cyan-600 dark:text-cyan-400',
+ category: 'productivity',
+ core: true,
+ badge: 'Core',
+ platforms: ['Web'],
+ available: true,
+ },
+ {
+ id: 'notes',
+ name: 'Gothwad Notes',
+ tagline: 'Notes and lists, synced',
+ description: 'Markdown notes with lists and quick capture, synced via Gothwad account.',
+ host: 'notes',
+ href: url('notes'),
+ githubRepo: 'notes',
+ githubUrl: repoUrl('notes'),
+ icon: NotebookText,
+ accent: 'bg-rose-500',
+ iconBg: 'bg-rose-500/10 border-rose-500/20',
+ iconText: 'text-rose-600 dark:text-rose-400',
+ category: 'productivity',
+ core: true,
+ badge: 'Core',
+ platforms: ['Web'],
+ available: true,
+ },
+ {
+ id: 'store',
+ name: 'Gothwad Store',
+ tagline: 'Apps and add-ons',
+ description: 'Kiwi Store — India’s open-source app HUB. Discover and install Gothwad add-ons.',
+ host: 'store',
+ href: url('store'),
+ githubRepo: 'store',
+ githubUrl: repoUrl('store'),
+ icon: ShoppingBag,
+ accent: 'bg-orange-600',
+ iconBg: 'bg-orange-500/10 border-orange-500/20',
+ iconText: 'text-orange-700 dark:text-orange-400',
+ category: 'media',
+ core: true,
+ badge: 'Store',
+ platforms: ['Web'],
+ available: true,
+ },
+ // ——————————————————————————————————
+ // Consumer / Communication / Media
+ // ——————————————————————————————————
+ {
+ id: 'tube',
+ name: 'Gothwad Tube',
+ tagline: 'A better way to watch',
+ description: 'Video discovery — PlusTube web platform + PlusTube app with Gothwad Account login.',
+ host: 'tube',
+ href: url('tube'),
+ githubRepo: 'tubeweb',
+ githubUrl: repoUrl('tubeweb'),
+ icon: Play,
+ accent: 'bg-red-600',
+ iconBg: 'bg-red-500/10 border-red-500/20',
+ iconText: 'text-red-600 dark:text-red-400',
+ category: 'media',
+ badge: 'Video',
+ platforms: ['Web', 'Android'],
+ available: true,
+ },
+ {
+ id: 'grixchat',
+ name: 'GrixChat',
+ tagline: 'Messaging, together',
+ description: 'Real-time messenger & calling. Instagram + WhatsApp-like, mobile-first. <15ms dispatch.',
+ host: 'grixchat',
+ href: url('grixchat'),
+ githubRepo: 'grixchat',
+ githubUrl: repoUrl('grixchat'),
+ icon: MessageCircle,
+ accent: 'bg-teal-500',
+ iconBg: 'bg-teal-500/10 border-teal-500/20',
+ iconText: 'text-teal-600 dark:text-teal-400',
+ category: 'communication',
+ badge: 'Messenger',
+ platforms: ['Web', 'Android'],
+ available: true,
+ },
+ {
+ id: 'indogram',
+ name: 'Indogram',
+ tagline: 'Sovereign cloud communities',
+ description: 'Telegram-style sovereign cloud: 200k groups, unlimited storage, bots & multi-device.',
+ host: 'indogram',
+ href: url('indogram'),
+ githubRepo: 'indogramapp',
+ githubUrl: repoUrl('indogramapp'),
+ icon: Send,
+ accent: 'bg-sky-500',
+ iconBg: 'bg-sky-500/10 border-sky-500/20',
+ iconText: 'text-sky-600 dark:text-sky-400',
+ category: 'communication',
+ badge: 'Cloud Messenger',
+ platforms: ['Web', 'Android'],
+ available: true,
+ },
+ {
+ id: 'browser',
+ name: 'Gothwad Browser',
+ tagline: 'Built for the bigger screen',
+ description: 'Ultra-light Rust/C++ sovereign browser — 11.8 MB, 75% less RAM, TurboShield ad-block.',
+ host: 'browser',
+ href: url('browser'),
+ githubRepo: 'browser',
+ githubUrl: repoUrl('browser'),
+ icon: Globe,
+ accent: 'bg-[#0494f4]',
+ iconBg: 'bg-[#0494f4]/10 border-[#0494f4]/20',
+ iconText: 'text-[#0494f4]',
+ category: 'devices',
+ badge: 'Flagship',
+ platforms: ['Android', 'Android TV', 'Web'],
+ available: true,
+ },
+ {
+ id: 'launcher',
+ name: 'Gothwad Launcher',
+ tagline: 'Android TV home',
+ description: 'TV Launcher for Android TVs & tablets — simple, remote-friendly, ad-free recent apps.',
+ host: 'launcher',
+ href: repoUrl('launcher'),
+ githubRepo: 'launcher',
+ githubUrl: repoUrl('launcher'),
+ icon: MonitorSmartphone,
+ accent: 'bg-blue-600',
+ iconBg: 'bg-blue-500/10 border-blue-500/20',
+ iconText: 'text-blue-600 dark:text-blue-400',
+ category: 'devices',
+ badge: 'Android TV',
+ platforms: ['Android TV'],
+ available: true,
+ },
+ {
+ id: 'manager',
+ name: 'Gothwad Manager',
+ tagline: 'File manager for Android',
+ description: 'All-in-one file manager — RTL, folder sizes, fast and efficient explorer.',
+ host: 'manager',
+ href: repoUrl('manager'),
+ githubRepo: 'manager',
+ githubUrl: repoUrl('manager'),
+ icon: FileText,
+ accent: 'bg-orange-500',
+ iconBg: 'bg-orange-500/10 border-orange-500/20',
+ iconText: 'text-orange-600 dark:text-orange-400',
+ category: 'devices',
+ badge: 'File Manager',
+ platforms: ['Android', 'TV'],
+ available: true,
+ },
+ {
+ id: 'remotedesk',
+ name: 'Gothwad Remote Desktop',
+ tagline: 'Windows remote, zero-database',
+ description: '100% Zero-Database Cloudflare Pages portal — Win11 OS + Hyper-V isolated VM, WebRTC P2P.',
+ host: 'remotedesk',
+ href: url('remotedesk'),
+ githubRepo: 'remotedesk',
+ githubUrl: repoUrl('remotedesk'),
+ icon: Computer,
+ accent: 'bg-zinc-800',
+ iconBg: 'bg-zinc-800/10 border-zinc-800/20',
+ iconText: 'text-zinc-700 dark:text-zinc-300',
+ category: 'devtools',
+ badge: 'Windows',
+ platforms: ['Web', 'Windows'],
+ available: true,
+ },
+ {
+ id: 'internet',
+ name: 'Gothwad Internet',
+ tagline: 'Lightweight phone browser',
+ description: 'Lightweight browser for Android phones — fastest, lightest multitasking with file manager.',
+ host: 'internet',
+ href: repoUrl('internet'),
+ githubRepo: 'internet',
+ githubUrl: repoUrl('internet'),
+ icon: Wifi,
+ accent: 'bg-sky-600',
+ iconBg: 'bg-sky-500/10 border-sky-500/20',
+ iconText: 'text-sky-700 dark:text-sky-400',
+ category: 'devices',
+ badge: 'Phone Browser',
+ platforms: ['Android'],
+ available: true,
+ },
+ {
+ id: 'computer',
+ name: 'Gothwad Computer',
+ tagline: 'Desktop mode for Android',
+ description: 'Android app that gives phones a desktop-like TV experience with external input support.',
+ host: 'computer',
+ href: repoUrl('computer'),
+ githubRepo: 'computer',
+ githubUrl: repoUrl('computer'),
+ icon: Computer,
+ accent: 'bg-zinc-700',
+ iconBg: 'bg-zinc-700/10 border-zinc-700/20',
+ iconText: 'text-zinc-700 dark:text-zinc-300',
+ category: 'devices',
+ badge: 'Desktop',
+ platforms: ['Android', 'TV'],
+ available: true,
+ },
+ // ——————————————————————————————————
+ // Education + Dev + AI
+ // ——————————————————————————————————
+ {
+ id: 'education',
+ name: 'Gothwad Education',
+ tagline: 'School & learning platform',
+ description: 'Admin + Teacher + Student + Parent experiences. PWParent apps, fees, attendance, ERP.',
+ host: 'education',
+ href: url('education'),
+ githubRepo: 'education',
+ githubUrl: 'https://github.com/GothwadTech/education',
+ icon: GraduationCap,
+ accent: 'bg-indigo-500',
+ iconBg: 'bg-indigo-500/10 border-indigo-500/20',
+ iconText: 'text-indigo-600 dark:text-indigo-400',
+ category: 'education',
+ badge: 'ERP',
+ platforms: ['Web', 'Android'],
+ available: true,
+ },
+ {
+ id: 'clashdrive',
+ name: 'ClashDrive',
+ tagline: 'Telegram-backed storage',
+ description: 'Browser storage workspace built over Telegram supergroup forum topics.',
+ host: 'clashdrive',
+ href: url('clashdrive'),
+ githubRepo: 'Clashdrive',
+ githubUrl: repoUrl('Clashdrive'),
+ icon: HardDriveIcon,
+ accent: 'bg-lime-600',
+ iconBg: 'bg-lime-600/10 border-lime-600/20',
+ iconText: 'text-lime-700 dark:text-lime-400',
+ category: 'productivity',
+ badge: 'Storage',
+ platforms: ['Web'],
+ available: true,
+ },
+ {
+ id: 'ai',
+ name: 'Gothwad AI Studio',
+ tagline: 'Developer workspace',
+ description: 'Mobile-first dev workspace: browse GH repos, manage files and edit code on the go.',
+ host: 'ai',
+ href: url('ai'),
+ githubRepo: 'ai',
+ githubUrl: repoUrl('ai'),
+ icon: Sparkles,
+ accent: 'bg-fuchsia-500',
+ iconBg: 'bg-fuchsia-500/10 border-fuchsia-500/20',
+ iconText: 'text-fuchsia-600 dark:text-fuchsia-400',
+ category: 'devtools',
+ badge: 'AI',
+ platforms: ['Web', 'Mobile'],
+ available: true,
+ },
+ {
+ id: 'plusgit',
+ name: 'PlusGit',
+ tagline: 'Git for mobile',
+ description: 'Gothwad Git client — manage repositories from your phone with ease.',
+ host: 'plusgit',
+ href: repoUrl('plusgit'),
+ githubRepo: 'plusgit',
+ githubUrl: repoUrl('plusgit'),
+ icon: Terminal,
+ accent: 'bg-zinc-900',
+ iconBg: 'bg-zinc-900/10 border-zinc-900/20',
+ iconText: 'text-zinc-900 dark:text-zinc-400',
+ category: 'devtools',
+ badge: 'Git',
+ platforms: ['Android', 'Web'],
+ available: true,
+ },
+ // ——————————————————————————————————
+ // Company hubs
+ // ——————————————————————————————————
+ {
+ id: 'docs',
+ name: 'Gothwad Docs',
+ tagline: 'Developer documentation',
+ description: 'Central source-based docs — Accounts OAuth/PKCE, Mail REST, Tube web, GrixChat, Meet & more.',
+ host: 'docs',
+ href: url('docs'),
+ githubRepo: 'docs',
+ githubUrl: repoUrl('docs'),
+ icon: BookOpen,
+ accent: 'bg-amber-600',
+ iconBg: 'bg-amber-600/10 border-amber-600/20',
+ iconText: 'text-amber-700 dark:text-amber-400',
+ category: 'company',
+ badge: 'Docs',
+ platforms: ['Web'],
+ available: true,
+ },
+ {
+ id: 'ceo',
+ name: 'CEO — Yuvkesh Meena',
+ tagline: 'Leadership profile',
+ description: 'Meet Yuvkesh Meena, CEO of Gothwad Tech. Born in Dausa, Rajasthan.',
+ host: 'ceo',
+ href: url('ceo'),
+ githubRepo: 'ceo',
+ githubUrl: repoUrl('ceo'),
+ icon: Building2,
+ accent: 'bg-zinc-700',
+ iconBg: 'bg-zinc-800/10 border-zinc-800/20',
+ iconText: 'text-zinc-700 dark:text-zinc-300',
+ category: 'company',
+ badge: 'Leadership',
+ platforms: ['Web'],
+ available: true,
+ },
+ {
+ id: 'about',
+ name: 'About Gothwad Tech',
+ tagline: 'Corporate & company site',
+ description: 'Learn about mission: Aatmanirbhar Bharat, sovereign consumer apps & enterprise solutions.',
+ host: 'www',
+ href: 'https://www.gothwadtech.com',
+ githubRepo: 'gothwadtech',
+ githubUrl: repoUrl('gothwadtech'),
+ icon: Building2,
+ accent: 'bg-[#0494f4]',
+ iconBg: 'bg-[#0494f4]/10 border-[#0494f4]/20',
+ iconText: 'text-[#0494f4]',
+ category: 'company',
+ badge: 'About',
+ platforms: ['Web'],
+ available: true,
+ },
+ {
+ id: 'accountsapp',
+ name: 'Gothwad Accounts App',
+ tagline: 'Native account manager',
+ description: 'Android accounts companion: manage Gothwad identity on device.',
+ host: 'accountsapp',
+ href: repoUrl('accountsapp'),
+ githubRepo: 'accountsapp',
+ githubUrl: repoUrl('accountsapp'),
+ icon: Smartphone,
+ accent: 'bg-orange-500',
+ iconBg: 'bg-orange-500/10 border-orange-500/20',
+ iconText: 'text-orange-600 dark:text-orange-400',
+ category: 'identity',
+ badge: 'Android',
+ platforms: ['Android'],
+ available: true,
+ },
+ {
+ id: 'domains',
+ name: 'Gothwad Domains',
+ tagline: 'Ecosystem domains',
+ description: 'Public domain registry and routing map for Gothwad Tech.',
+ host: 'domains',
+ href: repoUrl('domains'),
+ githubRepo: 'domains',
+ githubUrl: repoUrl('domains'),
+ icon: LayoutGrid,
+ accent: 'bg-zinc-600',
+ iconBg: 'bg-zinc-600/10 border-zinc-600/20',
+ iconText: 'text-zinc-600 dark:text-zinc-400',
+ category: 'company',
+ badge: 'Registry',
+ platforms: ['Git'],
+ available: true,
+ },
+];
+
+export const CATEGORIES = [
+ { id: 'all', label: 'All products', count: ECOSYSTEM_APPS.length },
+ { id: 'identity', label: 'Identity & security' },
+ { id: 'productivity', label: 'Productivity' },
+ { id: 'communication', label: 'Communication' },
+ { id: 'media', label: 'Media & apps' },
+ { id: 'devices', label: 'Devices & TV' },
+ { id: 'education', label: 'Education' },
+ { id: 'devtools', label: 'Developer tools' },
+ { id: 'company', label: 'Company & docs' },
+] as const;
+
+export type CategoryId = (typeof CATEGORIES)[number]['id'];
+
+// Legacy alias for home portal quick shortcuts (mirrors GOTHWAD_APPS)
+export const PORTAL_FAVORITES = ['mail', 'drive', 'meet', 'tube', 'grixchat', 'browser', 'docs', 'accounts', 'education', 'store', 'ai', 'ceo'];
diff --git a/src/hooks/useGothwadSession.ts b/src/hooks/useGothwadSession.ts
new file mode 100644
index 0000000..230e6ca
--- /dev/null
+++ b/src/hooks/useGothwadSession.ts
@@ -0,0 +1,25 @@
+import { useEffect, useState, useCallback } from "react";
+import { fetchGothwadSession, getCurrentAuthuser, type FetchMeResult } from "../lib/gothwadSso";
+import { preloadGothwadAccountMenu } from "../lib/accountMenuWidget";
+
+export function useGothwadSession() {
+ const [data, setData] = useState(null);
+ const [loading, setLoading] = useState(true);
+
+ const refresh = useCallback(async () => {
+ const authuser = getCurrentAuthuser();
+ setLoading(true);
+ const res = await fetchGothwadSession(authuser);
+ setData(res);
+ setLoading(false);
+ if (res.authenticated) preloadGothwadAccountMenu();
+ }, []);
+
+ useEffect(() => {
+ void refresh();
+ // preload widget even before auth resolves, so first click is 0ms
+ preloadGothwadAccountMenu();
+ }, [refresh]);
+
+ return { data, loading, refresh, authuser: data?.authuser ?? getCurrentAuthuser(), authenticated: data?.authenticated ?? false };
+}
diff --git a/src/index.css b/src/index.css
new file mode 100644
index 0000000..2cf418f
--- /dev/null
+++ b/src/index.css
@@ -0,0 +1,73 @@
+@import "tailwindcss";
+
+@custom-variant dark (&:where(.dark, .dark *));
+
+@theme {
+ --color-brand-50: #eef8ff;
+ --color-brand-100: #d8efff;
+ --color-brand-200: #bae3ff;
+ --color-brand-300: #8bd3ff;
+ --color-brand-400: #54baff;
+ --color-brand-500: #0494f4;
+ --color-brand-600: #0077cd;
+ --color-brand-700: #005fa7;
+ --color-brand-800: #045089;
+ --color-brand-900: #0a4372;
+ --color-brand-950: #062b4c;
+ --color-brand: #0494f4;
+
+ --color-zinc-950: #202124;
+ --color-zinc-900: #292a2d;
+ --color-zinc-850: #2e2f33;
+ --color-zinc-800: #303134;
+ --color-zinc-700: #3c4043;
+ --color-zinc-600: #5f6368;
+ --color-zinc-500: #80868b;
+ --color-zinc-400: #9aa0a6;
+ --color-zinc-300: #bdc1c6;
+ --color-zinc-200: #dadce0;
+ --color-zinc-100: #f1f3f4;
+ --color-zinc-50: #f8f9fa;
+}
+
+:root {
+ --primary-brand: #0494f4;
+}
+
+html.dark,
+html.dark body {
+ background-color: #202124 !important;
+ color: #e8eaed !important;
+}
+
+html.light,
+html.light body {
+ background-color: #ffffff !important;
+ color: #202124 !important;
+}
+
+* {
+ -webkit-tap-highlight-color: transparent;
+}
+
+body {
+ will-change: auto;
+ font-family: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
+}
+
+h1,h2,h3 {
+ font-family: 'Space Grotesk', sans-serif;
+}
+
+/* scrollbar */
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+::-webkit-scrollbar-thumb {
+ background: #dadce0;
+ border-radius: 999px;
+}
+.dark ::-webkit-scrollbar-thumb {
+ background: #3c4043;
+}
diff --git a/src/lib/accountMenuWidget.ts b/src/lib/accountMenuWidget.ts
new file mode 100644
index 0000000..00d90fc
--- /dev/null
+++ b/src/lib/accountMenuWidget.ts
@@ -0,0 +1,242 @@
+/**
+ * Gothwad Website — Account switcher (port of drive's accountMenuWidget)
+ * Same Google-style sheet that Mail/Drive use, hosted at accounts.gothwadtech.com/widget/account-menu.js
+ * Falls back to inline shadow-DOM sheet when widget unreachable/offline.
+ */
+import {
+ ACCOUNT_WIDGET_URL,
+ ACCOUNTS_API_ORIGIN,
+ ACCOUNTS_WEB_ORIGIN,
+ APP_DOMAIN,
+ ECOSYSTEM_NAME,
+} from "../config/brand";
+import type { GothwadAccountItem, GothwadSsoUser } from "./gothwadSso";
+
+export interface GothwadAccountMenuOptions {
+ appDomain?: string;
+ accountsWebOrigin?: string;
+ accountsApiOrigin?: string;
+ ecosystemName?: string;
+ theme?: "light" | "dark" | "system";
+ anchorEl?: HTMLElement | null;
+ nextUrl?: string;
+ manageAccountHref?: string;
+ accountHref?: (acct: GothwadAccountItem) => string;
+ onSwitchAccount?: (acct: GothwadAccountItem) => void | Promise;
+ onSignOutAccount?: (slotId: string) => void | Promise;
+ onSignOutAll?: () => void | Promise;
+ onClose?: () => void;
+ onError?: (msg: string) => void;
+ extraActions?: { label: string; onClick: () => void }[];
+}
+
+export interface GothwadAccountMenuState {
+ user: GothwadSsoUser | null;
+ accounts: GothwadAccountItem[];
+ activeId: string | null;
+ authuser: number;
+}
+
+export interface GothwadAccountMenuController {
+ isOpen(): boolean;
+ open(state: GothwadAccountMenuState, opts?: GothwadAccountMenuOptions): void;
+ update(patchState: Partial, patchOpts?: Partial): void;
+ close(): void;
+}
+
+declare global {
+ interface Window {
+ GothwadAccountMenu?: GothwadAccountMenuController;
+ }
+}
+
+const AVATAR_PALETTE = ["#9334a6", "#0b57d0", "#0d652d", "#c5221f", "#00639b", "#b06000", "#7627bb", "#185abc"];
+
+function esc(value: unknown): string {
+ return String(value ?? "").replace(/[&<>"']/g, (ch) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[ch] || ch));
+}
+
+export function avatarColorFor(seed: string): string {
+ const s = String(seed || "u").toLowerCase();
+ let hash = 0;
+ for (let i = 0; i < s.length; i += 1) hash = ((hash << 5) - hash + s.charCodeAt(i)) | 0;
+ return AVATAR_PALETTE[Math.abs(hash) % AVATAR_PALETTE.length];
+}
+
+export function initialsFrom(name?: string, fallback?: string): string {
+ const full = String(name || fallback || "?").trim();
+ const parts = full.split(/[\s._@-]+/).filter(Boolean);
+ if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase();
+ return full.slice(0, 1).toUpperCase() || "?";
+}
+
+export function initialsFromAccount(item?: Partial | null): string {
+ const full = `${item?.firstName || ""} ${item?.lastName || ""}`.trim() || String(item?.name || (item as any)?.username || "?").trim();
+ return initialsFrom(full);
+}
+
+const FALLBACK_CSS = `
+.gw-layer{--gw-surface:#eef3f8;--gw-card:#ffffff;--gw-card-hover:#f5f8fc;--gw-text:#1f1f1f;--gw-subtext:#444746;--gw-accent:#0b57d0;--gw-danger:#b3261e;--gw-danger-bg:#fceeee;--gw-border:rgba(0,0,0,0.08);position:fixed;inset:0;z-index:2147483000;font-family:system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;color:var(--gw-text)}
+.gw-layer[data-theme="dark"]{--gw-surface:#1b1f26;--gw-card:#282c34;--gw-card-hover:#323741;--gw-text:#e3e3e3;--gw-subtext:#c4c7c5;--gw-accent:#8ab4f8;--gw-danger:#f28b82;--gw-danger-bg:#3c2525;--gw-border:rgba(255,255,255,0.1)}
+.gw-backdrop{position:fixed;inset:0;background:rgba(0,0,0,0.28)}
+.gw-sheet{position:fixed;inset:0;display:flex;flex-direction:column;background:var(--gw-surface);overflow-y:auto;padding:14px 16px 20px}
+@media(min-width:640px){.gw-backdrop{background:transparent}.gw-sheet{inset:auto;top:var(--gw-top,58px);right:var(--gw-right,16px);width:388px;max-width:calc(100vw - 24px);border-radius:28px;border:1px solid var(--gw-border);box-shadow:0 16px 42px rgba(0,0,0,0.24),0 2px 8px rgba(0,0,0,0.12)}}
+.gw-topbar{display:flex;justify-content:flex-end;margin-bottom:4px}
+.gw-close{width:36px;height:36px;border:none;border-radius:999px;background:transparent;color:var(--gw-subtext);cursor:pointer;font-size:18px}
+.gw-stack{display:flex;flex-direction:column;gap:2px}
+.gw-hero{display:flex;align-items:center;gap:14px;background:var(--gw-card);padding:16px 18px;border-radius:24px 24px 4px 4px}
+.gw-avatar{display:inline-grid;place-items:center;border-radius:999px;overflow:hidden;color:#fff;font-weight:600;flex-shrink:0}
+.gw-avatar img{width:100%;height:100%;object-fit:cover;display:block}
+.gw-hero-name{font-size:18px;font-weight:600;color:var(--gw-text)}
+.gw-hero-email{font-size:13px;color:var(--gw-subtext);margin-top:2px}
+.gw-row{display:flex;align-items:center;gap:14px;width:100%;min-height:56px;padding:10px 18px;border:none;border-radius:4px;background:var(--gw-card);color:var(--gw-text);text-align:left;text-decoration:none;font-size:14px;font-weight:500;cursor:pointer;box-sizing:border-box}
+.gw-row:hover{background:var(--gw-card-hover)}
+.gw-row.is-last{border-radius:4px 4px 24px 24px}
+.gw-acct-meta{flex:1;min-width:0}
+.gw-acct-name{display:block;font-size:14px;font-weight:500;color:var(--gw-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
+.gw-acct-email{display:block;font-size:12px;color:var(--gw-subtext);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
+.gw-manage-pill{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;min-height:50px;margin-top:12px;padding:0 20px;border-radius:999px;background:var(--gw-card);color:var(--gw-text);text-decoration:none;font-size:14px;font-weight:500;box-sizing:border-box}
+.gw-manage-pill:hover{background:var(--gw-card-hover)}
+.gw-extra-group{display:flex;flex-direction:column;gap:2px;margin-top:10px}
+.gw-extra-group .gw-row{border-radius:20px}
+`;
+
+function renderAvatarHtml(acct: Partial, sizePx: number): string {
+ const bg = avatarColorFor((acct as any).username || (acct as any).email || (acct as any).name || "u");
+ const label = esc(initialsFromAccount(acct));
+ const fontSize = Math.max(13, Math.round(sizePx * 0.42));
+ if ((acct as any).avatarUrl || (acct as any).avatar_url) {
+ const url = esc((acct as any).avatarUrl || (acct as any).avatar_url);
+ return ` `;
+ }
+ return `${label} `;
+}
+
+class FallbackAccountMenu implements GothwadAccountMenuController {
+ private hostEl: HTMLDivElement | null = null;
+ private layerEl: HTMLDivElement | null = null;
+ private state: GothwadAccountMenuState = { user: null, accounts: [], activeId: null, authuser: 0 };
+ private opts: GothwadAccountMenuOptions = {};
+ private onKey = (e: KeyboardEvent) => { if (e.key === "Escape") this.close(); };
+ isOpen() { return Boolean(this.hostEl); }
+ open(state: GothwadAccountMenuState, opts: GothwadAccountMenuOptions = {}) {
+ this.state = { ...this.state, ...state };
+ this.opts = { ...opts };
+ if (!this.hostEl && typeof document !== "undefined") {
+ this.hostEl = document.createElement("div");
+ const shadow = (this.hostEl as any).attachShadow ? this.hostEl.attachShadow({ mode: "open" }) : this.hostEl;
+ const style = document.createElement("style");
+ style.textContent = FALLBACK_CSS;
+ this.layerEl = document.createElement("div");
+ this.layerEl.className = "gw-layer";
+ shadow.appendChild(style);
+ shadow.appendChild(this.layerEl);
+ document.body.appendChild(this.hostEl);
+ window.addEventListener("keydown", this.onKey);
+ }
+ this.render();
+ }
+ update(patchState: Partial, patchOpts?: Partial) {
+ this.state = { ...this.state, ...patchState };
+ if (patchOpts) this.opts = { ...this.opts, ...patchOpts };
+ if (this.isOpen()) this.render();
+ }
+ close() {
+ if (!this.hostEl) return;
+ this.hostEl.remove();
+ this.hostEl = null;
+ this.layerEl = null;
+ window.removeEventListener("keydown", this.onKey);
+ this.opts.onClose?.();
+ }
+ private render() {
+ if (!this.layerEl) return;
+ const isDark = this.opts.theme === "dark" || (this.opts.theme !== "light" && document.documentElement.classList.contains("dark"));
+ this.layerEl.setAttribute("data-theme", isDark ? "dark" : "light");
+ const rect = this.opts.anchorEl?.getBoundingClientRect?.();
+ if (rect) {
+ this.layerEl.style.setProperty("--gw-top", `${Math.max(12, Math.round(rect.bottom + 10))}px`);
+ this.layerEl.style.setProperty("--gw-right", `${Math.max(12, Math.round(window.innerWidth - rect.right))}px`);
+ }
+ const active = this.state.user || (this.state.accounts[0] as any);
+ const others = (this.state.accounts || []).filter((a) => (a.username || (a as any).email || "").toLowerCase() !== (active?.username || (active as any)?.email || "").toLowerCase());
+ const webOrigin = this.opts.accountsWebOrigin || ACCOUNTS_WEB_ORIGIN;
+ const nextUrl = this.opts.nextUrl || (typeof window !== "undefined" ? window.location.href : "");
+ const addHref = `${webOrigin}/signin?choose=1&add=1&next=${encodeURIComponent(nextUrl)}`;
+ const manageHref = this.opts.manageAccountHref || `${webOrigin}/u/${this.state.authuser}/me`;
+ const extraActions = this.opts.extraActions || [];
+ this.layerEl.innerHTML = `
+
+
+ `;
+ this.layerEl.querySelectorAll('[data-action="close"]').forEach((el) => el.addEventListener("click", () => this.close()));
+ this.layerEl.querySelectorAll("[data-switch]").forEach((el) => {
+ el.addEventListener("click", (e) => {
+ if ((e as MouseEvent).metaKey || (e as MouseEvent).ctrlKey) return;
+ e.preventDefault();
+ const id = el.getAttribute("data-switch");
+ const target = this.state.accounts.find((a) => a.id === id);
+ this.close();
+ if (target) void this.opts.onSwitchAccount?.(target);
+ });
+ });
+ this.layerEl.querySelector('[data-action="signout-active"]')?.addEventListener("click", () => {
+ const slotId = this.state.activeId || this.state.accounts[0]?.id || "a";
+ this.close();
+ if (this.opts.onSignOutAccount) void this.opts.onSignOutAccount(slotId);
+ else void this.opts.onSignOutAll?.();
+ });
+ this.layerEl.querySelectorAll("[data-extra]").forEach((el) => {
+ el.addEventListener("click", () => {
+ const idx = Number(el.getAttribute("data-extra"));
+ this.close();
+ extraActions[idx]?.onClick?.();
+ });
+ });
+ }
+}
+
+let preloadStarted = false;
+
+export function preloadGothwadAccountMenu(): void {
+ if (typeof window === "undefined") return;
+ if (!window.GothwadAccountMenu) window.GothwadAccountMenu = new FallbackAccountMenu();
+ if (preloadStarted) return;
+ preloadStarted = true;
+ try {
+ if (!document.querySelector(`script[src="${ACCOUNT_WIDGET_URL}"]`)) {
+ const script = document.createElement("script");
+ script.type = "module";
+ script.async = true;
+ script.src = ACCOUNT_WIDGET_URL;
+ document.head.appendChild(script);
+ }
+ } catch {}
+}
+
+export function openGothwadAccountMenu(state: GothwadAccountMenuState, opts: GothwadAccountMenuOptions): void {
+ preloadGothwadAccountMenu();
+ window.GothwadAccountMenu?.open(state, {
+ appDomain: APP_DOMAIN,
+ accountsWebOrigin: ACCOUNTS_WEB_ORIGIN,
+ accountsApiOrigin: `${ACCOUNTS_API_ORIGIN}/api`,
+ ecosystemName: ECOSYSTEM_NAME,
+ ...opts,
+ });
+}
+
+export const preloadAccountMenuWidget = preloadGothwadAccountMenu;
+export const openAccountMenu = openGothwadAccountMenu;
diff --git a/src/lib/gothwadSso.ts b/src/lib/gothwadSso.ts
new file mode 100644
index 0000000..1e89c76
--- /dev/null
+++ b/src/lib/gothwadSso.ts
@@ -0,0 +1,167 @@
+import {
+ ACCOUNTS_API_ORIGIN,
+ ACCOUNTS_WEB_ORIGIN,
+ buildAccountSlotPath,
+ buildSignInUrl,
+ formatGothwadEmail,
+ parseAuthuserFromUrl,
+} from "../config/brand";
+
+export const DEFAULT_API_TIMEOUT_MS = 8000;
+
+export interface GothwadSsoUser {
+ id: string;
+ username?: string;
+ email: string;
+ firstName?: string;
+ lastName?: string;
+ name: string;
+ avatarUrl?: string | null;
+ avatar_url?: string | null;
+}
+
+export interface GothwadAccountItem {
+ id: string;
+ authuser: number;
+ username?: string;
+ name: string;
+ firstName?: string;
+ lastName?: string;
+ email: string;
+ avatarUrl?: string | null;
+ avatar_url?: string | null;
+ accountUrl?: string | null;
+}
+
+export type ServiceErrorKind = "none" | "routing_html" | "http_5xx" | "rate_limited" | "network" | "timeout" | "redirect";
+
+export interface FetchMeResult {
+ status: "authenticated" | "anonymous" | "error";
+ authenticated: boolean;
+ activeId: string | null;
+ authuser: number;
+ user: GothwadSsoUser | null;
+ accounts: GothwadAccountItem[];
+ errorKind: ServiceErrorKind;
+ errorMessage: string | null;
+}
+
+function normalizeClientUser(raw: any): GothwadSsoUser | null {
+ if (!raw || typeof raw !== "object") return null;
+ const id = String(raw.id || raw.userId || "").trim();
+ const rawEmail = String(raw.email || "").trim().toLowerCase();
+ const username = String(raw.username || (rawEmail ? rawEmail.split("@")[0] : "")).trim().toLowerCase();
+ if (!id || !username) return null;
+ const firstName = String(raw.firstName ?? raw.first_name ?? "").trim();
+ const lastName = String(raw.lastName ?? raw.last_name ?? "").trim();
+ const name = String(raw.name || `${firstName} ${lastName}`.trim() || username).trim();
+ const avatarUrl = raw.avatarUrl ?? raw.avatar_url ?? null;
+ return { id, username, email: formatGothwadEmail(raw.email || username), firstName, lastName, name, avatarUrl: avatarUrl ? String(avatarUrl) : null, avatar_url: avatarUrl ? String(avatarUrl) : null };
+}
+
+function normalizeClientAccount(raw: any, idx: number): GothwadAccountItem {
+ const username = String(raw?.username || "").trim().toLowerCase();
+ const firstName = String(raw?.firstName ?? raw?.first_name ?? "").trim();
+ const lastName = String(raw?.lastName ?? raw?.last_name ?? "").trim();
+ const name = String(raw?.name || `${firstName} ${lastName}`.trim() || username || "Account").trim();
+ const authuser = Number.isInteger(raw?.authuser) ? Number(raw.authuser) : idx;
+ const avatarUrl = raw?.avatarUrl ?? raw?.avatar_url ?? null;
+ return {
+ id: String(raw?.id || raw?.slot || "a"),
+ authuser,
+ username,
+ name,
+ firstName,
+ lastName,
+ email: formatGothwadEmail(raw?.email || username),
+ avatarUrl: avatarUrl ? String(avatarUrl) : null,
+ avatar_url: avatarUrl ? String(avatarUrl) : null,
+ accountUrl: raw?.accountUrl || `${ACCOUNTS_WEB_ORIGIN}/u/${authuser}/me`,
+ };
+}
+
+export function getCurrentAuthuser(): number {
+ return parseAuthuserFromUrl().authuser;
+}
+export const slotUrl = buildAccountSlotPath;
+export const buildSsoSignInUrl = buildSignInUrl;
+
+function buildAuthuserHeaders(authuser?: number): Record {
+ const h: Record = { Accept: "application/json" };
+ if (Number.isInteger(authuser) && authuser! >= 0 && authuser! <= 5) h["X-Gothwad-Authuser"] = String(authuser);
+ return h;
+}
+
+async function fetchBounded(url: string, init: RequestInit, timeoutMs = DEFAULT_API_TIMEOUT_MS): Promise {
+ const controller = new AbortController();
+ const timer = setTimeout(() => controller.abort(new Error("RequestTimeout")), timeoutMs);
+ try {
+ return await fetch(url, { ...init, cache: "no-store", redirect: "manual", signal: controller.signal });
+ } finally {
+ clearTimeout(timer);
+ }
+}
+
+export async function fetchGothwadSession(authuser = 0): Promise {
+ const headers = buildAuthuserHeaders(authuser);
+ const endpoint = `${ACCOUNTS_API_ORIGIN}/api/me`;
+ try {
+ const res = await fetchBounded(endpoint, { method: "GET", credentials: "include", headers });
+ if (res.type === "opaqueredirect" || (res as any).redirected || (res.status >= 300 && res.status < 400)) {
+ return { status: "error", authenticated: false, activeId: null, authuser, user: null, accounts: [], errorKind: "redirect", errorMessage: "Identity redirect" };
+ }
+ const ct = (res.headers.get("content-type") || "").toLowerCase();
+ if (ct.includes("text/html")) {
+ return { status: "error", authenticated: false, activeId: null, authuser, user: null, accounts: [], errorKind: "routing_html", errorMessage: "HTML response" };
+ }
+ if (res.status === 429) return { status: "error", authenticated: false, activeId: null, authuser, user: null, accounts: [], errorKind: "rate_limited", errorMessage: "Rate limited" };
+ const data: any = await res.json().catch(() => null);
+ if (res.ok && data?.authenticated && data?.user) {
+ const user = normalizeClientUser(data.user);
+ if (!user) return { status: "error", authenticated: false, activeId: null, authuser, user: null, accounts: [], errorKind: "http_5xx", errorMessage: "Bad payload" };
+ const accounts: GothwadAccountItem[] = Array.isArray(data.accounts) && data.accounts.length > 0
+ ? data.accounts.map((a: any, i: number) => normalizeClientAccount(a, i))
+ : [normalizeClientAccount({ ...user, id: data.activeId || "a", authuser: data.authuser ?? authuser }, 0)];
+ return { status: "authenticated", authenticated: true, activeId: String(data.activeId || accounts[0]?.id || "a"), authuser: Number.isInteger(data.authuser) ? Number(data.authuser) : authuser, user, accounts, errorKind: "none", errorMessage: null };
+ }
+ if (res.status === 200 || res.status === 401) {
+ return { status: "anonymous", authenticated: false, activeId: null, authuser, user: null, accounts: [], errorKind: "none", errorMessage: null };
+ }
+ if (res.status >= 500) return { status: "error", authenticated: false, activeId: null, authuser, user: null, accounts: [], errorKind: "http_5xx", errorMessage: data?.message || `HTTP ${res.status}` };
+ return { status: "anonymous", authenticated: false, activeId: null, authuser, user: null, accounts: [], errorKind: "none", errorMessage: null };
+ } catch (err: any) {
+ const msg = err?.message || String(err);
+ if (msg.includes("RequestTimeout") || err?.name === "AbortError") {
+ return { status: "error", authenticated: false, activeId: null, authuser, user: null, accounts: [], errorKind: "timeout", errorMessage: "Timeout" };
+ }
+ return { status: "error", authenticated: false, activeId: null, authuser, user: null, accounts: [], errorKind: "network", errorMessage: "Network error" };
+ }
+}
+
+export const fetchSsoMe = fetchGothwadSession;
+
+// Helpers for switch / signout — mirrored from drive
+export async function switchGothwadAccountSlot(slotId: string, authuser: number): Promise<{ ok: boolean; error?: string }> {
+ const headers: Record = { ...buildAuthuserHeaders(authuser), "Content-Type": "application/json" };
+ try {
+ const res = await fetchBounded(`${ACCOUNTS_API_ORIGIN}/api/auth/switch`, { method: "POST", credentials: "include", headers, body: JSON.stringify({ id: slotId, authuser }) });
+ const ct = (res.headers.get("content-type") || "").toLowerCase();
+ if (ct.includes("application/json")) {
+ const data: any = await res.json().catch(() => null);
+ if (res.ok && data?.ok !== false) return { ok: true };
+ return { ok: false, error: data?.message || `Switch failed (${res.status})` };
+ }
+ return { ok: res.ok };
+ } catch { return { ok: false, error: "Network error" }; }
+}
+
+export async function signOutGothwadSlot(slotId?: string, authuser = 0): Promise<{ ok: boolean }> {
+ const path = slotId ? `/api/auth/accounts/${encodeURIComponent(slotId)}/signout` : "/api/auth/signout";
+ const headers: Record = { ...buildAuthuserHeaders(authuser), "Content-Type": "application/json" };
+ try {
+ const res = await fetchBounded(`${ACCOUNTS_API_ORIGIN}${path}`, { method: "POST", credentials: "include", headers, body: "{}" });
+ return { ok: res.ok };
+ } catch { return { ok: false }; }
+}
+export const signOutSsoSlot = (slotId: string, authuser = 0) => signOutGothwadSlot(slotId, authuser);
+export const signOutAllSso = (authuser = 0) => signOutGothwadSlot(undefined, authuser);
diff --git a/src/main.tsx b/src/main.tsx
new file mode 100644
index 0000000..2339d59
--- /dev/null
+++ b/src/main.tsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import App from './App';
+import './index.css';
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+
+);
diff --git a/src/pages/CompanyPage.tsx b/src/pages/CompanyPage.tsx
new file mode 100644
index 0000000..52c24bb
--- /dev/null
+++ b/src/pages/CompanyPage.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import { Breadcrumbs } from '../components/Breadcrumbs';
+
+export const CompanyPage: React.FC<{ onNavigate: (p: string) => void }> = ({ onNavigate }) => {
+ return (
+
+
+
Gothwad Tech
+
+ Sovereign software from Jaipur, Rajasthan — founder Pawan Gothwad , CEO Yuvkesh Meena . We build browsers, messaging and business tools for Bharat. Open-source on GitHub.
+
+
+
+ {[
+ { name: 'Pawan Gothwad', role: 'Founder', email: 'pawan@gothwadtech.com' },
+ { name: 'Yuvkesh Meena', role: 'CEO', email: 'ceo@gothwadtech.com', highlight: true },
+ { name: 'Vishnu Meena', role: 'CTO', email: 'vishnu@gothwadtech.com' },
+ ].map((p) => (
+
+ {p.name.split(' ').map(n=>n[0]).join('')}
+ {p.name}
+ {p.role}
+ {p.email}
+
+ ))}
+
+
+
+ 12 specialists • founded 2023 • Aatmanirbhar Bharat •
GitHub
+
+
+ );
+};
diff --git a/src/pages/ContactPage.tsx b/src/pages/ContactPage.tsx
new file mode 100644
index 0000000..73cfd95
--- /dev/null
+++ b/src/pages/ContactPage.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import { Mail, Phone, MessageSquare } from 'lucide-react';
+import { Breadcrumbs } from '../components/Breadcrumbs';
+import { COMPANY_INFO } from '../data/companyData';
+
+export const ContactPage: React.FC = () => {
+ return (
+
+
+
Contact
+
We reply in 2–4 hours.
+
+
+ {[
+ { label: 'Business', email: COMPANY_INFO.email },
+ { label: 'Support', email: COMPANY_INFO.supportEmail },
+ { label: 'Help', email: COMPANY_INFO.helpEmail },
+ ].map((it) => (
+
+
+
+ {it.label}
+
+ {it.email}
+
+ ))}
+
+
+
+ );
+};
diff --git a/src/pages/DocsPage.tsx b/src/pages/DocsPage.tsx
new file mode 100644
index 0000000..74ed165
--- /dev/null
+++ b/src/pages/DocsPage.tsx
@@ -0,0 +1,40 @@
+import React from 'react';
+import { BookOpen, ArrowRight } from 'lucide-react';
+import { Breadcrumbs } from '../components/Breadcrumbs';
+
+const DOCS = [
+ { title: 'Quickstart', desc: 'Run your first Gothwad app', href: 'https://docs.gothwadtech.com/docs/quickstart' },
+ { title: 'Accounts OAuth', desc: 'PKCE flow + user info', href: 'https://docs.gothwadtech.com/docs/oauth' },
+ { title: 'Mail setup', desc: 'Deploy inbox on Cloudflare', href: 'https://docs.gothwadtech.com/docs/mail-setup' },
+ { title: 'API reference', desc: 'Accounts + Mail REST', href: 'https://docs.gothwadtech.com/docs/api' },
+ { title: 'Ecosystem', desc: 'How apps connect', href: 'https://docs.gothwadtech.com/docs/architecture' },
+ { title: 'Browser', desc: 'Android TV & mobile', href: 'https://docs.gothwadtech.com/docs/browser' },
+];
+
+export const DocsPage: React.FC = () => {
+ return (
+
+
+
Docs
+
Source-based docs for Gothwad ecosystem.
+
+
+ {DOCS.map((d) => (
+
+
+
+
+ ))}
+
+
+
+
+ );
+};
diff --git a/src/pages/EcosystemPage.tsx b/src/pages/EcosystemPage.tsx
new file mode 100644
index 0000000..21a06e9
--- /dev/null
+++ b/src/pages/EcosystemPage.tsx
@@ -0,0 +1,136 @@
+import React, { useMemo, useState } from 'react';
+import { ArrowUpRight, Github, Search, ExternalLink, Fingerprint, Mail, HardDrive, Video } from 'lucide-react';
+import { ECOSYSTEM_APPS, CATEGORIES } from '../data/ecosystem';
+import type { CategoryId } from '../data/ecosystem';
+import { Breadcrumbs } from '../components/Breadcrumbs';
+import { COMPANY_INFO } from '../data/companyData';
+
+export const EcosystemPage: React.FC<{ onNavigate?: (p: string) => void }> = () => {
+ const [category, setCategory] = useState('all');
+ const [query, setQuery] = useState('');
+
+ const apps = useMemo(() => {
+ const q = query.trim().toLowerCase();
+ return ECOSYSTEM_APPS.filter((app) => {
+ const catOk = category === 'all' ? true : app.category === category;
+ if (!catOk) return false;
+ if (!q) return true;
+ return (
+ app.name.toLowerCase().includes(q) ||
+ app.tagline.toLowerCase().includes(q) ||
+ app.description.toLowerCase().includes(q) ||
+ app.host.toLowerCase().includes(q) ||
+ (app.githubRepo ?? '').toLowerCase().includes(q)
+ );
+ });
+ }, [category, query]);
+
+ return (
+
+
+
+
+ Ecosystem Directory
+
+
+ All Gothwad products — direct links
+
+
+ Every Gothwad product in one place. Each card shows the live subdomain ({'{host}.gothwadtech.com'}), a short description, GitHub repo and one-click access. Connected apps use your Gothwad Account; standalone apps use “Sign in with Gothwad”.
+
+
+
+
+
+ {CATEGORIES.map((c) => (
+ setCategory(c.id as CategoryId)}
+ className={`px-3 py-1.5 rounded-xl text-xs font-semibold border transition-colors cursor-pointer ${category === c.id ? 'bg-[#0494f4] text-white border-[#0494f4]' : 'bg-white dark:bg-zinc-950 text-zinc-600 dark:text-zinc-400 border-zinc-200 dark:border-zinc-800 hover:bg-zinc-100 dark:hover:bg-zinc-800'}`}
+ >
+ {c.label}
+
+ ))}
+
+
+
+ setQuery(e.target.value)}
+ placeholder="Search: Mail, Drive, Tube, Browser…"
+ className="w-full pl-9 pr-3 py-2 rounded-xl bg-white dark:bg-zinc-950 border border-zinc-200 dark:border-zinc-800 text-xs text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:border-[#0494f4] focus:ring-2 focus:ring-[#0494f4]/20"
+ />
+
+
+
+
+ Showing {apps.length} {apps.length === 1 ? 'product' : 'products'} • Core = Gothwad Account connected (cannot be revoked) • Others = “Sign in with Gothwad” (revocable)
+
+
+
+ {apps.map((app) => {
+ const Icon = app.icon;
+ return (
+
+
+
+
+
+
+
+ {app.badge}
+
+ {app.core && Core }
+
+
+
+
{app.name}
+
{app.tagline}
+
{app.description}
+
+
+ {app.platforms.map((p) => (
+
+ {p}
+
+ ))}
+
+
+
+
{app.host}.gothwadtech.com
+
+ );
+ })}
+
+
+ {/* Bottom helper — mirrors docs “leadership themes” but as product CTA */}
+
+
+
A connected ecosystem
+
Accounts, Mail, Drive, Meet and Store live alongside standalone products in the same Gothwad Account directory — same as our docs portal.
+
+
+
Web & mobile, side by side
+
From Cloudflare Pages web apps to native Android apps for phones, tablets & Android TVs — one portfolio, many platforms.
+
+
+
Public record of the work
+
Every card links to its GitHub repo and documentation boundary. Read the source, not just the marketing copy.
+
+
+
+
+
+ );
+};
diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx
new file mode 100644
index 0000000..20b1a14
--- /dev/null
+++ b/src/pages/HomePage.tsx
@@ -0,0 +1,142 @@
+import React, { useState } from 'react';
+import { Search, ArrowUpRight, Grid2X2, Github, BookOpen } from 'lucide-react';
+import { Logo } from '../components/Logo';
+import { ECOSYSTEM_APPS } from '../data/ecosystem';
+
+export const HomePage: React.FC<{ onNavigate: (p: string) => void }> = ({ onNavigate }) => {
+ const [q, setQ] = useState('');
+
+ const filtered = ECOSYSTEM_APPS.filter((app) => {
+ if (!q.trim()) return true;
+ const s = q.toLowerCase();
+ return (
+ app.name.toLowerCase().includes(s) ||
+ app.tagline.toLowerCase().includes(s) ||
+ app.host.toLowerCase().includes(s) ||
+ app.description.toLowerCase().includes(s)
+ );
+ });
+
+ return (
+
+ {/* Google-like centered hero */}
+
+ {/* Big logo — like Google doodle */}
+
+
+
Gothwad Tech — Official Website
+
+ Everything Gothwad, in one place.
+
+
+
+ {/* Search bar — Google rounded-full */}
+
+
+
+ setQ(e.target.value)}
+ placeholder="Search products — try Mail, Drive, Browser..."
+ className="flex-1 h-full bg-transparent outline-none text-sm text-zinc-900 dark:text-white placeholder:text-zinc-400"
+ autoFocus
+ />
+ {q && (
+ setQ('')}
+ className="text-xs text-zinc-500 hover:text-zinc-900 dark:hover:text-white px-2 cursor-pointer"
+ >
+ Clear
+
+ )}
+
+
+ setQ('')}
+ className="px-4 py-1.5 rounded-full bg-zinc-100 dark:bg-zinc-800 hover:bg-zinc-200 dark:hover:bg-zinc-700 text-zinc-700 dark:text-zinc-300 text-xs font-medium border border-zinc-200 dark:border-zinc-700 cursor-pointer"
+ >
+ I’m feeling lucky
+
+ onNavigate('ecosystem')}
+ className="px-4 py-1.5 rounded-full bg-[#0494f4] hover:bg-[#0077cd] text-white text-xs font-medium cursor-pointer"
+ >
+ Browse ecosystem
+
+
+
+
+ {/* Product grid — like Google apps / Chrome shortcuts */}
+
+
+
QUICK ACCESS
+
+
onNavigate('ecosystem')}
+ className="text-xs text-[#0494f4] hover:underline inline-flex items-center gap-1 cursor-pointer"
+ >
+ See all
+
+
+
+
+
+ {filtered.length === 0 && (
+
+
No products found for “{q}”
+
setQ('')} className="mt-2 text-xs text-[#0494f4] hover:underline cursor-pointer">Clear search
+
+ )}
+
+
+ {/* Minimal language + India */}
+
+ Offered by Gothwad Tech in: English • हिन्दी
+
+
+
+ {/* Google-like footer */}
+
+
+ );
+};
diff --git a/src/pages/ProductsPage.tsx b/src/pages/ProductsPage.tsx
new file mode 100644
index 0000000..ff602b3
--- /dev/null
+++ b/src/pages/ProductsPage.tsx
@@ -0,0 +1,45 @@
+import React from 'react';
+import { Compass, MessageSquare, Send, ArrowRight, ExternalLink } from 'lucide-react';
+import { Breadcrumbs } from '../components/Breadcrumbs';
+
+const PRODUCTS = [
+ { id: 'browser', name: 'Gothwad Browser', desc: '11.8 MB • 75% less RAM • TurboShield', icon: Compass, color: 'text-[#0494f4]', href: 'https://browser.gothwadtech.com', play: 'https://play.google.com/store/apps/details?id=com.gothwad.browser' },
+ { id: 'grixchat', name: 'GrixChat', desc: '<15ms • 2GB files • HD calling', icon: MessageSquare, color: 'text-emerald-600', href: 'https://grixchat.gothwadtech.com', play: 'https://play.google.com/store/apps/details?id=com.gothwad.grixchat' },
+ { id: 'indogram', name: 'Indogram', desc: '200k members • unlimited cloud', icon: Send, color: 'text-sky-600', href: 'https://indogram.gothwadtech.com', play: 'https://play.google.com/store/apps/details?id=com.gothwad.indogram' },
+];
+
+export const ProductsPage: React.FC = () => {
+ return (
+
+
+
Sovereign apps
+
Three flagships — open on any device.
+
+
+ {PRODUCTS.map((p) => {
+ const Icon = p.icon;
+ return (
+
+
+
+
+
{p.name}
+
{p.desc}
+
+
+ );
+ })}
+
+
+
+
Want all products? Try the ecosystem hub.
+
Ecosystem
+
+
+ );
+};
diff --git a/src/pages/SolutionsPage.tsx b/src/pages/SolutionsPage.tsx
new file mode 100644
index 0000000..7255c3d
--- /dev/null
+++ b/src/pages/SolutionsPage.tsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import { GraduationCap, Utensils, Store, Building2, ArrowRight } from 'lucide-react';
+import { Breadcrumbs } from '../components/Breadcrumbs';
+
+const ITEMS = [
+ { icon: GraduationCap, title: 'School ERP', desc: 'Fees, attendance, parent app', price: '₹24,999' },
+ { icon: Utensils, title: 'Restaurant POS', desc: 'Ordering + QR + billing', price: '₹19,999' },
+ { icon: Store, title: 'Shop billing', desc: 'Barcode + Khata + storefront', price: '₹14,999' },
+ { icon: Building2, title: 'Business CRM', desc: 'Leads, invoices, payroll', price: '₹29,999' },
+];
+
+export const SolutionsPage: React.FC<{ onNavigate: (p: string) => void }> = ({ onNavigate }) => {
+ return (
+
+
+
Solutions
+
Simple tools for shops, schools and startups.
+
+
+ {ITEMS.map((it) => {
+ const Icon = it.icon;
+ return (
+
+
+
+
+
+
{it.title}
+
{it.desc}
+
+
{it.price}
+
+ );
+ })}
+
+
+
+
onNavigate('contact')} className="px-5 py-2 rounded-full bg-[#0494f4] text-white text-sm font-medium hover:bg-[#0077cd] cursor-pointer">
+ Contact for demo
+
+
+
+ );
+};
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..a63109e
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "strict": true,
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "noFallthroughCasesInSwitch": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": true,
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/tsconfig.node.json b/tsconfig.node.json
new file mode 100644
index 0000000..482b7fd
--- /dev/null
+++ b/tsconfig.node.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "target": "ES2022",
+ "lib": ["ES2022"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": false,
+ "strict": true,
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 0000000..1c5bdca
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,18 @@
+import tailwindcss from '@tailwindcss/vite';
+import react from '@vitejs/plugin-react';
+import path from 'path';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [react(), tailwindcss()],
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, '.'),
+ },
+ },
+ server: {
+ allowedHosts: true as const,
+ hmr: process.env.DISABLE_HMR !== 'true',
+ watch: process.env.DISABLE_HMR === 'true' ? null : {},
+ },
+});